@ -1,13 +1,14 @@
package com.fr.design.data.datapane ;
import com.fr.design.ui.util.UIUtil ;
import java.awt.Component ;
import java.awt.event.ItemEvent ;
import java.util.Iterator ;
import java.util.Map.Entry ;
import javax.swing.DefaultComboBoxModel ;
import javax.swing.JLabel ;
import javax.swing.JList ;
import javax.swing.event.AncestorEvent ;
import javax.swing.event.AncestorListener ;
import javax.swing.event.ChangeEvent ;
import javax.swing.event.ChangeListener ;
@ -32,16 +33,53 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
protected java . util . Map < String , TableDataWrapper > resMap ;
private java . util . Map < String , TableDataWrapper > dsMap ;
private static final long serialVersionUID = 1L ;
private boolean refresModel = false ;
private String treeName ; //树数据集本身的名字
private boolean refresh Model = false ;
private String treeName = StringUtils . EMPTY ; //树数据集本身的名字
private ChangeListener changeListener ;
/ * *
* 兼容插件调用
*
* @param source 传入的数据源
* /
public TableDataComboBox ( TableDataSource source ) {
this ( source , StringUtils . EMPTY ) ;
this ( ) ;
}
/ * *
* 兼容插件调用
*
* @param source 传入的数据源
* @param treeName 树数据集名称
* /
public TableDataComboBox ( TableDataSource source , String treeName ) {
this ( treeName ) ;
}
/ * *
* 根据树名称创建TableDataComboBox 。
*
* @param treeName 树数据集名称
* /
public TableDataComboBox ( String treeName ) {
this ( ) ;
// 传入树数据集名称
this . treeName = treeName ;
}
/ * *
* 初始化TableDataComboBox
* /
public TableDataComboBox ( ) {
super ( ) ;
this . treeName = treeName ;
setListCellRenderer ( ) ;
addComboBoxListener ( ) ;
}
/ * *
* 设置渲染器
* /
private void setListCellRenderer ( ) {
this . setRenderer ( new UIComboBoxRenderer ( ) {
private static final long serialVersionUID = 1L ;
@ -60,37 +98,66 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
return renderer ;
}
} ) ;
refresh ( source ) ;
registerDSChangeListener ( ) ;
}
/ * *
* refresh ComboBox
* @param source
* /
/ * *
* 在comboBox可见时添加数据集响应事件与refresh操作
* /
private void addComboBoxListener ( ) {
this . addAncestorListener ( new AncestorListener ( ) {
@Override
public void ancestorAdded ( AncestorEvent event ) {
registerDSChangeListener ( ) ;
refresh ( DesignTableDataManager . getEditingTableDataSource ( ) ) ;
}
@Override
public void ancestorRemoved ( AncestorEvent event ) {
DesignTableDataManager . removeDsChangeListener ( changeListener ) ;
}
@Override
public void ancestorMoved ( AncestorEvent event ) {
}
} ) ;
}
/ * *
* 刷新数据源并更新下拉框的模型和选中项
*
* @param source 数据源 , 用于刷新模型
* /
public void refresh ( TableDataSource source ) {
TableDataWrapper dataWrapper = getSelectedItem ( ) ;
refresModel = true ;
setResMap ( source ) ;
setDsMap ( ) ;
DefaultComboBoxModel model = new DefaultComboBoxModel ( ) ;
this . setModel ( model ) ;
model . addElement ( UIConstants . PENDING ) ;
Iterator < Entry < String , TableDataWrapper > > entryIt = dsMap . entrySet ( ) . iterator ( ) ;
while ( entryIt . hasNext ( ) ) {
TableDataWrapper tableDataWrapper = entryIt . next ( ) . getValue ( ) ;
if ( ! ComparatorUtils . equals ( tableDataWrapper . getTableDataName ( ) , treeName ) ) {
model . addElement ( tableDataWrapper ) ;
}
}
if ( dataWrapper ! = null ) {
if ( DesignTableDataManager . isDsNameChanged ( dataWrapper . getTableDataName ( ) ) ) {
this . setSelectedTableDataByName ( DesignTableDataManager . getChangedDsNameByOldDsName ( dataWrapper . getTableDataName ( ) ) ) ;
} else {
this . getModel ( ) . setSelectedItem ( dataWrapper ) ;
}
}
refresModel = false ;
UIUtil . executeAsyncTaskAndUpdateUI (
( ) - > {
setResMap ( source ) ;
setDsMap ( ) ;
return null ;
} ,
result - > refreshComboBoxModel ( )
) ;
}
/ * *
* 刷新下拉框模型 , 同时保留当前选中的数据项
* < p >
* 1 . 获取下拉框中当前选中的数据项
* 2 . 刷新下拉框的模型 ( 清空并重新填充数据 ) , 此操作会重置选中的数据项
* 3 . 在刷新模型后 , 恢复之前选中的数据项
* < p >
* 关于 ` refreshModel ` 的作用 :
* 1 . * * 抑制事件触发 * * : 下拉框模型在调用 ` addElement ` 方法时会触发 ` fireItemStateChanged ` 事件 ,
* 通过标记 ` refreshModel ` , 可以在刷新过程中抑制此事件
* 2 . * * 处理异步和顺序问题 * * : 由于取数操作是异步的 , 可能会导致回调后的 UI 操作与其他逻辑 ( 如 ` populateBean ` ) 的调用顺序交错 。
* 标记 ` refreshModel ` 可确保在刷新模型时 , 不触发选中事件 , 从而避免逻辑干扰
* 3 . * * 逻辑清晰性 * * : 刷新模型本质上是更新数据源的操作 , 不应触发与用户交互相关的选中事件 , 避免对上层逻辑造成额外负担
* /
private void refreshComboBoxModel ( ) {
refreshModel = true ;
TableDataWrapper selectedItem = getSelectedItem ( ) ;
refreshModel ( ) ;
updateSelectedItem ( selectedItem ) ;
refreshModel = false ;
}
protected void setResMap ( TableDataSource source ) {
@ -101,6 +168,26 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
dsMap = DesignTableDataManager . getAllDataSetIncludingProcedure ( resMap ) ;
}
private void refreshModel ( ) {
//创建ComboBox模型并设置
DefaultComboBoxModel model = new DefaultComboBoxModel ( ) ;
this . setModel ( model ) ;
model . addElement ( UIConstants . PENDING ) ;
// 遍历添加所有数据项到模型,树数据集comboBox下拉模型中排除掉本身
dsMap . values ( ) . stream ( )
. filter ( tableDataWrapper - > tableDataWrapper ! = null & & ! ComparatorUtils . equals ( tableDataWrapper . getTableDataName ( ) , treeName ) )
. forEach ( model : : addElement ) ;
}
private void updateSelectedItem ( TableDataWrapper dataWrapper ) {
if ( dataWrapper ! = null ) {
if ( DesignTableDataManager . isDsNameChanged ( dataWrapper . getTableDataName ( ) ) ) {
this . setSelectedTableData ( DesignTableDataManager . getChangedDsNameByOldDsName ( dataWrapper . getTableDataName ( ) ) ) ;
} else {
this . getModel ( ) . setSelectedItem ( dataWrapper ) ;
}
}
}
/ * *
@ -117,8 +204,18 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
}
public void setSelectedTableDataByName ( String name ) {
TableDataWrapper tableDataWrappe = dsMap . get ( name ) = = null ? dsMap . get ( name + "_P_CURSOR" ) : dsMap . get ( name ) ;
this . getModel ( ) . setSelectedItem ( tableDataWrappe ) ;
setResMap ( DesignTableDataManager . getEditingTableDataSource ( ) ) ;
setDsMap ( ) ;
// 数据集名称修改后控件传入的还是旧名称
if ( DesignTableDataManager . isDsNameChanged ( name ) ) {
name = DesignTableDataManager . getChangedDsNameByOldDsName ( name ) ;
}
setSelectedTableData ( name ) ;
}
private void setSelectedTableData ( String name ) {
TableDataWrapper tableDataWrapper = dsMap . get ( name ) = = null ? dsMap . get ( name + "_P_CURSOR" ) : dsMap . get ( name ) ;
this . getModel ( ) . setSelectedItem ( tableDataWrapper ) ;
}
@Override
@ -132,7 +229,7 @@ public class TableDataComboBox extends UIComboBox implements Prepare4DataSourceC
//august:addElement方法竟然会fireItemStateChanged,蛋疼
@Override
protected void fireItemStateChanged ( ItemEvent e ) {
if ( ! refresModel ) {
if ( ! refresh Model ) {
super . fireItemStateChanged ( e ) ;
}
}