diff --git a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java index 763ffcd1f..7b13c94a0 100644 --- a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java +++ b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java @@ -2,7 +2,6 @@ package com.fr.design.file; import com.fr.base.chart.chartdata.CallbackEvent; import com.fr.base.io.BaseBook; -import com.fr.design.DesignModelAdapter; import com.fr.design.DesignerEnvManager; import com.fr.design.base.mode.DesignModeContext; import com.fr.design.data.DesignTableDataManager; @@ -23,7 +22,6 @@ import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; import com.fr.third.org.apache.commons.io.FilenameUtils; -import javax.swing.SwingUtilities; import java.io.ByteArrayOutputStream; import java.util.ArrayList; import java.util.Collections; @@ -441,4 +439,5 @@ public class HistoryTemplateListCache implements CallbackEvent { } }); } + } diff --git a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java index 69aee1b50..269918448 100644 --- a/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java +++ b/designer-base/src/main/java/com/fr/design/file/MutilTempalteTabPane.java @@ -18,8 +18,6 @@ import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.Constants; import com.fr.third.javax.annotation.Nonnull; -import com.fr.workspace.WorkContext; -import com.fr.workspace.server.lock.TplOperator; import javax.swing.BorderFactory; import javax.swing.ButtonModel; @@ -707,7 +705,7 @@ public class MutilTempalteTabPane extends JComponent { // 只有是环境内的文件,才执行释放锁 if (file != null && file.isEnvFile()) { // release lock - WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(file.getPath()); + TemplateResourceManager.getResource().closeTemplate(file.getPath()); } } diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateResource.java b/designer-base/src/main/java/com/fr/design/file/TemplateResource.java new file mode 100644 index 000000000..f394822d6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/file/TemplateResource.java @@ -0,0 +1,71 @@ +package com.fr.design.file; + +import com.fr.common.annotations.Open; +import com.fr.file.FILE; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * 模板资源操作,可操作模板及模板目录 + * + * @author hades + * @version 10.0 + * Created by hades on 2020/12/23 + */ +@Open +public interface TemplateResource { + + /** + * 读取模板 + * @param path + * @return + * @throws Exception + */ + InputStream readTemplate(String path) throws Exception; + + /** + * 保存模板 + * @param file + * @return + * @throws Exception + */ + OutputStream saveTemplate(FILE file) throws Exception; + + /** + * 删除某个目录/某个模板 + * @param file + * @return + */ + boolean delete(FILE file); + + /** + * 关闭模板 + * @param path + * @return + */ + boolean closeTemplate(String path); + + /** + * 重命名模板/目录 + * @param from + * @param to + * @return + */ + boolean rename(String from, String to); + + /** + * 模板/目录是否存在 + * @param path + * @return + */ + boolean exist(String path); + + /** + * 创建目录 + * @param path + * @return + */ + boolean mkdir(String path); + + +} diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateResourceManager.java b/designer-base/src/main/java/com/fr/design/file/TemplateResourceManager.java new file mode 100644 index 000000000..384b1a3e1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/file/TemplateResourceManager.java @@ -0,0 +1,66 @@ +package com.fr.design.file; + +import com.fr.design.ExtraDesignClassManager; +import com.fr.design.file.impl.DefaultTemplateResource; +import com.fr.design.fun.LocalResourceProvider; +import com.fr.design.mainframe.DesignerFrameFileDealerPane; +import com.fr.design.ui.util.UIUtil; +import com.fr.file.filetree.FileNodes; +import com.fr.file.filetree.LocalFileNodes; +import com.fr.plugin.injectable.PluginModule; +import com.fr.plugin.manage.PluginFilter; +import com.fr.plugin.observer.PluginEvent; +import com.fr.plugin.observer.PluginEventListener; +import com.fr.plugin.observer.PluginEventType; +import com.fr.plugin.observer.PluginListenerRegistration; +import com.fr.workspace.WorkContext; +import com.fr.workspace.engine.base.FineObjectPool; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/23 + */ +public class TemplateResourceManager { + + private static final TemplateResource DEFAULT_OPERATION = new DefaultTemplateResource(); + + private static TemplateResource OPERATION = DEFAULT_OPERATION; + + static { + PluginFilter filter = pluginContext -> pluginContext.contain(PluginModule.ExtraDesign, LocalResourceProvider.XML_TAG); + + PluginListenerRegistration.getInstance().listen(PluginEventType.AfterStop, new PluginEventListener() { + @Override + public void on(PluginEvent event) { + registerOperation(new DefaultTemplateResource()); + FineObjectPool.getInstance().getLocalPool().put(FileNodes.class, new LocalFileNodes()); + UIUtil.invokeLaterIfNeeded(() -> DesignerFrameFileDealerPane.getInstance().refresh()); + } + }, filter); + + PluginListenerRegistration.getInstance().listen(PluginEventType.AfterRun, new PluginEventListener() { + @Override + public void on(PluginEvent event) { + LocalResourceProvider provider = ExtraDesignClassManager.getInstance().getSingle(LocalResourceProvider.XML_TAG); + if (provider != null && WorkContext.getCurrent().isLocal()) { + registerOperation(provider.createResourceOperation()); + FineObjectPool.getInstance().getLocalPool().put(FileNodes.class, provider.createFileNodes()); + UIUtil.invokeLaterIfNeeded(() -> DesignerFrameFileDealerPane.getInstance().refresh()); + } + } + }, filter); + } + + private static void registerOperation(TemplateResource operation) { + OPERATION = operation; + } + + public static TemplateResource getResource() { + if (OPERATION == null) { + return DEFAULT_OPERATION; + } + return OPERATION; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java index 5041cc34a..0fc3ca728 100644 --- a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java +++ b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java @@ -4,7 +4,9 @@ package com.fr.design.file; import com.fr.base.FRContext; +import com.fr.design.ExtraDesignClassManager; import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.fun.TemplateTreeDefineProcessor; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; @@ -23,12 +25,11 @@ import com.fr.stable.CoreConstants; import com.fr.stable.StableUtils; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; -import com.fr.workspace.server.lock.TplOperator; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; -import javax.swing.UIManager; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; @@ -87,6 +88,16 @@ public class TemplateTreePane extends JPanel implements FileOperations { } } + @Override + public void mouseClicked(MouseEvent e) { + if (SwingUtilities.isRightMouseButton(e)) { + TemplateTreeDefineProcessor processor = ExtraDesignClassManager.getInstance().getSingle(TemplateTreeDefineProcessor.XML_TAG); + if (processor != null) { + processor.rightClickAction(e); + } + } + } + @Override public void mouseReleased(MouseEvent e) { if (toolBarStateChangeListener != null) { @@ -182,7 +193,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { @Override public boolean mkdir(String path) { - return WorkContext.getWorkResource().createDirectory(path); + return TemplateResourceManager.getResource().mkdir(path); } /** @@ -325,7 +336,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { if (node instanceof FileNode) { FileNodeFILE nodeFILE = new FileNodeFILE((FileNode) node); if (nodeFILE.exists()) { - if (WorkContext.getCurrent().get(TplOperator.class).delete(nodeFILE.getPath())) { + if (TemplateResourceManager.getResource().delete(nodeFILE)) { HistoryTemplateListCache.getInstance().deleteFile(nodeFILE); } else { success = false; @@ -427,7 +438,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { try { // 接收的是WEB-INF下的路径 - return WorkContext.getCurrent().get(TplOperator.class).rename(from, to); + return TemplateResourceManager.getResource().rename(from, to); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); return false; diff --git a/designer-base/src/main/java/com/fr/design/file/impl/AbstractTemplateResource.java b/designer-base/src/main/java/com/fr/design/file/impl/AbstractTemplateResource.java new file mode 100644 index 000000000..cb76792a1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/file/impl/AbstractTemplateResource.java @@ -0,0 +1,19 @@ +package com.fr.design.file.impl; + + +import com.fr.design.file.TemplateResource; +import com.fr.file.FILE; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.lock.TplOperator; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/23 + */ +public abstract class AbstractTemplateResource implements TemplateResource { + +} diff --git a/designer-base/src/main/java/com/fr/design/file/impl/DefaultTemplateResource.java b/designer-base/src/main/java/com/fr/design/file/impl/DefaultTemplateResource.java new file mode 100644 index 000000000..8c54cc8cc --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/file/impl/DefaultTemplateResource.java @@ -0,0 +1,52 @@ +package com.fr.design.file.impl; + +import com.fr.file.FILE; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.lock.TplOperator; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/23 + */ +public class DefaultTemplateResource extends AbstractTemplateResource { + + @Override + public InputStream readTemplate(String path) throws Exception { + return new ByteArrayInputStream(WorkContext.getCurrent().get(TplOperator.class).readAndLockFile(path)); + } + + @Override + public OutputStream saveTemplate(FILE file) throws Exception { + return file.asOutputStream(); + } + + @Override + public boolean closeTemplate(String path) { + return WorkContext.getCurrent().get(TplOperator.class).closeAndFreeFile(path); + } + + @Override + public boolean delete(FILE file) { + return WorkContext.getCurrent().get(TplOperator.class).delete(file.getPath()); + } + + @Override + public boolean rename(String from, String to) { + return WorkContext.getCurrent().get(TplOperator.class).rename(from, to); + } + + @Override + public boolean exist(String path) { + return WorkContext.getWorkResource().exist(path); + } + + @Override + public boolean mkdir(String path) { + return WorkContext.getWorkResource().createDirectory(path); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/LocalResourceProvider.java b/designer-base/src/main/java/com/fr/design/fun/LocalResourceProvider.java new file mode 100644 index 000000000..56a98a235 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/LocalResourceProvider.java @@ -0,0 +1,34 @@ +package com.fr.design.fun; + +import com.fr.design.file.TemplateResource; +import com.fr.file.filetree.FileNodes; +import com.fr.stable.fun.mark.Immutable; + +/** + * 本地资源操作插件接口 + * + * @author hades + * @version 10.0 + * Created by hades on 2020/12/22 + */ +public interface LocalResourceProvider extends Immutable { + + String XML_TAG = "LocalResourceProvider"; + + int CURRENT_LEVEL = 1; + + /** + * eg: DefaultResourceOperation + * + * @return 目录/模板的各种操作 + */ + TemplateResource createResourceOperation(); + + /** + * eg: LocalFileNodes + * + * @return 构建目录树的方式 + */ + FileNodes createFileNodes(); + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/TemplateTreeDefineProcessor.java b/designer-base/src/main/java/com/fr/design/fun/TemplateTreeDefineProcessor.java new file mode 100644 index 000000000..cfa5bcecb --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/TemplateTreeDefineProcessor.java @@ -0,0 +1,19 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.mark.Immutable; +import java.awt.event.MouseEvent; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/14 + */ +public interface TemplateTreeDefineProcessor extends Immutable { + + String XML_TAG = "TemplateTreeDefineProcessor"; + + int CURRENT_LEVEL = 1; + + void rightClickAction(MouseEvent mouseEvent); + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractLocalResourceProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractLocalResourceProvider.java new file mode 100644 index 000000000..ebefc2ba6 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractLocalResourceProvider.java @@ -0,0 +1,23 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.LocalResourceProvider; +import com.fr.stable.fun.mark.API; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/22 + */ +@API(level = LocalResourceProvider.CURRENT_LEVEL) +public abstract class AbstractLocalResourceProvider implements LocalResourceProvider { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public int layerIndex() { + return DEFAULT_LAYER_INDEX; + } +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTemplateTreeDefineProcessor.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTemplateTreeDefineProcessor.java new file mode 100644 index 000000000..eba101aad --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractTemplateTreeDefineProcessor.java @@ -0,0 +1,24 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.TemplateTreeDefineProcessor; +import com.fr.stable.fun.mark.API; + +/** + * @author hades + * @version 10.0 + * Created by hades on 2020/12/21 + */ +@API(level = TemplateTreeDefineProcessor.CURRENT_LEVEL) +public abstract class AbstractTemplateTreeDefineProcessor implements TemplateTreeDefineProcessor { + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + public int layerIndex() { + return DEFAULT_LAYER_INDEX; + } + +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java index 4f59032dc..83120e4fb 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerFrameFileDealerPane.java @@ -17,7 +17,6 @@ import com.fr.design.file.FileToolbarStateChangeListener; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.MutilTempalteTabPane; -import com.fr.design.file.SaveSomeTemplatePane; import com.fr.design.file.TemplateTreePane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; @@ -58,7 +57,6 @@ import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingConstants; -import javax.swing.UIManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import java.awt.BorderLayout; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index eb191383f..5cfd7a13d 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -3,7 +3,6 @@ package com.fr.design.mainframe; import com.fr.base.BaseUtils; import com.fr.base.FRContext; import com.fr.base.Parameter; -import com.fr.base.ScreenResolution; import com.fr.base.io.BaseBook; import com.fr.base.iofile.attr.DesignBanCopyAttrMark; import com.fr.base.iofile.attr.TemplateIdAttrMark; @@ -24,6 +23,7 @@ import com.fr.design.designer.TargetComponent; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.InformationWarnPane; import com.fr.design.file.HistoryTemplateListPane; +import com.fr.design.file.TemplateResourceManager; import com.fr.design.file.TemplateTreePane; import com.fr.design.fun.DesignerFrameUpButtonProvider; import com.fr.design.fun.MenuHandler; @@ -813,7 +813,7 @@ public abstract class JTemplate> return false; } try { - this.getTarget().export(editingFILE.asOutputStream()); + this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE)); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); JOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), e.getMessage(), "Save Error", JOptionPane.ERROR_MESSAGE); diff --git a/designer-base/src/main/java/com/fr/file/FileNodeFILE.java b/designer-base/src/main/java/com/fr/file/FileNodeFILE.java index b033d229b..d096faf8a 100644 --- a/designer-base/src/main/java/com/fr/file/FileNodeFILE.java +++ b/designer-base/src/main/java/com/fr/file/FileNodeFILE.java @@ -2,6 +2,7 @@ package com.fr.file; import com.fr.base.BaseUtils; import com.fr.base.FRContext; +import com.fr.design.file.TemplateResourceManager; import com.fr.io.FineEncryptUtils; import com.fr.base.io.XMLEncryptUtils; import com.fr.design.file.NodeAuthProcessor; @@ -22,10 +23,8 @@ import com.fr.workspace.WorkContext; import com.fr.workspace.Workspace; import com.fr.workspace.WorkspaceEvent; import com.fr.workspace.resource.WorkResourceTempRenameStream; -import com.fr.workspace.server.lock.TplOperator; import javax.swing.*; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; @@ -324,7 +323,7 @@ public class FileNodeFILE implements FILE { } try { - return WorkContext.getWorkResource().exist(node.getEnvPath()); + return TemplateResourceManager.getResource().exist(node.getEnvPath()); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); return false; @@ -379,14 +378,11 @@ public class FileNodeFILE implements FILE { if (!envPath.startsWith(ProjectConstants.REPORTLETS_NAME)) { return null; } - InputStream in = new ByteArrayInputStream( - WorkContext.getCurrent().get(TplOperator.class).readAndLockFile( - StableUtils.pathJoin( - ProjectConstants.REPORTLETS_NAME, - envPath.substring(ProjectConstants.REPORTLETS_NAME.length() + 1) - ) - ) - ); + InputStream in = TemplateResourceManager.getResource().readTemplate( + StableUtils.pathJoin( + ProjectConstants.REPORTLETS_NAME, + envPath.substring(ProjectConstants.REPORTLETS_NAME.length() + 1) + )); return envPath.endsWith(".cpt") || envPath.endsWith(".frm") ? XMLEncryptUtils.decodeInputStream(EncryptUtils.decodeInputStream(FineEncryptUtils.decode(in))) : in; diff --git a/designer-realize/src/main/java/com/fr/grid/GridUI.java b/designer-realize/src/main/java/com/fr/grid/GridUI.java index 5f5476511..711ecee83 100644 --- a/designer-realize/src/main/java/com/fr/grid/GridUI.java +++ b/designer-realize/src/main/java/com/fr/grid/GridUI.java @@ -49,6 +49,7 @@ import com.fr.stable.script.CalculatorUtils; import com.fr.stable.unit.FU; import com.fr.stable.AssistUtils; import com.fr.third.antlr.ANTLRException; +import com.fr.third.guava.collect.HashMultimap; import javax.swing.JComponent; import javax.swing.UIManager; @@ -73,6 +74,7 @@ import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Objects; public class GridUI extends ComponentUI { @@ -91,6 +93,7 @@ public class GridUI extends ComponentUI { protected List paintCellElementList = new ArrayList(); protected List paintCellElementRectangleList = new ArrayList(); protected List paginateLineList = new ArrayList(); // 分页线 + protected HashMultimap mergeCellElementTable = HashMultimap.create(); // 为了画白色的背景. protected static Background WHITE_Backgorund = ColorBackground.getInstance(Color.WHITE); // CellElementPainter @@ -247,7 +250,7 @@ public class GridUI extends ComponentUI { - reportSettings.getFooterHeight().toPixD(resolution); } - private void paintGridLine(Graphics g, Grid grid, double realWidth, double realHeight, + private void paintGridLine(Graphics g, Grid grid, TemplateElementCase report, double realWidth, double realHeight, int resolution) { Graphics2D g2d = (Graphics2D) g; @@ -257,22 +260,51 @@ public class GridUI extends ComponentUI { // 分页线 paginateLineList.clear(); + // 合并单元格 + mergeCellElementTable.clear(); boolean isShowVerticalPaginateLine = grid.getPaginateLineShowType() == Grid.MULTIPLE_PAGINATE_LINE; boolean isShowHorizontalPaginateLine = grid.getPaginateLineShowType() != Grid.NO_PAGINATE_LINE; - new DrawVerticalLineHelper(grid.getVerticalBeginValue(), verticalEndValue, - grid.isShowGridLine(), isShowVerticalPaginateLine, rowHeightList, paperPaintHeight, - paginateLineList, realWidth, resolution).iterateStart2End(g2d); + Iterator cells = report.intersect(grid.getHorizontalBeginValue(), grid.getVerticalBeginValue(), + horizontalEndValue - grid.getHorizontalBeginValue(), verticalEndValue - grid.getVerticalBeginValue()); + while (cells.hasNext()) { + TemplateCellElement cellElement = (TemplateCellElement) cells.next(); + if (cellElement == null) { + continue; + } + int columnSpan = cellElement.getColumnSpan(); + int rowSpan = cellElement.getRowSpan(); + if (columnSpan > 1 || rowSpan > 1) { + for (int c = 0; c < columnSpan - 1; c++) { + for (int r = 0; r < rowSpan; r++) { + mergeCellElementTable.put(CellPosition.value(cellElement.getRow() + r, cellElement.getColumn() + c), CellPosition.RIGHT); + } + } + for (int r = 0; r < rowSpan - 1; r++) { + for (int c = 0; c < columnSpan; c++) { + mergeCellElementTable.put(CellPosition.value(cellElement.getRow() + r, cellElement.getColumn() + c), CellPosition.BOTTOM); + } + } + } + } + GridRange gridRange = GridRange.range(grid.getHorizontalBeginValue(), horizontalEndValue, grid.getVerticalBeginValue(), verticalEndValue) + .rangeList(rowHeightList, columnWidthList) + .realSize(realWidth, realHeight); + + new DrawVerticalLineHelper(gridRange, grid.isShowGridLine(), + isShowVerticalPaginateLine, paperPaintHeight, + paginateLineList, resolution).iterateStart2End(g2d); - new DrawHorizontalLineHelper(grid.getHorizontalBeginValue(), horizontalEndValue, - grid.isShowGridLine(), isShowHorizontalPaginateLine, columnWidthList, paperPaintWidth, - paginateLineList, realHeight, resolution).iterateStart2End(g2d); + new DrawHorizontalLineHelper(gridRange, grid.isShowGridLine(), + isShowHorizontalPaginateLine, paperPaintWidth, + paginateLineList, resolution).iterateStart2End(g2d); } /** * 最后处理 */ + @Override public void finalize() { try { super.finalize(); @@ -285,80 +317,34 @@ public class GridUI extends ComponentUI { } private static abstract class DrawLineHelper { - private int startIndex; - private int endIndex; + protected GridRange gridRange; - private boolean showGridLine; - private boolean showPaginateLine; + protected boolean showGridLine; + protected boolean showPaginateLine; - private DynamicUnitList sizeList; - private double paperPaintSize; + protected double paperPaintSize; - private List paginateLineList; + protected List paginateLineList; Line2D tmpLine2D = new Line2D.Double(0, 0, 0, 0); - private int resolution; + protected int resolution; - private static final double THRESHOLD = 1.0E-4D; + protected static final double THRESHOLD = 1.0E-4D; - DrawLineHelper(int startIndex, int endIndex, boolean showGridLine, - boolean showPaginateLine, DynamicUnitList sizeList, double paperPaintSize, + DrawLineHelper(GridRange gridRange, boolean showGridLine, + boolean showPaginateLine, double paperPaintSize, List paginateLineList, int resolution) { - this.startIndex = startIndex; - this.endIndex = endIndex; + this.gridRange = gridRange; this.showGridLine = showGridLine; this.showPaginateLine = showPaginateLine; - this.sizeList = sizeList; this.paperPaintSize = paperPaintSize; this.paginateLineList = paginateLineList; this.resolution = resolution; } - protected void iterateStart2End(Graphics2D g2d) { - float tmpSize = 0, paperSumSize = 0, sumSize = 0; - for (int i = 0; i <= endIndex; i++) { - // denny: 开始 - if (i == 0) { - i = startIndex; - - // denny: 增加从0到Grid左边被hide的列宽 - for (int k = 0; k < startIndex; k++) { - tmpSize = sizeList.get(k).toPixF(resolution); - - paperSumSize += tmpSize; - if (paperSumSize >= paperPaintSize) { - paperSumSize = tmpSize; - } - } - } - - // adjust height. - tmpSize = sizeList.get(i).toPixF(resolution); - paperSumSize += tmpSize; - - if (showGridLine) {// paint line. - setLine2D((int) sumSize); - g2d.draw(tmpLine2D); - } - - // paint paper margin line. - if (showPaginateLine && paperSumSize - paperPaintSize > THRESHOLD) { - paginateLineList.add(getPaginateLine2D((int) sumSize)); - paperSumSize = tmpSize; - } - - sumSize += tmpSize; - } - - // paint 最后一个横线.. - if (showGridLine) { - drawLastLine(g2d, (int) sumSize); - } - } - - protected abstract void setLine2D(int sumSize); + protected abstract void iterateStart2End(Graphics2D g2d); protected abstract Line2D.Double getPaginateLine2D(int sumSize); @@ -366,14 +352,12 @@ public class GridUI extends ComponentUI { } private class DrawVerticalLineHelper extends DrawLineHelper { - private double realWidth; - DrawVerticalLineHelper(int startIndex, int endIndex, boolean showGridLine, - boolean showPaginateLine, DynamicUnitList unitSizeList, double paperPaintSize, - List paginateLineList, double realWidth, int resolution) { - super(startIndex, endIndex, showGridLine, showPaginateLine, unitSizeList, + DrawVerticalLineHelper(GridRange gridRange, boolean showGridLine, + boolean showPaginateLine, double paperPaintSize, + List paginateLineList, int resolution) { + super(gridRange, showGridLine, showPaginateLine, paperPaintSize, paginateLineList, resolution); - this.realWidth = realWidth; } @Override @@ -382,25 +366,58 @@ public class GridUI extends ComponentUI { } @Override - protected void setLine2D(int sumHeight) { - tmpLine2D.setLine(0, sumHeight, realWidth, sumHeight); + protected void drawLastLine(Graphics2D g2d, int sumHeight) { + GraphHelper.drawLine(g2d, 0, sumHeight, gridRange.realWidth, sumHeight); } @Override - protected void drawLastLine(Graphics2D g2d, int sumHeight) { - GraphHelper.drawLine(g2d, 0, sumHeight, realWidth, sumHeight); + protected void iterateStart2End(Graphics2D g2d) { + float rowHeight, paperYAxisSumSize = 0, yAxisSumSize = 0; + for (int i = 0; i <= gridRange.yEndIndex; i++) { + if (i == 0) { + i = gridRange.yBeginIndex; + for (int k = 0; k < gridRange.yBeginIndex; k++) { + rowHeight = gridRange.rowHeightList.get(k).toPixF(resolution); + + paperYAxisSumSize += rowHeight; + if (paperYAxisSumSize >= paperPaintSize) { + paperYAxisSumSize = rowHeight; + } + } + } + rowHeight = gridRange.rowHeightList.get(i).toPixF(resolution); + paperYAxisSumSize += rowHeight; + if (showGridLine) { + float columnWidth, xAxisSumSize = 0; + for (int j = gridRange.xBeginIndex; j <= gridRange.xEndIndex; j++) { + columnWidth = gridRange.columnWidthList.get(j).toPixF(resolution); + if (!mergeCellElementTable.get(CellPosition.value(i - 1, j)).contains(CellPosition.BOTTOM)) { + tmpLine2D.setLine(xAxisSumSize, yAxisSumSize, xAxisSumSize + columnWidth, yAxisSumSize); + g2d.draw(tmpLine2D); + } + xAxisSumSize += columnWidth; + } + } + if (showPaginateLine && paperYAxisSumSize - paperPaintSize > THRESHOLD) { + paginateLineList.add(getPaginateLine2D((int) yAxisSumSize)); + paperYAxisSumSize = rowHeight; + } + yAxisSumSize += rowHeight; + } + // paint 最后一个横线.. + if (showGridLine) { + drawLastLine(g2d, (int) yAxisSumSize); + } } } private class DrawHorizontalLineHelper extends DrawLineHelper { - private double realHeight; - DrawHorizontalLineHelper(int startIndex, int endIndex, boolean showGridLine, - boolean showPaginateLine, DynamicUnitList unitSizeList, double paperPaintSize, - List paginateLineList, double realHeight, int resolution) { - super(startIndex, endIndex, showGridLine, showPaginateLine, unitSizeList, + DrawHorizontalLineHelper(GridRange gridRange, boolean showGridLine, + boolean showPaginateLine, double paperPaintSize, + List paginateLineList, int resolution) { + super(gridRange, showGridLine, showPaginateLine, paperPaintSize, paginateLineList, resolution); - this.realHeight = realHeight; } @Override @@ -409,13 +426,47 @@ public class GridUI extends ComponentUI { } @Override - protected void setLine2D(int sumWidth) { - tmpLine2D.setLine(sumWidth, 0, sumWidth, realHeight); + protected void drawLastLine(Graphics2D g2d, int sumWidth) { + GraphHelper.drawLine(g2d, sumWidth, 0, sumWidth, gridRange.realHeight); } @Override - protected void drawLastLine(Graphics2D g2d, int sumWidth) { - GraphHelper.drawLine(g2d, sumWidth, 0, sumWidth, realHeight); + protected void iterateStart2End(Graphics2D g2d) { + float columnWidth, paperXAxisSumSize = 0, xAxisSumSize = 0; + for (int i = 0; i <= gridRange.xEndIndex; i++) { + if (i == 0) { + i = gridRange.xBeginIndex; + for (int k = 0; k < gridRange.xBeginIndex; k++) { + columnWidth = gridRange.columnWidthList.get(k).toPixF(resolution); + paperXAxisSumSize += columnWidth; + if (paperXAxisSumSize >= paperPaintSize) { + paperXAxisSumSize = columnWidth; + } + } + } + columnWidth = gridRange.columnWidthList.get(i).toPixF(resolution); + paperXAxisSumSize += columnWidth; + if (showGridLine) { + float rowHeight, yAxisSumSize = 0; + for (int j = gridRange.yBeginIndex; j <= gridRange.yEndIndex; j++) { + rowHeight = gridRange.rowHeightList.get(j).toPixF(resolution); + if (!mergeCellElementTable.get(CellPosition.value(j, i - 1)).contains(CellPosition.RIGHT)) { + tmpLine2D.setLine(xAxisSumSize, yAxisSumSize, xAxisSumSize, yAxisSumSize + rowHeight); + g2d.draw(tmpLine2D); + } + yAxisSumSize += rowHeight; + } + } + if (showPaginateLine && paperXAxisSumSize - paperPaintSize > THRESHOLD) { + paginateLineList.add(getPaginateLine2D((int) xAxisSumSize)); + paperXAxisSumSize = columnWidth; + } + xAxisSumSize += columnWidth; + } + // paint 最后一个横线.. + if (showGridLine) { + drawLastLine(g2d, (int) xAxisSumSize); + } } } @@ -482,18 +533,6 @@ public class GridUI extends ComponentUI { // peter:tmpRectangle2D_3只是一个临时的Rectangle2D,由于后面不少地方需要用到这个矩形 this.cell_back_rect.setRect(0, 0, this.tmpRectangle.getWidth() - 1, this.tmpRectangle.getHeight() - 1.5); - // peter:对于合并的单元格,需要先白色的背景来清除背景. - if (tmpCellElement.getColumnSpan() > 1 || tmpCellElement.getRowSpan() > 1) { - // REPORT-23492 要看下是否设置了纸张背景 如果设置了按照背景来画 - ReportSettingsProvider reportSettings = getReportSettings(report); - Background currentBackground = reportSettings.getBackground(); - if (currentBackground != null) { - currentBackground.paint(g2d, this.cell_back_rect); - } else { - WHITE_Backgorund.paint(g2d, this.cell_back_rect); - } - //daniel:上面这里就有问题了啊....报表的背景在这个之前画的 会覆盖报表背景....不过只是设计器中看到预览浏览没问题 - } // peter:将这个元素添加到需要paint的元素列表当中去,留着画边框线.. paintCellElementList.add(tmpCellElement); paintCellElementRectangleList.add(this.tmpRectangle.clone()); @@ -1093,8 +1132,7 @@ public class GridUI extends ComponentUI { this.paintBackground(g2d, grid, elementCase, resolution); // 画Grid Line - this.paintGridLine(g2d, grid, realWidth, realHeight, resolution); - + this.paintGridLine(g2d, grid, elementCase, realWidth, realHeight, resolution); // peter:添上线程的支持,有时候,paint元素的时候,可能会有元素被删除了. // 需要先清除画Border需要的元素. paintCellElementList.clear(); @@ -1277,4 +1315,101 @@ public class GridUI extends ComponentUI { paginateLineList.add(new Line2D.Double(0, sumHeight, width, sumHeight)); } } + + /** + * 描述单元格位置的POJO + */ + private static class CellPosition { + public final static int TOP = 0; + public static final int LEFT = 1; + public final static int BOTTOM = 2; + public static final int RIGHT = 4; + public int x; + public int y; + + public CellPosition(int x, int y) { + this.x = x; + this.y = y; + } + + public static CellPosition value(int x, int y) { + return new CellPosition(x, y); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + CellPosition that = (CellPosition) o; + return x == that.x && y == that.y; + } + + @Override + public int hashCode() { + return Objects.hash(x, y); + } + } + + /** + * 描述表格范围的POJO + * x轴为水平方向,对应的宽度表为列宽列表 + * y轴为垂直方向,对应的宽度表为行高列表 + */ + private static class GridRange { + + public int xBeginIndex; + public int xEndIndex; + public int yBeginIndex; + public int yEndIndex; + double realWidth; + double realHeight; + /** + * 行高列表,对应y方向线段 + */ + public DynamicUnitList rowHeightList; + + /** + * 列宽列表,对应x方向线段 + */ + public DynamicUnitList columnWidthList; + + public GridRange(int xBeginIndex, int xEndIndex, int yBeginIndex, int yEndIndex) { + this.xBeginIndex = xBeginIndex; + this.xEndIndex = xEndIndex; + this.yBeginIndex = yBeginIndex; + this.yEndIndex = yEndIndex; + } + + /** + * 设置行高列宽列表 + * + * @param rowHeightList 行高列表 + * @param columnWidthList 列宽列表 + */ + public GridRange rangeList(DynamicUnitList rowHeightList, DynamicUnitList columnWidthList) { + this.rowHeightList = rowHeightList; + this.columnWidthList = columnWidthList; + return this; + } + + /** + * 设置表格真实宽高 + * + * @param realWidth 宽度 + * @param realHeight 高度 + */ + public GridRange realSize(double realWidth, double realHeight) { + this.realWidth = realWidth; + this.realHeight = realHeight; + return this; + } + + public static GridRange range(int xBeginIndex, int xEndIndex, int yBeginIndex, int yEndIndex) { + return new GridRange(xBeginIndex, xEndIndex, yBeginIndex, yEndIndex); + } + } }