GridBag-Layout
awt-like GridBagLayout with columns, and rows
Layout that knows about rows and column to define positions, and size of subelements
Sample code
package org.vaadin.wolfgang.demo; import com.vaadin.flow.component.html.Div; import com.vaadin.flow.router.Route; import org.vaadin.wolfgang.layout.GridBagLayout; @Route("appSkeleton") public class DemoView extends Div { private static int TOTAL_WIDTH = 6; private static int NAVIGATION_WIDTH = 1; private static int CONTENT_WIDTH = TOTAL_WIDTH - NAVIGATION_WIDTH; public DemoView() { GridBagLayout layout = new GridBagLayout(TOTAL_WIDTH, 1); layout.setGap(5); layout.setMargin(true); Div header = createCell("Header"); Div navigation1 = createCell("Navigation 1"); Div navigation2 = createCell("Navigation 2"); Div navigation3 = createCell("Navigation 3"); Div footer = createCell("Footer"); Div content = createCell("Content"); content.addClassName("content-area"); layout.add(header, content, footer, navigation1, navigation2, navigation3); layout.setDimensions(header, new GridBagLayout.Dimensions(null, null, null, TOTAL_WIDTH)); layout.setDimensions(navigation1, new GridBagLayout.Dimensions(2, null, null, NAVIGATION_WIDTH)); layout.setDimensions(navigation2, new GridBagLayout.Dimensions(3, null, null, NAVIGATION_WIDTH)); layout.setDimensions(navigation3, new GridBagLayout.Dimensions(4, null, null, NAVIGATION_WIDTH)); layout.setDimensions(footer, new GridBagLayout.Dimensions(5, null, null, TOTAL_WIDTH)); layout.setDimensions(content, new GridBagLayout.Dimensions(2, 2, 3, CONTENT_WIDTH)); add(layout); } private Div createCell(String text) { Div result = new Div(); result.addClassName("grid-cell"); result.setText(text); return result; } }
package org.vaadin.wolfgang.demo; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.dnd.DragSource; import com.vaadin.flow.component.dnd.DropEffect; import com.vaadin.flow.component.dnd.DropTarget; import com.vaadin.flow.component.dnd.EffectAllowed; import com.vaadin.flow.component.html.Div; import com.vaadin.flow.router.Route; import org.vaadin.wolfgang.layout.GridBagLayout; import java.util.Collection; import java.util.HashSet; import java.util.stream.Stream; @Route("move") public class MoveView extends Div { private static int COLUMNS = 7; private static int ROWS = 5; private int number = 1; private GridBagLayout layout = new GridBagLayout(COLUMNS, ROWS); private Collection<DropTarget> dropTargets = new HashSet<>(); public MoveView() { layout.setGap(5); layout.setMargin(true); Stream.generate(() -> String.valueOf(number)).map(this::createCell).limit(ROWS * COLUMNS).forEach(div -> { layout.add(div); layout.setDimensions(div, getNewLocation()); }); add(layout); setHeight("100%"); DropTarget<MoveView> dropTarget = DropTarget.create(this); dropTarget.addDropListener(playViewDropEvent -> { playViewDropEvent.getDragSourceComponent().ifPresent(component -> { Div placeholder = new Div(); layout.setDimensions(placeholder, layout.getDimensions(component)); layout.setDimensions(component, getNewLocation()); layout.add(placeholder); becomeDropTarget(placeholder); }); }); } private GridBagLayout.Dimensions getNewLocation() { int top = (number - 1) / COLUMNS + 1; int left = (number - 1) % COLUMNS + 1; number++; return new GridBagLayout.Dimensions(top, left, 1, 1); } private Component createCell(String text) { Div result = new Div(); result.addClassName("grid-cell"); result.getElement().getStyle().set("font-size", "36px"); result.setText(text); DragSource<Component> source = DragSource.create(result); result.getStyle().set("cursor", "pointer"); source.setEffectAllowed(EffectAllowed.MOVE); becomeDropTarget(result); return result; } private void becomeDropTarget(Component target) { DropTarget<Component> dropTarget = DropTarget.create(target); dropTarget.setDropEffect(DropEffect.MOVE); dropTarget.addDropListener(divDropEvent -> { divDropEvent.getDragSourceComponent().ifPresent(component -> { GridBagLayout.Dimensions dropDimensions = layout.getDimensions(target); if (component.getElement().getClassList().contains("grid-cell")) { layout.setDimensions(target, layout.getDimensions(component)); layout.setDimensions(component, dropDimensions); } else { GridBagLayout.Dimensions oldComponentDimensions = layout.getDimensions(target); int top = oldComponentDimensions.getVpos(); int left = oldComponentDimensions.getHpos(); int bottom = dropDimensions.getVpos() + dropDimensions.getVsize(); int right = dropDimensions.getHpos() + dropDimensions.getHsize(); GridBagLayout.Dimensions newComponentDimensions = new GridBagLayout.Dimensions(top, left, bottom, right); layout.setDimensions(component, newComponentDimensions); } }); }); dropTargets.add(dropTarget); } }
package org.vaadin.wolfgang.demo; import com.vaadin.flow.component.Component; import com.vaadin.flow.component.dnd.DropTarget; import com.vaadin.flow.component.html.Div; import com.vaadin.flow.component.html.Image; import com.vaadin.flow.dom.ElementConstants; import com.vaadin.flow.router.Route; import com.vaadin.flow.server.StreamResource; import org.apache.commons.collections4.Transformer; import org.apache.commons.collections4.map.LazyMap; import org.apache.commons.lang3.StringUtils; import org.vaadin.wolfgang.layout.GridBagLayout; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; import java.util.stream.Stream; @Route("zoom") public class ZoomView extends Div { private static int COLUMNS = 7; private static int ROWS = 5; private static int MAX_WIDTH = 110; private GridBagLayout layout = new GridBagLayout(COLUMNS, ROWS); private Collection<DropTarget> dropTargets = new HashSet<>(); private static final String IMAGES_ROOT = "META-INF/resources/frontend/images/"; private static final Map<String, BufferedImage> IMAGES = LazyMap.lazyMap(new HashMap<>(), new Transformer<String, BufferedImage>() { @Override public BufferedImage transform(String text) { InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(IMAGES_ROOT + text); try { return ImageIO.read(stream); } catch (IOException e) { e.printStackTrace(); return null; } } }); public ZoomView() throws IOException { layout.setGap(5); layout.setMargin(true); layout.setFullSize(false); List<String> imageNames = new ArrayList<>(); Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(IMAGES_ROOT); while (resources.hasMoreElements()) { File f = new File(resources.nextElement().getFile()); if (f.isDirectory()) { Arrays.stream(f.listFiles()).forEach(file -> imageNames.add(file.getName())); } } Random r = new Random(); Stream.generate(() -> r.nextInt(imageNames.size())).map(integer -> imageNames.get(integer)).map(this::createCell).limit(ROWS * COLUMNS).forEach(component -> { layout.add(component); }); add(layout); setHeight("100%"); } private int calcScale(int width, int height) { double hScale = (double) width / (double) MAX_WIDTH; return (int) Math.floor(hScale); } private Component createCell(String text) { Component result = new Div(); BufferedImage bufferedImage = IMAGES.get(text); int height = bufferedImage.getHeight(); int width = bufferedImage.getWidth(); int scale = calcScale(width, height); final int scaledHeight = height / scale; final int scaledWidth = width / scale; boolean portrait = height > width; InputStream stream2 = Thread.currentThread().getContextClassLoader().getResourceAsStream(IMAGES_ROOT + text); StreamResource resource = new StreamResource("reindeer", () -> stream2); Image image = new Image(resource, "image not found"); image.setHeight(scaledHeight + "px"); image.setWidth(scaledWidth + "px"); image.setClassName("zoomed-out"); if (portrait) { layout.setDimensions(image, new GridBagLayout.Dimensions(null, null, 2, null)); } image.addClickListener(divClickEvent -> { if (StringUtils.isNotEmpty(image.getHeight())) { // zoom in image.getElement().getStyle().remove(ElementConstants.STYLE_HEIGHT); image.getElement().getStyle().remove(ElementConstants.STYLE_WIDTH); if (portrait) { layout.resize(image, new GridBagLayout.Dimension(scale, scale * 2)); } else { layout.resize(image, new GridBagLayout.Dimension(scale, scale)); } image.setClassName("zoomed-in"); } else { image.setHeight(scaledHeight + "px"); image.setWidth(scaledWidth + "px"); if (portrait) { layout.setDimensions(image, new GridBagLayout.Dimensions(null, null, 2, null)); } else { layout.setDimensions(image, new GridBagLayout.Dimensions(null, null, null, null)); } image.setClassName("zoomed-out"); } }); result = image; return result; } }
Links
Compatibility
Was this helpful? Need more help?
Leave a comment or a question below. You can also join
the chat on Discord or
ask questions on StackOverflow.
Version
- Released
- 2020-08-14
- Maturity
- TESTED
- License
- Apache License 2.0
Compatibility
- Framework
- Vaadin 10+
- Browser
- Firefox
- Opera
- Safari
- Google Chrome
- iOS Browser
GridBag-Layout - Vaadin Add-on Directory
awt-like GridBagLayout with columns, and rowsLayout that knows about rows and column to define positions, and size of subelements