Browse Source

REPORT-58744 【主题切换】撤销操作后,样式设置不符合预期

【问题原因】
目前的撤销回退机制是基于AbstractNoScrollPane的自动注册
回调来完成的,灵活性较低,且存在重复注册监听器的问题,
导致一个交互操作会产生多个撤销回退,不适用于日趋复杂的
交互逻辑,后面需要想办法重新设计下。

针对主题的撤销回退,主要原因是跟随主题切换到自定义时,需要将
自定义样式面板设置为跟随主题时一样的配置,但因为上述自动发送
属性更新的逻辑,导致中间产生了大量无效的撤销回退状态。因此
需要临时禁止AbstractAttrNoScrollPane的自动发送属性变化
事件的行为,待面板内容更新完毕后,再恢复自动发送.

【改动思路】
同上
bugfix/11.0
Starryi 3 years ago
parent
commit
fcaf293f10
  1. 14
      designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java
  2. 47
      designer-base/src/main/java/com/fr/design/gui/frpane/AttributeChangeUtils.java
  3. 16
      designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java
  4. 49
      designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java

14
designer-base/src/main/java/com/fr/design/gui/frpane/AbstractAttrNoScrollPane.java

@ -24,6 +24,16 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane {
private AttributeChangeListener listener;
private String globalName = "";
private boolean autoFireAttributesChanged = true;
public boolean isAutoFireAttributesChanged() {
return this.autoFireAttributesChanged;
}
public void setAutoFireAttributesChanged(boolean autoFireAttributesChanged) {
this.autoFireAttributesChanged = autoFireAttributesChanged;
}
protected AbstractAttrNoScrollPane() {
initAll();
}
@ -127,7 +137,9 @@ public abstract class AbstractAttrNoScrollPane extends BasicPane {
public void attributeChanged() {
synchronized (this) {
if (listener != null) {
listener.attributeChange();
if (autoFireAttributesChanged) {
listener.attributeChange();
}
}
}
}

47
designer-base/src/main/java/com/fr/design/gui/frpane/AttributeChangeUtils.java

@ -0,0 +1,47 @@
package com.fr.design.gui.frpane;
import java.awt.Component;
import java.awt.Container;
/**
* @author Starryi
* @version 1.0
* Created by Starryi on 2021/9/17
*/
public class AttributeChangeUtils {
private static AbstractAttrNoScrollPane findNearestAttrNoScrollPaneAncestor(Component c) {
for(Container p = c.getParent(); p != null; p = p.getParent()) {
if (p instanceof AbstractAttrNoScrollPane) {
return (AbstractAttrNoScrollPane) p;
}
}
return null;
}
public static void changeComposedUI(Component composedComponent, boolean fireMiddleStateChanged, UIChangeAction action) {
AbstractAttrNoScrollPane attrPane = findNearestAttrNoScrollPaneAncestor(composedComponent);
boolean oldAutoFire = true;
if (!fireMiddleStateChanged) {
// 禁止属性面板自动处理属性更新
if (attrPane != null) {
oldAutoFire = attrPane.isAutoFireAttributesChanged();
attrPane.setAutoFireAttributesChanged(false);
}
}
// 更新UI
action.changeComposedUI();
if (!fireMiddleStateChanged) {
// 恢复属性面板自动处理属性更新
if (attrPane != null) {
attrPane.setAutoFireAttributesChanged(oldAutoFire);
}
}
}
public interface UIChangeAction {
void changeComposedUI();
}
}

16
designer-base/src/main/java/com/fr/design/gui/style/FollowingThemePane.java

@ -5,6 +5,7 @@ import com.fr.design.dialog.BasicPane;
import com.fr.design.event.UIObserver;
import com.fr.design.event.UIObserverListener;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.gui.frpane.AttributeChangeUtils;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
@ -52,12 +53,15 @@ public class FollowingThemePane extends BasicPane implements UIObserver {
followingThemeButtonGroup.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (FollowingThemeActionChangeListener changeListener : changeListeners) {
changeListener.onFollowingTheme(isFollowingTheme());
}
invalidate();
// 与主题相关的属性面板更新完毕后,再通知外层更新数据
AttributeChangeUtils.changeComposedUI(FollowingThemePane.this, false, new AttributeChangeUtils.UIChangeAction() {
@Override
public void changeComposedUI() {
for (FollowingThemeActionChangeListener changeListener : changeListeners) {
changeListener.onFollowingTheme(isFollowingTheme());
}
invalidate();
}
});
if (uiObserverListener != null) {
uiObserverListener.doChange();
}

49
designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/style/StylePane.java

@ -6,6 +6,7 @@ import com.fr.design.designer.IntervalConstants;
import com.fr.design.dialog.BasicPane;
import com.fr.design.event.UIObserver;
import com.fr.design.event.UIObserverListener;
import com.fr.design.gui.frpane.AttributeChangeUtils;
import com.fr.design.gui.ibutton.UIButtonGroup;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
@ -73,27 +74,13 @@ public class StylePane extends BasicPane implements UIObserver {
followingThemeButtonGroup.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int selectedIndex = followingThemeButtonGroup.getSelectedIndex();
cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[selectedIndex]);
if (selectedIndex == 1) {
// 对于同一个单元格,跟随主题切换到自定义,自定义中的配置与其保持一致
NameStyle lastSelectedNameStyle = themedCellStyleListPane.updateBean();
if (lastSelectedNameStyle != null) {
Style lastSelectedRealStyle = lastSelectedNameStyle.getRealStyle();
try {
lastSelectedRealStyle = (Style) lastSelectedRealStyle.clone();
if (lastSelectedRealStyle != null) {
customStylePane.populateBean(lastSelectedRealStyle);
}
} catch (CloneNotSupportedException ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
AttributeChangeUtils.changeComposedUI(StylePane.this, false, new AttributeChangeUtils.UIChangeAction() {
@Override
public void changeComposedUI() {
int selectedIndex = followingThemeButtonGroup.getSelectedIndex();
onFollowingThemeSettingChanged(selectedIndex, selectedIndex == 0);
}
} else {
// 对于同一个单元格,自定义切换到跟随主题,跟随主题选中"默认"样式,并使用默认样式设置选中的单元格
themedCellStyleListPane.reset();
}
});
fireStateChanged();
}
});
@ -109,6 +96,28 @@ public class StylePane extends BasicPane implements UIObserver {
IntervalConstants.INTERVAL_L1, 0);
}
private void onFollowingThemeSettingChanged(int selectedIndex, boolean isFollowingTheme) {
cardLayout.show(contentPane, FOLLOWING_THEME_STRING_ARRAYS[selectedIndex]);
if (!isFollowingTheme) {
// 对于同一个单元格,跟随主题切换到自定义,自定义中的配置与其保持一致
NameStyle lastSelectedNameStyle = themedCellStyleListPane.updateBean();
if (lastSelectedNameStyle != null) {
Style lastSelectedRealStyle = lastSelectedNameStyle.getRealStyle();
try {
lastSelectedRealStyle = (Style) lastSelectedRealStyle.clone();
if (lastSelectedRealStyle != null) {
customStylePane.populateBean(lastSelectedRealStyle);
}
} catch (CloneNotSupportedException ex) {
FineLoggerFactory.getLogger().error(ex.getMessage(), ex);
}
}
} else {
// 对于同一个单元格,自定义切换到跟随主题,跟随主题选中"默认"样式,并使用默认样式设置选中的单元格
themedCellStyleListPane.reset();
}
}
protected JPanel createTabbedContentPane() {
JPanel contentPane = new JPanel(cardLayout) {
@Override

Loading…
Cancel
Save