Directory

← Back

GridBag-Layout

awt-like GridBagLayout with columns, and rows

Author

Rating

Popularity

<100

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;
    }

}

Compatibility

(Loading compatibility data...)

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 rows GridBag-Layout - Vaadin Add-on Directory
Layout that knows about rows and column to define positions, and size of subelements
Online