diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..3bae475
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,37 @@
+pipeline {
+ environment {
+ JAVA_TOOL_OPTIONS = '-Duser.home=/var/jenkins_home'
+ }
+ agent {
+ docker {
+ image 'maven:3.6.1-jdk-8-alpine'
+ args '-e MAVEN_CONFIG=/var/jenkins_home/.m2'
+ }
+ }
+ stages {
+ stage('Preparation') {
+ steps {
+ git url: 'https://github.com/rlsutton1/GridStack.git', credentialsId: 'bitbucket'
+ }
+ }
+ stage('Build') {
+ steps {
+ sh 'mvn -B -Dmaven.test.skip=true -DskipTests -f gridstack-addon/pom.xml clean package'
+ }
+ }
+ stage('Deliver') {
+ steps {
+ sh 'mvn jar:jar install:install help:evaluate -Dexpression=project.name -f gridstack-addon/pom.xml'
+ }
+ }
+ }
+ post {
+ always {
+ emailext attachLog: true,
+ to: '$DEFAULT_RECIPIENTS',
+ subject: '$DEFAULT_SUBJECT',
+ body: '$DEFAULT_CONTENT'
+ }
+ }
+}
+
diff --git a/gridstack-addon/pom.xml b/gridstack-addon/pom.xml
index 4e68e70..a37ceb3 100644
--- a/gridstack-addon/pom.xml
+++ b/gridstack-addon/pom.xml
@@ -5,7 +5,7 @@
org.vaadin.alump.gridstack
gridstack-addon
bundle
- 0.3.1-SNAPSHOT
+ 0.3.1-nj
GridStack Add-on
diff --git a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayout.java b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayout.java
index 843d7e6..87d4f1e 100644
--- a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayout.java
+++ b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayout.java
@@ -18,18 +18,6 @@
package org.vaadin.alump.gridstack;
import com.vaadin.annotations.JavaScript;
-import com.vaadin.event.LayoutEvents;
-import com.vaadin.shared.Connector;
-import com.vaadin.shared.EventId;
-import com.vaadin.shared.MouseEventDetails;
-import com.vaadin.ui.AbstractLayout;
-import com.vaadin.ui.Component;
-import org.vaadin.alump.gridstack.client.shared.*;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
/**
* Vaadin layout using gridstack.js library to layout components
@@ -37,623 +25,18 @@
* gridstack.js by Pavel Reznikov: http://troolee.github.io/gridstack.js/
*/
@JavaScript({"jquery-1.11.3.min.js", "jquery-ui.min.js", "lodash.min.js", "gridstack.js"})
-public class GridStackLayout extends AbstractLayout implements LayoutEvents.LayoutClickNotifier {
-
- protected final List components = new ArrayList();
-
- private boolean initialClientResponseSent = false;
-
- private final List moveListeners = new ArrayList();
-
- /**
- * Use this as x or y coordinate if you want to leave slot selection of component to client side
- */
- public final static int CLIENT_SIDE_SELECTS = -1;
-
- private GridStackServerRpc serverRpc = new GridStackServerRpc() {
-
- @Override
- public void layoutClick(MouseEventDetails mouseEventDetails, Connector connector) {
- fireEvent(LayoutEvents.LayoutClickEvent.createEvent(GridStackLayout.this,
- mouseEventDetails, connector));
- }
-
- @Override
- public void onChildrenMoved(List moves) {
- Collection events = new ArrayList();
- for(GridStackMoveData move : moves) {
- Component childComponent = (Component)move.child;
- GridStackCoordinates oldCoordinates = getCoordinates(childComponent);
-
- GridStackChildOptions info = getState(false).childOptions.get(move.child);
- info.x = move.x;
- info.y = move.y;
- info.width = move.width;
- info.height = move.height;
-
- if(!oldCoordinates.equals(getCoordinates(childComponent))) {
- events.add(createMoveEvent(childComponent, oldCoordinates));
- }
- }
- fireMoveEvents(events);
- }
- };
-
- /**
- * Creates GridStackLayout with default 3 columns
- */
- public GridStackLayout() {
- super();
- registerRpc(serverRpc, GridStackServerRpc.class);
- }
-
- /**
- * Create GridStackLayout with defined column count.
- * @param columns Number of columns, if more than 8 see documentation (extra SCSS including required)
- */
- public GridStackLayout(int columns) {
- this();
- if(columns <= 0) {
- throw new IllegalArgumentException("Amount of columns can not be 0 or negative");
- }
- addStyleName("with-" + columns + "-columns");
- getState().gridStackOptions.width = columns;
- }
-
- /**
- * Create GridStackLayout with defined column and row count.
- * @param columns Number of columns, if more than 8 see documentation (extra SCSS including required)
- * @param rows Maxium amount of rows allowed
- */
- public GridStackLayout(int columns, int rows) {
- this(columns);
- if(rows <= 0) {
- throw new IllegalArgumentException("Amount of rows can not be 0 or negative");
- }
- getState().gridStackOptions.height = rows;
- }
-
- @Override
- public void beforeClientResponse(boolean initial) {
- super.beforeClientResponse(initial);
- initialClientResponseSent = true;
- }
-
-
- @Override
- protected GridStackLayoutState getState() {
- return (GridStackLayoutState)super.getState();
- }
-
- @Override
- protected GridStackLayoutState getState(boolean markDirty) {
- return (GridStackLayoutState)super.getState(markDirty);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addComponent(Component component) {
- addComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS);
- }
-
- /**
- * Add component to layout
- * @param component Component added
- * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
- * drag handle. Notice that using a separate drag handle is recommended if you component
- * is or contains any active components (buttons etc..)
- */
- public void addComponent(Component component, boolean useDragHandle) {
- addComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS, useDragHandle);
- }
-
- /**
- * Add component to given slot
- * @param component Component added
- * @param x Slot's X coordinate
- * @param y Slot's Y coordinate
- */
- public void addComponent(Component component, int x, int y) {
- addComponent(component, x, y, 1, 1);
- }
-
- /**
- * Add component to given slot
- * @param component Component added
- * @param x Slot's X coordinate
- * @param y Slot's Y coordinate
- * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
- * drag handle. Notice that using a separate drag handle is recommended if you component
- * is or contains any active components (buttons etc..)
- */
- public void addComponent(Component component, int x, int y, boolean useDragHandle) {
- addComponent(component, x, y, 1, 1, useDragHandle);
- }
-
- /**
- * Add component to given slot, and define it's size
- * @param component Component added
- * @param x Slot's X coordinate (use negative values if position can be defined on client side)
- * @param y Slot's Y coordinate (use negative values if position can be defined on client side)
- * @param width Width of space reserved (in slots)
- * @param height Height of space reserved (in slots)
- */
- public void addComponent(Component component, int x, int y, int width, int height) {
- addComponent(component, x, y, width, height, true);
- }
-
- /**
- * Add component to given slot, and define it's size
- * @param component Component added
- * @param x Slot's X coordinate (use negative values if position can be defined on client side)
- * @param y Slot's Y coordinate (use negative values if position can be defined on client side)
- * @param width Width of space reserved (in slots)
- * @param height Height of space reserved (in slots)
- * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
- * drag handle. Notice that using a separate drag handle is recommended if you component
- * is or contains any active components (buttons etc..)
- */
- public void addComponent(Component component, int x, int y, int width, int height, boolean useDragHandle) {
- super.addComponent(component);
- components.add(component);
-
- GridStackChildOptions info = new GridStackChildOptions();
- info.x = x;
- info.y = y;
- info.width = width;
- info.height = height;
- info.useDragHandle = useDragHandle;
- getState().childOptions.put(component, info);
- }
-
- /**
- * Reset component's position and allow child side define new position for it.
- * @param component Child component which position is reset
- */
- public void resetComponentPosition(Component component) {
- moveComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS);
- }
-
- /**
- * Move given child component
- * @param component Child component moved and/or resized
- * @param x When defined component's X value is updated, if null old value is kept
- * @param y When defined component's Y value is updated, if null old value is kept
- * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout)
- */
- public void moveComponent(Component component, Integer x, Integer y) throws IllegalArgumentException {
- moveAndResizeComponent(component, x, y, null, null);
- }
-
- /**
- * Move given child component
- * @param component Child component moved and/or resized
- * @param width When defined component's width is updated, if null old value is kept
- * @param height When defined component's height is updated, if null old value is kept
- * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout)
- */
- public void resizeComponent(Component component, Integer width, Integer height) throws IllegalArgumentException {
- moveAndResizeComponent(component, null, null, width, height);
- }
-
- /**
- * Move and/or resize given child component
- * @param component Child component moved and/or resized
- * @param x When defined component's X value is updated, if null old value is kept
- * @param y When defined component's Y value is updated, if null old value is kept
- * @param width When defined component's width is updated, if null old value is kept
- * @param height When defined component's height is updated, if null old value is kept
- * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout, or
- * coordinates are invalid).
- */
- public void moveAndResizeComponent(Component component, Integer x, Integer y, Integer width, Integer height)
- throws IllegalArgumentException {
-
- if(x != null & width != null && x >= 0 && x + width > getState(false).gridStackOptions.width) {
- throw new IllegalArgumentException("Component would go outside the right edge of layout");
- }
-
- GridStackChildOptions info = getState().childOptions.get(component);
- if(info == null) {
- throw new IllegalArgumentException("Given component is not child of GridStackLayout");
- }
- if(x != null) {
- info.x = x;
- }
- if(y != null) {
- info.y = y;
- }
- if(width != null) {
- info.width = width;
- }
- if(height != null) {
- info.height = height;
- }
- }
-
- /**
- * Get component with given slot coordinate
- * @param x Slot's X coordinate
- * @param y Slot's Y coordinate
- * @return Component at slot, or null if component not found
- */
- public Component getComponent(int x, int y) {
- return getComponent(x, y, false);
- }
-
- /**
- * Get component with given slot coordinate
- * @param x Slot's X coordinate
- * @param y Slot's Y coordinate
- * @param acceptInsideHit If true also other slots reserved by component are accepted
- * @return Component at slot, or null if component not found
- */
- public Component getComponent(int x, int y, boolean acceptInsideHit) {
- for(Connector connector : getState().childOptions.keySet()) {
- GridStackChildOptions info = getState().childOptions.get(connector);
- if(acceptInsideHit) {
- if(x >= info.x && x < (info.x + info.width) && y >= info.y && y < (info.y + info.width)) {
- return (Component) connector;
- }
- } else {
- if (info.x == x && info.y == y) {
- return (Component) connector;
- }
- }
- }
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void removeComponent(Component component) {
- getState().childOptions.remove(component);
- components.remove(component);
- super.removeComponent(component);
- }
-
- @Override
- public void replaceComponent(Component oldComponent, Component newComponent) {
- if(oldComponent == newComponent) {
- return;
- }
- if(oldComponent.getParent() != this) {
- throw new IllegalArgumentException("Replacable component not child of this layout");
- }
- GridStackChildOptions oldOptions = getState(false).childOptions.get(oldComponent);
- removeComponent(oldComponent);
-
- if(newComponent.getParent() == this) {
- removeComponent(newComponent);
- }
- addComponent(newComponent, oldOptions.x, oldOptions.y, oldOptions.width, oldOptions.height);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int getComponentCount() {
- return components.size();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator iterator() {
- return components.iterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void addLayoutClickListener(LayoutEvents.LayoutClickListener listener) {
- addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER,
- LayoutEvents.LayoutClickEvent.class, listener,
- LayoutEvents.LayoutClickListener.clickMethod);
- }
-
- @Override
- @Deprecated
- public void addListener(LayoutEvents.LayoutClickListener layoutClickListener) {
- addLayoutClickListener(layoutClickListener);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void removeLayoutClickListener(LayoutEvents.LayoutClickListener listener) {
- removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER,
- LayoutEvents.LayoutClickEvent.class, listener);
- }
-
- @Override
- @Deprecated
- public void removeListener(LayoutEvents.LayoutClickListener layoutClickListener) {
- removeLayoutClickListener(layoutClickListener);
- }
-
- /**
- * Add listener for component move events
- * @param listener Listener added
- */
- public void addGridStackMoveListener(GridStackMoveEvent.GridStackMoveListener listener) {
- moveListeners.add(listener);
- }
-
- /**
- * Remove listener of component move events
- * @param listener Listener removed
- */
- public void removeGridStackMoveListener(GridStackMoveEvent.GridStackMoveListener listener) {
- moveListeners.remove(listener);
- }
-
- /**
- * Get coordinates (X,Y,width,height) of component
- * @param child Child component of layout
- * @return Coordinates (X,Y,width,height) of component
- * @throws IllegalArgumentException If child not found
- */
- public GridStackCoordinates getCoordinates(Component child) {
- GridStackChildOptions opts = getComponentOptions(child, false);
- return new GridStackCoordinates(opts.x, opts.y, opts.width, opts.height);
- }
-
- protected GridStackMoveEvent createMoveEvent(Component component, GridStackCoordinates oldCoordinates) {
- return new GridStackMoveEvent(this, component, oldCoordinates,
- getCoordinates(component));
- }
-
- protected void fireMoveEvents(Collection events) {
- if(events.isEmpty()) {
- return;
- }
-
- for(GridStackMoveEvent.GridStackMoveListener listener : moveListeners) {
- listener.onGridStackMove(events);
- }
- }
-
- /**
- * Define size limitations to child component. For now some values must be defined before child has been rendered
- * on client side.
- * @param child Child of this layout
- * @param minWidth Mininum width in slots (null is undefined)
- * @param maxWidth Maxium width in slots (null is undefined)
- * @param minHeight Mininum height in slots (null is undefined)
- * @param maxHeight Maximum height in slots (null is undefined)
- */
- public void setComponentSizeLimits(Component child, Integer minWidth, Integer maxWidth, Integer minHeight, Integer maxHeight) {
- GridStackChildOptions childOpts = getComponentOptions(child);
- childOpts.minWidth = minWidth;
- childOpts.maxWidth = maxWidth;
- childOpts.minHeight = minHeight;
- childOpts.maxHeight = maxHeight;
- }
-
- /**
- * Check if given child is locked (not allowed to move because of other dragged children)
- * @param child Child component of layout
- * @return true if locked, false if not
- * @throws IllegalArgumentException If child not found
- */
- public boolean isComponentLocked(Component child) {
- return getComponentOptions(child, false).locked;
- }
-
- /**
- * Change locked state of child. Locked children will not be moved away from other dragged children.
- * @param child Child component of layout
- * @param locked true if locked, false if not
- * @throws IllegalArgumentException If child not found
- */
- public void setComponentLocked(Component child, boolean locked) {
- getComponentOptions(child).locked = locked;
- }
-
- protected GridStackChildOptions getComponentOptions(Component child) {
- return getComponentOptions(child, true, true);
- }
-
- protected GridStackChildOptions getComponentOptions(Component child, boolean modify) {
- return getComponentOptions(child, modify, true);
- }
-
- protected GridStackChildOptions getComponentOptions(Component child, boolean modify, boolean throwIfMissing) {
- if(child == null || child.getParent() != this) {
- throw new IllegalArgumentException("Given component is not child of this layout");
- }
- GridStackChildOptions opt = getState(modify).childOptions.get(child);
- if(opt == null) {
- throw new IllegalStateException("Missing child options");
- }
- return opt;
- }
-
- /**
- * Define if layout is animated when child components are moved
- * @param animate true to animate, false to not animate
- * @return This GridStackLayout for command chaining
- */
- public GridStackLayout setAnimate(boolean animate) {
- getState().gridStackOptions.animate = animate;
- return this;
- }
-
- /**
- * Check if layout is animated
- * @return true if animated, false if not
- */
- public boolean isAnimate() {
- return getState(false).gridStackOptions.animate;
- }
-
- /**
- * Set layout static (no dragging of resizing) or dynamic (dragging and resizing allowed)
- * @param staticGrid true to set static (no dragging of resizing), false to set dynamic (dragging and resizing
- * allowed)
- * @return This GridStackLayout for command chaining
- */
- public GridStackLayout setStaticGrid(boolean staticGrid) {
- getState().gridStackOptions.staticGrid = staticGrid;
- return this;
- }
-
- /**
- * Check if layout is in static mode
- * @return true if in static mode, false if not, null if not defined by server side
- */
- public Boolean isStaticGrid() {
- return getState(false).gridStackOptions.staticGrid;
- }
-
-
- /**
- * Check if component has specific dragging handle
- * @param child Child component of layout
- * @return true if component has separate dragging handle, false if whole content acts as dragging handle
- */
- public boolean isComponentWithDragHandle(Component child) {
- return getComponentOptions(child, false).useDragHandle;
- }
-
- /**
- * Define vertical margin between components on GridStack layout. Value is only read when rendered on client side
- * first time, so changing value after that will not have any effect (unless client side is detached).
- * @param marginPx Vertical margin in pixels
- * @return This GridStackLayout for command chaining
- */
- public GridStackLayout setVerticalMargin(int marginPx) {
- getState(true).gridStackOptions.verticalMargin = marginPx;
- return this;
- }
-
- /**
- * Get vertical margin between components. Value might be mismatch to actual value used, if changed after client
- * side was last attached.
- * @return Vertical margin in pixels, if null the gridstack.js default is used.
- */
- public Integer getVerticalMargin() {
- return getState(false).gridStackOptions.verticalMargin;
- }
-
- /**
- * Define height of cell in pixels.
- * @param heightPx Cell height in pixels
- * @return This GridStackLayout for command chaining
- */
- public GridStackLayout setCellHeight(int heightPx) {
- getState(true).gridStackOptions.cellHeight = heightPx;
- return this;
- }
-
- /**
- * Get height of cell in pixels.
- * @return Cell height in pixels, if null the gridstack.js default is used.
- */
- public Integer getCellHeight() {
- return getState(false).gridStackOptions.cellHeight;
- }
-
- /**
- * Set minimal width. If window width is less, grid will be shown in one-column mode. Changing value after
- * it has been attached on client side will not apply until client side is detached and attached.
- * @param minWidthPx Minimal width in pixels
- * @return This GridStackLayout for command chaining
- */
- public GridStackLayout setMinWidth(int minWidthPx) {
- getState(true).gridStackOptions.minWidth = minWidthPx;
- return this;
- }
-
- /**
- * Get minimal width. If window width is less, grid will be shown in one-column mode. Value might be mismatch to
- * actual value used, if changed after client side was last attached.
- * @return Minimal width in pixels, if null the gridstack.js default is used.
- */
- public Integer getMinWidth() {
- return getState(false).gridStackOptions.minWidth;
- }
-
- /**
- * Define if wrapper around child should allow vertical scrolling or not
- * @param child Child of layout
- * @param scrolling true to enable vertical scrolling, false to disable it
- * @throws IllegalArgumentException If child not found
- */
- public void setWrapperScrolling(Component child, boolean scrolling) {
- getComponentOptions(child, true).disableScrolling = !scrolling;
- }
-
- /**
- * Check if wrapper around child allows vertical scrolling or not
- * @param child Child of layout
- * @return true if wrapper allows vertical scrolling, false if wrapper hides vertical overflow
- * @throws IllegalArgumentException If child not found
- */
- public boolean isWrapperScrolling(Component child) {
- return getComponentOptions(child, false).disableScrolling;
- }
-
- /**
- * Check if given area is empty. Remember that any client side defined positioning not yet reported back to
- * server side will be unknown and so can result work results.
- * @param x Left edge coordinate of area
- * @param x Top edge coordinate of area
- * @param width Width of area in slots
- * @param height Height of area in slots
- * @return true if area is available and valid for use
- * @throws IllegalArgumentException If invalid values given
- */
- public boolean isAreaEmpty(int x, int y, int width, int height) throws IllegalArgumentException {
- return isAreaEmpty(new GridStackCoordinates(x, y, width, height));
- }
-
- /**
- * Check if given area is empty. Remember that any client side defined positioning not yet reported back to
- * server side will be unknown and so can result work results. Will also return false if area would go outside the
- * right edge.
- * @param coordinates Coordinate area checked (x, y, width, height)
- * @return true if area is available and valid for use
- * @throws IllegalArgumentException If invalid values given
- */
- public boolean isAreaEmpty(GridStackCoordinates coordinates) throws IllegalArgumentException {
- if(coordinates.getX() < 0) {
- throw new IllegalArgumentException("X can not be negative");
- }
- if(coordinates.getY() < 0) {
- throw new IllegalArgumentException("Y can not be negative");
- }
- if(coordinates.getWidth() <= 0) {
- throw new IllegalArgumentException("Width most be larger than zero");
- }
- if(coordinates.getHeight() <= 0) {
- throw new IllegalArgumentException("Height most be larger than zero");
- }
-
- // If item would drop out of left side, return false
- if(coordinates.getX() + coordinates.getWidth() > getState(false).gridStackOptions.width) {
- return false;
- }
-
- for(int dx = 0; dx < coordinates.getWidth(); ++dx) {
- for(int dy = 0; dy < coordinates.getHeight(); ++dy) {
- Component occupant = getComponent(coordinates.getX() + dx, coordinates.getY() + dy, true);
- if(occupant != null) {
- return false;
- }
- }
- }
-
- return true;
- }
-
+public class GridStackLayout extends GridStackLayoutNoJQuery{
+
+ private static final long serialVersionUID = 6467470894116980564L;
+
+ public GridStackLayout(int i)
+ {
+ super(i);
+ }
+
+ public GridStackLayout(int columns, int rows)
+ {
+ super(columns,rows);
+ }
+
}
diff --git a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayoutNoJQuery.java b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayoutNoJQuery.java
new file mode 100644
index 0000000..aed586b
--- /dev/null
+++ b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackLayoutNoJQuery.java
@@ -0,0 +1,674 @@
+/**
+ * GridStackLayout.java (GridStackLayout)
+ *
+ * Copyright 2015 Vaadin Ltd, Sami Viitanen
+ *
+ * Licensed 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.vaadin.alump.gridstack;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.vaadin.alump.gridstack.client.shared.GridStackChildOptions;
+import org.vaadin.alump.gridstack.client.shared.GridStackLayoutState;
+import org.vaadin.alump.gridstack.client.shared.GridStackMoveData;
+import org.vaadin.alump.gridstack.client.shared.GridStackServerRpc;
+
+import com.vaadin.annotations.JavaScript;
+import com.vaadin.event.LayoutEvents;
+import com.vaadin.shared.Connector;
+import com.vaadin.shared.EventId;
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.ui.AbstractLayout;
+import com.vaadin.ui.Component;
+
+/**
+ * Vaadin layout using gridstack.js library to layout components
+ *
+ * gridstack.js by Pavel Reznikov: http://troolee.github.io/gridstack.js/
+ */
+@JavaScript({ "lodash.min.js", "gridstack.js"})
+public class GridStackLayoutNoJQuery extends AbstractLayout implements LayoutEvents.LayoutClickNotifier {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7108377304337805340L;
+
+ protected final List components = new ArrayList();
+
+ private boolean initialClientResponseSent;
+
+ private final List moveListeners = new ArrayList();
+
+ /**
+ * Use this as x or y coordinate if you want to leave slot selection of component to client side
+ */
+ public final static int CLIENT_SIDE_SELECTS = -1;
+
+ private GridStackServerRpc serverRpc = new GridStackServerRpc() {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5534784708887723233L;
+
+ @Override
+ public void layoutClick(MouseEventDetails mouseEventDetails, Connector connector) {
+ fireEvent(LayoutEvents.LayoutClickEvent.createEvent(GridStackLayoutNoJQuery.this,
+ mouseEventDetails, connector));
+ }
+
+ @Override
+ public void onChildrenMoved(List moves) {
+ Collection events = new ArrayList();
+ for(GridStackMoveData move : moves) {
+ Component childComponent = (Component)move.child;
+ GridStackCoordinates oldCoordinates = getCoordinates(childComponent);
+
+ GridStackChildOptions info = getState(false).childOptions.get(move.child);
+ info.x = move.x;
+ info.y = move.y;
+ info.width = move.width;
+ info.height = move.height;
+
+ if(!oldCoordinates.equals(getCoordinates(childComponent))) {
+ events.add(createMoveEvent(childComponent, oldCoordinates));
+ }
+ }
+ fireMoveEvents(events);
+ }
+ };
+
+
+ /**
+ * Creates GridStackLayout with default 3 columns
+ */
+ public GridStackLayoutNoJQuery() {
+ super();
+ registerRpc(serverRpc, GridStackServerRpc.class);
+ }
+
+ /**
+ * Create GridStackLayout with defined column count.
+ * @param columns Number of columns, if more than 8 see documentation (extra SCSS including required)
+ */
+ public GridStackLayoutNoJQuery(int columns) {
+ this();
+ if(columns <= 0) {
+ throw new IllegalArgumentException("Amount of columns can not be 0 or negative");
+ }
+ addStyleName("with-" + columns + "-columns");
+ getState().gridStackOptions.width = columns;
+ }
+
+ /**
+ * Create GridStackLayout with defined column and row count.
+ * @param columns Number of columns, if more than 8 see documentation (extra SCSS including required)
+ * @param rows Maxium amount of rows allowed
+ */
+ public GridStackLayoutNoJQuery(int columns, int rows) {
+ this(columns);
+ if(rows <= 0) {
+ throw new IllegalArgumentException("Amount of rows can not be 0 or negative");
+ }
+ getState().gridStackOptions.height = rows;
+ }
+
+ @Override
+ public void beforeClientResponse(boolean initial) {
+ super.beforeClientResponse(initial);
+ initialClientResponseSent = true;
+ }
+
+
+ @Override
+ protected GridStackLayoutState getState() {
+ return (GridStackLayoutState)super.getState();
+ }
+
+ @Override
+ protected GridStackLayoutState getState(boolean markDirty) {
+ return (GridStackLayoutState)super.getState(markDirty);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addComponent(Component component) {
+ addComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS);
+ }
+
+ /**
+ * Add component to layout
+ * @param component Component added
+ * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
+ * drag handle. Notice that using a separate drag handle is recommended if you component
+ * is or contains any active components (buttons etc..)
+ */
+ public void addComponent(Component component, boolean useDragHandle) {
+ addComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS, useDragHandle);
+ }
+
+ /**
+ * Add component to given slot
+ * @param component Component added
+ * @param x Slot's X coordinate
+ * @param y Slot's Y coordinate
+ */
+ public void addComponent(Component component, int x, int y) {
+ addComponent(component, x, y, 1, 1);
+ }
+
+ /**
+ * Add component to given slot
+ * @param component Component added
+ * @param x Slot's X coordinate
+ * @param y Slot's Y coordinate
+ * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
+ * drag handle. Notice that using a separate drag handle is recommended if you component
+ * is or contains any active components (buttons etc..)
+ */
+ public void addComponent(Component component, int x, int y, boolean useDragHandle) {
+ addComponent(component, x, y, 1, 1, useDragHandle);
+ }
+
+ /**
+ * Add component to given slot, and define it's size
+ * @param component Component added
+ * @param x Slot's X coordinate (use negative values if position can be defined on client side)
+ * @param y Slot's Y coordinate (use negative values if position can be defined on client side)
+ * @param width Width of space reserved (in slots)
+ * @param height Height of space reserved (in slots)
+ */
+ public void addComponent(Component component, int x, int y, int width, int height) {
+ addComponent(component, x, y, width, height, true);
+ }
+
+ /**
+ * Add component to given slot, and define it's size
+ * @param component Component added
+ * @param x Slot's X coordinate (use negative values if position can be defined on client side)
+ * @param y Slot's Y coordinate (use negative values if position can be defined on client side)
+ * @param width Width of space reserved (in slots)
+ * @param height Height of space reserved (in slots)
+ * @param useDragHandle true to add component with a separate drag handle, or false to make whole content act as a
+ * drag handle. Notice that using a separate drag handle is recommended if you component
+ * is or contains any active components (buttons etc..)
+ */
+ public void addComponent(Component component, int x, int y, int width, int height, boolean useDragHandle) {
+ super.addComponent(component);
+ components.add(component);
+
+ GridStackChildOptions info = new GridStackChildOptions();
+ info.x = x;
+ info.y = y;
+ info.width = width;
+ info.height = height;
+ info.useDragHandle = useDragHandle;
+ getState().childOptions.put(component, info);
+ }
+
+ /**
+ * Reset component's position and allow child side define new position for it.
+ * @param component Child component which position is reset
+ */
+ public void resetComponentPosition(Component component) {
+ moveComponent(component, CLIENT_SIDE_SELECTS, CLIENT_SIDE_SELECTS);
+ }
+
+ /**
+ * Move given child component
+ * @param component Child component moved and/or resized
+ * @param x When defined component's X value is updated, if null old value is kept
+ * @param y When defined component's Y value is updated, if null old value is kept
+ * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout)
+ */
+ public void moveComponent(Component component, Integer x, Integer y) throws IllegalArgumentException {
+ moveAndResizeComponent(component, x, y, null, null);
+ }
+
+ /**
+ * Move given child component
+ * @param component Child component moved and/or resized
+ * @param width When defined component's width is updated, if null old value is kept
+ * @param height When defined component's height is updated, if null old value is kept
+ * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout)
+ */
+ public void resizeComponent(Component component, Integer width, Integer height) throws IllegalArgumentException {
+ moveAndResizeComponent(component, null, null, width, height);
+ }
+
+ /**
+ * Move and/or resize given child component
+ * @param component Child component moved and/or resized
+ * @param x When defined component's X value is updated, if null old value is kept
+ * @param y When defined component's Y value is updated, if null old value is kept
+ * @param width When defined component's width is updated, if null old value is kept
+ * @param height When defined component's height is updated, if null old value is kept
+ * @throws IllegalArgumentException If given value are invalid (eg. component is not child of this layout, or
+ * coordinates are invalid).
+ */
+ public void moveAndResizeComponent(Component component, Integer x, Integer y, Integer width, Integer height)
+ throws IllegalArgumentException {
+
+ if(x != null & width != null && x >= 0 && x + width > getState(false).gridStackOptions.width) {
+ throw new IllegalArgumentException("Component would go outside the right edge of layout");
+ }
+
+ GridStackChildOptions info = getState().childOptions.get(component);
+ if(info == null) {
+ throw new IllegalArgumentException("Given component is not child of GridStackLayout");
+ }
+ if(x != null) {
+ info.x = x;
+ }
+ if(y != null) {
+ info.y = y;
+ }
+ if(width != null) {
+ info.width = width;
+ }
+ if(height != null) {
+ info.height = height;
+ }
+ }
+
+ /**
+ * Get component with given slot coordinate
+ * @param x Slot's X coordinate
+ * @param y Slot's Y coordinate
+ * @return Component at slot, or null if component not found
+ */
+ public Component getComponent(int x, int y) {
+ return getComponent(x, y, false);
+ }
+
+ /**
+ * Get component with given slot coordinate
+ * @param x Slot's X coordinate
+ * @param y Slot's Y coordinate
+ * @param acceptInsideHit If true also other slots reserved by component are accepted
+ * @return Component at slot, or null if component not found
+ */
+ public Component getComponent(int x, int y, boolean acceptInsideHit) {
+ for(Connector connector : getState().childOptions.keySet()) {
+ GridStackChildOptions info = getState().childOptions.get(connector);
+ if(acceptInsideHit) {
+ if(x >= info.x && x < (info.x + info.width) && y >= info.y && y < (info.y + info.width)) {
+ return (Component) connector;
+ }
+ } else {
+ if (info.x == x && info.y == y) {
+ return (Component) connector;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeComponent(Component component) {
+ getState().childOptions.remove(component);
+ components.remove(component);
+ super.removeComponent(component);
+ }
+
+ @Override
+ public void replaceComponent(Component oldComponent, Component newComponent) {
+ if(oldComponent == newComponent) {
+ return;
+ }
+ if(oldComponent.getParent() != this) {
+ throw new IllegalArgumentException("Replacable component not child of this layout");
+ }
+ GridStackChildOptions oldOptions = getState(false).childOptions.get(oldComponent);
+ removeComponent(oldComponent);
+
+ if(newComponent.getParent() == this) {
+ removeComponent(newComponent);
+ }
+ addComponent(newComponent, oldOptions.x, oldOptions.y, oldOptions.width, oldOptions.height);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getComponentCount() {
+ return components.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterator iterator() {
+ return components.iterator();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addLayoutClickListener(LayoutEvents.LayoutClickListener listener) {
+ addListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER,
+ LayoutEvents.LayoutClickEvent.class, listener,
+ LayoutEvents.LayoutClickListener.clickMethod);
+ }
+
+ @Override
+ @Deprecated
+ public void addListener(LayoutEvents.LayoutClickListener layoutClickListener) {
+ addLayoutClickListener(layoutClickListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeLayoutClickListener(LayoutEvents.LayoutClickListener listener) {
+ removeListener(EventId.LAYOUT_CLICK_EVENT_IDENTIFIER,
+ LayoutEvents.LayoutClickEvent.class, listener);
+ }
+
+ @Override
+ @Deprecated
+ public void removeListener(LayoutEvents.LayoutClickListener layoutClickListener) {
+ removeLayoutClickListener(layoutClickListener);
+ }
+
+ /**
+ * Add listener for component move events
+ * @param listener Listener added
+ */
+ public void addGridStackMoveListener(GridStackMoveEvent.GridStackMoveListener listener) {
+ moveListeners.add(listener);
+ }
+
+ /**
+ * Remove listener of component move events
+ * @param listener Listener removed
+ */
+ public void removeGridStackMoveListener(GridStackMoveEvent.GridStackMoveListener listener) {
+ moveListeners.remove(listener);
+ }
+
+ /**
+ * Get coordinates (X,Y,width,height) of component
+ * @param child Child component of layout
+ * @return Coordinates (X,Y,width,height) of component
+ * @throws IllegalArgumentException If child not found
+ */
+ public GridStackCoordinates getCoordinates(Component child) {
+ GridStackChildOptions opts = getComponentOptions(child, false);
+ return new GridStackCoordinates(opts.x, opts.y, opts.width, opts.height);
+ }
+
+ protected GridStackMoveEvent createMoveEvent(Component component, GridStackCoordinates oldCoordinates) {
+ return new GridStackMoveEvent(this, component, oldCoordinates,
+ getCoordinates(component));
+ }
+
+ protected void fireMoveEvents(Collection events) {
+ if(events.isEmpty()) {
+ return;
+ }
+
+ for(GridStackMoveEvent.GridStackMoveListener listener : moveListeners) {
+ listener.onGridStackMove(events);
+ }
+ }
+
+ /**
+ * Define size limitations to child component. For now some values must be defined before child has been rendered
+ * on client side.
+ * @param child Child of this layout
+ * @param minWidth Mininum width in slots (null is undefined)
+ * @param maxWidth Maxium width in slots (null is undefined)
+ * @param minHeight Mininum height in slots (null is undefined)
+ * @param maxHeight Maximum height in slots (null is undefined)
+ */
+ public void setComponentSizeLimits(Component child, Integer minWidth, Integer maxWidth, Integer minHeight, Integer maxHeight) {
+ GridStackChildOptions childOpts = getComponentOptions(child);
+ childOpts.minWidth = minWidth;
+ childOpts.maxWidth = maxWidth;
+ childOpts.minHeight = minHeight;
+ childOpts.maxHeight = maxHeight;
+ }
+
+ /**
+ * Check if given child is locked (not allowed to move because of other dragged children)
+ * @param child Child component of layout
+ * @return true if locked, false if not
+ * @throws IllegalArgumentException If child not found
+ */
+ public boolean isComponentLocked(Component child) {
+ return getComponentOptions(child, false).locked;
+ }
+
+ /**
+ * Change locked state of child. Locked children will not be moved away from other dragged children.
+ * @param child Child component of layout
+ * @param locked true if locked, false if not
+ * @throws IllegalArgumentException If child not found
+ */
+ public void setComponentLocked(Component child, boolean locked) {
+ getComponentOptions(child).locked = locked;
+ }
+
+ protected GridStackChildOptions getComponentOptions(Component child) {
+ return getComponentOptions(child, true, true);
+ }
+
+ protected GridStackChildOptions getComponentOptions(Component child, boolean modify) {
+ return getComponentOptions(child, modify, true);
+ }
+
+ protected GridStackChildOptions getComponentOptions(Component child, boolean modify, boolean throwIfMissing) {
+ if(child == null || child.getParent() != this) {
+ throw new IllegalArgumentException("Given component is not child of this layout");
+ }
+ GridStackChildOptions opt = getState(modify).childOptions.get(child);
+ if(opt == null) {
+ throw new IllegalStateException("Missing child options");
+ }
+ return opt;
+ }
+
+ /**
+ * Define if layout is animated when child components are moved
+ * @param animate true to animate, false to not animate
+ * @return This GridStackLayout for command chaining
+ */
+ public GridStackLayoutNoJQuery setAnimate(boolean animate) {
+ getState().gridStackOptions.animate = animate;
+ return this;
+ }
+
+ /**
+ * Check if layout is animated
+ * @return true if animated, false if not
+ */
+ public boolean isAnimate() {
+ return getState(false).gridStackOptions.animate;
+ }
+
+ /**
+ * Set layout static (no dragging of resizing) or dynamic (dragging and resizing allowed)
+ * @param staticGrid true to set static (no dragging of resizing), false to set dynamic (dragging and resizing
+ * allowed)
+ * @return This GridStackLayout for command chaining
+ */
+ public GridStackLayoutNoJQuery setStaticGrid(boolean staticGrid) {
+ getState().gridStackOptions.staticGrid = staticGrid;
+ return this;
+ }
+
+ /**
+ * Check if layout is in static mode
+ * @return true if in static mode, false if not, null if not defined by server side
+ */
+ public Boolean isStaticGrid() {
+ return getState(false).gridStackOptions.staticGrid;
+ }
+
+
+ /**
+ * Check if component has specific dragging handle
+ * @param child Child component of layout
+ * @return true if component has separate dragging handle, false if whole content acts as dragging handle
+ */
+ public boolean isComponentWithDragHandle(Component child) {
+ return getComponentOptions(child, false).useDragHandle;
+ }
+
+ /**
+ * Define vertical margin between components on GridStack layout. Value is only read when rendered on client side
+ * first time, so changing value after that will not have any effect (unless client side is detached).
+ * @param marginPx Vertical margin in pixels
+ * @return This GridStackLayout for command chaining
+ */
+ public GridStackLayoutNoJQuery setVerticalMargin(int marginPx) {
+ getState(true).gridStackOptions.verticalMargin = marginPx;
+ return this;
+ }
+
+ /**
+ * Get vertical margin between components. Value might be mismatch to actual value used, if changed after client
+ * side was last attached.
+ * @return Vertical margin in pixels, if null the gridstack.js default is used.
+ */
+ public Integer getVerticalMargin() {
+ return getState(false).gridStackOptions.verticalMargin;
+ }
+
+ /**
+ * Define height of cell in pixels.
+ * @param heightPx Cell height in pixels
+ * @return This GridStackLayout for command chaining
+ */
+ public GridStackLayoutNoJQuery setCellHeight(int heightPx) {
+ getState(true).gridStackOptions.cellHeight = heightPx;
+ return this;
+ }
+
+ /**
+ * Get height of cell in pixels.
+ * @return Cell height in pixels, if null the gridstack.js default is used.
+ */
+ public Integer getCellHeight() {
+ return getState(false).gridStackOptions.cellHeight;
+ }
+
+ /**
+ * Set minimal width. If window width is less, grid will be shown in one-column mode. Changing value after
+ * it has been attached on client side will not apply until client side is detached and attached.
+ * @param minWidthPx Minimal width in pixels
+ * @return This GridStackLayout for command chaining
+ */
+ public GridStackLayoutNoJQuery setMinWidth(int minWidthPx) {
+ getState(true).gridStackOptions.minWidth = minWidthPx;
+ return this;
+ }
+
+ /**
+ * Get minimal width. If window width is less, grid will be shown in one-column mode. Value might be mismatch to
+ * actual value used, if changed after client side was last attached.
+ * @return Minimal width in pixels, if null the gridstack.js default is used.
+ */
+ public Integer getMinWidth() {
+ return getState(false).gridStackOptions.minWidth;
+ }
+
+ /**
+ * Define if wrapper around child should allow vertical scrolling or not
+ * @param child Child of layout
+ * @param scrolling true to enable vertical scrolling, false to disable it
+ * @throws IllegalArgumentException If child not found
+ */
+ public void setWrapperScrolling(Component child, boolean scrolling) {
+ getComponentOptions(child, true).disableScrolling = !scrolling;
+ }
+
+ /**
+ * Check if wrapper around child allows vertical scrolling or not
+ * @param child Child of layout
+ * @return true if wrapper allows vertical scrolling, false if wrapper hides vertical overflow
+ * @throws IllegalArgumentException If child not found
+ */
+ public boolean isWrapperScrolling(Component child) {
+ return getComponentOptions(child, false).disableScrolling;
+ }
+
+ /**
+ * Check if given area is empty. Remember that any client side defined positioning not yet reported back to
+ * server side will be unknown and so can result work results.
+ * @param x Left edge coordinate of area
+ * @param x Top edge coordinate of area
+ * @param width Width of area in slots
+ * @param height Height of area in slots
+ * @return true if area is available and valid for use
+ * @throws IllegalArgumentException If invalid values given
+ */
+ public boolean isAreaEmpty(int x, int y, int width, int height) throws IllegalArgumentException {
+ return isAreaEmpty(new GridStackCoordinates(x, y, width, height));
+ }
+
+ /**
+ * Check if given area is empty. Remember that any client side defined positioning not yet reported back to
+ * server side will be unknown and so can result work results. Will also return false if area would go outside the
+ * right edge.
+ * @param coordinates Coordinate area checked (x, y, width, height)
+ * @return true if area is available and valid for use
+ * @throws IllegalArgumentException If invalid values given
+ */
+ public boolean isAreaEmpty(GridStackCoordinates coordinates) throws IllegalArgumentException {
+ if(coordinates.getX() < 0) {
+ throw new IllegalArgumentException("X can not be negative");
+ }
+ if(coordinates.getY() < 0) {
+ throw new IllegalArgumentException("Y can not be negative");
+ }
+ if(coordinates.getWidth() <= 0) {
+ throw new IllegalArgumentException("Width most be larger than zero");
+ }
+ if(coordinates.getHeight() <= 0) {
+ throw new IllegalArgumentException("Height most be larger than zero");
+ }
+
+ // If item would drop out of left side, return false
+ if(coordinates.getX() + coordinates.getWidth() > getState(false).gridStackOptions.width) {
+ return false;
+ }
+
+ for(int dx = 0; dx < coordinates.getWidth(); ++dx) {
+ for(int dy = 0; dy < coordinates.getHeight(); ++dy) {
+ Component occupant = getComponent(coordinates.getX() + dx, coordinates.getY() + dy, true);
+ if(occupant != null) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackMoveEvent.java b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackMoveEvent.java
index 25e9e94..db7d0be 100644
--- a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackMoveEvent.java
+++ b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/GridStackMoveEvent.java
@@ -27,7 +27,7 @@
*/
public class GridStackMoveEvent {
- private final GridStackLayout layout;
+ private final GridStackLayoutNoJQuery layout;
private final Component movedChild;
private final GridStackCoordinates oldCoordinates;
private final GridStackCoordinates newCoordinates;
@@ -41,7 +41,7 @@ public interface GridStackMoveListener {
void onGridStackMove(Collection events);
}
- public GridStackMoveEvent(GridStackLayout layout, Component movedChild, GridStackCoordinates oldCoordinates,
+ public GridStackMoveEvent(GridStackLayoutNoJQuery layout, Component movedChild, GridStackCoordinates oldCoordinates,
GridStackCoordinates newCoordinates) {
this.layout = layout;
this.movedChild = movedChild;
@@ -49,7 +49,7 @@ public GridStackMoveEvent(GridStackLayout layout, Component movedChild, GridStac
this.oldCoordinates = oldCoordinates;
}
- public GridStackLayout getLayout() {
+ public GridStackLayoutNoJQuery getLayout() {
return layout;
}
diff --git a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/client/GridStackLayoutConnector.java b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/client/GridStackLayoutConnector.java
index 9880e4c..cfb672d 100644
--- a/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/client/GridStackLayoutConnector.java
+++ b/gridstack-addon/src/main/java/org/vaadin/alump/gridstack/client/GridStackLayoutConnector.java
@@ -41,7 +41,7 @@
import java.util.List;
import java.util.logging.Logger;
-@Connect(org.vaadin.alump.gridstack.GridStackLayout.class)
+@Connect(org.vaadin.alump.gridstack.GridStackLayoutNoJQuery.class)
public class GridStackLayoutConnector extends AbstractLayoutConnector {
private transient final static Logger LOGGER = Logger.getLogger(GridStackLayoutConnector.class.getName());