Skip to content
This repository was archived by the owner on Dec 31, 2020. It is now read-only.

Gridstack read only - fixes #28 #30

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@
*/
package org.vaadin.alump.gridstack;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

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;
Expand All @@ -25,9 +37,6 @@
import com.vaadin.shared.Registration;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Component;
import org.vaadin.alump.gridstack.client.shared.*;

import java.util.*;

/**
* Vaadin layout using gridstack.js library to layout components
Expand Down Expand Up @@ -61,8 +70,8 @@ public void layoutClick(MouseEventDetails mouseEventDetails, Connector connector
@Override
public void onChildrenMoved(List<GridStackMoveData> moves) {
Collection<GridStackMoveEvent> events = new ArrayList<GridStackMoveEvent>();
for(GridStackMoveData move : moves) {
Component childComponent = (Component)move.child;
for (GridStackMoveData move : moves) {
Component childComponent = (Component) move.child;
GridStackCoordinates oldCoordinates = getCoordinates(childComponent);

GridStackChildOptions info = getState(false).childOptions.get(move.child);
Expand Down Expand Up @@ -291,7 +300,7 @@ public Component getComponent(int x, int y) {
* @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()) {
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.height)) {
Expand Down Expand Up @@ -421,7 +430,7 @@ protected void fireMoveEvents(Collection<GridStackMoveEvent> events) {
return;
}

for(GridStackMoveEvent.GridStackMoveListener listener : moveListeners) {
for (GridStackMoveEvent.GridStackMoveListener listener : moveListeners) {
listener.onGridStackMove(events);
}
}
Expand Down Expand Up @@ -704,4 +713,24 @@ public Optional<String> getChildItemStyleName(Component child) {
.flatMap(o -> Optional.ofNullable(o.styleName));
}

/**
* Sets read only state to child component. If the child is set to read only it will not be able to be moved, resized or moved by another component
*
* @param child - Child component
* @param readOnly - State of the component
*/
public void setComponentReadOnly(final Component child, final boolean readOnly) {
getComponentOptions(child).readOnly = readOnly;
}

/**
* Check if the child component is in read only state
*
* @param child - Child component
* @return true if the component is in read only state
*/
public boolean isComponentReadOnly(final Component child) {
return getComponentOptions(child).readOnly;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,24 @@
*/
package org.vaadin.alump.gridstack.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.vaadin.alump.gridstack.client.shared.GridStackChildOptions;
import org.vaadin.alump.gridstack.client.shared.GridStackOptions;

import com.google.gwt.core.client.Duration;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;
import org.vaadin.alump.gridstack.client.shared.GridStackChildOptions;
import org.vaadin.alump.gridstack.client.shared.GridStackOptions;

import java.util.*;
import java.util.logging.Logger;

public class GwtGridStack extends ComplexPanel {

Expand Down Expand Up @@ -78,7 +84,7 @@ public boolean isInitialized() {
}

public void setOptions(Integer width, Integer height, GridStackOptions options) {
if(!initialized) {
if (!initialized) {
initialize(width, height, GwtGridStackOptions.createFrom(options));
} else {
if(options.cellHeight != null) {
Expand All @@ -91,7 +97,7 @@ public void setOptions(Integer width, Integer height, GridStackOptions options)
}

public void initialize(Integer width, Integer height, GwtGridStackOptions options) {
if(initialized) {
if (initialized) {
LOGGER.severe("gridstack already initialized");
return;
}
Expand Down Expand Up @@ -123,7 +129,7 @@ public void add(Widget widget) {

public void add(Widget widget, GridStackChildOptions info) {
Element wrapper = createWrapper(info);
if(initialized) {
if (initialized) {
addWidgetWrapperToGridStack(wrapper);
} else {
getElement().appendChild(wrapper);
Expand All @@ -135,8 +141,10 @@ public void add(Widget widget, GridStackChildOptions info) {

@Override
public boolean remove(Widget widget) {
if(initialized) {
Element wrapper = widget.getElement().getParentElement().getParentElement();
if (initialized) {
Element wrapper = widget.getElement()
.getParentElement()
.getParentElement();
widgetWrappers.remove(wrapper);
removeWidgetWrapperFromGridStack(wrapper);
wrapper.removeFromParent();
Expand All @@ -145,7 +153,8 @@ public boolean remove(Widget widget) {
}

protected Element createWrapper(GridStackChildOptions info) {
Element wrapper = Document.get().createDivElement();
Element wrapper = Document.get()
.createDivElement();
wrapper.addClassName("grid-stack-item");

if(info.x >= 0 && info.y >= 0) {
Expand Down Expand Up @@ -174,7 +183,14 @@ protected Element createWrapper(GridStackChildOptions info) {
wrapper.setAttribute("data-gs-locked", "yes");
}

Element content = Document.get().createDivElement();
if (info.readOnly) {
wrapper.setAttribute("data-gs-locked", "yes");
wrapper.setAttribute("data-gs-no-resize", "yes");
wrapper.setAttribute("data-gs-no-move", "yes");
}

final Element content = Document.get()
.createDivElement();
content.addClassName(CONTENT_CLASSNAME);

if(!info.useDragHandle) {
Expand All @@ -191,8 +207,9 @@ protected Element createWrapper(GridStackChildOptions info) {

wrapper.appendChild(content);

if(info.useDragHandle) {
Element dragHandle = Document.get().createDivElement();
if (info.useDragHandle) {
Element dragHandle = Document.get()
.createDivElement();
dragHandle.addClassName("separate-handle");
dragHandle.addClassName(DRAG_HANDLE_CLASSNAME);
wrapper.appendChild(dragHandle);
Expand Down Expand Up @@ -345,12 +362,15 @@ public void removeReadyListener(GwtGridStackReadyListener listener) {


public void updateChild(Widget widget, GridStackChildOptions options) {
Element wrapper = widget.getElement().getParentElement().getParentElement();
Element wrapper = widget.getElement()
.getParentElement()
.getParentElement();
updateWidgetWrapper(wrapper, options.x, options.y, options.width, options.height);
updateWidgetSizeLimits(wrapper, GwtGridSizeLimits.create(options));
setLocked(wrapper, options.locked);
setReadOnly(wrapper, options.readOnly);

if(options.disableScrolling) {
if (options.disableScrolling) {
wrapper.addClassName(DISABLE_SCROLLING_CLASSNAME);
} else {
wrapper.removeClassName(DISABLE_SCROLLING_CLASSNAME);
Expand Down Expand Up @@ -391,9 +411,19 @@ protected native final void setLocked(Element element, boolean locked)
});
}-*/;

protected native final void setReadOnly(Element element, boolean readOnly)
/*-{
var elementId = this.@org.vaadin.alump.gridstack.client.GwtGridStack::elementId;
$wnd.$(function () {
var grid = $wnd.$('#' + elementId).data('gridstack');
grid.locked(element, readOnly);
grid.resizable(element, !readOnly);
grid.movable(element, !readOnly);
});
}-*/;

public void commit() {
if(initialized && isAttached()) {
if (initialized && isAttached()) {
nativeCommit();
}
}
Expand All @@ -408,7 +438,7 @@ protected native final void nativeCommit()
}-*/;

public void batchUpdate() {
if(initialized && isAttached()) {
if (initialized && isAttached()) {
nativeBatchUpdate();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class GridStackChildOptions implements Serializable {
public Integer maxWidth = null;
public Integer maxHeight = null;
public boolean locked = false;
public boolean readOnly = false;

public boolean useDragHandle = false;
public String styleName = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ $gridstack_item_padding: $gridstack_horizontal_padding / 2 !default;
}
}

&.ui-draggable-disabled .grid-stack-item-drag-handle.separate-handle {
display: none !important;
}

&:hover .grid-stack-item-drag-handle.separate-handle {
display: block;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
package org.vaadin.alump.gridstack.demo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.vaadin.alump.gridstack.GridStackButton;
import org.vaadin.alump.gridstack.GridStackCoordinates;
import org.vaadin.alump.gridstack.GridStackLayout;

import com.vaadin.event.LayoutEvents;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.Resource;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.*;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Image;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
import org.vaadin.alump.gridstack.GridStackButton;
import org.vaadin.alump.gridstack.GridStackCoordinates;
import org.vaadin.alump.gridstack.GridStackLayout;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Main test/demo view of GridStackLayout
Expand All @@ -33,6 +47,7 @@ public class TestView extends AbstractView {
private Random rand = new Random(0xDEADBEEF);

private Component locked;
private final Component readOnly;

// This value can be used as x and y when client side can pick the best slot
private final static int CLIENT_SELECTS = GridStackLayout.CLIENT_SIDE_SELECTS;
Expand Down Expand Up @@ -78,6 +93,10 @@ public TestView() {
locked.setWidth(100, Unit.PERCENTAGE);
gridStack.addComponent(locked, 1, 0, 3, 1);

this.readOnly = new Label("This component can be set to read only (moving and resizing is disabled and moving children over will not move this)");
this.readOnly.setWidth(100, Unit.PERCENTAGE);
this.gridStack.addComponent(this.readOnly, 0, 8, 3, 1);

gridStack.addComponent(createForm(), 0, 5, 2, 3, false);
gridStack.addComponent(createConsole(), 0, 3, 4, 2);

Expand All @@ -90,7 +109,7 @@ public TestView() {
final int eventId = eventCounter.getAndIncrement();
events.stream().forEach(event -> {
if(event.getMovedChild() instanceof TestItem) {
TestItem item = (TestItem)event.getMovedChild();
TestItem item = (TestItem) event.getMovedChild();
item.setHeader(event.getNew());
}
addEvent("event #" + eventId + ": Moved from " + event.getOld().toString() + " to "
Expand All @@ -115,7 +134,7 @@ private Component createToolbar() {
}));

toolbar.addComponent(createButton(VaadinIcons.TRASH, "Remove component", e -> {
if(gridStack.getComponentCount() < 1) {
if (gridStack.getComponentCount() < 1) {
Notification.show("Nothing to remove!");
return;
}
Expand Down Expand Up @@ -157,6 +176,13 @@ private Component createToolbar() {
});
toolbar.addComponent(lockItem);

final CheckBox readOnlyItem = new CheckBox("Read only child");
readOnlyItem.setDescription("Define if item with text \"Read only\" is read only or not");
readOnlyItem.addValueChangeListener(e -> {
this.gridStack.setComponentReadOnly(this.readOnly, e.getValue());
});
toolbar.addComponent(readOnlyItem);

return toolbar;
}

Expand Down Expand Up @@ -203,7 +229,7 @@ private Component createForm() {
password.addStyleName(ValoTheme.TEXTFIELD_SMALL);
password.setCaption("Password:");
layout.addComponent(password);
Button login = new GridStackButton("Login", e-> Notification.show("Logged in?"));
Button login = new GridStackButton("Login", e -> Notification.show("Logged in?"));
login.addStyleName(ValoTheme.BUTTON_FRIENDLY);
login.addStyleName(ValoTheme.BUTTON_SMALL);
layout.addComponent(login);
Expand Down Expand Up @@ -249,7 +275,8 @@ private Component createImage() {

if(clickedAtChild) {
sb.append(": ");
sb.append(gridStack.getCoordinates(e.getChildComponent()).toString());
sb.append(gridStack.getCoordinates(e.getChildComponent())
.toString());
}

addEvent(sb.toString());
Expand All @@ -262,7 +289,8 @@ private void reorderAll() {

private void moveRandomChildToAnotherFreePosition() {
List<Component> children = new ArrayList<>();
gridStack.iterator().forEachRemaining(child -> children.add(child));
gridStack.iterator()
.forEachRemaining(child -> children.add(child));
if(!children.isEmpty()) {
addEvent("Move random child to new position...");
Collections.shuffle(children, rand);
Expand Down