Browse Source

Pull request #3439: REPORT-43833 【10.0.14】远程设计数据连接/服务器数据集增加锁定

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
parent
commit
ff08b8bc73
  1. 52
      designer-base/src/main/java/com/fr/design/actions/UpdateAction.java
  2. 37
      designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java
  3. 43
      designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java
  4. 23
      designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java
  5. 47
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  6. 58
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  7. 25
      designer-base/src/main/java/com/fr/design/editlock/ConnectionLockChangeChecker.java
  8. 73
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java
  9. 25
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeEvent.java
  10. 16
      designer-base/src/main/java/com/fr/design/editlock/EditLockChangeListener.java
  11. 79
      designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java
  12. 23
      designer-base/src/main/java/com/fr/design/editlock/ServerTableDataLockChangeChecker.java
  13. 55
      designer-base/src/main/java/com/fr/design/gui/ibutton/UILockButton.java
  14. 47
      designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItem.java
  15. 28
      designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItemUI.java
  16. 14
      designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java
  17. 15
      designer-base/src/main/resources/com/fr/design/images/m_web/connection_locked_normal.svg
  18. 14
      designer-base/src/main/resources/com/fr/design/images/m_web/locked_normal.svg
  19. BIN
      designer-base/src/main/resources/com/fr/design/images/m_web/warningIcon.png
  20. 14
      designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java

52
designer-base/src/main/java/com/fr/design/actions/UpdateAction.java

@ -339,33 +339,37 @@ public abstract class UpdateAction extends ShortCut implements Action {
if (!(object instanceof AbstractButton)) {
UIButton button = null;
button = new UIButton();
// 添加一个名字作为自动化测试用
button.setName(getName());
button.set4ToolbarButton();
//设置属性.
Integer mnemonicInteger = (Integer) this.getValue(Action.MNEMONIC_KEY);
if (mnemonicInteger != null) {
button.setMnemonic((char) mnemonicInteger.intValue());
}
button.setIcon((Icon) this.getValue(Action.SMALL_ICON));
setPressedIcon4Button(button);
setDisabledIcon4Button(button);
button.addActionListener(this);
object = initButton(button, UIButton.class.getName());
}
button.registerKeyboardAction(this, this.getAccelerator(), JComponent.WHEN_IN_FOCUSED_WINDOW);
return (JComponent) object;
}
this.putValue(UIButton.class.getName(), button);
button.setText(StringUtils.EMPTY);
button.setEnabled(this.isEnabled());
protected JComponent initButton(UIButton button, String name) {
// 添加一个名字作为自动化测试用
button.setName(getName());
button.set4ToolbarButton();
//peter:产生tooltip
button.setToolTipText(getToolTipText());
object = button;
//设置属性.
Integer mnemonicInteger = (Integer) this.getValue(Action.MNEMONIC_KEY);
if (mnemonicInteger != null) {
button.setMnemonic((char) mnemonicInteger.intValue());
}
return (JComponent) object;
button.setIcon((Icon) this.getValue(Action.SMALL_ICON));
setPressedIcon4Button(button);
setDisabledIcon4Button(button);
button.addActionListener(this);
button.registerKeyboardAction(this, this.getAccelerator(), JComponent.WHEN_IN_FOCUSED_WINDOW);
this.putValue(name, button);
button.setText(StringUtils.EMPTY);
button.setEnabled(this.isEnabled());
//peter:产生tooltip
button.setToolTipText(getToolTipText());
return button;
}
/**
@ -641,14 +645,14 @@ public abstract class UpdateAction extends ShortCut implements Action {
shortPinyin.append(PinyinHelper.getShortPinyin(title)).append(separator);
}
private void setPressedIcon4Button(AbstractButton button) {
protected void setPressedIcon4Button(AbstractButton button) {
Icon pressedIcon = (Icon) this.getValue(UpdateAction.PRESSED_ICON);
if (pressedIcon != null && pressedIcon instanceof SVGIcon) {
button.setPressedIcon(pressedIcon);
}
}
private void setDisabledIcon4Button(AbstractButton button) {
protected void setDisabledIcon4Button(AbstractButton button) {
Icon disabledIcon = (Icon) this.getValue(UpdateAction.DISABLED_ICON);
if (disabledIcon != null && disabledIcon instanceof SVGIcon) {
button.setDisabledIcon(disabledIcon);

37
designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java

@ -1,19 +1,23 @@
package com.fr.design.actions.server;
import com.fr.base.svg.IconUtils;
import com.fr.data.impl.Connection;
import com.fr.design.actions.UpdateAction;
import com.fr.design.data.datapane.connect.ConnectionShowPane;
import com.fr.design.data.datapane.connect.DatabaseConnectionPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.gui.NameInspector;
import com.fr.design.gui.imenu.UILockMenuItem;
import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.menu.MenuKeySet;
import com.fr.stable.os.support.OSBasedAction;
import com.fr.stable.os.support.OSSupportCenter;
import com.fr.design.os.impl.DatabaseDialogAction;
import com.fr.file.ConnectionConfig;
import com.fr.report.LockItem;
import javax.swing.*;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.util.Map;
@ -53,8 +57,16 @@ public class ConnectionListAction extends UpdateAction {
* @param evt 事件
*/
public void actionPerformed(ActionEvent evt) {
OSBasedAction osBasedAction = OSSupportCenter.getAction(DatabaseDialogAction.class);
osBasedAction.execute();
// 尝试为数据连接加锁
boolean actionLock = EditLockUtils.lock(LockItem.CONNECTION);
if (!actionLock) {
// 锁定失败,代表已经被其他用户锁定,跳出弹窗提示
EditLockUtils.showLockMessage();
} else {
// 锁定成功,执行后续操作
OSBasedAction osBasedAction = OSSupportCenter.getAction(DatabaseDialogAction.class);
osBasedAction.execute();
}
}
/**
@ -96,4 +108,21 @@ public class ConnectionListAction extends UpdateAction {
public void update() {
this.setEnabled(true);
}
@Override
public UIMenuItem createMenuItem() {
Object object = this.getValue(UILockMenuItem.class.getName());
if (object == null && !(object instanceof UILockMenuItem)) {
UILockMenuItem menuItem = new UILockMenuItem(this, EditLockUtils.CONNECTION_LOCKED_TOOLTIPS, null, LockItem.CONNECTION);
// 设置名字用作单元测
menuItem.setName(getName());
setPressedIcon4Button(menuItem);
setDisabledIcon4Button(menuItem);
object = menuItem;
this.putValue(UILockMenuItem.class.getName(), object);
ConnectionLockChangeChecker.getInstance().addEditLockChangeListener((UILockMenuItem)object);
}
return (UILockMenuItem) object;
}
}

43
designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java

@ -4,7 +4,6 @@
package com.fr.design.actions.server;
import com.fr.base.TableData;
import com.fr.base.svg.IconUtils;
import com.fr.design.DesignModelAdapter;
import com.fr.design.actions.UpdateAction;
import com.fr.design.data.DesignTableDataManager;
@ -13,7 +12,11 @@ import com.fr.design.data.tabledata.ResponseDataSourceChange;
import com.fr.design.data.tabledata.tabledatapane.TableDataManagerPane;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.editlock.ServerTableDataLockChangeChecker;
import com.fr.design.gui.NameInspector;
import com.fr.design.gui.imenu.UILockMenuItem;
import com.fr.design.gui.imenu.UIMenuItem;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.design.menu.MenuKeySet;
@ -22,9 +25,10 @@ import com.fr.file.TableDataConfig;
import com.fr.transaction.CallBackAdaptor;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerFacade;
import com.fr.report.LockItem;
import javax.swing.KeyStroke;
import java.awt.*;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;
@ -66,6 +70,14 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS
* @param evt 事件
*/
public void actionPerformed(ActionEvent evt) {
// 尝试为服务器数据集加锁
boolean actionLock = EditLockUtils.lock(LockItem.SERVER_TABLE_DATA);
if (!actionLock) {
// 锁定失败,代表已经被其他用户锁定,跳出弹窗提示
EditLockUtils.showLockMessage();
return;
}
// 锁定成功,执行后续操作
final DesignerFrame designerFrame = DesignerContext.getDesignerFrame();
final TableDataConfig tableDataConfig = TableDataConfig.getInstance();
final TableDataManagerPane globalTableDataPane = new TableDataManagerPane() {
@ -90,7 +102,6 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS
globalTableDataDialog.setDoOKSucceed(false);
return;
}
DesignTableDataManager.clearGlobalDs();
// 保存时 移除服务器数据集列名缓存
for (String name : tableDataConfig.getTableDatas().keySet()) {
@ -114,9 +125,18 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS
// 刷新共有数据集
TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter());
fireDSChanged(globalTableDataPane.getDsChangedNameMap());
// 关闭服务器数据集页面,为其解锁
EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA);
}
}));
}
@Override
public void doCancel() {
super.doCancel();
// 关闭服务器数据集页面,为其解锁
EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA);
}
});
globalTableDataDialog.setVisible(true);
}
@ -166,4 +186,21 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS
public void fireDSChanged(Map<String, String> map) {
DesignTableDataManager.fireDSChanged(map);
}
@Override
public UIMenuItem createMenuItem() {
Object object = this.getValue(UILockMenuItem.class.getName());
if (object == null && !(object instanceof UILockMenuItem)) {
UILockMenuItem menuItem = new UILockMenuItem(this, EditLockUtils.SERVER_TABLEDATA_LOCKED_TOOLTIPS, null, LockItem.SERVER_TABLE_DATA);
// 设置名字用作单元测
menuItem.setName(getName());
setPressedIcon4Button(menuItem);
setDisabledIcon4Button(menuItem);
object = menuItem;
this.putValue(UILockMenuItem.class.getName(), object);
ServerTableDataLockChangeChecker.getInstance().addEditLockChangeListener((UILockMenuItem)object);
}
return (UILockMenuItem) object;
}
}

23
designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java

@ -18,7 +18,10 @@ import com.fr.design.data.tabledata.wrapper.TableDataWrapper;
import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane;
import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.gui.ibutton.UIHeadGroup;
import com.fr.design.gui.ibutton.UILockButton;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.icon.IconPathConstants;
@ -31,8 +34,11 @@ import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTree;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
@ -439,6 +445,23 @@ public abstract class BasicTableDataTreePane extends DockingView implements Resp
this.setMnemonic('D');
this.setSmallIcon("/com/fr/design/images/m_web/connection");
}
@Override
public JComponent createToolBarComponent() {
Object object = this.getValue(UILockButton.class.getName());
if (!(object instanceof AbstractButton)) {
UILockButton button = new UILockButton(
EditLockUtils.CONNECTION_LOCKED_ICON,
(Icon) this.getValue(Action.SMALL_ICON),
EditLockUtils.CONNECTION_LOCKED_TOOLTIPS,
getToolTipText()
);
initButton(button, UILockButton.class.getName());
object = button;
ConnectionLockChangeChecker.getInstance().addEditLockChangeListener((UILockButton)object);
}
return (JComponent) object;
}
}
/**

47
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -1,5 +1,6 @@
package com.fr.design.data.datapane.connect;
import com.fr.base.svg.IconUtils;
import com.fr.data.impl.AbstractDatabaseConnection;
import com.fr.data.impl.Connection;
import com.fr.data.impl.NameDatabaseConnection;
@ -7,6 +8,10 @@ import com.fr.design.DesignerEnvManager;
import com.fr.design.actions.server.ConnectionListAction;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ibutton.UILockButton;
import com.fr.design.mainframe.DesignerContext;
import com.fr.file.ConnectionConfig;
import com.fr.general.ComparatorUtils;
@ -16,8 +21,12 @@ import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerFacade;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import com.fr.report.LockItem;
import javax.swing.SwingUtilities;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
@ -56,6 +65,24 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
refreshItems();
}
@Override
protected UIButton initEditButton(UIButton editButton, Dimension buttonSize) {
editButton = new UILockButton(
EditLockUtils.CONNECTION_LOCKED_ICON,
IconUtils.readIcon("/com/fr/design/images/m_web/connection"),
EditLockUtils.CONNECTION_LOCKED_TOOLTIPS,
StringUtils.EMPTY
);
editButton.setPreferredSize(buttonSize);
editButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
editItems();
}
});
ConnectionLockChangeChecker.getInstance().addEditLockChangeListener((UILockButton) editButton);
return editButton;
}
/*
* 刷新ComboBox.items
*/
@ -97,6 +124,14 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
* 弹出对话框编辑Items
*/
protected void editItems() {
// 尝试为数据连接加锁
boolean actionLock = EditLockUtils.lock(LockItem.CONNECTION);
if (!actionLock) {
// 锁定失败,代表已经被其他用户锁定,跳出弹窗提示
EditLockUtils.showLockMessage();
return;
}
// 锁定成功,执行后续操作
final ConnectionListPane connectionListPane = new ConnectionListPane();
final ConnectionConfig connectionConfig = ConnectionConfig.getInstance();
ConnectionConfig cloned = connectionConfig.mirror();
@ -109,7 +144,8 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
connectionListDialog.setDoOKSucceed(false);
return;
}
// 关闭定义数据连接页面,为其解锁
EditLockUtils.unlock(LockItem.CONNECTION);
Configurations.modify(new WorkerFacade(ConnectionConfig.class) {
@Override
public void run() {
@ -129,6 +165,13 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
}));
}
@Override
public void doCancel() {
// 关闭定义数据连接页面,为其解锁
super.doCancel();
EditLockUtils.unlock(LockItem.CONNECTION);
}
});
connectionListDialog.setVisible(true);
refreshItems();
@ -158,4 +201,4 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
}
}
}
}
}

58
designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java

@ -12,7 +12,7 @@ import java.awt.event.ActionListener;
public abstract class ItemEditableComboBoxPanel extends JPanel {
/**
*
*
*/
private static final long serialVersionUID = 1L;
@ -21,37 +21,29 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
return "";
}
};
protected UIComboBox itemComboBox;
protected UIButton editButton;
protected UIButton refreshButton;
public ItemEditableComboBoxPanel() {
super();
initComponents();
}
protected void initComponents() {
this.setLayout(FRGUIPaneFactory.createM_BorderLayout());
Dimension buttonSize = new Dimension(26, 20);
itemComboBox = new UIComboBox();
itemComboBox.setEnabled(true);
this.add(itemComboBox, BorderLayout.CENTER);
editButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/control-center2.png"));
refreshButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/refresh.png"));
JPanel jPanel = FRGUIPaneFactory.createNColumnGridInnerContainer_Pane(2, 4 ,4);
editButton = initEditButton(editButton, buttonSize);
jPanel.add(editButton);
jPanel.add(refreshButton);
this.add(jPanel, BorderLayout.EAST);
Dimension buttonSize = new Dimension(26, 20);
editButton.setPreferredSize(buttonSize);
editButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
editItems();
}
});
refreshButton.setPreferredSize(buttonSize);
refreshButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@ -59,32 +51,44 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
}
});
}
protected UIButton initEditButton(UIButton editButton, Dimension buttonSize) {
editButton = new UIButton(BaseUtils.readIcon("/com/fr/design/images/control/control-center2.png"));
editButton.setPreferredSize(buttonSize);
editButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
editItems();
}
});
return editButton;
}
/**
* 给itemComboBox添加ActionListener
*/
public void addComboBoxActionListener(ActionListener l) {
itemComboBox.addActionListener(l);
}
/*
* 刷新itemComboBox的内容
*/
protected void refreshItems() {
// 记录原来选中的Item,重新加载后需要再次选中
Object lastSelectedItem = itemComboBox.getSelectedItem();
DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel());
model.removeAllElements();
// 先加EMPTY,再加items
model.addElement(EMPTY);
java.util.Iterator<String> itemIt = items();
while(itemIt.hasNext()) {
model.addElement(itemIt.next());
}
// 再次选中之前选中的Item
int idx = model.getIndexOf(lastSelectedItem);
if(idx < 0) {
@ -92,16 +96,16 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
}
itemComboBox.setSelectedIndex(idx);
}
/*
* 得到其中的itemComboBox所选中的Item
*/
public String getSelectedItem() {
Object selected = itemComboBox.getSelectedItem();
return selected instanceof String ? (String)selected : null;
}
/*
* 选中name项
*/
@ -109,14 +113,14 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
DefaultComboBoxModel model = ((DefaultComboBoxModel) itemComboBox.getModel());
model.setSelectedItem(name);
}
/*
* 刷新ComboBox.items
*/
protected abstract java.util.Iterator<String> items();
/*
* 弹出对话框编辑Items
*/
protected abstract void editItems();
}
}

25
designer-base/src/main/java/com/fr/design/editlock/ConnectionLockChangeChecker.java

@ -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;
}
}

73
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java

@ -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));
}
}
});
}
}

25
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeEvent.java

@ -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;
}
}

16
designer-base/src/main/java/com/fr/design/editlock/EditLockChangeListener.java

@ -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);
}

79
designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java

@ -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);
}
}

23
designer-base/src/main/java/com/fr/design/editlock/ServerTableDataLockChangeChecker.java

@ -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;
}
}

55
designer-base/src/main/java/com/fr/design/gui/ibutton/UILockButton.java

@ -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();
}
}

47
designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItem.java

@ -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();
}
}

28
designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItemUI.java

@ -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);
}
}
}

14
designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java

@ -1,18 +1,17 @@
package com.fr.design.os.impl;
import com.fr.config.ServerPreferenceConfig;
import com.fr.design.data.datapane.connect.ConnectionManagerPane;
import com.fr.design.dcm.UniversalDatabaseOpener;
import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.DialogActionAdapter;
import com.fr.design.editlock.EditLockUtils;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.DesignerFrame;
import com.fr.file.ConnectionConfig;
import com.fr.stable.os.OperatingSystem;
import com.fr.stable.os.support.OSBasedAction;
import com.fr.transaction.CallBackAdaptor;
import com.fr.transaction.Configurations;
import com.fr.transaction.WorkerFacade;
import com.fr.report.LockItem;
import static com.fr.design.actions.server.ConnectionListAction.doWithDatasourceManager;
/**
@ -68,9 +67,18 @@ public class DatabaseDialogAction implements OSBasedAction {
@Override
public void afterCommit() {
DesignerContext.getDesignerBean("databasename").refreshBeanElement();
// 定义数据连接弹窗关闭后,解锁
EditLockUtils.unlock(LockItem.CONNECTION);
}
}));
}
@Override
public void doCancel() {
super.doCancel();
// 定义数据连接弹窗关闭后,解锁
EditLockUtils.unlock(LockItem.CONNECTION);
}
});
databaseListDialog.setVisible(true);
}

15
designer-base/src/main/resources/com/fr/design/images/m_web/connection_locked_normal.svg

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 3</title>
<g id="远程设计数据连接/服务器数据集增加锁定" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-162.000000, -121.000000)" id="template">
<g transform="translate(24.000000, 115.000000)">
<g id="编组-3" transform="translate(138.000000, 6.000000)">
<rect id="矩形" fill-opacity="0" fill="#FFFFFF" x="0" y="0" width="16" height="16"></rect>
<path d="M13.9931545,2 C14.5492199,2 15,2.44371665 15,2.99980749 L15,6.00019251 C15,6.18235446 14.9510312,6.35313811 14.8654084,6.50022573 C14.9510251,6.64542671 15,6.81651267 15,6.99980749 L15,8 L13.999,8 L14,6.99980749 L2.00684547,7 C2.00567632,7 2.00469979,7.12351139 2.00388585,7.32041361 L2.003125,7.53992312 C2.00300685,7.57996653 2.00289294,7.6215845 2.00278313,7.66454498 L2.00201498,8.01864019 L2.00184669,8.11271215 L2.00184669,8.11271215 L2.00113666,8.59786697 C2.00105585,8.66296526 2.00098034,8.72781696 2.00090983,8.7919289 L2.00000644,9.98367135 C2.00000205,9.99452107 2,10.0001925 2,10.0001925 L8,10 L8,10.999 L2.00684547,11 C2.00567632,11 2.00469979,11.1235114 2.00388585,11.3204136 L2.003125,11.5399231 C2.00300685,11.5799665 2.00289294,11.6215845 2.00278313,11.664545 L2.00201498,12.0186402 L2.00184669,12.1127121 L2.00184669,12.1127121 L2.00113666,12.597867 C2.00105585,12.6629653 2.00098034,12.727817 2.00090983,12.7919289 L2.00000644,13.9836714 C2.00000205,13.9945211 2,14.0001925 2,14.0001925 L8,14 L8,15 L2.00684547,15 C1.45078007,15 1,14.5562834 1,14.0001925 L1,10.9998075 C1,10.8176455 1.04896881,10.6468619 1.13459156,10.4997743 C1.04897491,10.3545733 1,10.1834873 1,10.0001925 L1,6.99980749 C1,6.81764554 1.04896881,6.64686189 1.13459156,6.49977427 C1.04897491,6.35457329 1,6.18348733 1,6.00019251 L1,2.99980749 C1,2.44762906 1.44994876,2 2.00684547,2 L13.9931545,2 Z M14,2.99980749 L2.00684547,3 C2.00567632,3 2.00469979,3.12351139 2.00388585,3.32041361 L2.003125,3.53992312 C2.00300685,3.57996653 2.00289294,3.6215845 2.00278313,3.66454498 L2.00201498,4.01864019 L2.00184669,4.11271215 L2.00184669,4.11271215 L2.00113666,4.59786697 C2.00105585,4.66296526 2.00098034,4.72781696 2.00090983,4.7919289 L2.00000644,5.98367135 C2.00000205,5.99452107 2,6.00019251 2,6.00019251 L13.9814047,6.00000045 C13.9891898,6.00000015 13.9931545,6 13.9931545,6 C13.9943237,6 13.9953002,5.87648861 13.9961142,5.67958639 L13.996875,5.46007688 C13.9969932,5.42003347 13.9971071,5.3784155 13.9972169,5.33545502 L13.997985,4.98135981 L13.9981533,4.88728785 L13.9981533,4.88728785 L13.9988633,4.40213303 C13.9989441,4.33703474 13.9990197,4.27218304 13.9990902,4.2080711 L14,2.99980749 Z M4,4 L4,5 L3,5 L3,4 L4,4 Z M6,4 L6,5 L5,5 L5,4 L6,4 Z" id="形状结合" fill="#333334" fill-rule="nonzero"></path>
<path d="M14,8 L14,10 L15,10 L15,15 L9,15 L9,10 L10,10 L10,8 L14,8 Z M13,12 L11,12 L11,13 L13,13 L13,12 Z M13,9 L11,9 L11,10 L13,10 L13,9 Z" id="形状结合" fill="#E21E20" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

14
designer-base/src/main/resources/com/fr/design/images/m_web/locked_normal.svg

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 2</title>
<g id="远程设计数据连接/服务器数据集增加锁定" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-476.000000, -106.000000)" id="列表/导航栏下拉列表">
<g transform="translate(243.000000, 70.000000)">
<g id="编组-2" transform="translate(233.000000, 36.000000)">
<rect id="矩形" fill="#FFFFFF" opacity="0" x="0" y="0" width="16" height="16"></rect>
<path d="M11,3 L11,6 L12,6 L12,13 L4,13 L4,6 L5,6 L5,3 L11,3 Z M10,9 L6,9 L6,10 L10,10 L10,9 Z M10,4 L6,4 L6,6 L10,6 L10,4 Z" id="形状结合" fill="#E21E20" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 959 B

BIN
designer-base/src/main/resources/com/fr/design/images/m_web/warningIcon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

14
designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java

@ -3,6 +3,8 @@ package com.fr.start.module;
import com.fr.design.DesignerEnvManager;
import com.fr.design.EnvChangeEntrance;
import com.fr.design.constants.DesignerLaunchStatus;
import com.fr.design.editlock.ConnectionLockChangeChecker;
import com.fr.design.editlock.ServerTableDataLockChangeChecker;
import com.fr.design.env.DesignerWorkspaceGenerator;
import com.fr.design.env.DesignerWorkspaceInfo;
import com.fr.design.env.LocalDesignerWorkspaceInfo;
@ -88,6 +90,12 @@ public class DesignerWorkspaceProvider extends Activator {
}
}
pluginErrorRemind();
editLockCheckerStart();
}
private void editLockCheckerStart() {
ConnectionLockChangeChecker.getInstance().start();
ServerTableDataLockChangeChecker.getInstance().start();
}
private void pluginErrorRemind() {
@ -102,6 +110,12 @@ public class DesignerWorkspaceProvider extends Activator {
@Override
public void stop() {
// void
editLockCheckerStop();
}
private void editLockCheckerStop() {
ConnectionLockChangeChecker.getInstance().stop();
ServerTableDataLockChangeChecker.getInstance().stop();
}
@Override

Loading…
Cancel
Save