summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'dozentenmodul/src/main/java')
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridManager.java329
-rw-r--r--dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridPos.java5
2 files changed, 334 insertions, 0 deletions
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridManager.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridManager.java
new file mode 100644
index 00000000..8b941f6a
--- /dev/null
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridManager.java
@@ -0,0 +1,329 @@
+package org.openslx.dozmod.gui.helper;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.ArrayList;
+
+import javax.swing.Box;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+/**
+ * Helper class for using the GridBagLayout.
+ */
+public class GridManager {
+
+ /**
+ * Setting this to true will insert green panels in cells where nothing was
+ * added
+ */
+ public static boolean debugEmptyCells = false;
+
+ private final JComponent container;
+ private final Insets defaultInsets;
+ private final int columnCount;
+ private final boolean strict;
+ private int nextColumn = 0;
+ private int currentRow = 0;
+ private boolean valid = true;
+
+ private final ArrayList<Component[]> currentRows = new ArrayList<>();
+
+ private final GridBagConstraints mainConstraints = new GridBagConstraints();
+ private GBC currentGbc = null;
+
+ // Static general constraints
+
+ private static final GridBagConstraints emptyFiller = new GridBagConstraints(0, 0, 1, 1, 0, 0,
+ GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0);
+
+ /**
+ * Create a new GridManager for the given component. The manager will use
+ * strict mode and use an inset of 1px for every side of every cell.
+ *
+ * @param container The component to apply the layout to
+ * @param columnCount The number of columns per row
+ */
+ public GridManager(JComponent container, int columnCount) {
+ this(container, columnCount, true);
+ }
+
+ /**
+ * Create a new GridManager for the given component. The manager will use an
+ * inset of 1px for every side of every cell.
+ *
+ * @param container The component to apply the layout to
+ * @param columnCount The number of columns per row
+ * @param strict If true, the manager will ensure you call
+ * {@link #nextRow()} after finishing each row, and that you
+ * don't call it if the current row is empty. Otherwise, the
+ * manager will silently advance to the next row if the current
+ * row is full, and will ignore calls to {@link #nextRow()} if
+ * the current row is empty
+ */
+ public GridManager(JComponent container, int columnCount, boolean strict) {
+ this(container, columnCount, strict, new Insets(1, 1, 1, 1));
+ }
+
+ /**
+ * Create a new GridManager for the given component. The manager will use an
+ * inset of 1px for every side of every cell.
+ *
+ * @param container The component to apply the layout to
+ * @param columnCount The number of columns per row
+ * @param strict If true, the manager will ensure you call
+ * {@link #nextRow()} after finishing each row, and that you
+ * don't call it if the current row is empty. Otherwise, the
+ * manager will silently advance to the next row if the current
+ * row is full, and will ignore calls to {@link #nextRow()} if
+ * the current row is empty
+ * @param defaultInsets an {@link Insets} instance to use for every cell by
+ * default
+ */
+ public GridManager(JComponent container, int columnCount, boolean strict, Insets defaultInsets) {
+ this.defaultInsets = defaultInsets;
+ this.container = container;
+ this.columnCount = columnCount;
+ this.strict = strict;
+ this.container.setLayout(new GridBagLayout());
+ this.currentRows.add(new Component[columnCount]);
+ }
+
+ /**
+ * Add the given component to the next free grid cell.
+ *
+ * @param component Component to add
+ * @return A {@link GBC} instance that can be used to further influence the
+ * behavior of this component
+ * @throws IllegalArgumentException If there aren't enough columns left in
+ * the current row to add the given component with the desired
+ * horizontal span, or if one of the span parameters is
+ * <code>&lt; 1</code>
+ */
+ public GBC add(Component component) {
+ return add(component, 1, 1);
+ }
+
+ /**
+ * Add the given component to the next free grid cell, applying the given
+ * horizontal and vertical cell-span.
+ *
+ * @param component Component to add
+ * @param spanX horizontal span
+ * @param spanY vertical span
+ * @return A {@link GBC} instance that can be used to further influence the
+ * behavior of this component
+ * @throws IllegalArgumentException If there aren't enough columns left in
+ * the current row to add the given component with the desired
+ * horizontal span, or if one of the span parameters is
+ * <code>&lt; 1</code>
+ */
+ public GBC add(Component component, int spanX, int spanY) {
+ checkValid();
+ if (spanX < 1 || spanY < 1)
+ throw new IllegalArgumentException("Span must be >= 1");
+ // Automatically advance to next row if strict mode is not enabled and we're at the end of the current one
+ if (!strict && nextColumn == columnCount) {
+ nextRow();
+ }
+ if (!hasFreeColumns(spanX))
+ throw new IllegalArgumentException("Cannot add component: Not enough columns left in row");
+ addCurrentControl();
+ currentGbc = new GBC(component, spanX, spanY);
+ nextColumn += spanX;
+ skipToFreeColumn();
+ return currentGbc;
+ }
+
+ /**
+ * Advance to next row.
+ *
+ * @throws IllegalStateException if strict mode is enabled and the current
+ * row is empty
+ */
+ public void nextRow() {
+ checkValid();
+ if (nextColumn == 0 && currentRows.size() == 1 && allCellsEmpty()) {
+ if (strict)
+ throw new IllegalStateException("Cannot call nextRow when current row is empty");
+ return;
+ }
+ addCurrentControl();
+ if (nextColumn < columnCount && debugEmptyCells) {
+ emptyFiller.gridy = currentRow;
+ Component[] row = currentRows.get(0);
+ for (int i = nextColumn; i < columnCount; ++i) {
+ if (row[i] != null)
+ continue;
+ JPanel p = new JPanel();
+ p.setBackground(Color.GREEN);
+ emptyFiller.gridx = i;
+ container.add(p, emptyFiller);
+ }
+ }
+ currentRow++;
+ if (currentRows.size() == 1) {
+ Component[] row = currentRows.get(0);
+ for (int i = 0; i < columnCount; ++i) {
+ row[i] = null;
+ }
+ } else {
+ currentRows.remove(0);
+ }
+ nextColumn = 0;
+ skipToFreeColumn();
+ }
+
+ /**
+ * Finish the layout. Further calls to the <code>add</code>-methods will
+ * result in an exception being thrown
+ *
+ * @param addVerticalGlue Whether to add expanding vertical glue to the
+ * layout, so all components will be pushed to the top of the
+ * container
+ */
+ public void finish(boolean addVerticalGlue) {
+ checkValid();
+ if (nextColumn != 0) {
+ nextRow();
+ }
+ if (addVerticalGlue) {
+ while (currentRows.size() > 1 || !allCellsEmpty()) {
+ nextRow();
+ }
+ add(Box.createGlue(), columnCount, 1).expand(true, true).fill(true, true);
+ nextRow();
+ }
+ valid = false;
+ }
+
+ // Private helpers
+
+ private boolean hasFreeColumns(int num) {
+ num--;
+ Component[] row = currentRows.get(0);
+ for (int i = nextColumn; i < columnCount; ++i) {
+ if (row[i] != null)
+ return false;
+ if (i - nextColumn >= num)
+ return true;
+ }
+ return false;
+ }
+
+ private void addCurrentControl() {
+ if (currentGbc == null)
+ return;
+ container.add(currentGbc.component, mainConstraints);
+ // Remember placement for future sanity checks
+ for (int relrow = 0; relrow < mainConstraints.gridheight; ++relrow) {
+ if (currentRows.size() <= relrow) {
+ currentRows.add(new Component[columnCount]);
+ }
+ Component[] row = currentRows.get(relrow);
+ for (int relcol = 0; relcol < mainConstraints.gridwidth; ++relcol) {
+ if (row[relcol + mainConstraints.gridx] != null)
+ throw new IllegalStateException("Collision detected in cell ("
+ + (relcol + mainConstraints.gridx) + "|" + (relrow + mainConstraints.gridy)
+ + "): Have " + row[relcol + mainConstraints.gridx].getClass().getSimpleName()
+ + ", trying to add " + currentGbc.component.getClass().getSimpleName());
+ row[relcol + mainConstraints.gridx] = currentGbc.component;
+ }
+ }
+ currentGbc.valid = false;
+ currentGbc = null;
+ }
+
+ private boolean allCellsEmpty() {
+ Component[] row = currentRows.get(0);
+ for (int i = 0; i < columnCount; ++i) {
+ if (row[i] != null)
+ return false;
+ }
+ return true;
+ }
+
+ private void checkValid() {
+ if (!valid)
+ throw new IllegalStateException("Layout is already finalized!");
+ }
+
+ private void skipToFreeColumn() {
+ Component[] row = currentRows.get(0);
+ while (nextColumn < columnCount && row[nextColumn] != null) {
+ nextColumn++;
+ }
+ }
+
+ //
+
+ public class GBC {
+ private boolean valid = true;
+ private final Component component;
+
+ /**
+ * Set the fill properties of the element being added.
+ *
+ * @param fillX Fill the cell horizontally, enlarging the control
+ * @param fillY Fill the cell vertically, enlarging the control
+ * @return This instance, so calls can be chained
+ */
+ public GBC fill(boolean fillX, boolean fillY) {
+ checkValid();
+ if (fillX && fillY) {
+ mainConstraints.fill = GridBagConstraints.BOTH;
+ } else if (fillX) {
+ mainConstraints.fill = GridBagConstraints.HORIZONTAL;
+ } else if (fillY) {
+ mainConstraints.fill = GridBagConstraints.VERTICAL;
+ }
+ return this;
+ }
+
+ /**
+ * Set the expand properties of the element being added.
+ * If multiple components are set to expand, they'll distribute the
+ * excess space among them.
+ *
+ * @param expandX Assign any remaining horizontal space to this cell
+ * @param expandY Assign any remaining vertical space to this cell
+ * @return This instance, so calls can be chained
+ */
+ public GBC expand(boolean expandX, boolean expandY) {
+ checkValid();
+ if (expandX) {
+ mainConstraints.weightx = 1;
+ }
+ if (expandY) {
+ mainConstraints.weighty = 1;
+ }
+ return this;
+ }
+
+ // Extend with more helpers as needed
+
+ private GBC(Component component, int spanX, int spanY) {
+ mainConstraints.gridx = nextColumn;
+ mainConstraints.gridy = currentRow;
+ mainConstraints.gridwidth = spanX;
+ mainConstraints.gridheight = spanY;
+ mainConstraints.weightx = 0;
+ mainConstraints.weighty = 0;
+ mainConstraints.anchor = GridBagConstraints.LINE_START;
+ mainConstraints.fill = GridBagConstraints.NONE;
+ mainConstraints.insets = defaultInsets;
+ mainConstraints.ipadx = 0;
+ mainConstraints.ipady = 0;
+ this.component = component;
+ }
+
+ private void checkValid() {
+ if (!valid)
+ throw new IllegalAccessError("Cannot modify constraints after adding next control");
+ }
+ }
+
+}
diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridPos.java b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridPos.java
index 82871fec..2a1b0200 100644
--- a/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridPos.java
+++ b/dozentenmodul/src/main/java/org/openslx/dozmod/gui/helper/GridPos.java
@@ -3,6 +3,11 @@ package org.openslx.dozmod.gui.helper;
import java.awt.GridBagConstraints;
import java.awt.Insets;
+/**
+ * Helper for creating Constraints when using GridBagLayout.
+ * Deprecated, use GridManager instead.
+ */
+@Deprecated
public class GridPos {
private static final Insets inset = new Insets(1, 1, 1, 1);