Browse Source
Merge in DESIGN/design from ~YVAN/design:REPORT-43833 to release/10.0 * commit 'e5585ff488ed78cd428a8a23ba4606243d7a61ea': REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定 1. 将本地实现作为默认实现,注册起来,以兼容远程连接老版服务器的情况 2. 之前清理脏数据的逻辑有点问题,修改方式为:为LockItem对象添加一个成员变量birth,代表其创建时间,并且会为每个ClientID在对应的服务中存上一个key=clientID,value=LockItem的键值对,在用户登入时初始化,每隔30s更新创建时间,用户登出时清除,并且在轮询任务中加入检查当前各个LockItem对应的服务下这个键值对里value的birth是否超时了,如果超时,清理脏数据 3. 将之前使用的applyForService修改为applyForCleanableService,便于集群重启时清理服务数据 REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定 将通知组件的操作放到EDT中 REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定 将弹窗关闭后解锁的操作,放到afterCommit中 REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定 【问题原因】自测+修改一些bug 【改动思路】自测+修改一些bug REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定 【问题原因】迭代提交 【改动思路】迭代提交feature/big-screen
ju|剧浩宇
4 years ago
20 changed files with 625 additions and 63 deletions
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
* 定义数据连接的checker |
||||||
|
*/ |
||||||
|
public class ConnectionLockChangeChecker extends EditLockChangeChecker{ |
||||||
|
|
||||||
|
private static class Holder { |
||||||
|
private static final ConnectionLockChangeChecker INSTANCE = new ConnectionLockChangeChecker(); |
||||||
|
} |
||||||
|
|
||||||
|
public static ConnectionLockChangeChecker getInstance() { |
||||||
|
return ConnectionLockChangeChecker.Holder.INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
public ConnectionLockChangeChecker() { |
||||||
|
this.lockItem = LockItem.CONNECTION; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
import com.fr.concurrent.NamedThreadFactory; |
||||||
|
import com.fr.design.ui.util.UIUtil; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.lock.editlock.EditLockOperator; |
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.Executors; |
||||||
|
import java.util.concurrent.ScheduledExecutorService; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/19 |
||||||
|
* 判断当前设计器在远程设计服务器中的锁状态是否发生了改变 |
||||||
|
*/ |
||||||
|
public abstract class EditLockChangeChecker { |
||||||
|
|
||||||
|
private static final int INTERVAL = 30000; |
||||||
|
private ScheduledExecutorService scheduler; |
||||||
|
protected LockItem lockItem; |
||||||
|
private boolean isLocked = false; |
||||||
|
private List<EditLockChangeListener> listeners = new ArrayList<>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 轮询任务,如果是远程设计状态,每隔30s查询一次相应lockItem的锁状态是否改变 |
||||||
|
*/ |
||||||
|
public void start() { |
||||||
|
this.scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("EditLockChangeChecker")); |
||||||
|
this.scheduler.scheduleAtFixedRate(new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
// 判断是否为远程设计环境
|
||||||
|
if (!WorkContext.getCurrent().isLocal()) { |
||||||
|
try { |
||||||
|
EditLockOperator operator = WorkContext.getCurrent().get(EditLockOperator.class); |
||||||
|
boolean locked = operator.isLocked(lockItem); |
||||||
|
if (isLocked != locked) { |
||||||
|
isLocked = locked; |
||||||
|
fireChange(); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, 0, INTERVAL, TimeUnit.MILLISECONDS); |
||||||
|
} |
||||||
|
|
||||||
|
public void stop() { |
||||||
|
this.scheduler.shutdown(); |
||||||
|
} |
||||||
|
|
||||||
|
public void addEditLockChangeListener(EditLockChangeListener listener) { |
||||||
|
this.listeners.add(listener); |
||||||
|
} |
||||||
|
|
||||||
|
private void fireChange() { |
||||||
|
UIUtil.invokeLaterIfNeeded(new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
for (EditLockChangeListener listener : EditLockChangeChecker.this.listeners) { |
||||||
|
listener.updateLockedState(new EditLockChangeEvent(isLocked)); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
import java.util.EventObject; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
*/ |
||||||
|
public class EditLockChangeEvent extends EventObject { |
||||||
|
|
||||||
|
private boolean isLocked; |
||||||
|
|
||||||
|
/** |
||||||
|
* @param source 锁状态发生了改变,且当前锁状态就是source |
||||||
|
*/ |
||||||
|
public EditLockChangeEvent(boolean source) { |
||||||
|
super(source); |
||||||
|
this.isLocked = source; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isLocked() { |
||||||
|
return isLocked; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
import java.util.EventListener; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
*/ |
||||||
|
public interface EditLockChangeListener extends EventListener { |
||||||
|
/** |
||||||
|
* 锁定状态改变后执行的动作 |
||||||
|
* @param event 事件 |
||||||
|
*/ |
||||||
|
void updateLockedState(EditLockChangeEvent event); |
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
import com.fr.base.svg.IconUtils; |
||||||
|
import com.fr.base.svg.SVGLoader; |
||||||
|
import com.fr.design.dialog.FineJOptionPane; |
||||||
|
import com.fr.design.i18n.Toolkit; |
||||||
|
import com.fr.design.mainframe.DesignerContext; |
||||||
|
import com.fr.general.IOUtils; |
||||||
|
import com.fr.workspace.WorkContext; |
||||||
|
import com.fr.workspace.server.lock.editlock.EditLockOperator; |
||||||
|
import com.fr.report.LockItem; |
||||||
|
import org.jetbrains.annotations.Nullable; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import java.awt.Image; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
* 关于编辑锁定的一些常量和静态方法 |
||||||
|
*/ |
||||||
|
public class EditLockUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据连接锁定标志 |
||||||
|
*/ |
||||||
|
public static final Icon CONNECTION_LOCKED_ICON = IconUtils.readIcon("/com/fr/design/images/m_web/connection_locked"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 小锁图片 |
||||||
|
*/ |
||||||
|
public static final @Nullable Image LOCKED_IMAGE = SVGLoader.load("/com/fr/design/images/m_web/locked_normal.svg"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 提示弹窗中的提示标志 |
||||||
|
*/ |
||||||
|
public static final Icon TOOLTIPS_ICON = IOUtils.readIcon("/com/fr/design/images/m_web/warningIcon.png"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 数据连接锁定中 |
||||||
|
*/ |
||||||
|
public static final String CONNECTION_LOCKED_TOOLTIPS = Toolkit.i18nText("Fine_Designer_Remote_Design_Data_Connection_Locked"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 服务器数据集锁定中 |
||||||
|
*/ |
||||||
|
public static final String SERVER_TABLEDATA_LOCKED_TOOLTIPS = Toolkit.i18nText("Fine_Designer_Remote_Design_Server_TableData_Locked"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 提示弹窗中的提示信息 |
||||||
|
*/ |
||||||
|
public static final String LOCKED_MESSAGE = Toolkit.i18nText("Fine_Designer_Remote_Design_Locked_Message"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 提示弹窗中的标题 |
||||||
|
*/ |
||||||
|
public static final String TOOLTIPS = Toolkit.i18nText("Fine-Design_Basic_Remote_Design_Title_Hint"); |
||||||
|
|
||||||
|
/** |
||||||
|
* 已经被锁,跳出弹窗提示 |
||||||
|
*/ |
||||||
|
public static void showLockMessage() { |
||||||
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), EditLockUtils.LOCKED_MESSAGE, EditLockUtils.TOOLTIPS, JOptionPane.INFORMATION_MESSAGE, EditLockUtils.TOOLTIPS_ICON); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean lock(LockItem lockItem) { |
||||||
|
return WorkContext.getCurrent().get(EditLockOperator.class).lock(lockItem); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean unlock(LockItem lockItem) { |
||||||
|
return WorkContext.getCurrent().get(EditLockOperator.class).unlock(lockItem); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isLocked(LockItem lockItem) { |
||||||
|
return WorkContext.getCurrent().get(EditLockOperator.class).isLocked(lockItem); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
package com.fr.design.editlock; |
||||||
|
|
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
* 服务器数据集的checker |
||||||
|
*/ |
||||||
|
public class ServerTableDataLockChangeChecker extends EditLockChangeChecker{ |
||||||
|
private static class Holder { |
||||||
|
private static final ServerTableDataLockChangeChecker INSTANCE = new ServerTableDataLockChangeChecker(); |
||||||
|
} |
||||||
|
|
||||||
|
public static ServerTableDataLockChangeChecker getInstance() { |
||||||
|
return ServerTableDataLockChangeChecker.Holder.INSTANCE; |
||||||
|
} |
||||||
|
|
||||||
|
public ServerTableDataLockChangeChecker() { |
||||||
|
this.lockItem = LockItem.SERVER_TABLE_DATA; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
package com.fr.design.gui.ibutton; |
||||||
|
|
||||||
|
import com.fr.design.editlock.EditLockChangeEvent; |
||||||
|
import com.fr.design.editlock.EditLockChangeListener; |
||||||
|
import com.fr.design.editlock.EditLockUtils; |
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
import javax.swing.Icon; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
*/ |
||||||
|
public class UILockButton extends UIButton implements EditLockChangeListener { |
||||||
|
|
||||||
|
/** |
||||||
|
* 锁定状态图标 |
||||||
|
*/ |
||||||
|
private Icon lockedIcon; |
||||||
|
/** |
||||||
|
* 正常状态图标 |
||||||
|
*/ |
||||||
|
private Icon normalIcon; |
||||||
|
/** |
||||||
|
* 锁定状态的提示信息 |
||||||
|
*/ |
||||||
|
private String lockedTooltips; |
||||||
|
/** |
||||||
|
* 正常状态的提示信息 |
||||||
|
*/ |
||||||
|
private String normalTooltips; |
||||||
|
|
||||||
|
public UILockButton(Icon lockedIcon, Icon normalIcon, String lockedTooltips, String normalTooltips) { |
||||||
|
super(); |
||||||
|
this.lockedIcon = lockedIcon; |
||||||
|
this.normalIcon = normalIcon; |
||||||
|
this.lockedTooltips = lockedTooltips; |
||||||
|
this.normalTooltips = normalTooltips; |
||||||
|
init(); |
||||||
|
} |
||||||
|
|
||||||
|
private void init() { |
||||||
|
boolean locked = EditLockUtils.isLocked(LockItem.CONNECTION); |
||||||
|
this.setIcon(locked ? lockedIcon : normalIcon); |
||||||
|
this.setToolTipText(locked ? lockedTooltips : normalTooltips); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateLockedState(EditLockChangeEvent event) { |
||||||
|
this.setIcon(event.isLocked() ? lockedIcon : normalIcon); |
||||||
|
this.setToolTipText(event.isLocked() ? lockedTooltips : normalTooltips); |
||||||
|
this.repaint(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package com.fr.design.gui.imenu; |
||||||
|
|
||||||
|
import com.fr.design.editlock.EditLockChangeEvent; |
||||||
|
import com.fr.design.editlock.EditLockChangeListener; |
||||||
|
import com.fr.report.LockItem; |
||||||
|
|
||||||
|
import javax.swing.Action; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
*/ |
||||||
|
public class UILockMenuItem extends UIMenuItem implements EditLockChangeListener { |
||||||
|
|
||||||
|
/** |
||||||
|
* 锁定状态的提示信息 |
||||||
|
*/ |
||||||
|
private String lockedTooltips; |
||||||
|
/** |
||||||
|
* 正常状态的提示信息 |
||||||
|
*/ |
||||||
|
private String normalTooltips; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前锁定项 |
||||||
|
*/ |
||||||
|
private LockItem lockItem; |
||||||
|
|
||||||
|
public UILockMenuItem(Action action, String lockedTooltips, String normalTooltips, LockItem lockItem) { |
||||||
|
super(action); |
||||||
|
this.lockedTooltips = lockedTooltips; |
||||||
|
this.normalTooltips = normalTooltips; |
||||||
|
this.lockItem = lockItem; |
||||||
|
setUI(new UILockMenuItemUI()); |
||||||
|
} |
||||||
|
|
||||||
|
public LockItem getLockItem() { |
||||||
|
return lockItem; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateLockedState(EditLockChangeEvent event) { |
||||||
|
this.setToolTipText(event.isLocked() ? lockedTooltips : normalTooltips); |
||||||
|
this.repaint(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
package com.fr.design.gui.imenu; |
||||||
|
|
||||||
|
import com.fr.design.editlock.EditLockUtils; |
||||||
|
|
||||||
|
import javax.swing.JMenuItem; |
||||||
|
import java.awt.Graphics; |
||||||
|
import java.awt.Rectangle; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Yvan |
||||||
|
* @version 10.0 |
||||||
|
* Created by Yvan on 2021/1/20 |
||||||
|
*/ |
||||||
|
public class UILockMenuItemUI extends UIMenuItemUI{ |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) { |
||||||
|
super.paintText(g, menuItem, textRect, text); |
||||||
|
// 除了绘制text之外,还需要画一下锁定图标
|
||||||
|
UILockMenuItem lockMenuItem = (UILockMenuItem) menuItem; |
||||||
|
if (EditLockUtils.isLocked(lockMenuItem.getLockItem())) { |
||||||
|
int width = menuItem.getWidth(); |
||||||
|
int height = menuItem.getHeight(); |
||||||
|
g.drawImage(EditLockUtils.LOCKED_IMAGE, (int) Math.round(width * 0.9), (int) Math.round(height * 0.1), 16, 16, null); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 959 B |
After Width: | Height: | Size: 1.2 KiB |
Loading…
Reference in new issue