org.nuiton.jaxx.runtime.swing.CardLayout2 Maven / Gradle / Ivy
/*
* #%L
* JAXX :: Runtime
* %%
* Copyright (C) 2008 - 2024 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.jaxx.runtime.swing;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
/**
* An override of the awt {@link CardLayout}.
*
* Because in the original layout is not overridable : everything is package level accessible.
*
* This new class offers to test if a constrains (as a Serializable) is actually dealed by the layout,
* via the method {@link #contains(Serializable)}.
*
* We had also another method to obtain the current visible component in a container layouted by the class,
* via the method {@link #getVisibleComponent(Container)}.
*
* @author Tony Chemit - [email protected]
* @version 1.0
*/
public class CardLayout2 extends CardLayout {
/** log */
static private final Logger log = LogManager.getLogger(CardLayout2.class);
private static final long serialVersionUID = 1L;
/** list of already loaded context (since the {@link #vector} attribute is package visible... */
protected final List contexts = new LinkedList<>();
/**
* A flag to compute dimension only on visible component.
*
* This is usefull when we only care of the visible component.
*/
protected boolean useOnlyVisibleComponentDimension;
@Override
public void addLayoutComponent(Component comp, Object constraints) {
super.addLayoutComponent(comp, constraints);
contexts.remove(constraints);
contexts.add((Serializable) constraints);
if (log.isDebugEnabled()) {
log.debug(this + " new constraints : " + constraints);
}
}
public void removeLayoutComponent(Component comp, Serializable constraints) {
removeLayoutComponent(comp);
contexts.remove(constraints);
}
/**
* Test if a constrains is contained in the layout.
*
* @param constraints l'identifiant a tester
* @return {@code true} si l'identifiant est deja present dans le
* layout, {@code false} otherwise.
*/
public boolean contains(Serializable constraints) {
return contexts.contains(constraints);
}
/**
* Obtain the visible component in the container.
*
* @param container the container using this layout
* @return the component visible in the container.
*/
public Component getVisibleComponent(Container container) {
checkContainer(container);
for (Component component : container.getComponents()) {
if (component.isVisible()) {
return component;
}
}
// no component actually visible
return null;
}
public Component getComponent(Container container, String constraints) {
checkContainer(container);
checkConstraints(constraints);
int index = contexts.indexOf(constraints);
return container.getComponents()[index];
}
/**
* Determines the preferred size of the container argument using
* this card layout.
*
* @param parent the parent container in which to do the layout
* @return the preferred dimensions to lay out the subcomponents
* of the specified container
* @see Container#getPreferredSize
* @see CardLayout#minimumLayoutSize
*/
@Override
public Dimension preferredLayoutSize(Container parent) {
Dimension dimension = null;
if (useOnlyVisibleComponentDimension) {
Component comp = getVisibleComponent(parent);
if (comp != null) {
dimension = comp.getPreferredSize();
}
}
if (dimension == null) {
dimension = super.preferredLayoutSize(parent);
}
return dimension;
}
/**
* Calculates the minimum size for the specified panel.
*
* @param parent the parent container in which to do the layout
* @return the minimum dimensions required to lay out the
* subcomponents of the specified container
* @see Container#doLayout
* @see CardLayout#preferredLayoutSize
*/
@Override
public Dimension minimumLayoutSize(Container parent) {
Dimension dimension = null;
if (useOnlyVisibleComponentDimension) {
Component comp = getVisibleComponent(parent);
if (comp != null) {
dimension = comp.getMinimumSize();
}
}
if (dimension == null) {
dimension = super.minimumLayoutSize(parent);
}
return dimension;
}
/**
* Returns the maximum dimensions for this layout given the components
* in the specified target container.
*
* @param target the component which needs to be laid out
* @see Container
* @see #minimumLayoutSize
* @see #preferredLayoutSize
*/
@Override
public Dimension maximumLayoutSize(Container target) {
Dimension dimension = null;
if (useOnlyVisibleComponentDimension) {
Component comp = getVisibleComponent(target);
if (comp != null) {
dimension = comp.getMaximumSize();
}
}
if (dimension == null) {
dimension = super.maximumLayoutSize(target);
}
return dimension;
}
/**
* Lays out the specified container using this card layout.
*
* Each component in the parent
container is reshaped
* to be the size of the container, minus space for surrounding
* insets, horizontal gaps, and vertical gaps.
*
* @param parent the parent container in which to do the layout
* @see Container#doLayout
*/
@Override
public void layoutContainer(Container parent) {
if (useOnlyVisibleComponentDimension) {
Component comp = getVisibleComponent(parent);
if (comp != null) {
//dimension = comp.getMinimumSize();
Insets insets = parent.getInsets();
comp.setBounds(getHgap() + insets.left, getVgap() + insets.top,
parent.getWidth() - (getHgap() * 2 + insets.left + insets.right),
parent.getHeight() - (getVgap() * 2 + insets.top + insets.bottom));
} else {
super.layoutContainer(parent);
}
} else {
super.layoutContainer(parent);
}
}
public boolean isUseOnlyVisibleComponentDimension() {
return useOnlyVisibleComponentDimension;
}
public void setUseOnlyVisibleComponentDimension(boolean useOnlyVisibleComponentDimension) {
this.useOnlyVisibleComponentDimension = useOnlyVisibleComponentDimension;
}
/**
* remove from cardlayout and linked container all his components.
*
* @param parent the parent container linked with the layout
*/
public void reset(Container parent) {
checkContainer(parent);
for (Component component : parent.getComponents()) {
removeLayoutComponent(component);
parent.remove(component);
}
contexts.clear();
}
protected void checkContainer(Container container) {
if (!equals(container.getLayout())) {
throw new IllegalArgumentException("the container is not managed by the current layout");
}
}
protected void checkConstraints(String constraints) {
if (!contains(constraints)) {
throw new IllegalArgumentException("the constraints '" + constraints + "' is not supported by this layout : " + contexts);
}
}
public Serializable[] getContexts() {
return contexts.toArray(new Serializable[contexts.size()]);
}
}