|
|
|
package com.fine.theme.utils;
|
|
|
|
|
|
|
|
import com.fine.swing.ui.layout.Column;
|
|
|
|
import com.fine.swing.ui.layout.Layouts;
|
|
|
|
import com.fine.swing.ui.layout.Row;
|
|
|
|
import com.fine.swing.ui.layout.Spacer;
|
|
|
|
import com.fr.design.constants.LayoutConstants;
|
|
|
|
import com.fr.design.foldablepane.UIExpandablePane;
|
|
|
|
import com.fr.log.FineLoggerFactory;
|
|
|
|
import com.fr.stable.collections.combination.Pair;
|
|
|
|
|
|
|
|
import javax.swing.JPanel;
|
|
|
|
import java.awt.BorderLayout;
|
|
|
|
import java.awt.Component;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
import java.util.stream.IntStream;
|
|
|
|
|
|
|
|
import static com.fine.swing.ui.layout.Layouts.cell;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 设计器典型布局构建器
|
|
|
|
*
|
|
|
|
* @author Levy.Xie
|
|
|
|
* @since 11.0
|
|
|
|
* Created on 2024/05/08
|
|
|
|
*/
|
|
|
|
public class FineLayoutBuilder {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建标准行列表格布局,行内元素均匀分布
|
|
|
|
*
|
|
|
|
* @param elePerRow 每行元素数
|
|
|
|
* @param rowSpacing 行内间距
|
|
|
|
* @param colSpacing 列内间距
|
|
|
|
* @param componentList 组件
|
|
|
|
* @return 表格面板
|
|
|
|
*/
|
|
|
|
public static Column createCommonTableLayout(int elePerRow, int rowSpacing, int colSpacing, List<? extends Component> componentList) {
|
|
|
|
int rowNum = componentList.size() / elePerRow + 1;
|
|
|
|
Iterator<? extends Component> iterator = componentList.iterator();
|
|
|
|
|
|
|
|
Column column = new Column();
|
|
|
|
column.setSpacing(colSpacing);
|
|
|
|
|
|
|
|
Row currentRow;
|
|
|
|
for (int i = 0; i < rowNum; i++) {
|
|
|
|
currentRow = new Row();
|
|
|
|
currentRow.setSpacing(rowSpacing);
|
|
|
|
for (int j = 0; j < elePerRow; j++) {
|
|
|
|
Layouts.populate(currentRow, cell(
|
|
|
|
iterator.hasNext() ? iterator.next() : new Spacer(1)
|
|
|
|
).weight(1));
|
|
|
|
}
|
|
|
|
column.add(currentRow);
|
|
|
|
}
|
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 兼容TableLayout配置项,生成网格布局面板
|
|
|
|
*
|
|
|
|
* @param colSpacing 间距
|
|
|
|
* @param components 组件二维数组,内部每个一维数组均为行内组件,一维数组元素需与weight严格对应
|
|
|
|
* @param weight 行内权重列表,形如[0.4,0.6] 即首个元素占比0.4,第二个元素占比0.6
|
|
|
|
* @return 面板
|
|
|
|
*/
|
|
|
|
public static JPanel compatibleTableLayout(int colSpacing, Component[][] components, double[] weight) {
|
|
|
|
Column column = new Column();
|
|
|
|
column.setSpacing(colSpacing);
|
|
|
|
try {
|
|
|
|
for (Component[] componentArray : components) {
|
|
|
|
Row row = new Row();
|
|
|
|
List<Component> visibleComponents = Arrays.stream(componentArray)
|
|
|
|
.filter(com -> com != null && com.isVisible()).collect(Collectors.toList());
|
|
|
|
if (!visibleComponents.isEmpty()) {
|
|
|
|
// 仅当存在可见组件时处理布局
|
|
|
|
dealWithVisibleComponents(weight, column, componentArray, row, visibleComponents);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return asBorderLayoutWrapped(column);
|
|
|
|
} catch (Exception e) {
|
|
|
|
FineLoggerFactory.getLogger().error(e, "[Designer] create layout failed.");
|
|
|
|
}
|
|
|
|
return new JPanel();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 典型的左右网格布局,竖向间距为典型间距,标签及组件比例采用典型比例
|
|
|
|
*
|
|
|
|
* @param components 组件,两列多行
|
|
|
|
* @return 面板
|
|
|
|
*/
|
|
|
|
public static JPanel commonLeftRightLayout(Component[][] components) {
|
|
|
|
return compatibleTableLayout(LayoutConstants.VERTICAL_GAP, components,
|
|
|
|
new double[]{LayoutConstants.LEFT_WEIGHT, LayoutConstants.RIGHT_WEIGHT});
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void dealWithVisibleComponents(double[] weight, Column column, Component[] value, Row row, List<Component> components) {
|
|
|
|
if (components.size() == 1 && value[0] != null) {
|
|
|
|
// 仅存在首个元素,则该元素自适应占满整行
|
|
|
|
Layouts.populate(row, cell(components.get(0)).weight(1));
|
|
|
|
} else {
|
|
|
|
// 其他场景,按权重分配布局,以适配原TableLayout形式
|
|
|
|
for (int j = 0; j < value.length; j++) {
|
|
|
|
Component component = value[j];
|
|
|
|
if (component == null) {
|
|
|
|
component = new Spacer(1);
|
|
|
|
}
|
|
|
|
Layouts.populate(row, cell(component).weight(weight[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
column.add(row);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建竖向排列的扩展面板列表
|
|
|
|
*
|
|
|
|
* @param spacing 间距
|
|
|
|
* @param elements 面板元素,含标题、面板
|
|
|
|
* @return 竖向排列面板
|
|
|
|
*/
|
|
|
|
@SafeVarargs
|
|
|
|
public static Column createVerticalExpandPaneLayout(int spacing, Pair<String, JPanel>... elements) {
|
|
|
|
UIExpandablePane[] panes = IntStream.range(0, elements.length)
|
|
|
|
.mapToObj(i -> {
|
|
|
|
Pair<String, JPanel> pair = elements[i];
|
|
|
|
if (i != elements.length - 1) {
|
|
|
|
return new UIExpandablePane(pair.getFirst(), pair.getSecond(), true);
|
|
|
|
}
|
|
|
|
return new UIExpandablePane(pair.getFirst(), pair.getSecond());
|
|
|
|
})
|
|
|
|
.toArray(UIExpandablePane[]::new);
|
|
|
|
return createVerticalLayout(spacing, panes);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建垂直布局面板
|
|
|
|
*
|
|
|
|
* @param spacing 间距
|
|
|
|
* @param elements 面板元素
|
|
|
|
* @return 面板
|
|
|
|
*/
|
|
|
|
public static Column createVerticalLayout(int spacing, Component... elements) {
|
|
|
|
Column column = new Column();
|
|
|
|
column.setSpacing(spacing);
|
|
|
|
for (Component element : elements) {
|
|
|
|
column.add(element);
|
|
|
|
}
|
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建水平布局面板
|
|
|
|
*
|
|
|
|
* @param spacing 间距
|
|
|
|
* @param elements 面板元素
|
|
|
|
* @return 面板
|
|
|
|
*/
|
|
|
|
public static Row createHorizontalLayout(int spacing, double[] weight, Component... elements) {
|
|
|
|
Row row = new Row();
|
|
|
|
row.setSpacing(spacing);
|
|
|
|
for (int i = 0; i < elements.length; i++) {
|
|
|
|
Layouts.populate(row, cell(elements[i]).weight(weight[i]));
|
|
|
|
}
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 创建水平布局面板
|
|
|
|
*
|
|
|
|
* @param spacing 间距
|
|
|
|
* @param elements 面板元素
|
|
|
|
* @return 面板
|
|
|
|
*/
|
|
|
|
public static Row createHorizontalLayout(int spacing, Component... elements) {
|
|
|
|
Row row = new Row();
|
|
|
|
row.setSpacing(spacing);
|
|
|
|
for (Component element : elements) {
|
|
|
|
Layouts.populate(row, cell(element));
|
|
|
|
}
|
|
|
|
return row;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 组件包装于BorderLayout中
|
|
|
|
*
|
|
|
|
* @param component 组件
|
|
|
|
* @return 包装后的面板
|
|
|
|
*/
|
|
|
|
public static JPanel asBorderLayoutWrapped(Component component) {
|
|
|
|
JPanel panel = new JPanel(new BorderLayout());
|
|
|
|
panel.add(component);
|
|
|
|
return panel;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|