From f169fb0b0fe07b3ebf32bb10d24f8c79d696622b Mon Sep 17 00:00:00 2001 From: zack Date: Thu, 7 Jun 2018 16:26:40 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-8357=20=20.0=E4=B9=8B=E5=89=8D=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E7=9A=84=E5=8A=9F=E8=83=BD=E4=B8=8Ebug=20patch?= =?UTF-8?q?=E5=88=B010.0=20=E5=9B=BE=E7=89=87=E5=8E=8B=E7=BC=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/fr/design/DesignerEnvManager.java | 12 + .../design/gui/frpane/ImgChooseWrapper.java | 154 ++++++ .../ImageBackgroundQuickPane.java | 38 +- .../backgroundpane/ImagePreviewPane.java | 514 +++++++++--------- .../background/image/ExpandFileChooser.java | 196 +++++++ .../background/image/ImageFileChooser.java | 31 +- .../background/image/ImagePreviewPane.java | 118 ++-- .../background/image/ImagePreviewer.java | 40 ++ .../background/image/ImageSelectPane.java | 16 +- .../background/impl/ImageBackgroundPane.java | 56 +- .../impl/ImageBackgroundPane4Browser.java | 13 - .../impl/ImageButtonBackgroundPane.java | 22 +- .../src/com/fr/design/utils/ImageUtils.java | 285 ++++++++++ .../com/fr/design/headerfooter/ImagePane.java | 53 +- 14 files changed, 1105 insertions(+), 443 deletions(-) create mode 100644 designer-base/src/com/fr/design/gui/frpane/ImgChooseWrapper.java create mode 100644 designer-base/src/com/fr/design/style/background/image/ExpandFileChooser.java create mode 100644 designer-base/src/com/fr/design/style/background/image/ImagePreviewer.java create mode 100644 designer-base/src/com/fr/design/utils/ImageUtils.java diff --git a/designer-base/src/com/fr/design/DesignerEnvManager.java b/designer-base/src/com/fr/design/DesignerEnvManager.java index 634240489..6517e705e 100644 --- a/designer-base/src/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/com/fr/design/DesignerEnvManager.java @@ -148,6 +148,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { private boolean isHttps = false; private static List mapWorkerList = new ArrayList(); + private boolean imageCompress = false;//图片压缩 /** * DesignerEnvManager. @@ -1412,6 +1413,7 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { this.setOracleSystemSpace(reader.getAttrAsBoolean("useOracleSystemSpace", true)); this.setCachingTemplateLimit(reader.getAttrAsInt("cachingTemplateLimit", CACHINGTEMPLATE_LIMIT)); this.setJoinProductImprove(reader.getAttrAsBoolean("joinProductImprove", true)); + this.setImageCompress(reader.getAttrAsBoolean("imageCompress", true)); this.setAutoBackUp(reader.getAttrAsBoolean("autoBackUp", true)); this.setTemplateTreePaneExpanded(reader.getAttrAsBoolean("templateTreePaneExpanded", false)); // peter:读取webinfLocation @@ -1637,6 +1639,9 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (!this.isJoinProductImprove()) { writer.attr("joinProductImprove", this.isJoinProductImprove()); } + if (!this.isImageCompress()) { + writer.attr("imageCompress", this.isImageCompress()); + } if (!this.isAutoBackUp()) { writer.attr("autoBackUp", this.isAutoBackUp()); } @@ -1884,4 +1889,11 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { return this; } } + public boolean isImageCompress() { + return imageCompress; + } + + public void setImageCompress(boolean imageCompress) { + this.imageCompress = imageCompress; + } } \ No newline at end of file diff --git a/designer-base/src/com/fr/design/gui/frpane/ImgChooseWrapper.java b/designer-base/src/com/fr/design/gui/frpane/ImgChooseWrapper.java new file mode 100644 index 000000000..95073bf42 --- /dev/null +++ b/designer-base/src/com/fr/design/gui/frpane/ImgChooseWrapper.java @@ -0,0 +1,154 @@ +package com.fr.design.gui.frpane; + +import com.fr.base.BaseUtils; +import com.fr.base.Style; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.style.background.image.ImageFileChooser; +import com.fr.design.style.background.image.ImagePreviewer; +import com.fr.design.utils.ImageUtils; +import com.fr.general.ImageWithSuffix; +import com.fr.general.Inter; +import com.fr.stable.CoreGraphHelper; +import com.fr.stable.StringUtils; + +import javax.swing.JFileChooser; +import javax.swing.SwingWorker; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.Image; +import java.io.File; + +/** + * 图片选择框包装类 + * Created by zack on 2018/3/9. + */ +public class ImgChooseWrapper { + private ImagePreviewer previewPane = null; + + private ImageFileChooser imageFileChooser = null; + + private Style imageStyle = null; + + private SwingWorker imageWorker; + private ChangeListener changeListener; + + private transient Image selectImage; + private UILabel imageSizeLabel; + + public static ImgChooseWrapper getInstance(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle) { + return getInstance(previewPane, imageFileChooser, imageStyle, null); + } + + public static ImgChooseWrapper getInstance(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle, ChangeListener changeListener) { + return new ImgChooseWrapper(previewPane, imageFileChooser, imageStyle, changeListener, null, null); + } + + public static ImgChooseWrapper getInstance(Image selectImage, UILabel imageSizeLabel, ImageFileChooser imageFileChooser) { + return new ImgChooseWrapper(null, imageFileChooser, null, null, selectImage, imageSizeLabel); + } + + private ImgChooseWrapper(ImagePreviewer previewPane, ImageFileChooser imageFileChooser, Style imageStyle, ChangeListener changeListener, Image selectImage, UILabel imageSizeLabel) { + this.previewPane = previewPane; + this.imageFileChooser = imageFileChooser; + this.imageStyle = imageStyle; + this.changeListener = changeListener; + this.selectImage = selectImage; + this.imageSizeLabel = imageSizeLabel; + } + + + public void setPreviewPane(ImagePreviewer previewPane) { + this.previewPane = previewPane; + } + + public ImageFileChooser getImageFileChooser() { + return imageFileChooser; + } + + public void setImageFileChooser(ImageFileChooser imageFileChooser) { + this.imageFileChooser = imageFileChooser; + } + + public Style getImageStyle() { + return imageStyle; + } + + public void setImageStyle(Style imageStyle) { + this.imageStyle = imageStyle; + } + + public SwingWorker getImageWorker() { + return imageWorker; + } + + public void setImageWorker(SwingWorker imageWorker) { + this.imageWorker = imageWorker; + } + + public void dealWithImageFile(int returnVal) { + if (returnVal != JFileChooser.CANCEL_OPTION) { + final File selectedFile = imageFileChooser.getSelectedFile(); + + if (selectedFile != null && selectedFile.isFile()) { + if (previewPane != null) { + previewPane.showLoading(); + } + if (imageWorker != null && !imageWorker.isDone()) { + imageWorker = null; + } + imageWorker = new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + ImageWithSuffix imageWithSuffix = null; + if (imageFileChooser.isCheckSelected()) { + imageWithSuffix = ImageUtils.defaultImageCompWithSuff(selectedFile); + } else { + Image image = BaseUtils.readImage(selectedFile.getPath()); + String type = ImageUtils.getImageType(selectedFile); + imageWithSuffix = new ImageWithSuffix(image, type); + } + + CoreGraphHelper.waitForImage(imageWithSuffix); + + if (previewPane != null) { + previewPane.setImageStyle(imageStyle); + previewPane.setImageWithSuffix(imageWithSuffix); + previewPane.repaint(); + } + checkLabelText(); + fireChangeListener(); + return null; + } + }; + imageWorker.execute(); + } else { + if (previewPane != null) { + previewPane.setImage(null); + } + + } + if (previewPane != null) { + previewPane.repaint(); + } + } + } + + private void fireChangeListener() { + if (this.changeListener != null) { + ChangeEvent evt = new ChangeEvent(this); + this.changeListener.stateChanged(evt); + } + } + + private void checkLabelText() { + if (imageSizeLabel == null) { + return; + } + if (selectImage == null) { + imageSizeLabel.setText(StringUtils.EMPTY); + } else { + imageSizeLabel.setText(selectImage.getWidth(null) + "x" + + selectImage.getHeight(null) + Inter.getLocText("px")); + } + } +} diff --git a/designer-base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundQuickPane.java b/designer-base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundQuickPane.java index 405e1fc18..8076f4784 100644 --- a/designer-base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundQuickPane.java +++ b/designer-base/src/com/fr/design/mainframe/backgroundpane/ImageBackgroundQuickPane.java @@ -1,30 +1,28 @@ package com.fr.design.mainframe.backgroundpane; -import com.fr.base.BaseUtils; import com.fr.base.Style; import com.fr.base.background.ImageFileBackground; import com.fr.base.frpx.pack.PictureCollection; -import com.fr.base.frpx.util.ImageIOHelper; -import com.fr.design.constants.UIConstants; import com.fr.design.border.UIRoundedBorder; +import com.fr.design.constants.UIConstants; import com.fr.design.event.UIObserverListener; +import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButtonGroup; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; +import com.fr.design.style.background.image.ImageFileChooser; import com.fr.general.Background; import com.fr.general.Inter; import com.fr.stable.Constants; -import com.fr.stable.CoreGraphHelper; -import com.fr.design.style.background.image.ImageFileChooser; -import javax.swing.*; +import javax.swing.JPanel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; /** * @author zhou @@ -90,32 +88,14 @@ public class ImageBackgroundQuickPane extends BackgroundQuickPane { */ ActionListener selectPictureActionListener = new ActionListener() { - @Override public void actionPerformed(ActionEvent evt) { if (imageFileChooser == null) { imageFileChooser = new ImageFileChooser(); imageFileChooser.setMultiSelectionEnabled(false); } int returnVal = imageFileChooser.showOpenDialog(DesignerContext.getDesignerFrame()); - if (returnVal != JFileChooser.CANCEL_OPTION) { - File selectedFile = imageFileChooser.getSelectedFile(); - - if (selectedFile != null && selectedFile.isFile()) { - String path = selectedFile.getPath(); - suffix = ImageIOHelper.getSuffix(path); - Image image = BaseUtils.readImage(path); - CoreGraphHelper.waitForImage(image); - - previewPane.setImage(image); - imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(imageLayoutPane.getSelectedItem()); - previewPane.setImageStyle(imageStyle); - previewPane.repaint(); - } else { - previewPane.setImage(null); - } - fireChagneListener(); - } - + imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(imageLayoutPane.getSelectedItem()); + ImgChooseWrapper.getInstance(previewPane, imageFileChooser, imageStyle, changeListener).dealWithImageFile(returnVal); } }; @@ -128,7 +108,7 @@ public class ImageBackgroundQuickPane extends BackgroundQuickPane { Style.DEFAULT_STYLE.deriveImageLayout(imageBackground.getLayout()); previewPane.setImageStyle(ImageBackgroundQuickPane.this.imageStyle); - previewPane.setImage(imageBackground.getImage()); + previewPane.setImageWithSuffix(imageBackground.getImageWithSuffix()); previewPane.repaint(); } diff --git a/designer-base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java b/designer-base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java index 1a170ce4b..a97699ff6 100644 --- a/designer-base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java +++ b/designer-base/src/com/fr/design/mainframe/backgroundpane/ImagePreviewPane.java @@ -4,285 +4,311 @@ package com.fr.design.mainframe.backgroundpane; * Copyright(c) 2001-2010, FineReport Inc, All Rights Reserved. */ -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; +import com.fr.base.BaseUtils; +import com.fr.base.GraphHelper; +import com.fr.base.Style; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.iscrollbar.UIScrollBar; +import com.fr.design.style.background.image.ImagePreviewer; +import com.fr.general.ImageWithSuffix; +import com.fr.general.Inter; +import com.fr.stable.Constants; +import com.fr.stable.CoreGraphHelper; import javax.swing.BorderFactory; import javax.swing.JComponent; - -import com.fr.design.constants.UIConstants; -import com.fr.design.gui.ilable.UILabel; import javax.swing.JPanel; import javax.swing.JViewport; import javax.swing.Scrollable; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; - -import com.fr.base.BaseUtils; -import com.fr.base.GraphHelper; -import com.fr.base.Style; -import com.fr.design.gui.iscrollbar.UIScrollBar; -import com.fr.stable.Constants; -import com.fr.stable.CoreGraphHelper; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; /** * The pane use to preview image */ -public class ImagePreviewPane extends JComponent implements Scrollable { +public class ImagePreviewPane extends JComponent implements Scrollable, ImagePreviewer { private static final int LABEL_DELTA_X = 10; private static final int LABEL_DELTA_Y = 20; private static final int LABEL_HEIGHT = 20; private static final int INCRE_DELTA = 10; - private Image image = null; - // carl:image style - private Style imageStyle = null; - private int imageWidth = 0; - private int imageHeight = 0; + private ImageWithSuffix image = null; + // carl:image style + private Style imageStyle = null; + private int imageWidth = 0; + private int imageHeight = 0; + + private List changeListenerList = new ArrayList(); + private UILabel sizeLabel; + private boolean isLoading = false; + + public ImagePreviewPane() { + sizeLabel = new UILabel(); + this.add(sizeLabel); + this.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10)); + this.setLayout(new BorderLayout()); + this.add(new JPanel() { + public void paintComponent(Graphics g) { + super.paintComponent(g); + if (isLoading) { + g.drawString(Inter.getLocText("FR-Designer_Image_Loading"), getWidth() / 2 - 25, getHeight() / 2); + return; + } + // draw image. + if (getImage() != null) { + // carl:让imagePreviewPane能预览样式 + if (getImageStyle() == null) { + g.drawImage(getImage(), 0, 0, this); + } else { + if (getImage().getWidth(this) > getWidth() || getImage().getHeight(this) > getHeight()) { + GraphHelper.paintImageMoved(g, this.getWidth(), this.getHeight(), getImage(), Constants.IMAGE_ADJUST, BaseUtils.getAlignment4Horizontal(getImageStyle()), + getImageStyle().getVerticalAlignment(), -1, -1, 0, 0, false, UIConstants.NORMAL_BACKGROUND); + } else { + int totalwidth = this.getWidth(); + int totalheight = this.getHeight(); + g.drawImage(getImage(), totalwidth / 2 - imageWidth / 2, totalheight / 2 - imageHeight / 2, this); + } + } + } + } + }, BorderLayout.CENTER); + // this.setToolTipText("View Image"); + } + + /** + * Return image + */ + public Image getImage() { + return image == null ? null : this.image.getImage(); + } + + /** + * Return ImageWithSuffix + */ + public ImageWithSuffix getImageWithSuffix() { + return this.image; + } - private List changeListenerList = new ArrayList(); - private UILabel sizeLabel; + /** + * Set image. + * + * @param image the new image. + */ + @Override + public void setImageWithSuffix(ImageWithSuffix image) { + this.image = image; + // need to reset the size of JViewPort. + if (this.image == null) { + if (this.getParent() instanceof JViewport) { + UIScrollBar tmpJScrollBar = new UIScrollBar(UIScrollBar.HORIZONTAL); + Dimension newDimension = new Dimension(this.getSize().width - tmpJScrollBar.getPreferredSize().height, this.getSize().height + - tmpJScrollBar.getPreferredSize().height); + ((JViewport) this.getParent()).setPreferredSize(newDimension); + (this.getParent()).setSize(newDimension); + ((JViewport) this.getParent()).setMinimumSize(newDimension); + ((JViewport) this.getParent()).setMaximumSize(newDimension); + } + sizeLabel.setText(null); + } else { + isLoading = false; + // wait for the size of image. + CoreGraphHelper.waitForImage(image); - public ImagePreviewPane() { - sizeLabel = new UILabel(); - this.add(sizeLabel); - this.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10)); - this.setLayout(new BorderLayout()); - this.add(new JPanel() { - public void paintComponent(Graphics g) { - super.paintComponent(g); + imageWidth = image.getWidth(null); + imageHeight = image.getHeight(null); + int totalwidth = ImagePreviewPane.this.getWidth(); + int totalheight = ImagePreviewPane.this.getHeight(); + String text = imageWidth + "x" + imageHeight; + sizeLabel.setText(text); + FontMetrics cellFM = this.getFontMetrics(getFont()); + int width = cellFM.stringWidth(text); + sizeLabel.setBounds(totalwidth - width - LABEL_DELTA_X, totalheight - LABEL_DELTA_Y, width, LABEL_HEIGHT); + } + fireChangeListener(); + this.revalidate(); + } - // draw image. - if (getImage() != null) { - // carl:让imagePreviewPane能预览样式 - if (getImageStyle() == null) { - g.drawImage(getImage(), 0, 0, this); - } else { - if (getImage().getWidth(this) > getWidth() || getImage().getHeight(this) > getHeight()) { - GraphHelper.paintImageMoved(g, this.getWidth(), this.getHeight(), getImage(), Constants.IMAGE_ADJUST, BaseUtils.getAlignment4Horizontal(getImageStyle()), - getImageStyle().getVerticalAlignment(), -1, -1,0, 0, false, UIConstants.NORMAL_BACKGROUND); - } else { - int totalwidth = this.getWidth(); - int totalheight = this.getHeight(); - g.drawImage(getImage(), totalwidth / 2 - imageWidth / 2, totalheight / 2 - imageHeight / 2, this); - } - } - } - } - }, BorderLayout.CENTER); - // this.setToolTipText("View Image"); - } + @Override + public void showLoading() { + isLoading = true; + setImage(null); + repaint(); + } - /** - * Return image - */ - public Image getImage() { - return this.image; - } + /** + * Paint component. + */ - /** - * Set image. - * - * @param image - * the new image. - */ - public void setImage(Image image) { - this.image = image; - // need to reset the size of JViewPort. - if (this.image == null) { - if (this.getParent() instanceof JViewport) { - UIScrollBar tmpJScrollBar = new UIScrollBar(UIScrollBar.HORIZONTAL); - Dimension newDimension = new Dimension(this.getSize().width - tmpJScrollBar.getPreferredSize().height, this.getSize().height - - tmpJScrollBar.getPreferredSize().height); - ((JViewport)this.getParent()).setPreferredSize(newDimension); - (this.getParent()).setSize(newDimension); - ((JViewport)this.getParent()).setMinimumSize(newDimension); - ((JViewport)this.getParent()).setMaximumSize(newDimension); - } - sizeLabel.setText(null); - } else { - // wait for the size of image. - CoreGraphHelper.waitForImage(image); + @Override + public Dimension getPreferredSize() { + if (this.image == null) { + return super.getPreferredSize(); + } - imageWidth = image.getWidth(null); - imageHeight = image.getHeight(null); - int totalwidth = ImagePreviewPane.this.getWidth(); - int totalheight = ImagePreviewPane.this.getHeight(); - String text = imageWidth + "x" + imageHeight; - sizeLabel.setText(text); - FontMetrics cellFM = this.getFontMetrics(getFont()); - int width = cellFM.stringWidth(text); - sizeLabel.setBounds(totalwidth - width - LABEL_DELTA_X, totalheight - LABEL_DELTA_Y, width, LABEL_HEIGHT); - } - fireChangeListener(); - this.revalidate(); - } + return new Dimension(imageWidth, imageHeight); + } - /** - * Paint component. - */ + /** + * Add change listener. + */ + public void addChangeListener(ChangeListener changeListener) { + changeListenerList.add(changeListener); + } - public Dimension getPreferredSize() { - if (this.image == null) { - return super.getPreferredSize(); - } + /** + * fire change listener when image changed. + */ + private void fireChangeListener() { + if (this.changeListenerList.size() > 0) { + ChangeEvent evt = new ChangeEvent(this); - return new Dimension(imageWidth, imageHeight); - } + for (int i = 0; i < changeListenerList.size(); i++) { + changeListenerList.get(i).stateChanged(evt); + } + } + } - /** - * Add change listener. - */ - public void addChangeListener(ChangeListener changeListener) { - changeListenerList.add(changeListener); - } + // --- Scrollable methods --------------------------------------------- - /** - * fire change listener when image changed. - */ - private void fireChangeListener() { - if (this.changeListenerList.size() > 0) { - ChangeEvent evt = new ChangeEvent(this); + /** + * Returns the preferred size of the viewport for a view component. This is + * implemented to do the default behavior of returning the preferred size of + * the component. + * + * @return the preferredSize of a JViewport whose + * view is this Scrollable + */ + @Override + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } - for (int i = 0; i < changeListenerList.size(); i++) { - changeListenerList.get(i).stateChanged(evt); - } - } - } + /** + * Components that display logical rows or columns should compute the scroll + * increment that will completely expose one new row or column, depending on + * the value of orientation. Ideally, components should handle a partially + * exposed row or column by returning the distance required to completely + * expose the item. + *

+ * The default implementation of this is to simply return 10% of the visible + * area. Subclasses are likely to be able to provide a much more reasonable + * value. + * + * @param visibleRect the view area visible within the viewport + * @param orientation either SwingConstants.VERTICAL or + * SwingConstants.HORIZONTAL + * @param direction less than zero to scroll up/left, greater than zero for + * down/right + * @return the "unit" increment for scrolling in the specified direction + * @throws IllegalArgumentException for an invalid orientation + * @see javax.swing.JScrollBar#setUnitIncrement + */ + @Override + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { + switch (orientation) { + case SwingConstants.VERTICAL: + return visibleRect.height / INCRE_DELTA; + case SwingConstants.HORIZONTAL: + return visibleRect.width / INCRE_DELTA; + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } - // --- Scrollable methods --------------------------------------------- + /** + * Components that display logical rows or columns should compute the scroll + * increment that will completely expose one block of rows or columns, + * depending on the value of orientation. + *

+ * The default implementation of this is to simply return the visible area. + * Subclasses will likely be able to provide a much more reasonable value. + * + * @param visibleRect the view area visible within the viewport + * @param orientation either SwingConstants.VERTICAL or + * SwingConstants.HORIZONTAL + * @param direction less than zero to scroll up/left, greater than zero for + * down/right + * @return the "block" increment for scrolling in the specified direction + * @throws IllegalArgumentException for an invalid orientation + * @see javax.swing.JScrollBar#setBlockIncrement + */ + @Override + public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { + switch (orientation) { + case SwingConstants.VERTICAL: + return visibleRect.height; + case SwingConstants.HORIZONTAL: + return visibleRect.width; + default: + throw new IllegalArgumentException("Invalid orientation: " + orientation); + } + } - /** - * Returns the preferred size of the viewport for a view component. This is - * implemented to do the default behavior of returning the preferred size of - * the component. - * - * @return the preferredSize of a JViewport whose - * view is this Scrollable - */ - public Dimension getPreferredScrollableViewportSize() { - return getPreferredSize(); - } + /** + * Returns true if a viewport should always force the width of this + * Scrollable to match the width of the viewport. For example a + * normal text view that supported line wrapping would return true here, + * since it would be undesirable for wrapped lines to disappear beyond the + * right edge of the viewport. Note that returning true for a + * Scrollable whose ancestor is a JScrollPane + * effectively disables horizontal scrolling. + *

+ * Scrolling containers, like JViewport, will use this method + * each time they are validated. + * + * @return true if a viewport should force the Scrollables + * width to match its own + */ + @Override + public boolean getScrollableTracksViewportWidth() { + if (getParent() instanceof JViewport) { + return (getParent().getWidth() > getPreferredSize().width); + } + return false; + } - /** - * Components that display logical rows or columns should compute the scroll - * increment that will completely expose one new row or column, depending on - * the value of orientation. Ideally, components should handle a partially - * exposed row or column by returning the distance required to completely - * expose the item. - *

- * The default implementation of this is to simply return 10% of the visible - * area. Subclasses are likely to be able to provide a much more reasonable - * value. - * - * @param visibleRect - * the view area visible within the viewport - * @param orientation - * either SwingConstants.VERTICAL or - * SwingConstants.HORIZONTAL - * @param direction - * less than zero to scroll up/left, greater than zero for - * down/right - * @return the "unit" increment for scrolling in the specified direction - * @throws IllegalArgumentException - * for an invalid orientation - * @see javax.swing.JScrollBar#setUnitIncrement - */ - public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { - switch (orientation) { - case SwingConstants.VERTICAL: - return visibleRect.height / INCRE_DELTA; - case SwingConstants.HORIZONTAL: - return visibleRect.width / INCRE_DELTA; - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } + /** + * Returns true if a viewport should always force the height of this + * Scrollable to match the height of the viewport. For example + * a columnar text view that flowed text in left to right columns could + * effectively disable vertical scrolling by returning true here. + *

+ * Scrolling containers, like JViewport, will use this method + * each time they are validated. + * + * @return true if a viewport should force the Scrollables height to match + * its own + */ + @Override + public boolean getScrollableTracksViewportHeight() { + if (getParent() instanceof JViewport) { + return (getParent().getHeight() > getPreferredSize().height); + } + return false; + } - /** - * Components that display logical rows or columns should compute the scroll - * increment that will completely expose one block of rows or columns, - * depending on the value of orientation. - *

- * The default implementation of this is to simply return the visible area. - * Subclasses will likely be able to provide a much more reasonable value. - * - * @param visibleRect - * the view area visible within the viewport - * @param orientation - * either SwingConstants.VERTICAL or - * SwingConstants.HORIZONTAL - * @param direction - * less than zero to scroll up/left, greater than zero for - * down/right - * @return the "block" increment for scrolling in the specified direction - * @throws IllegalArgumentException - * for an invalid orientation - * @see javax.swing.JScrollBar#setBlockIncrement - */ - public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { - switch (orientation) { - case SwingConstants.VERTICAL: - return visibleRect.height; - case SwingConstants.HORIZONTAL: - return visibleRect.width; - default: - throw new IllegalArgumentException("Invalid orientation: " + orientation); - } - } + @Override + public void setImageStyle(Style imageStyle) { + this.imageStyle = imageStyle; + } - /** - * Returns true if a viewport should always force the width of this - * Scrollable to match the width of the viewport. For example a - * normal text view that supported line wrapping would return true here, - * since it would be undesirable for wrapped lines to disappear beyond the - * right edge of the viewport. Note that returning true for a - * Scrollable whose ancestor is a JScrollPane - * effectively disables horizontal scrolling. - *

- * Scrolling containers, like JViewport, will use this method - * each time they are validated. - * - * @return true if a viewport should force the Scrollables - * width to match its own - */ - public boolean getScrollableTracksViewportWidth() { - if (getParent() instanceof JViewport) { - return (getParent().getWidth() > getPreferredSize().width); - } - return false; - } + @Override + public void setImage(Image image) { - /** - * Returns true if a viewport should always force the height of this - * Scrollable to match the height of the viewport. For example - * a columnar text view that flowed text in left to right columns could - * effectively disable vertical scrolling by returning true here. - *

- * Scrolling containers, like JViewport, will use this method - * each time they are validated. - * - * @return true if a viewport should force the Scrollables height to match - * its own - */ - public boolean getScrollableTracksViewportHeight() { - if (getParent() instanceof JViewport) { - return (getParent().getHeight() > getPreferredSize().height); - } - return false; - } + setImageWithSuffix(image == null ? null : new ImageWithSuffix(image)); - public void setImageStyle(Style imageStyle) { - this.imageStyle = imageStyle; - } + } - public Style getImageStyle() { - return imageStyle; - } + public Style getImageStyle() { + return imageStyle; + } } \ No newline at end of file diff --git a/designer-base/src/com/fr/design/style/background/image/ExpandFileChooser.java b/designer-base/src/com/fr/design/style/background/image/ExpandFileChooser.java new file mode 100644 index 000000000..b9690b243 --- /dev/null +++ b/designer-base/src/com/fr/design/style/background/image/ExpandFileChooser.java @@ -0,0 +1,196 @@ +package com.fr.design.style.background.image; + +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.Inter; +import com.fr.stable.StringUtils; + +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JPanel; +import javax.swing.plaf.metal.MetalFileChooserUI; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.ActionListener; + +/** + * 扩展的文件选择框(底部控制区域扩展一个复选框) + * Created by zack on 2018/3/8. + */ +public class ExpandFileChooser extends JFileChooser { + private JDialog dialog; + private UICheckBox checkBox;//选择框底部的复选按钮 + private int retVal = ERROR_OPTION; + private UIButton approve; + private UIButton cancel; + private static final int DEFAULT_WIDTH = 520; + + public ExpandFileChooser() { + this(StringUtils.EMPTY, StringUtils.EMPTY); + } + + public ExpandFileChooser(String checkBoxText, String approveButtonText) { + JPanel previewContainerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); + MetalFileChooserUI chooserUI = (MetalFileChooserUI) getUI(); + String approveText = StringUtils.isEmpty(approveButtonText) ? chooserUI.getApproveButtonText(this) : approveButtonText; + dialog = new JDialog(); + + dialog.setSize(new Dimension(DEFAULT_WIDTH, 362)); + dialog.add(previewContainerPane); + dialog.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png")); + dialog.setTitle(approveText); + previewContainerPane.add(this, BorderLayout.CENTER); + + + JPanel bottomControlPanel = new JPanel(); + bottomControlPanel.setLayout(new ImageAreaLayout()); + bottomControlPanel.setPreferredSize(new Dimension(DEFAULT_WIDTH, 40)); + + approve = new UIButton(approveText); + cancel = new UIButton(Inter.getLocText("FR-Designer_Button-Cancel")); + if (StringUtils.isNotEmpty(checkBoxText)) { + checkBox = new UICheckBox(checkBoxText); + checkBox.setSelected(DesignerEnvManager.getEnvManager().isImageCompress()); + bottomControlPanel.add(checkBox); + checkBox.addActionListener(checkAction()); + } + bottomControlPanel.add(approve); + approve.addActionListener(chooserUI.getApproveSelectionAction()); + cancel.addActionListener(chooserUI.getCancelSelectionAction()); + bottomControlPanel.add(cancel); + previewContainerPane.add(bottomControlPanel, BorderLayout.SOUTH); + GUICoreUtils.centerWindow(dialog); + } + + public ActionListener checkAction() { + return null; + } + + public boolean isCheckSelected() { + if (checkBox != null) { + return checkBox.isSelected(); + } + return false; + } + + + @Override + public int showDialog(Component parent, String approveButtonText) { + dialog.setModal(true); + dialog.setVisible(true); + return retVal; + } + + @Override + public void approveSelection() { + retVal = APPROVE_OPTION; + if (dialog != null) { + dialog.setVisible(false); + } + fireActionPerformed(APPROVE_SELECTION); + } + + @Override + public void cancelSelection() { + retVal = CANCEL_OPTION; + if (dialog != null) { + dialog.setVisible(false); + } + fireActionPerformed(CANCEL_SELECTION); + } + + @Override + public boolean getControlButtonsAreShown() { + return false;//隐藏默认的控制按钮(打开/取消) + } + + private class ImageAreaLayout implements LayoutManager { + private static final int TEN = 10; + private int hGap = 5; + private int topMargin = TEN; + private int leftMargin = TEN; + private int leftStart = 8; + + @Override + public void addLayoutComponent(String string, Component comp) { + } + + @Override + public void layoutContainer(Container container) { + Component[] children = container.getComponents(); + + if (children != null && children.length > 0) { + int numChildren = children.length; + Dimension[] sizes = new Dimension[numChildren]; + Insets insets = container.getInsets(); + int yLocation = insets.top + topMargin; + int maxWidth = 0; + + for (int counter = 0; counter < numChildren; counter++) { + sizes[counter] = children[counter].getPreferredSize(); + maxWidth = Math.max(maxWidth, sizes[counter].width); + } + int xLocation, xOffset; + if (container.getComponentOrientation().isLeftToRight()) { + xLocation = container.getSize().width - insets.left - maxWidth - leftMargin; + xOffset = hGap + maxWidth; + } else { + xLocation = insets.left; + xOffset = -(hGap + maxWidth); + } + //单独设置图片压缩按钮的位置 + children[0].setBounds(leftStart, yLocation, + maxWidth, sizes[0].height); + + for (int counter = numChildren - 1; counter >= 1; counter--) { + children[counter].setBounds(xLocation, yLocation, + maxWidth, sizes[counter].height); + xLocation -= xOffset; + } + } + } + + @Override + public Dimension minimumLayoutSize(Container c) { + if (c != null) { + Component[] children = c.getComponents(); + + if (children != null && children.length > 0) { + int numChildren = children.length; + int height = 0; + Insets cInsets = c.getInsets(); + int extraHeight = topMargin + cInsets.top + cInsets.bottom; + int extraWidth = cInsets.left + cInsets.right; + int maxWidth = 0; + + for (int counter = 0; counter < numChildren; counter++) { + Dimension aSize = children[counter].getPreferredSize(); + height = Math.max(height, aSize.height); + maxWidth = Math.max(maxWidth, aSize.width); + } + return new Dimension(extraWidth + numChildren * maxWidth + + (numChildren - 1) * hGap, + extraHeight + height); + } + } + return new Dimension(0, 0); + } + + @Override + public Dimension preferredLayoutSize(Container c) { + return minimumLayoutSize(c); + } + + @Override + public void removeLayoutComponent(Component c) { + } + } +} diff --git a/designer-base/src/com/fr/design/style/background/image/ImageFileChooser.java b/designer-base/src/com/fr/design/style/background/image/ImageFileChooser.java index e5fbb3bad..10fb9a061 100644 --- a/designer-base/src/com/fr/design/style/background/image/ImageFileChooser.java +++ b/designer-base/src/com/fr/design/style/background/image/ImageFileChooser.java @@ -3,25 +3,27 @@ */ package com.fr.design.style.background.image; +import com.fr.base.BaseUtils; +import com.fr.design.DesignerEnvManager; +import com.fr.design.style.ChooseFileView; +import com.fr.general.Inter; + +import javax.swing.filechooser.FileFilter; import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.util.Enumeration; import java.util.Hashtable; -import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; - -import com.fr.base.BaseUtils; -import com.fr.general.Inter; -import com.fr.design.style.ChooseFileView; - /** * This class used to choose image files. */ -public class ImageFileChooser extends JFileChooser { +public class ImageFileChooser extends ExpandFileChooser { public ImageFileChooser() { + super(Inter.getLocText("FR-Designer_Image_Compress"),Inter.getLocText("FR-Designer_Open")); ExampleFileFilter bothFilter = new ExampleFileFilter( new String[]{"jpg", "gif", "png", "bmp"}, Inter.getLocText("Image-Image_Files")); @@ -43,12 +45,23 @@ public class ImageFileChooser extends JFileChooser { return super.showDialog(parent, approveButtonText); } + @Override + public ActionListener checkAction() { + return new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + DesignerEnvManager.getEnvManager().setImageCompress(isCheckSelected()); + DesignerEnvManager.getEnvManager().saveXMLFile(); + } + }; + + } /** * A convenience implementation of FileFilter that filters out * all files except for those type extensions that it knows about. *

D:\finereport\develop\code\test\TestCase\WEB-INF\reportlets\TestCase\01903.cpt - + *

* Extensions are of the type ".foo", which is typically found on * Windows and Unix boxes, but not on Macinthosh. Case is ignored. *

diff --git a/designer-base/src/com/fr/design/style/background/image/ImagePreviewPane.java b/designer-base/src/com/fr/design/style/background/image/ImagePreviewPane.java index 35c5a5d3f..296686f24 100644 --- a/designer-base/src/com/fr/design/style/background/image/ImagePreviewPane.java +++ b/designer-base/src/com/fr/design/style/background/image/ImagePreviewPane.java @@ -3,12 +3,13 @@ */ package com.fr.design.style.background.image; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Image; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; +import com.fr.base.BaseUtils; +import com.fr.base.GraphHelper; +import com.fr.base.Style; +import com.fr.design.gui.iscrollbar.UIScrollBar; +import com.fr.general.ImageWithSuffix; +import com.fr.general.Inter; +import com.fr.stable.CoreGraphHelper; import javax.swing.JComponent; import javax.swing.JViewport; @@ -16,46 +17,67 @@ import javax.swing.Scrollable; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; - -import com.fr.base.BaseUtils; -import com.fr.base.GraphHelper; -import com.fr.base.Style; -import com.fr.design.gui.iscrollbar.UIScrollBar; -import com.fr.stable.CoreGraphHelper; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; /** * The pane use to preview image */ -public class ImagePreviewPane extends JComponent implements Scrollable { - private Image image = null; +public class ImagePreviewPane extends JComponent implements Scrollable, ImagePreviewer { + private ImageWithSuffix image = null; // carl:image style private Style imageStyle = null; - private int imageWidth = 0 ; - private int imageHeight = 0 ; + private int imageWidth = 0; + private int imageHeight = 0; + private boolean isLoading = false; private List changeListenerList = new ArrayList(); public ImagePreviewPane() { - this.setToolTipText("View Image"); + this.setToolTipText("View Image"); } /** * Return image */ public Image getImage() { + return image == null ? null : image.getImage(); + } + /** + * Return image + */ + public ImageWithSuffix getImageWithSuffix() { return this.image; } + public void showLoading() { + isLoading = true; + setImage(null); + repaint(); + } + + @Override + public void setImage(Image image) { + + setImageWithSuffix(image == null ? null : new ImageWithSuffix(image)); + + } + /** * Set image. * * @param image the new image. */ - public void setImage(Image image) { + @Override + public void setImageWithSuffix(ImageWithSuffix image) { this.image = image; //need to reset the size of JViewPort. if (this.image == null) { - if(this.getParent() instanceof JViewport) { + if (this.getParent() instanceof JViewport) { UIScrollBar tmpJScrollBar = new UIScrollBar(UIScrollBar.HORIZONTAL); Dimension newDimension = new Dimension( this.getSize().width - tmpJScrollBar.getPreferredSize().height, @@ -67,6 +89,7 @@ public class ImagePreviewPane extends JComponent implements Scrollable { } } else { //wait for the size of image. + isLoading = false; CoreGraphHelper.waitForImage(image); imageWidth = image.getWidth(null); @@ -81,25 +104,29 @@ public class ImagePreviewPane extends JComponent implements Scrollable { /** * Paint component. */ + @Override public void paintComponent(Graphics g) { super.paintComponent(g); - - //draw image. - if (this.getImage() != null) { - // carl:让imagePreviewPane能预览样式 - if (this.getImageStyle() == null) { - g.drawImage(this.getImage(), 0, 0, this); - } else { - GraphHelper.paintImage( - g, this.getWidth(), this.getHeight(), this.getImage(), - this.getImageStyle().getImageLayout(), - BaseUtils.getAlignment4Horizontal(this.getImageStyle()), - this.getImageStyle().getVerticalAlignment(), -1, -1 - ); - } + if (isLoading) { + g.drawString(Inter.getLocText("FR-Designer_Image_Loading"), getWidth() / 2 - 25, getHeight() / 2); + return; + } + if (this.getImage() != null) { //draw image. + // carl:让imagePreviewPane能预览样式 + if (this.getImageStyle() == null) { + g.drawImage(this.getImage(), 0, 0, this); + } else { + GraphHelper.paintImage( + g, this.getWidth(), this.getHeight(), this.getImage(), + this.getImageStyle().getImageLayout(), + BaseUtils.getAlignment4Horizontal(this.getImageStyle()), + this.getImageStyle().getVerticalAlignment(), -1, -1 + ); + } } } + @Override public Dimension getPreferredSize() { if (this.image == null) { return super.getPreferredSize(); @@ -123,7 +150,7 @@ public class ImagePreviewPane extends JComponent implements Scrollable { ChangeEvent evt = new ChangeEvent(this); for (int i = 0; i < changeListenerList.size(); i++) { - changeListenerList.get(i).stateChanged(evt); + changeListenerList.get(i).stateChanged(evt); } } } @@ -136,8 +163,9 @@ public class ImagePreviewPane extends JComponent implements Scrollable { * the preferred size of the component. * * @return the preferredSize of a JViewport - * whose view is this Scrollable + * whose view is this Scrollable */ + @Override public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } @@ -192,6 +220,7 @@ public class ImagePreviewPane extends JComponent implements Scrollable { * @throws IllegalArgumentException for an invalid orientation * @see javax.swing.JScrollBar#setBlockIncrement */ + @Override public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { switch (orientation) { case SwingConstants.VERTICAL: @@ -218,8 +247,9 @@ public class ImagePreviewPane extends JComponent implements Scrollable { * will use this method each time they are validated. * * @return true if a viewport should force the Scrollables - * width to match its own + * width to match its own */ + @Override public boolean getScrollableTracksViewportWidth() { if (getParent() instanceof JViewport) { return (getParent().getWidth() > getPreferredSize().width); @@ -238,8 +268,9 @@ public class ImagePreviewPane extends JComponent implements Scrollable { * will use this method each time they are validated. * * @return true if a viewport should force the Scrollables height - * to match its own + * to match its own */ + @Override public boolean getScrollableTracksViewportHeight() { if (getParent() instanceof JViewport) { return (getParent().getHeight() > getPreferredSize().height); @@ -247,11 +278,12 @@ public class ImagePreviewPane extends JComponent implements Scrollable { return false; } - public void setImageStyle(Style imageStyle) { - this.imageStyle = imageStyle; - } + @Override + public void setImageStyle(Style imageStyle) { + this.imageStyle = imageStyle; + } - public Style getImageStyle() { - return imageStyle; - } + public Style getImageStyle() { + return imageStyle; + } } \ No newline at end of file diff --git a/designer-base/src/com/fr/design/style/background/image/ImagePreviewer.java b/designer-base/src/com/fr/design/style/background/image/ImagePreviewer.java new file mode 100644 index 000000000..58fe65bcf --- /dev/null +++ b/designer-base/src/com/fr/design/style/background/image/ImagePreviewer.java @@ -0,0 +1,40 @@ +package com.fr.design.style.background.image; + +import com.fr.base.Style; +import com.fr.general.ImageWithSuffix; + +import java.awt.Image; + +/** + * 图片预览接口(由于子类上层父类差别较大,无奈的接口) + * Created by zack on 2018/3/10. + */ +public interface ImagePreviewer { + /** + * 设置图片样式(平铺,拉伸) + * @param style 样式 + */ + void setImageStyle(Style style); + + /** + * 设置图片 + * @param image 图片 + */ + void setImage(Image image); + + /** + * 设置图片(带格式) + * @param image 图片 + */ + void setImageWithSuffix(ImageWithSuffix image); + + /** + * 显示正在加载 + */ + void showLoading(); + + /** + * 重绘 + */ + void repaint(); +} diff --git a/designer-base/src/com/fr/design/style/background/image/ImageSelectPane.java b/designer-base/src/com/fr/design/style/background/image/ImageSelectPane.java index 7c2def75b..77c4c9bb8 100644 --- a/designer-base/src/com/fr/design/style/background/image/ImageSelectPane.java +++ b/designer-base/src/com/fr/design/style/background/image/ImageSelectPane.java @@ -1,9 +1,9 @@ package com.fr.design.style.background.image; -import com.fr.base.BaseUtils; import com.fr.base.background.ImageFileBackground; import com.fr.base.frpx.pack.PictureCollection; import com.fr.base.frpx.util.ImageIOHelper; +import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; @@ -13,7 +13,6 @@ import com.fr.design.style.background.BackgroundPane4BoxChange; import com.fr.general.Background; import com.fr.general.Inter; import com.fr.stable.Constants; -import com.fr.stable.CoreGraphHelper; import javax.swing.JFileChooser; import javax.swing.JPanel; @@ -100,20 +99,13 @@ public class ImageSelectPane extends BackgroundPane4BoxChange { } ActionListener selectPictureActionListener = new ActionListener() { - - @Override public void actionPerformed(ActionEvent evt) { int returnVal = imageFileChooser.showOpenDialog(ImageSelectPane.this); if (returnVal != JFileChooser.CANCEL_OPTION) { File selectedFile = imageFileChooser.getSelectedFile(); - if (selectedFile != null && selectedFile.isFile()) { - String path = selectedFile.getPath(); - suffix = ImageIOHelper.getSuffix(path); - Image image = BaseUtils.readImage(path); - CoreGraphHelper.waitForImage(image); - selectImage = image; - } - chechLabelText(); + String path = selectedFile.getPath(); + suffix = ImageIOHelper.getSuffix(path); + ImgChooseWrapper.getInstance(selectImage, imageSizeLabel, imageFileChooser).dealWithImageFile(returnVal); } } }; diff --git a/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane.java b/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane.java index c9643a6a3..cd35373bf 100644 --- a/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane.java +++ b/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane.java @@ -1,10 +1,8 @@ package com.fr.design.style.background.impl; -import com.fr.base.BaseUtils; import com.fr.base.Style; -import com.fr.base.background.ImageFileBackground; -import com.fr.base.frpx.pack.PictureCollection; -import com.fr.base.frpx.util.ImageIOHelper; +import com.fr.base.background.ImageBackground; +import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.ilable.UILabel; @@ -15,11 +13,9 @@ import com.fr.design.style.background.image.ImagePreviewPane; import com.fr.general.Background; import com.fr.general.Inter; import com.fr.stable.Constants; -import com.fr.stable.CoreGraphHelper; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; -import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.ChangeEvent; @@ -29,7 +25,6 @@ import java.awt.GridLayout; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.File; /** * Image background pane. @@ -47,8 +42,6 @@ public class ImageBackgroundPane extends BackgroundDetailPane { private UIRadioButton extendRadioButton = null; private UIRadioButton adjustRadioButton = null; - private String suffix = PictureCollection.DEFAULT_SUFFIX; - public ImageBackgroundPane() { this.setLayout(FRGUIPaneFactory.createBorderLayout()); @@ -124,36 +117,14 @@ public class ImageBackgroundPane extends BackgroundDetailPane { */ ActionListener selectPictureActionListener = new ActionListener() { - @Override public void actionPerformed(ActionEvent evt) { int returnVal = imageFileChooser.showOpenDialog(ImageBackgroundPane.this); - if (returnVal != JFileChooser.CANCEL_OPTION) { - File selectedFile = imageFileChooser.getSelectedFile(); - - if (selectedFile != null && selectedFile.isFile()) { - String path = selectedFile.getPath(); - suffix = ImageIOHelper.getSuffix(path); - Image image = BaseUtils.readImage(path); - CoreGraphHelper.waitForImage(image); - - previewPane.setImage(image); - imageStyleRepaint(); - previewPane.repaint(); - } else { - previewPane.setImage(null); - } - } - - fireChagneListener(); + setImageStyle(); + ImgChooseWrapper.getInstance(previewPane, imageFileChooser, imageStyle, changeListener).dealWithImageFile(returnVal); } }; - public void imageStyleRepaint() { - setImageStyle(); - previewPane.setImageStyle(imageStyle); - } - - private void setImageStyle() { + protected void setImageStyle() { if (tiledRadioButton.isSelected()) { imageStyle = Style.DEFAULT_STYLE.deriveImageLayout(Constants.IMAGE_TILED); } else if (adjustRadioButton.isSelected()) { @@ -182,9 +153,8 @@ public class ImageBackgroundPane extends BackgroundDetailPane { @Override public void populate(Background background) { - if (background instanceof ImageFileBackground) { - ImageFileBackground imageBackground = (ImageFileBackground) background; - suffix = imageBackground.getSuffix(); + if (background instanceof ImageBackground) { + ImageBackground imageBackground = (ImageBackground) background; if (imageBackground.getLayout() == Constants.IMAGE_CENTER) { defaultRadioButton.setSelected(true); @@ -202,7 +172,7 @@ public class ImageBackgroundPane extends BackgroundDetailPane { previewPane.setImageStyle(ImageBackgroundPane.this.imageStyle); if (imageBackground.getImage() != null) { - previewPane.setImage(imageBackground.getImage()); + previewPane.setImageWithSuffix(imageBackground.getImageWithSuffix()); imageSizeLabel.setText(previewPane.getImage().getWidth(null) + " X " + previewPane.getImage().getHeight(null)); } @@ -222,7 +192,7 @@ public class ImageBackgroundPane extends BackgroundDetailPane { @Override public Background update() throws Exception { - ImageFileBackground imageBackground = new ImageFileBackground(previewPane.getImage(), suffix); + ImageBackground imageBackground = new ImageBackground(previewPane.getImageWithSuffix()); setImageStyle(); imageBackground.setLayout(imageStyle.getImageLayout()); return imageBackground; @@ -253,12 +223,4 @@ public class ImageBackgroundPane extends BackgroundDetailPane { } } }; - - public String getSuffix() { - return suffix; - } - - public void setSuffix(String suffix) { - this.suffix = suffix; - } } diff --git a/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane4Browser.java b/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane4Browser.java index 431ad2c0d..537d03e57 100644 --- a/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane4Browser.java +++ b/designer-base/src/com/fr/design/style/background/impl/ImageBackgroundPane4Browser.java @@ -1,10 +1,5 @@ package com.fr.design.style.background.impl; -import com.fr.design.gui.ibutton.UIRadioButton; -import com.fr.stable.ArrayUtils; - -import javax.swing.*; - /** * Created by richie on 16/5/18. */ @@ -15,12 +10,4 @@ public class ImageBackgroundPane4Browser extends ImageBackgroundPane { super(); } - @Override - protected UIRadioButton[] imageLayoutButtons() { - - return (UIRadioButton[]) ArrayUtils.addAll(super.imageLayoutButtons(), new UIRadioButton[] { - defaultRadioButton, - tiledRadioButton, - }); - } } diff --git a/designer-base/src/com/fr/design/style/background/impl/ImageButtonBackgroundPane.java b/designer-base/src/com/fr/design/style/background/impl/ImageButtonBackgroundPane.java index 1464a4e9f..3e8540a3c 100644 --- a/designer-base/src/com/fr/design/style/background/impl/ImageButtonBackgroundPane.java +++ b/designer-base/src/com/fr/design/style/background/impl/ImageButtonBackgroundPane.java @@ -1,15 +1,16 @@ package com.fr.design.style.background.impl; import com.fr.base.Style; -import com.fr.base.background.ImageFileBackground; -import com.fr.base.frpx.pack.PictureCollection; +import com.fr.base.background.ImageBackground; import com.fr.design.gui.ibutton.UIButton; import com.fr.general.Background; import com.fr.general.Inter; import com.fr.stable.Constants; -import javax.swing.*; -import java.awt.*; +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.SwingConstants; +import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -55,24 +56,21 @@ public class ImageButtonBackgroundPane extends ImageBackgroundPane { public void actionPerformed(ActionEvent e) { previewPane.setImage(null); previewPane.repaint(); - setSuffix(PictureCollection.DEFAULT_SUFFIX); } }); } @Override - public void imageStyleRepaint() { - + public void setImageStyle() { } @Override public void populate(Background background) { - if (background instanceof ImageFileBackground) { - ImageFileBackground imageBackground = (ImageFileBackground) background; - setSuffix(imageBackground.getSuffix()); + if (background != null && background instanceof ImageBackground) { + ImageBackground imageBackground = (ImageBackground) background; if (imageBackground.getImage() != null) { - previewPane.setImage(imageBackground.getImage()); + previewPane.setImageWithSuffix(imageBackground.getImageWithSuffix()); } } @@ -83,6 +81,6 @@ public class ImageButtonBackgroundPane extends ImageBackgroundPane { if (previewPane.getImage() == null) { return null; } - return new ImageFileBackground(previewPane.getImage(), getSuffix()); + return new ImageBackground(previewPane.getImageWithSuffix()); } } diff --git a/designer-base/src/com/fr/design/utils/ImageUtils.java b/designer-base/src/com/fr/design/utils/ImageUtils.java new file mode 100644 index 000000000..33f928a46 --- /dev/null +++ b/designer-base/src/com/fr/design/utils/ImageUtils.java @@ -0,0 +1,285 @@ +package com.fr.design.utils; + +import com.fr.base.BaseUtils; +import com.fr.general.ComparatorUtils; +import com.fr.general.FRLogger; +import com.fr.general.ImageWithSuffix; +import com.fr.stable.CoreGraphHelper; +import com.fr.stable.StringUtils; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageReader; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.ImageInputStream; +import javax.imageio.stream.ImageOutputStream; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.Iterator; + +/** + * 设计器部分的图片处理工具类 + * Created by zack on 2018/3/8. + */ +public class ImageUtils { + public static final String TYPE_JPEG = "JPEG"; + public static final String TYPE_PNG = "png"; + + /** + * 默认压缩算法,采用75%质量压缩,带透明度的png默认使用缩放的方式实现压缩尺寸压缩50%,大小大约为1/4 + * + * @param imageFile 原文件 + * @return 压缩后的BufferedImage对象 + */ + public static Image defaultImageCompress(File imageFile) { + if (imageFile == null || !imageFile.exists()) { + return null; + } + try { + BufferedImage srcImg = BaseUtils.readImage(imageFile.getPath()); + if (canbeCompressedToJPEG(imageFile)) { + return jpegCompress(srcImg, 0.75f); + } else if (isPNGType(imageFile)) { + //带透明度的采用缩放的方式 + return scale(srcImg, 0.5f, true); + } + } catch (IOException e) { + FRLogger.getLogger().info("image compress failed!"); + + } + return BaseUtils.readImage(imageFile.getPath()); + } + + /** + * 默认压缩算法,返回带格式的image + * + * @param imageFile 原文件 + * @return 压缩后的BufferedImage对象 + */ + public static ImageWithSuffix defaultImageCompWithSuff(File imageFile) { + if (imageFile == null || !imageFile.exists()) { + return null; + } + BufferedImage srcImg = BaseUtils.readImage(imageFile.getPath()); + Image desImg = srcImg; + try { + + if (canbeCompressedToJPEG(imageFile)) { + return new ImageWithSuffix(jpegCompress(srcImg, 0.75f), TYPE_JPEG); + } else if (isPNGType(imageFile)) { + //带透明度的采用缩放的方式 + desImg = scale(srcImg, 0.5f, true); + } + } catch (IOException e) { + FRLogger.getLogger().info("image compress failed!"); + + } + return new ImageWithSuffix(desImg, TYPE_PNG); + } + + public static boolean canbeCompressedToJPEG(File imageFile) { + String imageType = getImageType(imageFile); + if (ComparatorUtils.equals(imageType, TYPE_JPEG)) {//JPEG大写 + return true; + } + if (ComparatorUtils.equals(imageType, TYPE_PNG)) {//png小写 + return !isAlphaAreaOverload(imageFile);//少量透明度系数的png直接压缩jpg + } + return false; + } + + /** + * 判断图片是否是png类型 + * + * @param imageFile + * @return + */ + public static boolean isPNGType(File imageFile) { + if (ComparatorUtils.equals(getImageType(imageFile), TYPE_PNG)) { + return true; + } + return false; + } + + /** + * JPEG格式图片压缩 + * + * @param image 压缩源图片 + * @param quality 压缩质量,在0-1之间, + * @return 返回的字节数组 + */ + public static BufferedImage jpegCompress(BufferedImage image, float quality) throws IOException { + if (image == null) { + return null; + } + // 得到指定Format图片的writer + Iterator iter = ImageIO + .getImageWritersByFormatName("jpeg");// 得到迭代器 + ImageWriter writer = iter.next(); + + // 得到指定writer的输出参数设置(ImageWriteParam ) + ImageWriteParam iwp = writer.getDefaultWriteParam(); + iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // 设置可否压缩 + iwp.setCompressionQuality(quality); // 设置压缩质量参数 + iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED); + + // 开始打包图片,写入byte[] + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ImageOutputStream ios = null; + ByteArrayInputStream in = null; + try { + image = copy(image, BufferedImage.TYPE_INT_RGB); + ios = ImageIO.createImageOutputStream(byteArrayOutputStream); + writer.setOutput(ios); + writer.write(null, new IIOImage(image, null, null), iwp); + in = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + if (ios == null || in == null) { + throw new IOException("The image file cannot be compressed"); + } + return ImageIO.read(in); + } finally { + writer.dispose(); + byteArrayOutputStream.close(); + if (ios != null) { + ios.close(); + } + if (in != null) { + in.close(); + } + } + } + + /** + * 判断图片中是否包含多于5%的透明区域,这个5%随便定的 + * + * @param imageFile 目标图片 + * @return 含透明度像素占比 + */ + public static boolean isAlphaAreaOverload(File imageFile) { + if (imageFile == null || !imageFile.isFile()) { + return false; + } + BufferedImage bufferedImage = BaseUtils.readImage(imageFile.getPath()); + int width = bufferedImage.getWidth(); + int height = bufferedImage.getHeight(); + long alphaCount = 0; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + int rgb = bufferedImage.getRGB(i, j); + int a = (0xff & (rgb >> 24)); + if (a != 0xff) { + alphaCount++; + } + } + } + return alphaCount / (double) (width * height) > 0.05; + } + + /** + * 获取图片类型 + * + * @param imageFile 图片文件 + * @return 图片类型(JPEG, PNG, GIF) + */ + public static String getImageType(File imageFile) { + try { + ImageInputStream iis = ImageIO.createImageInputStream(imageFile); + Iterator iter = ImageIO.getImageReaders(iis); + if (!iter.hasNext()) { + return StringUtils.EMPTY; + } + ImageReader reader = iter.next(); + iis.close(); + return reader.getFormatName(); + } catch (IOException ignore) { + } + return StringUtils.EMPTY; + } + + private static BufferedImage copy(BufferedImage img, int imageType) { + int width = img.getWidth(); + int height = img.getHeight(); + + BufferedImage newImage = CoreGraphHelper.createBufferedImage(width, height, imageType); + Graphics g = newImage.createGraphics(); + + g.drawImage(img, 0, 0, null); + + g.dispose(); + + return newImage; + } + + /** + * 缩放图像(按比例缩放) + * + * @param srcImg 源图像来源流 + * @param scale 缩放比例。比例大于1时为放大,小于1大于0为缩小 + * @param opacityCompatible 是否处理背景透明 + */ + public static Image scale(BufferedImage srcImg, float scale, boolean opacityCompatible) { + if (scale < 0) { + // 自动修正负数 + scale = -scale; + } + + int width = mul(Integer.toString(srcImg.getWidth(null)), Float.toString(scale)).intValue(); // 得到源图宽 + int height = mul(Integer.toString(srcImg.getHeight(null)), Float.toString(scale)).intValue(); // 得到源图长 + return scale(srcImg, width, height, opacityCompatible); + } + + private static BigDecimal mul(String v1, String v2) { + return mul(new BigDecimal(v1), new BigDecimal(v2)); + } + + private static BigDecimal mul(BigDecimal v1, BigDecimal v2) { + return v1.multiply(v2); + } + + /** + * 缩放图像(按长宽缩放) + * 目标长宽与原图不成比例会变形 + * + * @param srcImg 源图像来源流 + * @param width 目标宽度 + * @param height 目标高度 + * @param opacityCompatible 是否处理背景透明 + * @return {@link Image} + */ + private static Image scale(BufferedImage srcImg, int width, int height, boolean opacityCompatible) { + int srcHeight = srcImg.getHeight(null); + int srcWidth = srcImg.getWidth(null); + int scaleType; + if (srcHeight == height && srcWidth == width) { + // 源与目标长宽一致返回原图 + return srcImg; + } else if (srcHeight < height || srcWidth < width) { + // 放大图片使用平滑模式 + scaleType = Image.SCALE_SMOOTH; + } else { + scaleType = Image.SCALE_DEFAULT; + } + if (opacityCompatible) {//需要保留透明度背景 + BufferedImage toImg = CoreGraphHelper.createBufferedImage(width, height, srcImg.getType()); + Graphics2D g2d = toImg.createGraphics(); + toImg = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); + g2d.dispose(); + + g2d = toImg.createGraphics(); + Image from = srcImg.getScaledInstance(width, height, scaleType); + g2d.drawImage(from, 0, 0, null); + g2d.dispose(); + return toImg; + } + return srcImg.getScaledInstance(width, height, scaleType); + } +} diff --git a/designer-realize/src/com/fr/design/headerfooter/ImagePane.java b/designer-realize/src/com/fr/design/headerfooter/ImagePane.java index b018c2d57..2ccdc10fa 100644 --- a/designer-realize/src/com/fr/design/headerfooter/ImagePane.java +++ b/designer-realize/src/com/fr/design/headerfooter/ImagePane.java @@ -3,25 +3,22 @@ */ package com.fr.design.headerfooter; -import java.awt.BorderLayout; -import java.awt.Image; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.JFileChooser; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -import com.fr.base.BaseUtils; +import com.fr.design.dialog.BasicPane; +import com.fr.design.gui.frpane.ImgChooseWrapper; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.layout.FRGUIPaneFactory; -import com.fr.design.dialog.BasicPane; -import com.fr.general.Inter; -import com.fr.stable.CoreGraphHelper; import com.fr.design.style.background.image.ImageFileChooser; import com.fr.design.style.background.image.ImagePreviewPane; +import com.fr.general.Inter; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SwingWorker; +import java.awt.BorderLayout; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; /** * Image Pane. @@ -67,17 +64,17 @@ public class ImagePane extends BasicPane { imageFileChooser = new ImageFileChooser(); imageFileChooser.setMultiSelectionEnabled(false); } - + @Override protected String title4PopupWindow() { - return "image"; + return "image"; } public void populate(Image image) { - if(image == null) { - return; - } - + if(image == null) { + return; + } + this.imagePreviewPane.setImage(image); } @@ -91,19 +88,7 @@ public class ImagePane extends BasicPane { ActionListener selectPictureActionListener = new ActionListener() { public void actionPerformed(ActionEvent evt) { int returnVal = imageFileChooser.showOpenDialog(ImagePane.this); - if (returnVal != JFileChooser.CANCEL_OPTION) { - File selectedFile = imageFileChooser.getSelectedFile(); - - if (selectedFile != null && selectedFile.isFile()) { - Image image = BaseUtils.readImage(selectedFile.getPath()); - CoreGraphHelper.waitForImage(image); - - imagePreviewPane.setImage(image); - } else { - imagePreviewPane.setImage(null); - } - imagePreviewPane.repaint(); - } + ImgChooseWrapper.getInstance(imagePreviewPane, imageFileChooser, null).dealWithImageFile(returnVal); } }; } \ No newline at end of file