diff --git a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java b/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java index bb4ba4ccc..5c12ff29c 100644 --- a/designer-base/src/main/java/com/fr/design/actions/UpdateAction.java +++ b/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); diff --git a/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java b/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java index 820de79e5..45502c073 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java +++ b/designer-base/src/main/java/com/fr/design/actions/server/ConnectionListAction.java @@ -1,19 +1,25 @@ 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.ibutton.UILockButton; +import com.fr.design.gui.imenu.UILockMenuItem; +import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.menu.MenuKeySet; +import com.fr.stable.StringUtils; 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.workspace.server.lock.editlock.LockItem; -import javax.swing.*; +import javax.swing.KeyStroke; import java.awt.event.ActionEvent; import java.util.Map; @@ -53,8 +59,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 +110,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, StringUtils.EMPTY, 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; + } } diff --git a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java b/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java index 468fb1f98..14795066d 100644 --- a/designer-base/src/main/java/com/fr/design/actions/server/GlobalTableDataAction.java +++ b/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,18 +12,24 @@ 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; import com.fr.file.TableDataConfig; +import com.fr.stable.StringUtils; import com.fr.transaction.CallBackAdaptor; import com.fr.transaction.Configurations; import com.fr.transaction.WorkerFacade; +import com.fr.workspace.server.lock.editlock.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 +71,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 +103,8 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS globalTableDataDialog.setDoOKSucceed(false); return; } - + // 关闭服务器数据集页面,为其解锁 + EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA); DesignTableDataManager.clearGlobalDs(); // 保存时 移除服务器数据集列名缓存 for (String name : tableDataConfig.getTableDatas().keySet()) { @@ -117,6 +131,13 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS } })); } + + @Override + public void doCancel() { + super.doCancel(); + // 关闭服务器数据集页面,为其解锁 + EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA); + } }); globalTableDataDialog.setVisible(true); } @@ -166,4 +187,21 @@ public class GlobalTableDataAction extends UpdateAction implements ResponseDataS public void fireDSChanged(Map 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, StringUtils.EMPTY, 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; + } } diff --git a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java index 83740f685..34482d0d2 100644 --- a/designer-base/src/main/java/com/fr/design/data/BasicTableDataTreePane.java +++ b/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; + } } /** diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java index f4a7910b1..91813418b 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java +++ b/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.workspace.server.lock.editlock.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,25 @@ 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.setIcon(IconUtils.readIcon("/com/fr/design/images/m_web/connection")); + editButton.setPreferredSize(buttonSize); + editButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + editItems(); + } + }); + ConnectionLockChangeChecker.getInstance().addEditLockChangeListener((UILockButton) editButton); + return editButton; + } + /* * 刷新ComboBox.items */ @@ -97,6 +125,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 +145,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 +166,13 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { })); } + + @Override + public void doCancel() { + // 关闭定义数据连接页面,为其解锁 + super.doCancel(); + EditLockUtils.unlock(LockItem.CONNECTION); + } }); connectionListDialog.setVisible(true); refreshItems(); @@ -158,4 +202,4 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel { } } } -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java b/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java index 1c61eea26..f06d1405b 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java +++ b/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 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 items(); - + /* * 弹出对话框编辑Items */ protected abstract void editItems(); -} \ No newline at end of file +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/ConnectionLockChangeChecker.java b/designer-base/src/main/java/com/fr/design/editlock/ConnectionLockChangeChecker.java new file mode 100644 index 000000000..ac80cd53c --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/editlock/ConnectionLockChangeChecker.java @@ -0,0 +1,25 @@ +package com.fr.design.editlock; + + +import com.fr.workspace.server.lock.editlock.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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java new file mode 100644 index 000000000..13ac921e3 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeChecker.java @@ -0,0 +1,67 @@ +package com.fr.design.editlock; + +import com.fr.concurrent.NamedThreadFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.workspace.WorkContext; +import com.fr.workspace.server.lock.editlock.EditLockOperator; +import com.fr.workspace.server.lock.editlock.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 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() { + for (EditLockChangeListener listener : this.listeners) { + listener.updateLockedState(new EditLockChangeEvent(isLocked)); + } + } +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeEvent.java b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeEvent.java new file mode 100644 index 000000000..66420fd0b --- /dev/null +++ b/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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeListener.java b/designer-base/src/main/java/com/fr/design/editlock/EditLockChangeListener.java new file mode 100644 index 000000000..dcabe87cc --- /dev/null +++ b/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); +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java b/designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java new file mode 100644 index 000000000..20708462d --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/editlock/EditLockUtils.java @@ -0,0 +1,69 @@ +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.workspace.WorkContext; +import com.fr.workspace.server.lock.editlock.EditLockOperator; +import com.fr.workspace.server.lock.editlock.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 = IconUtils.readIcon("/com/fr/design/images/m_web/warningIcon"); + + /** + * 数据连接锁定中 + */ + 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-Engine_Report_Tooltips"); + + /** + * 已经被锁,跳出弹窗提示 + */ + 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); + } +} diff --git a/designer-base/src/main/java/com/fr/design/editlock/ServerTableDataLockChangeChecker.java b/designer-base/src/main/java/com/fr/design/editlock/ServerTableDataLockChangeChecker.java new file mode 100644 index 000000000..a3f2bbbf4 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/editlock/ServerTableDataLockChangeChecker.java @@ -0,0 +1,23 @@ +package com.fr.design.editlock; + +import com.fr.workspace.server.lock.editlock.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; + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/ibutton/UILockButton.java b/designer-base/src/main/java/com/fr/design/gui/ibutton/UILockButton.java new file mode 100644 index 000000000..aa643b6c1 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ibutton/UILockButton.java @@ -0,0 +1,46 @@ +package com.fr.design.gui.ibutton; + +import com.fr.design.editlock.EditLockChangeEvent; +import com.fr.design.editlock.EditLockChangeListener; + +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; + } + + @Override + public void updateLockedState(EditLockChangeEvent event) { + this.setIcon(event.isLocked() ? lockedIcon : normalIcon); + this.setToolTipText(event.isLocked() ? lockedTooltips : normalTooltips); + this.repaint(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItem.java b/designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItem.java new file mode 100644 index 000000000..092b76516 --- /dev/null +++ b/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.workspace.server.lock.editlock.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(); + } +} diff --git a/designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItemUI.java b/designer-base/src/main/java/com/fr/design/gui/imenu/UILockMenuItemUI.java new file mode 100644 index 000000000..c0f70795b --- /dev/null +++ b/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); + } + + } +} diff --git a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java b/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java index acd906897..3d343ab93 100644 --- a/designer-base/src/main/java/com/fr/design/os/impl/DatabaseDialogAction.java +++ b/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.workspace.server.lock.editlock.LockItem; import static com.fr.design.actions.server.ConnectionListAction.doWithDatasourceManager; /** @@ -53,6 +52,8 @@ public class DatabaseDialogAction implements OSBasedAction { databaseListDialog.setDoOKSucceed(false); return; } + // 定义数据连接弹窗关闭后,解锁 + EditLockUtils.unlock(LockItem.CONNECTION); Configurations.modify(new WorkerFacade(ConnectionConfig.class) { @Override public void run() { @@ -71,6 +72,13 @@ public class DatabaseDialogAction implements OSBasedAction { } })); } + + @Override + public void doCancel() { + super.doCancel(); + // 定义数据连接弹窗关闭后,解锁 + EditLockUtils.unlock(LockItem.CONNECTION); + } }); databaseListDialog.setVisible(true); } diff --git a/designer-base/src/main/resources/com/fr/design/images/m_web/connection_locked_normal.svg b/designer-base/src/main/resources/com/fr/design/images/m_web/connection_locked_normal.svg new file mode 100644 index 000000000..b1b9d1792 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/m_web/connection_locked_normal.svg @@ -0,0 +1,15 @@ + + + 编组 3 + + + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/m_web/locked_normal.svg b/designer-base/src/main/resources/com/fr/design/images/m_web/locked_normal.svg new file mode 100644 index 000000000..b3b2ac74f --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/m_web/locked_normal.svg @@ -0,0 +1,14 @@ + + + 编组 2 + + + + + + + + + + + \ No newline at end of file diff --git a/designer-base/src/main/resources/com/fr/design/images/m_web/warningIcon_normal.svg b/designer-base/src/main/resources/com/fr/design/images/m_web/warningIcon_normal.svg new file mode 100644 index 000000000..b7748925d --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/m_web/warningIcon_normal.svg @@ -0,0 +1,21 @@ + + + icon_WarningIcon_normal + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java b/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java index a7ef4f108..0a572e672 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerWorkspaceProvider.java +++ b/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