diff --git a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java index 67b369a6c..3508b3519 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/predefined/ui/PredefinedStyleBlock.java @@ -32,7 +32,7 @@ import java.awt.event.MouseListener; public class PredefinedStyleBlock extends JPanel { private PredefinedStyle previewObject; private PredefinedStyleSelectPane parentPane; - private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marked.png"); + private Icon markedMode = IOUtils.readIcon("/com/fr/design/form/images/marker_selected.png"); private static final Color BORDER_COLOR = new Color(141, 194, 249); private boolean mouseOver = false; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java index 13769cfc6..53de406af 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/ui/LabelUtils.java @@ -37,7 +37,7 @@ public class LabelUtils { Font newFont = FRFont.getInstance(tipLabel.getFont().getFontName(), Font.PLAIN, 12); tipLabel.setFont(newFont); tipLabel.setBorder(BorderFactory.createEmptyBorder()); - tipLabel.setEnabled(false); + tipLabel.setEditable(false); tipLabel.setText(title); tipLabel.setLineWrap(true); tipLabel.setWrapStyleWord(true); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java b/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java index 6cb00b6ff..03e8ab2c0 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/action/InstallComponentAction.java @@ -76,6 +76,7 @@ public class InstallComponentAction extends UpdateAction { try { InstallBackInfo info = get(); LocalWidgetRepoPane.getInstance().refreshAllGroupPane(); + LocalWidgetRepoPane.getInstance().doFetchAndCheckUpdate(); showMessageDialog(info); } catch (InterruptedException | ExecutionException e) { FineLoggerFactory.getLogger().error(e, e.getMessage()); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java index 4b48126d0..6839ee41f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java @@ -11,11 +11,11 @@ import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.WidgetToolBarPane; -import com.fr.design.mainframe.share.collect.ComponentCollector; import com.fr.design.mainframe.share.group.ui.GroupMoveDialog; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupAction; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupMenu; import com.fr.design.mainframe.share.ui.constants.ColorConstants; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.local.LocalWidgetSelectPane; import com.fr.design.mainframe.share.ui.local.WidgetSelectedManager; @@ -23,31 +23,42 @@ import com.fr.design.mainframe.share.util.ShareComponentUtils; import com.fr.design.mainframe.share.util.ShareUIUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.form.share.DefaultSharableWidget; +import com.fr.form.share.Group; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.constants.ShareComponentConstants; -import com.fr.form.share.Group; import com.fr.form.share.record.ShareWidgetInfoManager; import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; +import com.fr.general.FRFont; import com.fr.general.IOUtils; import com.fr.stable.Constants; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; + import javax.swing.Action; import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.JPopupMenu; +import java.awt.AlphaComposite; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Composite; import java.awt.Cursor; import java.awt.Dimension; +import java.awt.Font; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Image; import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Stroke; import java.awt.dnd.DnDConstants; import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; +import java.awt.font.FontRenderContext; +import java.awt.geom.Dimension2D; +import java.awt.image.BufferedImage; import java.util.UUID; /** @@ -65,13 +76,20 @@ public class LocalWidgetBlock extends PreviewWidgetBlock private boolean isMarked; private boolean pressed; - private final Icon markedMode = IOUtils.readIcon("/com/fr/base/images/share/marked.png"); - private final Icon unMarkedMode = IOUtils.readIcon("/com/fr/base/images/share/unmarked.png"); + private final Color COVER_COLOR = Color.decode("#333334"); + private final BufferedImage WIDGET_DOWNLOADING_ICON = IOUtils.readImage("/com/fr/base/images/share/downloading.png"); + private final BufferedImage WIDGET_UPDATABLE_ICON = IOUtils.readImage("/com/fr/base/images/share/updatable.png"); + private final Icon selectedMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_selected.png"); + private final Icon unselectedMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_unselected.png"); + private final Icon incompatibleMarker = IOUtils.readIcon("/com/fr/base/images/share/marker_incompatible.png"); + + private final LocalWidgetUpdater updater; public LocalWidgetBlock(DefaultSharableWidget provider, LocalWidgetSelectPane parentPane) { super(provider); this.parentPane = parentPane; new DragAndDropDragGestureListener(this, DnDConstants.ACTION_COPY_OR_MOVE); + updater = new LocalWidgetUpdater(this); initUI(); } @@ -103,6 +121,10 @@ public class LocalWidgetBlock extends PreviewWidgetBlock return this.getWidget(); } + public LocalWidgetUpdater getUpdater() { + return updater; + } + @Override protected void showPreview(DefaultSharableWidget widget) { this.parentPane.showPreviewPane(this, widget.getId()); @@ -192,11 +214,21 @@ public class LocalWidgetBlock extends PreviewWidgetBlock hidePreview(); Object source = e.getSource(); if (source instanceof LocalWidgetBlock) { - LocalWidgetBlock no = (LocalWidgetBlock) e.getSource(); - if (no == null) { + LocalWidgetBlock widgetBlock = (LocalWidgetBlock) e.getSource(); + if (widgetBlock == null) { + return; + } + SharableWidgetProvider widget = widgetBlock.getWidget(); + if (widget == null) { return; } - XCreator xCreator = transformXCreator(no); + if (!widget.isCompatibleWithCurrentEnv()) { + FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Share_Drag_And_Make_Incompatible_Component_Tip") + ); + return; + } + XCreator xCreator = transformXCreator(widgetBlock); if (xCreator == null) { return; } @@ -224,20 +256,121 @@ public class LocalWidgetBlock extends PreviewWidgetBlock @Override public void paint(Graphics g) { super.paint(g); + Graphics2D g2d = (Graphics2D) g; + + boolean isUnusable = !getWidget().isCompatibleWithCurrentEnv(); + if (isUnusable) { + paintUnusableMask(g2d); + } + //绘制删除标志 if (isEdit) { - Icon icon = isMarked ? markedMode : unMarkedMode; - icon.paintIcon(this, g, MARK_START_X, 0); + paintEditingMarker(g2d); } - if (ComparatorUtils.equals(this, this.parentPane.getSelectedBlock()) || this.mouseHover) { - g.setColor(XCreatorConstants.FORM_BORDER_COLOR); - Rectangle rectangle = new Rectangle(); - rectangle.width = this.getWidth(); - rectangle.height = this.getHeight(); - GraphHelper.draw(g, rectangle, Constants.LINE_LARGE); + + boolean ishHighlighting = ComparatorUtils.equals(this, this.parentPane.getSelectedBlock()) || this.mouseHover; + if (ishHighlighting) { + paintHighlightBorder(g2d); + } + + if (getUpdater().isUpdating()) { + paintLoadingIndicator(g2d, getUpdater().getProcessValue()); + } else if (LocalWidgetRepoUpdater.getInstance().checkUpdate(getWidget()) != null) { + paintUpdatableMarker(g2d); } } + protected void paintUnusableMask(Graphics2D g2d) { + Color oldColor = g2d.getColor(); + Font oldFont = g2d.getFont(); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + Dimension coverDim = getCoverDimension(); + double canvasX = 0; + double canvasY = 0; + double canvasW = coverDim.getWidth(); + double canvasH = coverDim.getHeight(); + + g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.4F)); + GraphHelper.fillRect(g2d, canvasX, canvasY, canvasW, canvasH - 16); + + g2d.setColor(new Color(0.0F, 0.0F, 0.0F, 0.5F)); + GraphHelper.fillRect(g2d, canvasX, canvasH - 16, canvasW, 16); + + String tipText = Toolkit.i18nText("Fine-Design_Share_Incompatible_Version_Tip"); + Font tipFont = FRFont.getInstance().deriveFont(8F); + FontRenderContext frc = g2d.getFontRenderContext(); + double tipTextWidth = GraphHelper.stringWidth(tipText, tipFont, frc); + Dimension2D dim = GraphHelper.stringDimensionWithRotation(tipText, tipFont, 0, frc); + double tipTextHeight = dim.getHeight(); + g2d.setColor(Color.WHITE); + g2d.setFont(tipFont); + GraphHelper.drawString(g2d, tipText, canvasX + (canvasW - tipTextWidth) / 2.0F, canvasY + canvasH - (16 - tipTextHeight) / 2.0F); + + int markerX = (int) (canvasX + (canvasW - incompatibleMarker.getIconWidth()) / 2); + int markerY = (int) (canvasY + (canvasH - incompatibleMarker.getIconHeight()) / 2); + incompatibleMarker.paintIcon(this, g2d, markerX, markerY); + + g2d.setColor(oldColor); + g2d.setFont(oldFont); + } + + protected void paintEditingMarker(Graphics2D g2d) { + Icon icon = isMarked ? selectedMarker : unselectedMarker; + icon.paintIcon(this, g2d, MARK_START_X, 0); + } + + protected void paintHighlightBorder(Graphics2D g2d) { + g2d.setColor(XCreatorConstants.FORM_BORDER_COLOR); + Rectangle rectangle = new Rectangle(); + rectangle.width = this.getWidth(); + rectangle.height = this.getHeight(); + GraphHelper.draw(g2d, rectangle, Constants.LINE_LARGE); + } + + protected void paintUpdatableMarker(Graphics2D g2d) { + g2d.drawImage(WIDGET_UPDATABLE_ICON, 0, 0, 25, 14, null); + } + + protected void paintLoadingIndicator(Graphics2D g2d, double processValue) { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + + Color oldColor = g2d.getColor(); + Stroke oldStroke = g2d.getStroke(); + Composite oldComposite = g2d.getComposite(); + + int x = 0; + int y = 0; + int w = getWidth(); + int h = getHeight(); + + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 20 / 100.0F)); + g2d.setColor(COVER_COLOR); + g2d.fillRect(x, y, w, h); + g2d.setComposite(oldComposite); + + BufferedImage image = WIDGET_DOWNLOADING_ICON; + g2d.drawImage( + image, + (x + w / 2 - 12), + (y + h / 2 - 16), + image.getWidth(), + image.getHeight(), + null, + this + ); + + g2d.setStroke(XCreatorConstants.STROKE); + g2d.setColor(Color.decode("#419BF9")); + double arcAngle = 36 + 360 * 0.9 * processValue; + g2d.drawArc(x + w / 2 - 12, y + h / 2 - 16, 24, 24, 90, -(int) arcAngle); + + g2d.setColor(oldColor); + g2d.setStroke(oldStroke); + } + /** * 由鼠标释放时调用该方法来触发左键点击事件 */ @@ -259,7 +392,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock } } - private Group getGroup() { + public Group getGroup() { return parentPane.getGroup(); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetUpdater.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetUpdater.java new file mode 100644 index 000000000..083df1b4e --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetUpdater.java @@ -0,0 +1,154 @@ +package com.fr.design.mainframe.share.ui.block; + +import com.fr.design.DesignerEnvManager; +import com.fr.design.extra.Process; +import com.fr.design.login.DesignerLoginHelper; +import com.fr.design.login.DesignerLoginSource; +import com.fr.design.mainframe.share.collect.ComponentCollector; +import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; +import com.fr.design.mainframe.share.util.DownloadUtils; +import com.fr.design.mainframe.share.util.ShareComponentUtils; +import com.fr.design.ui.util.UIUtil; +import com.fr.form.share.DefaultSharableWidget; +import com.fr.form.share.Group; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StableUtils; +import com.fr.stable.StringUtils; + +import javax.swing.SwingWorker; +import java.awt.Component; +import java.awt.Container; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/10/26 + */ +public class LocalWidgetUpdater implements Process { + + private double processValue = -1; + public LocalWidgetBlock widgetBlock; + private SwingWorker worker; + + public LocalWidgetUpdater(LocalWidgetBlock widgetBlock) { + this.widgetBlock = widgetBlock; + } + + private DefaultSharableWidget getWidget() { + return this.widgetBlock.getWidget(); + } + + private Group getGroup() { + return this.widgetBlock.getGroup(); + } + + public double getProcessValue() { + return processValue; + } + public boolean isUpdating() { + return 0 <= processValue && processValue <= 1; + } + + public void updateWidget(String remoteLatestWidgetId, UpdateListener updateListener) { + if (OnlineWidgetRepoPane.getInstance().isShowPackagePanel()) { + ComponentCollector.getInstance().collectDownloadPktNum(); + } + + LocalWidgetUpdater.this.process(0.0D); + String userName = DesignerEnvManager.getEnvManager().getDesignerLoginUsername(); + if (StringUtils.isEmpty(userName)) { + DesignerLoginHelper.showLoginDialog(DesignerLoginSource.NORMAL); + return; + } + + final DefaultSharableWidget widget = getWidget(); + + worker = new SwingWorker() { + + @Override + protected Boolean doInBackground() { + if (isCancelled()) { + return false; + } + String filePath; + try { + filePath = DownloadUtils.download(remoteLatestWidgetId, widget.getName() + "." + widget.getId(), LocalWidgetUpdater.this); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + return false; + } + ShareComponentUtils.checkReadMe(); + //安装 + File file = new File(filePath); + try { + if (file.exists()) { + getGroup().installUniqueIdModule(file); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + //删掉下载组件的目录 + StableUtils.deleteFile(file); + } + return true; + + } + + @Override + protected void done() { + LocalWidgetUpdater.this.process(-1.0); + boolean success = false; + try { + success = get(); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + if (updateListener != null) { + updateListener.onUpdated(success, getGroup().getGroupName(), widget.getId()); + } + } + }; + + worker.execute(); + } + + public void cancelUpdate() { + if (worker.isDone() || worker.isCancelled()) { + return; + } + worker.cancel(true); + process(-1.0); + } + + @Override + public void process(Double processValue) { + this.processValue = processValue; + + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override + public void run() { + Container absoluteLayoutParent = getAbsoluteLayoutAncestor(widgetBlock); + widgetBlock.repaint(); + if (absoluteLayoutParent != null) { + // 位于Block上方的遮罩层也要重绘下,否则Block的内容会绘制到遮罩层上方 + absoluteLayoutParent.repaint(); + } + } + }); + } + + public Container getAbsoluteLayoutAncestor(Component component) { + Container container = component.getParent(); + while (container != null && container.getLayout() != null) { + container = container.getParent(); + } + return container; + } + + public interface UpdateListener { + void onUpdated(boolean success, String group, String id); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java index 7512649d9..266a4e51b 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java @@ -18,7 +18,6 @@ import com.fr.form.share.DefaultSharableWidget; import com.fr.form.share.group.DefaultShareGroup; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; -import com.fr.design.mainframe.share.ui.online.OnlineWidgetSelectPane; import com.fr.design.mainframe.share.util.DownloadUtils; import com.fr.design.mainframe.share.util.ShareComponentUtils; import com.fr.design.mainframe.share.util.ShareUIUtils; @@ -215,7 +214,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { //安装 File file = new File(filePath); try { - if (file.exists() && getDefaultGroup().installModule(file)) { + if (file.exists() && getDefaultGroup().installUniqueIdModule(file)) { ShareUtils.recordInstallTime(file.getName(), System.currentTimeMillis()); ComponentCollector.getInstance().collectCmpDownLoad(widget.getUuid()); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/FramePane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/FramePane.java new file mode 100644 index 000000000..c6ebfdcd7 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/FramePane.java @@ -0,0 +1,30 @@ +package com.fr.design.mainframe.share.ui.local; + +import javax.swing.JPanel; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.LayoutManager2; +import java.io.Serializable; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/11/2 + */ +public class FramePane extends JPanel { + + public FramePane() { + setLayout(null); + } + + @Override + public void doLayout() { + super.doLayout(); + for (int i = 0; i < getComponentCount(); i++) { + getComponent(i).setSize(getSize()); + getComponent(i).setPreferredSize(getSize()); + getComponent(i).setBounds(0, 0, getWidth(), getHeight()); + } + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java index 1e9ca55a1..905e9d87b 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/GroupPane.java @@ -15,9 +15,9 @@ import com.fr.design.mainframe.share.ui.base.PopupMenuItem; import com.fr.design.mainframe.share.ui.widgetfilter.LocalWidgetFilter; import com.fr.design.mainframe.share.util.ShareUIUtils; import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.form.share.Group; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.group.DefaultShareGroupManager; -import com.fr.form.share.Group; import com.fr.form.share.record.ShareWidgetInfoManager; import com.fr.general.IOUtils; import com.fr.stable.StringUtils; @@ -107,6 +107,10 @@ public class GroupPane extends JPanel { expendGroup(needExpendGroup); } + public LocalWidgetSelectPane getWidgetListPane() { + return contentPanel; + } + public void reCreateShowPane(SharableWidgetProvider[] widgets) { if (contentPanel != null) { contentPanel.hidePreviewPane(); @@ -374,6 +378,12 @@ public class GroupPane extends JPanel { return new GroupPane(group); } }, + EXPANDED { + @Override + public GroupPane creteGroupPane(Group group) { + return new GroupPane(group, true); + } + }, CLOSURE { @Override public GroupPane creteGroupPane(Group group) { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java index fad64627f..d9c979f43 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoPane.java @@ -1,17 +1,27 @@ package com.fr.design.mainframe.share.ui.local; import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.VerticalFlowLayout; +import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.FormWidgetDetailPane; import com.fr.design.mainframe.share.sort.WidgetSortType; +import com.fr.design.mainframe.share.ui.base.DownloadProgressPane; +import com.fr.design.mainframe.share.ui.base.MouseClickListener; +import com.fr.design.mainframe.share.ui.block.LocalWidgetBlock; +import com.fr.design.mainframe.share.ui.block.LocalWidgetUpdater; import com.fr.design.mainframe.share.ui.widgetfilter.LocalWidgetFilter; import com.fr.design.mainframe.share.util.InstallComponentHelper; import com.fr.design.mainframe.share.util.ShareComponentUtils; -import com.fr.form.share.group.DefaultShareGroupManager; +import com.fr.design.mainframe.theme.edit.ui.LabelUtils; import com.fr.form.share.Group; +import com.fr.form.share.SharableWidgetProvider; +import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.form.share.group.DefaultShareGroupManager; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; @@ -21,7 +31,17 @@ import javax.swing.JScrollPane; import javax.swing.SwingWorker; import java.awt.BorderLayout; import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; @@ -30,10 +50,21 @@ import java.util.concurrent.atomic.AtomicBoolean; * Created by kerry on 2020-10-16 */ public class LocalWidgetRepoPane extends BasicPane { + private static class HOLDER { + private static final LocalWidgetRepoPane singleton = new LocalWidgetRepoPane(); + } + public static LocalWidgetRepoPane getInstance() { + return HOLDER.singleton; + } + + private int updateGuard = 0; + private Component updateTipPane; + private DownloadProgressPane updateProgressPane; private JPanel centerPane; private UIScrollPane groupsScrollPane; private JPanel groupsPane; + private ToolbarPane toolbarPane; private ManagePane managePane; private final Map groupPaneMap = new HashMap<>(); @@ -43,16 +74,10 @@ public class LocalWidgetRepoPane extends BasicPane { private String keyWord4Searching = StringUtils.EMPTY; private LocalWidgetRepoPane() { - setLayout(FRGUIPaneFactory.createBorderLayout()); - initPane(); - } - - public static LocalWidgetRepoPane getInstance() { - return HOLDER.singleton; - } - - private static class HOLDER { - private static final LocalWidgetRepoPane singleton = new LocalWidgetRepoPane(); + initializePane(this); + //新用户预装组件 + InstallComponentHelper.installPreComponent(); + doRefresh(); } public boolean isEditable() { @@ -63,16 +88,118 @@ public class LocalWidgetRepoPane extends BasicPane { return keyWord4Searching; } - /** - * 初始化 - */ - public void initPane() { - //新用户预装组件 - InstallComponentHelper.installPreComponent(); + private void initializePane(Container container) { + container.setLayout(new BorderLayout()); + + updateTipPane = createUpdateTipPane(); + container.add(updateTipPane, BorderLayout.NORTH); + + updateProgressPane = createUpdateMaskPane(); + FramePane framePane = new FramePane(); + + framePane.add(updateProgressPane); + framePane.add(createControlledMainPane(), BorderLayout.CENTER); + + add(framePane, BorderLayout.CENTER); + } + + private Component createUpdateTipPane() { + JPanel container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + container.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createEmptyBorder(10, 10, 5, 10), + BorderFactory.createLineBorder(new Color(0xD9DADD), 1, true) + )); + + final JPanel content = FRGUIPaneFactory.createBorderLayout_S_Pane(); + content.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + content.setBackground(Color.WHITE); + content.setOpaque(true); + + content.add(LabelUtils.createAutoWrapLabel(Toolkit.i18nText("Fine-Design_Share_Upgrade_Tip"), new Color(0x333334)), BorderLayout.CENTER); + + JPanel actionsPane = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0)); + actionsPane.setOpaque(false); + actionsPane.setBackground(null); + + UIButton cancelUpgradeButton = new UIButton(Toolkit.i18nText("Fine-Design_Share_Upgrade_Cancel")); + cancelUpgradeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + doQuitUpdateComponents(); + } + }); + + UIButton startUpgradeButton = new UIButton(Toolkit.i18nText("Fine-Design_Share_Upgrade_All")); + startUpgradeButton.setSelected(true); + startUpgradeButton.setForeground(Color.WHITE); + startUpgradeButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + doUpdateComponents(); + } + }); + + actionsPane.add(cancelUpgradeButton); + actionsPane.add(startUpgradeButton); + content.add(actionsPane, BorderLayout.SOUTH); + container.add(content, BorderLayout.NORTH); + + DefaultShareGroupManager.getInstance().setChangeListener(new DefaultShareGroupManager.ComponentChangeListener() { + @Override + public void onComponentRemoved(String group, String id) { + List updatableWidgetProviders = LocalWidgetRepoUpdater.getInstance().getUpdatableWidgetProviders(); + if (updatableWidgetProviders.size() == 0 && updateTipPane != null) { + updateTipPane.setVisible(false); + } + } + }); + + return container; + } + + private DownloadProgressPane createUpdateMaskPane() { + DownloadProgressPane progressPane = new DownloadProgressPane(new MouseClickListener() { + @Override + public void mouseClicked(MouseEvent e) { + super.mouseClicked(e); + int returnVal = FineJOptionPane.showConfirmDialog( + DesignerContext.getDesignerFrame(), + Toolkit.i18nText("Fine-Design_Share_Download_Cancel_Confirm"), + Toolkit.i18nText("Fine-Design_Share_Group_Confirm"), + FineJOptionPane.OK_CANCEL_OPTION + ); + if (returnVal == FineJOptionPane.OK_OPTION) { + List blockList = getUpdatableBlocks(); + for (LocalWidgetBlock block: blockList) { + block.getUpdater().cancelUpdate(); + } + updateGuard = 0; + updateProgressPane.setVisible(false); + LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance(); + updater.clearUpdate(); + refreshAllGroupPane(); + } + } + }); + // 屏蔽被遮罩内容的鼠标处理,避免鼠标透穿 + progressPane.addMouseListener(new MouseAdapter() {}); + progressPane.updateProgress(0); + progressPane.setOpaque(true); + progressPane.setBackground(new Color(0.25F, 0.25F, 0.25F, 0.65F)); + // 更新遮罩层初始不可见 + progressPane.setVisible(false); + return progressPane; + } + + public Component createControlledMainPane() { + Container container = FRGUIPaneFactory.createBorderLayout_S_Pane(); + JPanel componentLibPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); componentLibPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 15, 0)); - ToolbarPane toolbarPane = new ToolbarPane(); + toolbarPane = new ToolbarPane(); + toolbarPane.addFilterPopupStateChangeListener(state -> setWidgetPaneScrollEnable(!state)); + managePane = new ManagePane(); JPanel northPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); @@ -85,14 +212,14 @@ public class LocalWidgetRepoPane extends BasicPane { centerPane.add(LocalPaneStatus.EMPTY.getPanel(), LocalPaneStatus.EMPTY.name()); centerPane.add(LocalPaneStatus.LOADING.getPanel(), LocalPaneStatus.LOADING.name()); centerPane.add(LocalPaneStatus.INSTALLING.getPanel(), LocalPaneStatus.INSTALLING.name()); + cardLayout.show(centerPane, LocalPaneStatus.LOADING.name()); componentLibPanel.add(northPane, BorderLayout.NORTH); componentLibPanel.add(centerPane, BorderLayout.CENTER); - add(componentLibPanel, BorderLayout.CENTER); - cardLayout.show(centerPane, LocalPaneStatus.LOADING.name()); - toolbarPane.addFilterPopupStateChangeListener(state -> setWidgetPaneScrollEnable(!state)); - doRefresh(); + container.add(componentLibPanel, BorderLayout.CENTER); + + return container; } public void refreshAllGroupPane() { @@ -208,6 +335,7 @@ public class LocalWidgetRepoPane extends BasicPane { try { if (get()) { refreshAllGroupPane(); + doFetchAndCheckUpdate(); } } catch (InterruptedException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); @@ -222,6 +350,74 @@ public class LocalWidgetRepoPane extends BasicPane { }.execute(); } + public void doFetchAndCheckUpdate() { + LocalWidgetRepoUpdater.getInstance().fetchComponentUpdates(new LocalWidgetRepoUpdater.FetchComponentUpdatesListener() { + @Override + public void onFetchedBefore() { + updateTipPane.setVisible(false); + } + + @Override + public void onFetchedAfter(boolean success, Map remoteLatestWidgets) { + if (success) { + List updatableWidgetProviders = LocalWidgetRepoUpdater.getInstance().getUpdatableWidgetProviders(); + updateTipPane.setVisible(updatableWidgetProviders.size() > 0); + if (updatableWidgetProviders.size() > 0) { + refreshAllGroupPane(GroupPane.GroupCreateStrategy.EXPANDED); + } + } + } + }); + } + + public void doQuitUpdateComponents() { + LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance(); + updater.clearUpdate(); + if (updateTipPane != null) { + updateTipPane.setVisible(false); + } + } + + public void doUpdateComponents() { + if (updateGuard > 0) { + return; + } + + updateGuard = 0; + toolbarPane.reset(); + managePane.switchPanel(false); + switchPane(LocalPaneStatus.NORMAL); + refreshAllGroupPane(GroupPane.GroupCreateStrategy.EXPANDED); + List blockList = getUpdatableBlocks(); + + if (blockList.size() == 0) { + return; + } + + updateTipPane.setVisible(false); + updateProgressPane.updateProgress(0.0F); + updateProgressPane.setVisible(true); + + LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance(); + for (LocalWidgetBlock block: blockList) { + OnlineShareWidget remoteLatestWidget = updater.checkUpdate(block.getWidget()); + block.getUpdater().updateWidget(remoteLatestWidget.getId(), new LocalWidgetUpdater.UpdateListener() { + @Override + public void onUpdated(boolean success, String group, String id) { + updateGuard += 1; + updateProgressPane.updateProgress(1.0F * updateGuard / blockList.size()); + if (updateGuard == blockList.size()) { + updateGuard = 0; + updater.clearUpdate(); + updateProgressPane.setVisible(false); + refreshAllGroupPane(); + } + } + }); + } + } + + /** * 切换为要显示的面板 */ @@ -261,6 +457,30 @@ public class LocalWidgetRepoPane extends BasicPane { return groups.length == 1 && groups[0].getAllBindInfoList().length == 0; } + private List getUpdatableBlocks() { + List blockList = new ArrayList<>(); + + LocalWidgetRepoUpdater updater = LocalWidgetRepoUpdater.getInstance(); + + for (GroupPane groupPane : groupPaneMap.values()) { + LocalWidgetSelectPane widgetListPane = groupPane.getWidgetListPane(); + int count = widgetListPane.getComponentCount(); + for (int i = 0; i < count; i++) { + Component component = widgetListPane.getComponent(i); + if (component instanceof LocalWidgetBlock) { + + LocalWidgetBlock widgetBlock = (LocalWidgetBlock) component; + SharableWidgetProvider localProvider = widgetBlock.getWidget(); + OnlineShareWidget remoteLatestWidget = updater.checkUpdate(localProvider); + if (remoteLatestWidget != null) { + blockList.add(widgetBlock); + } + } + } + } + return blockList; + } + @Override protected String title4PopupWindow() { return Toolkit.i18nText("Fine-Design_Share_Local_Widget"); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoUpdater.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoUpdater.java new file mode 100644 index 000000000..03eb751f2 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/LocalWidgetRepoUpdater.java @@ -0,0 +1,140 @@ +package com.fr.design.mainframe.share.ui.local; + +import com.fr.design.mainframe.share.util.OnlineShopUtils; +import com.fr.form.share.Group; +import com.fr.form.share.SharableWidgetProvider; +import com.fr.form.share.bean.OnlineShareWidget; +import com.fr.form.share.group.DefaultShareGroupManager; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.basic.version.Version; +import com.fr.stable.ProductConstants; +import com.fr.stable.StringUtils; + +import javax.swing.SwingWorker; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @author Starryi + * @version 1.0 + * Created by Starryi on 2021/11/3 + */ +public class LocalWidgetRepoUpdater { + private LocalWidgetRepoUpdater() {} + private static class Holder { + public static LocalWidgetRepoUpdater INSTANCE = new LocalWidgetRepoUpdater(); + } + public static LocalWidgetRepoUpdater getInstance() { + return LocalWidgetRepoUpdater.Holder.INSTANCE; + } + + private final Map remoteLatestWidgetsBackup = new HashMap<>(); + + private final AtomicBoolean isCheckingComponentUpdates = new AtomicBoolean(false); + private SwingWorker checkingComponentsUpdateWorker; + + private Set getLocalWidgetIds() { + Set widgetIds = new HashSet<>(); + Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup(); + for (Group group: groups) { + SharableWidgetProvider[] widgetProviders = group.getAllBindInfoList(); + for (SharableWidgetProvider provider: widgetProviders) { + widgetIds.add(provider.getId()); + } + } + return widgetIds; + } + + public void clearUpdate() { + remoteLatestWidgetsBackup.clear(); + } + + public OnlineShareWidget checkUpdate(SharableWidgetProvider provider) { + OnlineShareWidget remoteLatestWidget = remoteLatestWidgetsBackup.get(provider.getId()); + if (remoteLatestWidget != null && StringUtils.isNotEmpty(remoteLatestWidget.getVersion())) { + Version remoteLatestVersion = Version.create(remoteLatestWidget.getVersion()); + Version localVersion = Version.create(provider.getVersion()); + + boolean isUpdatable = remoteLatestVersion.compareTo(localVersion) > 0; + if (isUpdatable) { + return remoteLatestWidget; + } + } + return null; + } + + public List getUpdatableWidgetProviders() { + List updatableProviders = new ArrayList<>(); + + Group[] groups = DefaultShareGroupManager.getInstance().getAllGroup(); + for (Group group: groups) { + SharableWidgetProvider[] widgetProviders = group.getAllBindInfoList(); + for (SharableWidgetProvider widgetProvider: widgetProviders) { + if (checkUpdate(widgetProvider) != null) { + updatableProviders.add(widgetProvider); + } + } + } + return updatableProviders; + } + + public void fetchComponentUpdates(FetchComponentUpdatesListener listener) { + if (isCheckingComponentUpdates.get()) { + if (checkingComponentsUpdateWorker != null) { + checkingComponentsUpdateWorker.cancel(true); + } + } + + clearUpdate(); + listener.onFetchedBefore(); + checkingComponentsUpdateWorker = new SwingWorker() { + @Override + protected Boolean doInBackground() { + if (isCancelled()) { + return false; + } + if (isCheckingComponentUpdates.compareAndSet(false, true)) { + clearUpdate(); + + Set widgetIds = getLocalWidgetIds(); + String envVersion = ProductConstants.RELEASE_VERSION; + + List remoteLatestWidgetList = OnlineShopUtils.getLatestReusesByDesignerVersion(widgetIds, envVersion); + remoteLatestWidgetsBackup.clear(); + for (OnlineShareWidget widget: remoteLatestWidgetList) { + remoteLatestWidgetsBackup.put(widget.getUuid(), widget); + } + + return true; + } + return false; + } + + @Override + public void done() { + boolean success = false; + try { + success = get(); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } finally { + listener.onFetchedAfter(success, remoteLatestWidgetsBackup); + isCheckingComponentUpdates.set(false); + } + } + }; + + checkingComponentsUpdateWorker.execute(); + } + + public interface FetchComponentUpdatesListener { + void onFetchedBefore(); + void onFetchedAfter(boolean success, Map remoteLatestWidgets); + } +} diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java index af94033b3..1aad30c1d 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/ToolbarPane.java @@ -118,6 +118,12 @@ class ToolbarPane extends JPanel { ); } + public void reset() { + filterPanel.reset(); + searchTextField.setText(StringUtils.EMPTY); + cardLayout.show(centerPane, NORMAL); + } + private FilterPane createFilterPane() { filterPanel = FilterPane.createLocalFilterPane(); filterPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java index d211887f5..0afbe25d2 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/local/WidgetSelectedManager.java @@ -1,7 +1,9 @@ package com.fr.design.mainframe.share.ui.local; +import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.group.DefaultShareGroupManager; import com.fr.form.share.Group; +import com.fr.stable.StringUtils; import java.util.HashMap; import java.util.List; @@ -53,7 +55,11 @@ public class WidgetSelectedManager { */ public synchronized boolean unInstallSelect(String groupName, String uuid) { Group group = DefaultShareGroupManager.getInstance().getGroup(groupName); - return group != null && group.unInstallSelect(Stream.of(uuid).collect(Collectors.toList())); + boolean success = group != null && group.unInstallSelect(Stream.of(uuid).collect(Collectors.toList())); + if (success) { + DefaultShareGroupManager.getInstance().notifyComponentRemoved(groupName, uuid); + } + return success; } /** @@ -64,6 +70,9 @@ public class WidgetSelectedManager { for (String groupName : selectedWidgetMap.keySet()) { Group group = DefaultShareGroupManager.getInstance().getGroup(groupName); result &= group != null && group.unInstallSelect(selectedWidgetMap.get(groupName)); + if (result) { + DefaultShareGroupManager.getInstance().notifyComponentRemoved(groupName, StringUtils.EMPTY); + } } selectedWidgetMap.clear(); return result; diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java index 3113fd06f..ab1793519 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/online/OnlineWidgetPopupPreviewPane.java @@ -9,6 +9,9 @@ import com.fr.design.mainframe.share.ui.constants.ColorConstants; import com.fr.form.share.bean.OnlineShareWidget; import com.fr.general.FRFont; import com.fr.general.IOUtils; +import com.fr.plugin.basic.version.Version; +import com.fr.plugin.basic.version.VersionInterval; +import com.fr.plugin.basic.version.VersionIntervalFactory; import com.fr.stable.StringUtils; import javax.swing.BorderFactory; @@ -37,7 +40,7 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane private static final int POPUP_BOTTOM_HEIGHT = 54; private PreviewImagePane previewImagePane; - private UILabel versionLabel; + private UILabel compatibleEnVersionLabel; private UILabel downloadsLabel; private UILabel priceLabel; @@ -95,10 +98,10 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane } private JPanel createWidgetInfoPane() { - versionLabel = new UILabel(); - versionLabel.setVerticalAlignment(SwingConstants.CENTER); - versionLabel.setFont(FRFont.getInstance(versionLabel.getFont()).deriveFont(12.0F)); - versionLabel.setForeground(new Color(0x333334)); + compatibleEnVersionLabel = new UILabel(); + compatibleEnVersionLabel.setVerticalAlignment(SwingConstants.CENTER); + compatibleEnVersionLabel.setFont(FRFont.getInstance(compatibleEnVersionLabel.getFont()).deriveFont(12.0F)); + compatibleEnVersionLabel.setForeground(new Color(0x333334)); downloadsLabel = new UILabel(); downloadsLabel.setVerticalAlignment(SwingConstants.TOP); @@ -125,7 +128,7 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane constraints.gridheight = 1; constraints.weightx = 1; constraints.weighty = 1; - container.add(versionLabel, constraints); + container.add(compatibleEnVersionLabel, constraints); constraints.gridx = 0; constraints.gridy = 1; @@ -167,6 +170,18 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane @Override public void populateBean(PreviewWidgetBlock block) { OnlineShareWidget widget = block.getWidget(); + populateThemeName(widget); + populatePrice(widget); + populateCompatibleEnvVersion(widget); + + downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes()); + previewImagePane.setPreviewImage(block.getPreviewImage()); + + int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT; + setPreferredSize(new Dimension(POPUP_WIDTH, height)); + } + + private void populateThemeName(OnlineShareWidget widget) { String themeName = widget.getThemeName(); if (StringUtils.isNotEmpty(themeName)) { suitableThemeNamePane.setVisible(true); @@ -174,19 +189,37 @@ public class OnlineWidgetPopupPreviewPane extends AbstractWidgetPopupPreviewPane } else { suitableThemeNamePane.setVisible(false); } + } + private void populatePrice(OnlineShareWidget widget) { String priceText = "¥" + widget.getPrice(); if (widget.getPrice() <= 0) { priceText = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Price_Free"); } priceLabel.setText(priceText); + } - versionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Version") + ": " + widget.getDesignerVersion()); - downloadsLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Download_Times") + ": " + widget.getDownloadTimes()); - previewImagePane.setPreviewImage(block.getPreviewImage()); + private void populateCompatibleEnvVersion(OnlineShareWidget widget) { + VersionInterval versionInterval = VersionIntervalFactory.create(widget.getDesignerVersion()); - int height = (suitableThemeNamePane.isVisible() ? POPUP_TOP_HEIGHT : 0) + 10 + previewImagePane.getPreferredSize().height + POPUP_BOTTOM_HEIGHT; - setPreferredSize(new Dimension(POPUP_WIDTH, height)); + Version floorVersion = versionInterval.floor(); + Version upperVersion = versionInterval.upper(); + + String compatibleEnVersion; + boolean includingMinVersion = versionInterval.contain(Version.create("0")); + boolean includingMaxVersion = versionInterval.contain(Version.create(Integer.toString(Integer.MAX_VALUE))); + + if (includingMinVersion && includingMaxVersion) { + compatibleEnVersion = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_All"); + } else if (includingMinVersion) { + compatibleEnVersion = StringUtils.messageFormat(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_Ceiling_Limit", upperVersion.getVersionStr())); + } else if (includingMaxVersion) { + compatibleEnVersion = StringUtils.messageFormat(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version_Interval_Floor_Limit", floorVersion.getVersionStr())); + } else { + compatibleEnVersion = floorVersion.getVersionStr() + "~" + upperVersion.getVersionStr(); + } + + compatibleEnVersionLabel.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Compatible_Designer_Version") + ": " + compatibleEnVersion); } private static class PreviewImagePane extends JPanel { diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java index cd3e8c1ad..39a18ac2a 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/InstallUtils.java @@ -117,7 +117,7 @@ public class InstallUtils { private static boolean installReuFile(Group group, File chosenFile, long installTime) { try { - if (!group.installModule(chosenFile)) { + if (!group.installUniqueIdModule(chosenFile)) { return false; } ShareUtils.recordInstallTime(chosenFile.getName(), installTime); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java b/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java index 7db6608c5..67326c853 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/util/OnlineShopUtils.java @@ -10,12 +10,14 @@ import com.fr.design.mainframe.share.Bean.WidgetFilterTypeInfo; import com.fr.design.mainframe.share.config.ComponentReuseConfigManager; import com.fr.general.ComparatorUtils; import com.fr.general.http.HttpClient; +import com.fr.general.http.HttpToolbox; import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.log.FineLoggerFactory; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; +import java.io.IOException; import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Comparator; @@ -23,6 +25,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; /** * Created by kerry on 2021/11/3 @@ -58,6 +61,10 @@ public class OnlineShopUtils { return StableUtils.pathJoin(getReuInfoPath(), "sort_parameter"); } + private static String getLatestReusesPath() { + return StableUtils.pathJoin(getReuInfoPath(), "prompt/update/"); + } + private static String getTestConnectionUrl() { return DesignerCloudURLManager.getInstance().acquireUrlByKind("ping"); } @@ -294,6 +301,28 @@ public class OnlineShopUtils { return getOnlineShareWidgets(plistUrl); } + public static List getLatestReusesByDesignerVersion(Set reuseIds, String designerVersion) { + List result = new ArrayList<>(); + try { + JSONObject params = JSONObject.create(); + StringBuilder reuseIdsStr = new StringBuilder(); + for (String id: reuseIds) { + reuseIdsStr.append(id).append(","); + } + params.put("reuseIds", reuseIdsStr.toString()); + params.put("designerVersion", designerVersion); + JSONArray resultArr = postResultAttrFormUrl(getLatestReusesPath(), params); + int size = resultArr.size(); + for (int i = 0; i < size; i++) { + JSONObject jo = resultArr.getJSONObject(i); + result.add(OnlineShareWidget.parseFromJSONObject(jo)); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return result; + } + private static JSONArray getResultAttrFromUrl(String url) { HttpClient httpClient = new HttpClient(url); httpClient.asGet(); @@ -302,4 +331,19 @@ public class OnlineShopUtils { return resultJSONObject.getJSONArray("result"); } + private static JSONArray postResultAttrFormUrl(String url, JSONObject params) { + JSONArray result = JSONArray.create(); + try { + String responseText = HttpToolbox.post(url, params.toMap()); + if (StringUtils.isNotEmpty(responseText)) { + JSONObject resultJSONObject = new JSONObject(responseText); + result = resultJSONObject.getJSONArray("result"); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + return result; + } + } diff --git a/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java b/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java index 5bbfc7a11..f71a504c8 100644 --- a/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java +++ b/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareGeneratePane.java @@ -131,6 +131,24 @@ public class ShareGeneratePane extends BasicPane { } }); + simplePane.getDesignerVersionField().getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void changedUpdate(DocumentEvent e) { + validInput(); + } + + @Override + public void insertUpdate(DocumentEvent e) { + validInput(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + validInput(); + } + }); + uploadPane.getNameField().getDocument().addDocumentListener(new DocumentListener() { @Override @@ -159,13 +177,13 @@ public class ShareGeneratePane extends BasicPane { } private void validInput() { - String userInput = getSelectMainPane().getNameField().getText().trim(); + String name = getSelectMainPane().getNameField().getText().trim(); + boolean isValidName = StringUtils.isNotEmpty(name); - if (StringUtils.isEmpty(userInput)) { - dialog.setButtonEnabled(false); - } else { - dialog.setButtonEnabled(true); - } + boolean isValidDesignerVersion = getSelectMainPane().getDesignerVersionField().isValidVersion(); + + boolean isValidInput = isValidName && isValidDesignerVersion; + dialog.setButtonEnabled(isValidInput); } diff --git a/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareMainPane.java b/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareMainPane.java index ea5298cf2..ffeedb770 100644 --- a/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareMainPane.java +++ b/designer-realize/src/main/java/com/fr/design/share/ui/generate/ShareMainPane.java @@ -48,6 +48,8 @@ import com.fr.stable.ProductConstants; import com.fr.stable.StringUtils; import com.fr.stable.collections.combination.Pair; import com.fr.stable.pinyin.PinyinHelper; + +import java.awt.TextField; import java.util.HashMap; import org.jetbrains.annotations.NotNull; @@ -90,7 +92,7 @@ import static javax.swing.JOptionPane.ERROR_MESSAGE; **/ public class ShareMainPane extends JPanel { - private static final int COLUMN_ITEM_SIZE = 60; + private static final int COLUMN_ITEM_SIZE = 80; private static final int COLUMN_FIELD_WIDTH = 555; private static final int TEXT_FIELD_WIDTH = 160; private static final int TEXT_FIELD_HEIGHT = 21; @@ -101,7 +103,7 @@ public class ShareMainPane extends JPanel { private static final int COMBO_HEIGHT = 20; private static final int BTN_WIDTH = 70; private static final int BTN_HEIGHT = 20; - private static final int BASEPANE_VERTICAL_GAP = 2; + private static final int BASEPANE_VERTICAL_GAP = 10; private UIScrollPane mainPane = null; @@ -123,6 +125,7 @@ public class ShareMainPane extends JPanel { private UIComboBox styleComboBox = null; private UITextField nameField = new UITextField(); + private VersionIntervalField designerVersionField = new VersionIntervalField(); private PlaceholderTextArea content = new LeftWordsTextArea(); @@ -214,6 +217,9 @@ public class ShareMainPane extends JPanel { UILabel classifyLabel = ShareUIUtils.createCenterRightUILabel(Toolkit.i18nText("Fine-Design_Share_Classify")); JPanel classifyPane = createClassifyPane(); + UILabel designerVersionLabel = ShareUIUtils.createCenterRightUILabel(Toolkit.i18nText("Fine-Design_Share_Designer_Version")); + JPanel designerVersionPane = createDesignerVersionFiledPane(); + //样式风格 UILabel styleThemeLabel = ShareUIUtils.createCenterRightUILabel(Toolkit.i18nText("Fine-Design_Share_Style_Theme")); JPanel styleThemePane = createStyleThemePane(); @@ -231,35 +237,37 @@ public class ShareMainPane extends JPanel { JPanel innerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel infoPane; + Component[][] components; if (upload) { - Component[][] components = new Component[][]{ + components = new Component[][]{ new Component[]{nameLabel, symbolTextField}, new Component[]{coverLabel, coverImagePane}, new Component[]{vendorLabel, vendorPane}, new Component[]{deviceLabel, devicePane}, new Component[]{classifyLabel, classifyPane}, + new Component[]{designerVersionLabel, designerVersionPane}, new Component[]{styleThemeLabel, styleThemePane}, new Component[]{pluginLabel, pluginPane}, new Component[]{priceLabel, pricePane}, }; - double[] rowSize = {p, p, p, p, p, p, p, p}; - double[] columnSize = {COLUMN_ITEM_SIZE, p}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},{1, 1}, {1, 1}}; - infoPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.HGAP_SMALL, BASEPANE_VERTICAL_GAP); } else { - Component[][] components = new Component[][]{ + components = new Component[][]{ new Component[]{nameLabel, symbolTextField}, new Component[]{coverLabel, coverImagePane}, new Component[]{deviceLabel, devicePane}, new Component[]{classifyLabel, classifyPane}, + new Component[]{designerVersionLabel, designerVersionPane}, new Component[]{localGroupLabel, localGroupPane} }; - double[] rowSize = {p, p, p, p, p}; - double[] columnSize = {COLUMN_ITEM_SIZE, p}; - int[][] rowCount = {{1, 1}, {1, 1}, {1, 1},{1, 1}, {1, 1}}; - infoPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.HGAP_SMALL, BASEPANE_VERTICAL_GAP); } + double[] rowSize = new double[components.length]; + Arrays.fill(rowSize, p); + double[] columnSize = {COLUMN_ITEM_SIZE, p}; + int[][] rowCount = new int[components.length][2]; + Arrays.fill(rowCount, new int[] { 1, 1 }); + infoPane = TableLayoutHelper.createGapTableLayoutPane(components, rowSize, columnSize, rowCount, LayoutConstants.HGAP_SMALL, BASEPANE_VERTICAL_GAP); + String title = Toolkit.i18nText("Fine-Design_Share_Base_Info"); JPanel overviewPane = FRGUIPaneFactory.createTitledBorderPane(title); @@ -398,6 +406,16 @@ public class ShareMainPane extends JPanel { return pane; } + private JPanel createDesignerVersionFiledPane() { + designerVersionField.setPreferredSize(new Dimension(TEXT_FIELD_WIDTH, TEXT_FIELD_HEIGHT)); + JPanel symbolTextFiled = FRGUIPaneFactory.createBorderLayout_S_Pane(); + UILabel validSymbol = new UILabel(" *"); + symbolTextFiled.add(designerVersionField, BorderLayout.CENTER); + symbolTextFiled.add(validSymbol, BorderLayout.EAST); + + return symbolTextFiled; + } + private JPanel createLocalGroupPane() { JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2)); @@ -623,7 +641,7 @@ public class ShareMainPane extends JPanel { provider.setDisplayDevice(displayDevice()); provider.setParentClassify(classify(parentClassify.getSelectedItem())); provider.setChildClassify(classify(childClassify.getSelectedItem())); - provider.setDesignerVersion(ProductConstants.VERSION); + provider.setDesignerVersion(designerVersionField.getText()); provider.setVendor(loginLabel.getText()); provider.setFileName(provider.getNameWithID()); provider.setVendorUid(DesignerEnvManager.getEnvManager().getDesignerLoginUid()); @@ -655,6 +673,10 @@ public class ShareMainPane extends JPanel { return nameField; } + public VersionIntervalField getDesignerVersionField() { + return designerVersionField; + } + private String classify(Object classify) { return classify == null ? StringUtils.EMPTY : classify.toString(); @@ -723,4 +745,35 @@ public class ShareMainPane extends JPanel { } } + public static class VersionIntervalField extends UITextField { + private static final String allowCharAsString = "0123456789."; + + public VersionIntervalField() { + setDocument(new PlainDocument() { + + @Override + public void insertString(int offset, String str, AttributeSet attrSet) throws BadLocationException { + if (str == null) { + return; + } + int count = str.length(); + for (int i = 0; i < count; i++) { + char c = str.charAt(i); + if (allowCharAsString.indexOf(c) < 0) { + java.awt.Toolkit.getDefaultToolkit().beep(); + return; + } + } + super.insertString(offset, str, attrSet); + } + }); + setPlaceholder(ProductConstants.RELEASE_VERSION); + setText(ProductConstants.RELEASE_VERSION); + } + + public boolean isValidVersion() { + String text = getText(); + return text.matches("(([0-9]|([1-9]([0-9]*))).){2}([0-9]|([1-9]([0-9]*)))"); + } + } }