自定义SWT控件五之自定义穿梭框

5、自定义穿梭框

package com.view.control.shuttlebox;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.global.constant.Constants;
import com.util.CollectionUtil;
import com.util.FileUtil;
import com.util.StringUtil;
import com.view.control.DefinedSearchText.SearchTextEvent;
import com.view.control.DefinedSearchText;
import com.view.control.select.SearchDropDown;
import com.view.swt.CustomMessageBox;
import com.view.swt.SWTResourceManager;
import com.view.swt.SWTUtil;
import com.view.swt.StyleTextLink;
import com.view.swt.CustomMessageBox.Model;
import com.view.util.ImageUtil;

public abstract class DefinedCommonSearchShuttleBox<T> extends SearchDropDown<T> {
    private static final Logger log = LoggerFactory.getLogger(DefinedCommonSearchShuttleBox.class);
    /***数字区域*****/
    protected CLabel num_label ;
    protected CLabel right_num_label;
    protected Composite rightScrolledContentComposite;
    protected StyleTextLink.StyleTextLinkEvent linkEvent;
    protected String noContentMention = "您可以更新获取选型数据后再进行查询";
    protected String linkText = "更新";
    protected SearchShuttleBoxEvent<T> searchShuttleBoxEvent;
    /***在左侧区域已选择的条目***/
    protected List<T> selectedList = new ArrayList<>();
    protected Map<T,Composite> selectMap = new HashMap<T,Composite>();
    /*****右侧区域选中的内容*******/
    protected Map<T,Composite> rightSelectMap = new HashMap<T,Composite>();
    /*****右侧区域所有数据****/
    protected List<T> rightDataList = new ArrayList<>();
    @Deprecated
    public DefinedCommonSearchShuttleBox(Composite parent, List<T> comboDataList, int comboRowWidth,
            SearchTextEvent<T> searchTextEvent) {
        super(parent, comboDataList, comboRowWidth, searchTextEvent);
    }

    public DefinedCommonSearchShuttleBox(Composite parent,DefinedSearchText.SearchTextEvent<T> searchTextEvent,int comboRowWidth){
        super(parent, searchTextEvent, comboRowWidth);
    }

    @Override
    public void paint() {
        Composite content_composite = new Composite(this.parent,SWT.NONE);
        GridData gd_content_composite = new GridData(SWT.FILL,SWT.FILL,true,true,1,1);
        content_composite.setLayoutData(gd_content_composite);
        GridLayout gl_content_composite = new GridLayout(3,false);
        gl_content_composite.marginWidth = 0;
        gl_content_composite.marginHeight = 0;
        gl_content_composite.horizontalSpacing = 5;
        gl_content_composite.verticalSpacing = 0;
        content_composite.setLayout(gl_content_composite);
        content_composite.setBackground(SWTResourceManager.getWhiteColor());
        //绘制左侧区域
        generateLeftComposite(content_composite);
        //绘制中间区域
        generateMiddleComposite(content_composite);
        //绘制右侧区域
        generateRightComposite(content_composite);
        if(!this.initEmpty){
            super.notifySearch();
        }
    }

    /**
     * 绘制左侧区域内容
     * @author wangfang5 2018年5月23日 上午11:04:28
     * @param content_composite
     */
    private void generateLeftComposite(Composite content_composite) {
        Composite left_content_composite = new Composite(content_composite, SWT.NONE);
        GridData gd_left_content_composite = new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1);
        left_content_composite.setLayoutData(gd_left_content_composite);
        GridLayout gl_left_content_composite = new GridLayout(1, true);
        gl_left_content_composite.marginHeight = 5;
        gl_left_content_composite.marginWidth = 5;
        gl_left_content_composite.verticalSpacing = 5;
        gl_left_content_composite.horizontalSpacing = 0;
        left_content_composite.setLayout(gl_left_content_composite);
        SWTUtil.paintBorder(left_content_composite, SWTResourceManager.getBorderColor());
        left_content_composite.setBackground(SWTResourceManager.getWhiteColor());

        // 绘制可选数字
        Composite title_composite = new Composite(left_content_composite, SWT.NONE);
        title_composite.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_title_composite = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
        title_composite.setLayoutData(gd_title_composite);
        GridLayout gl_title_composite = new GridLayout(2, false);
        gl_title_composite.verticalSpacing = 0;
        gl_title_composite.horizontalSpacing = 5;
        gl_title_composite.marginHeight = 0;
        gl_title_composite.marginWidth = 0;
        title_composite.setLayout(gl_title_composite);
        CLabel title_label = new CLabel(title_composite, SWT.NONE);
        title_label.setText("可选");
        title_label.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_title_label = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
        title_label.setLayoutData(gd_title_label);
        num_label = new CLabel(title_composite, SWT.NONE);
        num_label.setText("(当前选中0/0)");
        num_label.setBackground(SWTResourceManager.getWhiteColor());
        num_label.setForeground(SWTResourceManager.getTextColor());
        GridData gd_num_label = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
        num_label.setLayoutData(gd_num_label);

        searchTextEvent = new DefinedSearchText.SearchTextEvent<T>(){
            @Override
            public DefinedSearchText.SearchPageResult<T> search(Event event, String searchKeys, int pageNum, int pagePerNum, List<Object> filters) {
               if(null != searchShuttleBoxEvent){
                   return searchShuttleBoxEvent.search(event, searchKeys, pageNum, pagePerNum, filters);
               }else{
                   log.error(toLog("", "no searchTextEvent"));
                   return null;
               }
            }

            @Override
            public boolean beforeEvent(Event event,String searchKey) {
                if(null != searchShuttleBoxEvent){
                    String verifyMsg = searchShuttleBoxEvent.verifySearchContent(searchKey);
                    if(StringUtil.isNotNullAndEmpty(verifyMsg)){ //校验不通过
                        showErrorMention(verifyMsg);
                        return false;
                    }else{   //校验通过
                        showNormalMention();
                    }
                }
                externalBeforeEvent(event);
                beforeSearchClick(event);
                return true;
            }

            @Override
            public void afterEvent(Event event, List<T> dataList) {
                afterSearchClick(event,dataList);
            }
        };
        generateSearchCompoiste(left_content_composite);
    }
    /**
     * 搜索之前需要做的事情,将右侧中的数据作为筛选条件传递到搜索条件中
     * @param event
     */
    protected void externalBeforeEvent(Event event){
        if(event.button == 1){  //event.button == 1 表示点击搜索按钮
            selectedList.clear();
            selectMap.clear();
            replaceSearchExternalFilter(new ArrayList<>(rightDataList),0);
        }
    }

    /**
     * 绘制中间的区域
     * @param content_composite
     */
    private void generateMiddleComposite(Composite content_composite){
        Composite middle_composite = new Composite(content_composite,SWT.NONE);
        middle_composite.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_middle_composite = new GridData(SWT.FILL,SWT.CENTER,false,true,1,1);
        gd_middle_composite.widthHint = 50;
        middle_composite.setLayoutData(gd_middle_composite);
        GridLayout gl_middle_composite = new GridLayout(1,true);
        gl_middle_composite.verticalSpacing = 10;
        gl_middle_composite.marginHeight = 0;
        gl_middle_composite.marginWidth = 0;
        gl_middle_composite.horizontalSpacing = 0;
        middle_composite.setLayout(gl_middle_composite);

        //放置向右移动图标
        Label right_label = new Label(middle_composite,SWT.NONE);
        GridData gd_right_label = new GridData(SWT.CENTER,SWT.CENTER,false,false,1,1);
        gd_right_label.widthHint = 48;
        gd_right_label.heightHint = 32;
        right_label.setLayoutData(gd_right_label);
        right_label.setBackground(SWTResourceManager.getWhiteColor());
        right_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.SHUTTLE_RIGHT_IMG)));
        right_label.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        right_label.addListener(SWT.MouseDown, new Listener(){
            @Override
            public void handleEvent(Event event) {
                rightMoveEvent(event);
            }
        });

        //放置向左图标
        Label left_label = new Label(middle_composite,SWT.NONE);
        GridData gd_left_label= new GridData(SWT.CENTER,SWT.CENTER,true,false,1,1);
        gd_left_label.widthHint = 48;
        gd_left_label.heightHint = 32;
        left_label.setLayoutData(gd_left_label);
        left_label.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        left_label.setBackground(SWTResourceManager.getWhiteColor());
        left_label.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.SHUTTLE_LEFT_IMG)));
        left_label.addListener(SWT.MouseDown, new Listener(){
            @Override
            public void handleEvent(Event event) {
                leftMoveEvent(event);
            }
        });
    }

    /**
     * 向右移动触发的事件(绘制界面)
     * @param event
     */
    protected void rightMoveEvent(Event event){
        if(CollectionUtil.isEmpty(selectedList)){
            new CustomMessageBox(this.parent.getShell(), "请在左侧区域选择移动项!", Model.CONFIRM_MODEL).open();
            return;
        }
        boolean allowable = false;
        if(null == searchShuttleBoxEvent){
            allowable = true;
        }else if(searchShuttleBoxEvent.addEvent(selectedList,this)){
            allowable = true;
        }else{
            new CustomMessageBox(this.parent.getShell(), "向右测移动失败!", Model.CONFIRM_MODEL).open();
            return;
        }
        if(allowable){
            for(Entry<T, Composite> entry:selectMap.entrySet()){
                entry.getValue().dispose();
                //右侧绘制一个内容
                generateRightItem(entry.getKey());
                rightDataList.add(entry.getKey());
                this.totalCount--;
            }
            selectedList.clear();
            selectMap.clear();
            updateRightNum();
            updateLeftNum();
            notifyScrollSearch();
            relayoutScrollComposite();
            relayoutRightScrollComposite();
        }
    }

    /**
     * 绘制右侧的区域
     * @param content_composite
     */
    private void generateRightComposite(Composite content_composite){
        Composite right_content_composite = new Composite(content_composite, SWT.NONE);
        GridData gd_right_content_composite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
        right_content_composite.setLayoutData(gd_right_content_composite);
        GridLayout gl_right_content_composite = new GridLayout(1, true);
        gl_right_content_composite.marginHeight = 5;
        gl_right_content_composite.marginWidth = 5;
        gl_right_content_composite.verticalSpacing = 5;
        gl_right_content_composite.horizontalSpacing = 0;
        right_content_composite.setLayout(gl_right_content_composite);
        SWTUtil.paintBorder(right_content_composite, SWTResourceManager.getBorderColor());
        right_content_composite.setBackground(SWTResourceManager.getWhiteColor());

        // 绘制可选数字
        Composite title_composite = new Composite(right_content_composite, SWT.NONE);
        title_composite.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_title_composite = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
        title_composite.setLayoutData(gd_title_composite);
        GridLayout gl_title_composite = new GridLayout(2, false);
        gl_title_composite.verticalSpacing = 0;
        gl_title_composite.horizontalSpacing = 5;
        gl_title_composite.marginHeight = 0;
        gl_title_composite.marginWidth = 0;
        title_composite.setLayout(gl_title_composite);
        CLabel title_label = new CLabel(title_composite, SWT.NONE);
        title_label.setText("已选");
        title_label.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_title_label = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
        title_label.setLayoutData(gd_title_label);
        right_num_label = new CLabel(title_composite, SWT.NONE);
        right_num_label.setText("(0)");
        right_num_label.setBackground(SWTResourceManager.getWhiteColor());
        right_num_label.setForeground(SWTResourceManager.getTextColor());
        GridData gd_right_num_label = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
        right_num_label.setLayoutData(gd_right_num_label);
        generateRightListComposite(right_content_composite);
    }

    /**
     * 绘制右侧区域内容
     * @param right_composite
     */
    private void generateRightListComposite(Composite right_composite){
        ScrolledComposite rightScrolledComposite = new ScrolledComposite(right_composite, SWT.V_SCROLL);
        rightScrolledComposite.setExpandHorizontal(true);
        rightScrolledComposite.setExpandVertical(true);
        rightScrolledComposite.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_rightScrolledComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
        rightScrolledComposite.setLayoutData(gd_rightScrolledComposite);

        rightScrolledContentComposite = new Composite(rightScrolledComposite,SWT.NONE);
        rightScrolledComposite.setContent(rightScrolledContentComposite);
        rightScrolledContentComposite.setBackground(SWTResourceManager.getWhiteColor());
        GridLayout gl_rightScrolledContentComposite = new GridLayout(1, true);
        gl_rightScrolledContentComposite.marginWidth = 10;
        gl_rightScrolledContentComposite.marginHeight = 0;
        gl_rightScrolledContentComposite.verticalSpacing = 0;
        gl_rightScrolledContentComposite.horizontalSpacing = 0;
        rightScrolledContentComposite.setLayout(gl_rightScrolledContentComposite);
    }
    @Override
    protected void generateNoContentMentionComposite(Composite searchContentComposite, String searchContent,int width) {
        StyledText styledText = new StyledText(searchContentComposite,SWT.WRAP|SWT.MULTI);
        styledText.setText(StringUtil.isNotNullAndEmpty(searchContent)?"未找到与"+searchContent+"相关的内容,"+noContentMention:"暂无数据,"+noContentMention);
        GridData gd_styledText = new GridData(SWT.CENTER,SWT.CENTER,false,true,1,1);
        gd_styledText.widthHint = width;
        styledText.setLayoutData(gd_styledText);
        styledText.setEditable(false);
        StyleTextLink link = new StyleTextLink(linkEvent,styledText);
        link.ReplaceLink(linkText);
        searchContentComposite.layout(true);
    }

    @Override
    protected void generateComboContent(boolean append,List<T> dataList){
        Composite searchContentComposite = (Composite)searchScrollContentComposite.getData("searchComposite");
        if(null == this.comboDataList){
            this.comboDataList = new ArrayList<>();
        }
        if(!append){
            for(Control control:searchContentComposite.getChildren()){
                control.dispose();
            }
            this.comboDataList.clear();
            searchScrollContentComposite.setMinSize(0, 0);
        }
        if (CollectionUtil.isNotEmpty(dataList)) {
            for (T data : dataList) {
                generateComboItem(data);
            }
            this.comboDataList.addAll(dataList);
            if(append){
                CLabel loadLabel = (CLabel)searchScrollContentComposite.getData("load");
                GridData gd_loadLabel = (GridData)loadLabel.getLayoutData();
                gd_loadLabel.exclude = true;
                loadLabel.setVisible(false);
            }
            updateLeftNum();
        }else if(!append){   //形成待更新内容
            generateNoContentMentionComposite(searchContentComposite,this.getFilterContent(),this.comboRowWidth-30);
            updateLeftNum();
        }else{  //异步加载数据的情况
            if(CollectionUtil.isEmpty(this.comboDataList)){
                updateLeftNum();
                generateNoContentMentionComposite(searchContentComposite,this.getFilterContent(),this.comboRowWidth-30);
                CLabel loadLabel = (CLabel)searchScrollContentComposite.getData("load");
                GridData gd_loadLabel = (GridData)loadLabel.getLayoutData();
                gd_loadLabel.exclude = true;
                loadLabel.setVisible(false);
                finish = true;
            }else if(CollectionUtil.isEmpty(dataList)){
                CLabel loadLabel = (CLabel)searchScrollContentComposite.getData("load");
                GridData gd_loadLabel = (GridData)loadLabel.getLayoutData();
                gd_loadLabel.exclude = false;
                loadLabel.setText("无更多数据");
                loadLabel.setVisible(true);
                finish = true;
            }
        }
        relayoutScrollComposite();
    }

    abstract void generateRightItem(T data);

    /**
     * 向左移动触发的事件(绘制界面)
     * @param event
     */
    protected void leftMoveEvent(Event event){
        if(CollectionUtil.isEmpty(rightSelectMap)){
             new CustomMessageBox(this.parent.getShell(), "请在右侧区域选择移动项!", Model.CONFIRM_MODEL).open();
             return;
         }
         boolean allowable = false;
         if(null == searchShuttleBoxEvent){
             allowable = true;
         }else if(searchShuttleBoxEvent.deleteEvent(new ArrayList<>(rightSelectMap.keySet()),this)){
             allowable = true;
         }else{
             new CustomMessageBox(this.parent.getShell(), "向左侧移动失败!", Model.CONFIRM_MODEL).open();
             return;
         }
         if(allowable){
             if(totalCount == 0){  //原先总量为0
                 disposeLeftContentComposite();
             }
             for(Entry<T, Composite> entry:rightSelectMap.entrySet()){
                 entry.getValue().dispose();
                 rightDataList.remove(entry.getKey());
                 //左侧绘制一个内容
                 generateComboItem(entry.getKey());
                 this.totalCount++;
             }
             rightSelectMap.clear();
             updateRightNum();
             updateLeftNum();
             relayoutScrollComposite();
             relayoutRightScrollComposite();
         }
    }

    /**
     * 将checkbox变成选中状态
     * @param img
     */
    protected void changeSelectCheckBox(Label img) {
        if(img != null){
            img.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.CHECKBOX_SELF_ICON)));
            img.setData("checked", true);
        }
    }

    /**
     * 将checkbox变成未选中状态
     * @param img
     */
    protected void changeUnSelectCheckBox(Label img) {
        if(null != img){
            img.setImage(ImageUtil.getImage(FileUtil.loadResourceFileAsStream(Constants.CHECKBOX_NOR_ICON)));
            img.setData("checked", false);
        }
    }

    /**
     * 设置为选中状态
     * @param itemLabel
     */
    protected void changeItemSelection(CLabel itemLabel) {
        itemLabel.getParent().setBackground(SWTResourceManager.getColor(226, 235, 255));
        Control[] children = itemLabel.getParent().getChildren();
        for (Control child : children) {
            child.setBackground(SWTResourceManager.getColor(226, 235, 255));
        }
    }

    /**
     * 设置项为非选中状态
     * @param itemLabel
     */
    protected void changeItemUnSelection(CLabel itemLabel) {
        itemLabel.getParent().setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        Control[] children = itemLabel.getParent().getChildren();
        for (Control child : children) {
            child.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        }
    }

    /**
     * 重新绘制左侧滚动区域*/
    protected void relayoutScrollComposite(){
        Composite searchContentComposite = (Composite)searchScrollContentComposite.getData("searchComposite");
        searchContentComposite.layout(true);
        Composite scrollContentComposite = searchContentComposite.getParent();
        scrollContentComposite.layout(true);
        searchScrollContentComposite.setMinSize(scrollContentComposite.computeSize(SWT.DEFAULT,SWT.DEFAULT));
    }

    /**
     * 重新绘制右侧区域*/
    protected void relayoutRightScrollComposite(){
        this.rightScrolledContentComposite.layout(true);
        ((ScrolledComposite)rightScrolledContentComposite.getParent()).setMinSize(rightScrolledContentComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
    }

    /**
     * 销毁左侧*/
    protected void disposeLeftContentComposite(){
        Composite searchContentComposite = (Composite)searchScrollContentComposite.getData("searchComposite");
        for(Control child:searchContentComposite.getChildren()){
            child.dispose();
        }
    }

    /**
     * 更换左侧内容区域的数字*/
    protected void updateLeftNum(){
        num_label.setText("(当前选中"+this.selectedList.size()+"/"+this.totalCount+")");
        num_label.getParent().layout(true);
    }

    /**
     * 更新右侧区域的内容*/
    protected void updateRightNum(){
        right_num_label.setText("("+this.rightDataList.size()+")");
        right_num_label.getParent().layout(true);
    }

      /**
     * <p>穿梭框事件</p>
     * @version V1.0
     */
    public interface SearchShuttleBoxEvent<T>{
        /**
         * 添加左侧区域发生的后台逻辑,只有为true,才会将数据移向右侧区域
         * @param addData
         */
        boolean addEvent(List<T> addData,DefinedCommonSearchShuttleBox<T> box);
        /**
         * 将右侧区域数据移向左侧发生的后台事件,只有为true,才会将数据移向左侧区域
         * @param deleteData
         * @return
         */
        boolean deleteEvent(List<T> deleteData,DefinedCommonSearchShuttleBox<T> box);
        /**
         *
         * @param event
         * @param searchKeys
         * @param pageNum
         * @param pagePerNum
         * @param filters  默认右侧的数据从本次搜索范围剔除,右侧数据在filters的第一个object里面,类型为 List<T>
         * @return
         */
        DefinedSearchText.SearchPageResult<T> search(Event event, String searchKeys, int pageNum, int pagePerNum, List<Object> filters);

        /**
         * 校验输入的搜索条件是否正确
         * @param searchKey
         * @return
         */
         String verifySearchContent(String searchKey);
    }

    @Deprecated
    public void reLayoutComboComposite(){

    }
    public int getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public List<T> getSelectedList() {
        return selectedList;
    }

    public void setSelectedList(List<T> selectedList) {
        this.selectedList = selectedList;
    }

    public String getNoContentMention() {
        return noContentMention;
    }

    public void setNoContentMention(String noContentMention) {
        this.noContentMention = noContentMention;
    }

    public void setLinkEvent(StyleTextLink.StyleTextLinkEvent linkEvent) {
        this.linkEvent = linkEvent;
    }

    public void setSearchShuttleBoxEvent(SearchShuttleBoxEvent<T> searchShuttleBoxEvent) {
        this.searchShuttleBoxEvent = searchShuttleBoxEvent;
    }

    /**
     * 获取右侧所有数据内容
     * @return
     */
    public List<T> getRightDataList() {
        return rightDataList;
    }
}

DefinedCommonSearchShuttleBox.java  穿梭框的公共类,该章节中介绍的自定义穿梭框待搜索功能、且穿梭框分为两类:

  • 分类穿梭框:左侧按照分类进行呈现;
  • 无分类穿梭框:左侧无分类呈现;

5.1 分类穿梭框

package com.view.control.shuttlebox;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.util.CollectionUtil;
import com.view.control.select.DropDownBox;
import com.view.swt.CustomMessageBox;
import com.view.swt.SWTResourceManager;
import com.view.swt.CustomMessageBox.Model;

/**
 * <p>分类穿梭框控件</p>
 * @version V1.0
 */
public class DefinedClassifySearchShuttleBox extends DefinedCommonSearchShuttleBox<DefinedClassifySearchShuttleBox.ClassifySearchShuttleData> {
    private static final Logger log = LoggerFactory.getLogger(DefinedClassifySearchShuttleBox.class);
    /***左侧分类中仅能选择一个,不能多选******/
    private boolean classifyUnique;

    public DefinedClassifySearchShuttleBox(Composite parent, int comboRowWidth, SearchShuttleBoxEvent<ClassifySearchShuttleData> event) {
        super(parent, null, comboRowWidth);
        this.searchShuttleBoxEvent = event;
    }

    /**
     * 获取到数据之后的后续处理*/
    protected void afterSearchClick(Event searchTextEvent,List<DefinedClassifySearchShuttleBox.ClassifySearchShuttleData> searchData){
        boolean append = false;
        if(asynchronous){
            append = true;
        }
        if(searchTextEvent.button == 1){
            Composite searchContentComposite = (Composite)searchScrollContentComposite.getData("searchComposite");
            for(Control control:searchContentComposite.getChildren()){
                control.dispose();
            }
            this.comboDataList.clear();
            searchScrollContentComposite.setMinSize(0, 0);
            totalCount = 0;
        }
        if(CollectionUtil.isNotEmpty(searchData)){
            for(DefinedClassifySearchShuttleBox.ClassifySearchShuttleData data:searchData){
                if(data != null && CollectionUtil.isNotEmpty(data.getDataList())){
                    totalCount += data.getDataList().size();
                }
            }
        }
        generateComboContent(append,searchData);
        this.init  = false;
    }

    /**
     * 绘制右侧区域的每项
     */
    @SuppressWarnings("unchecked")
    @Override
    void generateRightItem(ClassifySearchShuttleData data) {
        Map<ClassifySearchShuttleData,Composite> classifySearchShuttleDataMap = (Map<ClassifySearchShuttleData, Composite>)rightScrolledContentComposite.getData("data");
        if(null == classifySearchShuttleDataMap){
            classifySearchShuttleDataMap = new HashMap<>();
            rightScrolledContentComposite.setData("data", classifySearchShuttleDataMap);
        }
        Composite itemClassifyComposite = classifySearchShuttleDataMap.get(data);
        if(null == itemClassifyComposite){
            itemClassifyComposite = new Composite(rightScrolledContentComposite,SWT.NONE);
            classifySearchShuttleDataMap.put(data, itemClassifyComposite);
            itemClassifyComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
            GridData gd_classItemComposite = new GridData(SWT.FILL,SWT.FILL,false,false,1,1);
            gd_classItemComposite.widthHint = this.comboRowWidth;
            itemClassifyComposite.setLayoutData(gd_classItemComposite);
            GridLayout gl_itemComposite = new GridLayout(1,true);
            gl_itemComposite.verticalSpacing = 0;
            gl_itemComposite.horizontalSpacing = 0;
            gl_itemComposite.marginHeight = 0;
            gl_itemComposite.marginWidth = 0;
            itemClassifyComposite.setLayout(gl_itemComposite);
            itemClassifyComposite.setData("data", data);
            //绘制标题内容
            generateTitleComposite(data.getClassifyName(),itemClassifyComposite);
        }else{
            ClassifySearchShuttleData oriClassifyData = (ClassifySearchShuttleData)itemClassifyComposite.getData("data");
            //需要找出右侧已经存在同类,进行项更换(一个类仅能有一个项存在右侧)
            if(this.classifyUnique){
                Map<DropDownBox.Data,Composite> itemCompositeList = (Map<DropDownBox.Data,Composite>)itemClassifyComposite.getData("dataComposite");
                if(CollectionUtil.isNotEmpty(itemCompositeList)){
                    ClassifySearchShuttleData toLeftClassifyData = new ClassifySearchShuttleData();
                    toLeftClassifyData.setClassifyName(oriClassifyData.getClassifyName());
                    toLeftClassifyData.setClassifyValue(oriClassifyData.getClassifyValue());
                    int index = this.rightDataList.indexOf(data);
                    for(Entry<DropDownBox.Data,Composite> entry:itemCompositeList.entrySet()){
                        oriClassifyData.getDataList().remove(entry.getKey());
                        toLeftClassifyData.addData(entry.getKey());
                        itemCompositeList.remove(entry.getKey()).dispose();
                        if(index != -1){
                            this.rightDataList.get(index).getDataList().remove(entry.getKey());
                        }
                    }
                    generateLeftItemComposite(toLeftClassifyData);
                }
            }
            oriClassifyData.getDataList().addAll(data.getDataList());
        }
        //绘制每项内容
        if(CollectionUtil.isNotEmpty(data.getDataList())){
            for(DropDownBox.Data item:data.getDataList()){
                generateItemComposite(item,itemClassifyComposite,new Listener(){
                    @Override
                    public void handleEvent(Event event) {
                        Label img = (Label)event.widget;
                        boolean select = (boolean)img.getData("checked");
                        DropDownBox.Data data = (DropDownBox.Data)img.getData("value");
                        if (select) {
                            removeItemSelectEvent(rightSelectMap,data,(ClassifySearchShuttleData)img.getParent().getParent().getData("data"));
                            changeUnSelectCheckBox(img);
                            select = false;
                        } else {
                            addItemSelectEvent(rightSelectMap,data,(ClassifySearchShuttleData)img.getParent().getParent().getData("data"),img.getParent().getParent());
                            changeSelectCheckBox(img);
                            select = true;
                        }
                        img.setData("checked", select);
                        updateRightNum();
                    }
                });
            }
        }
        int index = this.rightDataList.indexOf(data);
        if(index != -1){
            this.rightDataList.get(index).getDataList().addAll(data.getDataList());
        }else{
            ClassifySearchShuttleData rightClassifyData = new ClassifySearchShuttleData();
            rightClassifyData.setClassifyName(data.getClassifyName());
            rightClassifyData.setClassifyValue(data.getClassifyValue());
            rightClassifyData.getDataList().addAll(data.getDataList());
            this.rightDataList.add(rightClassifyData);
        }
    }

    /**
     * 从右侧的选择列表中去掉非选中的项
     * @param rightSelectMap  记录右侧选中的项,key为分类对象,分类对象中的dataList为该分类下选中的项
     * @param itemData   要移除的项
     * @param nowClassifyData  固定值,不可变
     */
    private void removeItemSelectEvent(Map<ClassifySearchShuttleData,Composite> rightSelectMap,DropDownBox.Data itemData,ClassifySearchShuttleData nowClassifyData){
        if(CollectionUtil.isNotEmpty(rightSelectMap)){
            ClassifySearchShuttleData selectClassifyData = null;
            for(Entry<ClassifySearchShuttleData,Composite> entry:rightSelectMap.entrySet()){
                if(entry.getKey().equals(nowClassifyData)){
                    selectClassifyData = entry.getKey();
                    break;
                }
            }
            if(null != selectClassifyData && CollectionUtil.isNotEmpty(selectClassifyData.getDataList()) && selectClassifyData.getDataList().contains(itemData)){
                selectClassifyData.getDataList().remove(itemData);
            }
            if(null == selectClassifyData || CollectionUtil.isEmpty(selectClassifyData.getDataList())){
                rightSelectMap.remove(selectClassifyData);
            }
        }
    }

    /**
     * 从右侧的选择列表中选中项
     * @param rightSelectMap  记录右侧选中的项,key为分类对象,分类对象中的dataList为该分类下选中的项
     * @param itemData  选中的项
     * @param nowClassifyData 固定值,不可变
     */
    private void addItemSelectEvent(Map<ClassifySearchShuttleData,Composite> rightSelectMap,DropDownBox.Data itemData,ClassifySearchShuttleData nowClassifyData,Composite classifyComposite){
        ClassifySearchShuttleData selectClassifyData = null;
        if(CollectionUtil.isNotEmpty(rightSelectMap)){
            for(Entry<ClassifySearchShuttleData,Composite> entry:rightSelectMap.entrySet()){
                if(entry.getKey().equals(nowClassifyData)){
                    selectClassifyData = entry.getKey();
                    break;
                }
            }
        }
        if(selectClassifyData == null){
            selectClassifyData = new ClassifySearchShuttleData();
            selectClassifyData.setClassifyName(nowClassifyData.getClassifyName());
            selectClassifyData.setClassifyValue(nowClassifyData.getClassifyValue());
        }
        if(!selectClassifyData.getDataList().contains(itemData)){
            selectClassifyData.getDataList().add(itemData);
        }
        rightSelectMap.put(selectClassifyData, classifyComposite);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void rightMoveEvent(Event event){
        if(CollectionUtil.isEmpty(selectedList)){
            new CustomMessageBox(this.parent.getShell(), "请在左侧区域选择移动项!", Model.CONFIRM_MODEL).open();
            return;
        }
        boolean allowable = false;
        if(null == searchShuttleBoxEvent){
            allowable = true;
        }else if(searchShuttleBoxEvent.addEvent(selectedList,this)){
            allowable = true;
        }else{
            log.trace("addEvent cancle move");
            return;
        }
        if(allowable){
            for(Entry<DefinedClassifySearchShuttleBox.ClassifySearchShuttleData, Composite> entry:selectMap.entrySet()){
                if(null != entry.getValue() && CollectionUtil.isNotEmpty(entry.getKey().getDataList())){
                    Map<DropDownBox.Data,Composite> itemCompositeDataMap = (Map<DropDownBox.Data, Composite>)entry.getValue().getData("dataComposite");
                    if(CollectionUtil.isNotEmpty(itemCompositeDataMap)){
                        for(DropDownBox.Data data:entry.getKey().getDataList()){
                            if(itemCompositeDataMap.containsKey(data)){
                                itemCompositeDataMap.remove(data).dispose();
                            }
                        }
                    }
                    if(CollectionUtil.isEmpty(itemCompositeDataMap)){
                        entry.getValue().dispose();
                    }
                    this.totalCount-=entry.getKey().getDataList().size();
                }
                //右侧绘制一个内容
                generateRightItem(entry.getKey());
            }
            selectedList.clear();
            selectMap.clear();
            updateRightNum();
            updateLeftNum();
            notifyScrollSearch();
            relayoutScrollComposite();
            relayoutRightScrollComposite();
        }
    }

    /**
     * 向左移动触发的事件(绘制界面)
     * @param event
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void leftMoveEvent(Event event){
        if(CollectionUtil.isEmpty(rightSelectMap)){
             new CustomMessageBox(this.parent.getShell(), "请在右侧区域选择移动项!", Model.CONFIRM_MODEL).open();
             return;
         }
         boolean allowable = false;
         if(null == searchShuttleBoxEvent){
             allowable = true;
         }else if(searchShuttleBoxEvent.deleteEvent(new ArrayList<>(rightSelectMap.keySet()),this)){
             allowable = true;
         }else{
             log.trace("deleteEvent cancle move");
             return;
         }
         if(allowable){
             if(totalCount == 0){  //原先总量为0
                 disposeLeftContentComposite();
             }
             for(Entry<ClassifySearchShuttleData, Composite> entry:rightSelectMap.entrySet()){
                 if(null != entry.getValue() && CollectionUtil.isNotEmpty(entry.getKey().getDataList())){
                    Map<DropDownBox.Data,Composite> itemCompositeDataMap = (Map<DropDownBox.Data, Composite>)entry.getValue().getData("dataComposite");
                    if(CollectionUtil.isNotEmpty(itemCompositeDataMap)){
                        for(DropDownBox.Data data:entry.getKey().getDataList()){
                            if(itemCompositeDataMap.containsKey(data)){
                                itemCompositeDataMap.remove(data).dispose();
                            }
                        }
                    }
                    if(CollectionUtil.isEmpty(itemCompositeDataMap)){
                        entry.getValue().dispose();
                        Map<ClassifySearchShuttleData,Composite> classifySearchShuttleDataMap = (Map<ClassifySearchShuttleData, Composite>)rightScrolledContentComposite.getData("data");
                        if(CollectionUtil.isNotEmpty(classifySearchShuttleDataMap) && classifySearchShuttleDataMap.containsKey(entry.getKey())){
                            classifySearchShuttleDataMap.remove(entry.getKey());
                        }
                    }
                    this.totalCount+=entry.getKey().getDataList().size();
                }
                 rightDataList.remove(entry.getKey());
                 //左侧绘制一个内容
                 generateLeftItemComposite(entry.getKey());
             }
             rightSelectMap.clear();
             updateRightNum();
             updateLeftNum();
             relayoutScrollComposite();
             relayoutRightScrollComposite();
         }
    } 

    /**
     * 将右侧选中的项换回到左侧区域时,右侧区域需要对应生成显示内容
     * @param data  右侧区域选中的项
     */
    private void generateLeftItemComposite(ClassifySearchShuttleData data){
        if(null != data && CollectionUtil.isNotEmpty(data.getDataList())){
            Composite classifyComposite = null;
            for(Control control:comboConenetComposite.getChildren()){
                if(null != control.getData("data") && ((ClassifySearchShuttleData)control.getData("data")).equals(data)){
                    classifyComposite = (Composite)control;
                    break;
                }
            }
            if(null == classifyComposite){
                generateComboItem(data);
            }else{
                //绘制每项内容
                for(DropDownBox.Data item:data.getDataList()){
                    generateItemComposite(item,classifyComposite,new Listener(){
                        @Override
                        public void handleEvent(Event event) {
                            Label img = (Label)event.widget;
                            boolean select = (boolean)img.getData("checked");
                            DropDownBox.Data data = (DropDownBox.Data)img.getData("value");
                            if (select) {
                                removeItemData(data,(ClassifySearchShuttleData)img.getParent().getParent().getData("data"),selectedList,selectMap);
                                changeUnSelectCheckBox(img);
                                select = false;
                            } else {
                                if(classifyUnique){  //若是仅允许一个分类中选中一个,需要将原先选中的取消掉
                                    removeAllClassifyItemData((ClassifySearchShuttleData)img.getParent().getParent().getData("data"),selectedList,selectMap);
                                }
                                addItemData(data,img.getParent().getParent(),(ClassifySearchShuttleData)img.getParent().getParent().getData("data"),selectedList,selectMap);
                                changeSelectCheckBox(img);
                                select = true;
                            }
                            img.setData("checked", select);
                            updateLeftNum();
                        }
                    });
                }
            }
        }
    }

    @Override
    protected void generateComboItemComposite(ClassifySearchShuttleData data, Composite itemClassifyComposite) {
        //itemComposite 为一个分类的composite,里面应该显示自己的子标题及类中的每个项
        if(null != data && CollectionUtil.isNotEmpty(data.getDataList())){
            GridData gd_itemComposite = (GridData)itemClassifyComposite.getLayoutData();
            gd_itemComposite.heightHint = -1;
            GridLayout gl_itemComposite = new GridLayout(1,true);
            gl_itemComposite.verticalSpacing = 0;
            gl_itemComposite.horizontalSpacing = 0;
            gl_itemComposite.marginHeight = 0;
            gl_itemComposite.marginWidth = 0;
            itemClassifyComposite.setLayout(gl_itemComposite);

            //绘制标题内容
            generateTitleComposite(data.getClassifyName(),itemClassifyComposite);
            //绘制每项内容
            for(DropDownBox.Data item:data.getDataList()){
                generateItemComposite(item,itemClassifyComposite,new Listener(){
                    @Override
                    public void handleEvent(Event event) {
                        Label img = (Label)event.widget;
                        boolean select = (boolean)img.getData("checked");
                        DropDownBox.Data data = (DropDownBox.Data)img.getData("value");
                        if (select) {
                            removeItemData(data,(ClassifySearchShuttleData)itemClassifyComposite.getData("data"),selectedList,selectMap);
                            changeUnSelectCheckBox(img);
                            select = false;
                        } else {
                            if(classifyUnique){  //若是仅允许一个分类中选中一个,需要将原先选中的取消掉
                                removeAllClassifyItemData((ClassifySearchShuttleData)itemClassifyComposite.getData("data"),selectedList,selectMap);
                            }
                            addItemData(data,itemClassifyComposite,(ClassifySearchShuttleData)itemClassifyComposite.getData("data"),selectedList,selectMap);
                            changeSelectCheckBox(img);
                            select = true;
                        }
                        img.setData("checked", select);
                        updateLeftNum();
                    }
                });
            }
        }
        itemClassifyComposite.layout(true);
    }

    /**
     * 绘制标题区域内容
     * @param title
     * @param itemClassifyComposite
     */
    private void generateTitleComposite(String title,Composite itemClassifyComposite){
        Composite title_composite = new Composite(itemClassifyComposite,SWT.NONE);
        GridData gd_title_composite = new GridData(SWT.FILL,SWT.FILL,true,false,1,1);
        gd_title_composite.heightHint = 35;
        title_composite.setLayoutData(gd_title_composite);
        GridLayout gl_title_composite = new GridLayout(1,true);
        gl_title_composite.marginWidth = 3;
        title_composite.setLayout(gl_title_composite);
        title_composite.setBackground(SWTResourceManager.getColor(245,245,245));
        CLabel title_label = new CLabel(title_composite,SWT.NONE);
        title_label.setBackground(SWTResourceManager.getColor(245,245,245));
        title_label.setForeground(SWTResourceManager.getTextColor());
        GridData gd_title_label = new GridData(SWT.FILL,SWT.FILL,true,true,1,1);
        title_label.setLayoutData(gd_title_label);
        title_label.setText(title);
    }

    /**
     * 绘制每个类中的项
     * @param data
     * @param itemComposite
     */
    @SuppressWarnings("unchecked")
    private void generateItemComposite(DropDownBox.Data data,Composite itemClassifyComposite,Listener checkboxListener){
        Composite itemComposite = new Composite(itemClassifyComposite,SWT.NONE);
        itemComposite.setBackground(SWTResourceManager.getWhiteColor());
        GridData gd_itemComposite = new GridData(SWT.FILL,SWT.FILL,false,false,1,1);
        gd_itemComposite.heightHint = this.comboRowHeight;
        gd_itemComposite.widthHint = this.comboRowWidth-20;
        itemComposite.setLayoutData(gd_itemComposite);
        GridLayout gl_itemComposite = new GridLayout(2,false);
        gl_itemComposite.verticalSpacing = 0;
        gl_itemComposite.horizontalSpacing = 5;
        itemComposite.setLayout(gl_itemComposite);
        Label img = new Label(itemComposite, SWT.NONE);
        GridData gd_img = new GridData(SWT.FILL,SWT.FILL,false,false,1,1);
        gd_img.widthHint = 24;
        gd_img.heightHint = 24;
        img.setLayoutData(gd_img);
        img.setData("value", data);
        changeUnSelectCheckBox(img);
        itemComposite.setData("checkbox", img);
        img.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        img.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        img.addListener(SWT.MouseDown, checkboxListener);

        CLabel itemLabel = new CLabel(itemComposite, SWT.NONE);
        itemLabel.setText(data.getDisplay());
        itemLabel.setData("value", data);
        itemLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        GridData gd_itemLabel= new GridData(SWT.FILL,SWT.FILL,true,true,1,1);
        itemLabel.setLayoutData(gd_itemLabel);
        itemLabel.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        itemLabel.addListener(SWT.MouseEnter, new Listener() {
            @Override
            public void handleEvent(Event event) {
                changeItemSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseExit, new Listener() {

            @Override
            public void handleEvent(Event event) {
                changeItemUnSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseDown, new Listener() {

            @Override
            public void handleEvent(Event event) {
                Event newEvent = new Event();
                newEvent.widget = img;
                img.notifyListeners(SWT.MouseDown, newEvent);
            }
        });
        itemComposite.layout(true);
        Map<DropDownBox.Data,Composite> itemCompositeList = (Map<DropDownBox.Data,Composite>)itemClassifyComposite.getData("dataComposite");
        if(null == itemCompositeList){
            itemCompositeList = new HashMap<DropDownBox.Data,Composite>();
            itemClassifyComposite.setData("dataComposite", itemCompositeList);
        }
        itemCompositeList.put(data,itemComposite);
        itemClassifyComposite.layout(true);
    }

    /**
     * 将左侧区域中一个类中所有项更改成非选中状态
     * @param classify    类容器上绑定的类数据,不可变更
     * @param classifyDataList
     * @param classifyDataMap
     */
    @SuppressWarnings("unchecked")
    private void removeAllClassifyItemData(ClassifySearchShuttleData classify,List<ClassifySearchShuttleData> classifyDataList,Map<ClassifySearchShuttleData,Composite> classifyDataMap){
        int index = classifyDataList.indexOf(classify);
        if(index != -1){
            ClassifySearchShuttleData newClassifyData = classifyDataList.get(index);
            Composite classifyComposite = classifyDataMap.get(newClassifyData);
            Map<DropDownBox.Data,Composite> itemDataMap = (Map<DropDownBox.Data, Composite>)classifyComposite.getData("dataComposite");
            if(CollectionUtil.isNotEmpty(newClassifyData.getDataList())){
                if(CollectionUtil.isNotEmpty(itemDataMap)){
                    for(DropDownBox.Data itemData:newClassifyData.getDataList()){
                        if(itemDataMap.containsKey(itemData)){
                            Composite itemComposite = itemDataMap.get(itemData);
                            Label img = (Label)itemComposite.getData("checkbox");
                            changeUnSelectCheckBox(img);
                            img.setData("checked",false);
                        }
                    }
                }
            }
        }
        classifyDataList.remove(classify);
        classifyDataMap.remove(classify);
    }

    /**
     * 左侧区域取消选中一个分类中的项
     * @param data
     * @param classifyDataList
     * @param classifyDataMap
     */
    private void removeItemData(DropDownBox.Data data,ClassifySearchShuttleData classify,List<ClassifySearchShuttleData> classifyDataList,Map<ClassifySearchShuttleData,Composite> classifyDataMap){
        if(CollectionUtil.isNotEmpty(classifyDataList) && data != null){
            List<ClassifySearchShuttleData> removeClassifySearchShuttleDataList = new ArrayList<>();
            int index = classifyDataList.indexOf(classify);
            if(index != -1){
                ClassifySearchShuttleData classifyData = classifyDataList.get(index);
                if(null != classifyData && CollectionUtil.isNotEmpty(classifyData.getDataList()) && classifyData.getDataList().contains(data)){
                    classifyData.getDataList().remove(data);
                    if(CollectionUtil.isEmpty(classifyData.getDataList())){
                        removeClassifySearchShuttleDataList.add(classifyData);
                        classifyDataMap.remove(classifyData);
                    }
                }
            }else{
                classifyDataMap.remove(classify);
            }
            if(CollectionUtil.isNotEmpty(removeClassifySearchShuttleDataList)){
                classifyDataList.removeAll(removeClassifySearchShuttleDataList);
            }
        }
    }

    /**
     * 左侧区域选中一个项
     * @param data
     * @param classifyDataList
     * @param classifyDataMap
     */
    private void addItemData(DropDownBox.Data data,Composite classifyComposite,ClassifySearchShuttleData classify,List<ClassifySearchShuttleData> classifyDataList,Map<ClassifySearchShuttleData,Composite> classifyDataMap){
        if(data != null && null != classifyDataList && null != classifyDataMap){
            int index = classifyDataList.indexOf(classify);
            ClassifySearchShuttleData newClassify;
            if(index != -1){
                newClassify = classifyDataList.get(index);
            }else{
                newClassify = new ClassifySearchShuttleData();
                newClassify.setClassifyName(classify.getClassifyName());
                newClassify.setClassifyValue(classify.getClassifyValue());
                classifyDataList.add(newClassify);
            }
            List<DropDownBox.Data> itemDataList = newClassify.getDataList();
            if(null == itemDataList){
                itemDataList = new ArrayList<>();
                newClassify.setDataList(itemDataList);
            }
            if(!itemDataList.contains(data)){
                itemDataList.add(data);
            }
            classifyDataMap.put(newClassify, classifyComposite);
        }
    }

    /**
     * 更换左侧内容区域的数字*/
    @Override
    protected void updateLeftNum(){
        num_label.setText("(当前选中"+ fixTotalSize(this.selectedList)+"/"+this.totalCount+")");
        num_label.getParent().layout(true);
    }

    /**
     * 更换右侧内容区域的数字
     */
    protected void updateRightNum(){
        right_num_label.setText("("+fixTotalSize(this.rightDataList)+")");
        right_num_label.getParent().layout(true);
    }

    /**
     * 计算条数
     * @param classifyList
     * @return
     */
    public int fixTotalSize(List<ClassifySearchShuttleData> classifyList){
        int size = 0;
        if(CollectionUtil.isNotEmpty(classifyList)){
            for(ClassifySearchShuttleData classifyData:classifyList){
                if(null != classifyData && CollectionUtil.isNotEmpty(classifyData.getDataList())){
                    size += classifyData.getDataList().size();
                }
            }
        }
        return size;
    }

    public boolean isClassifyUnique() {
        return classifyUnique;
    }

    public void setClassifyUnique(boolean classifyUnique) {
        this.classifyUnique = classifyUnique;
    }

    /**
     * <p>分类数据</p>
     * @version V1.0
     */
    public static class ClassifySearchShuttleData{
        private String classifyName;
        private String classifyValue;
        private List<DropDownBox.Data> dataList = new ArrayList<>();

        public String getClassifyName() {
            return classifyName;
        }

        public void setClassifyName(String classifyName) {
            this.classifyName = classifyName;
        }

        public String getClassifyValue() {
            return classifyValue;
        }

        public void setClassifyValue(String classifyValue) {
            this.classifyValue = classifyValue;
        }

        public List<DropDownBox.Data> getDataList() {
            return dataList;
        }

        public void setDataList(List<DropDownBox.Data> dataList) {
            this.dataList = dataList;
        }

        public void addData(DropDownBox.Data data){
            this.dataList.add(data);
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((classifyValue == null)?0:classifyValue.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            ClassifySearchShuttleData other = (ClassifySearchShuttleData)obj;
            if (classifyValue == null) {
                if (other.classifyValue != null)
                    return false;
            } else if (!classifyValue.equals(other.classifyValue))
                return false;
            return true;
        }
    }
}

5.2 无分类穿梭框

package com.view.control.shuttlebox;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;

import com.view.control.select.DropDownBox;
import com.view.swt.SWTResourceManager;

/**
 * <p>
 * 带搜索功能的穿梭框(gridLayout布局)
 * </p>
 * @version V1.0
 */
public class DefinedSearchShuttleBox extends DefinedCommonSearchShuttleBox<DropDownBox.Data> {

    public DefinedSearchShuttleBox(Composite parent,int comboRowWidth,SearchShuttleBoxEvent<DropDownBox.Data> event){
        super(parent, null, comboRowWidth);
        this.searchShuttleBoxEvent = event;
    }

    /**
     * 绘制右侧一个item框架
     * @param data
     */
    @Override
    protected void generateRightItem(DropDownBox.Data data){
        Composite itemComposite = new Composite(rightScrolledContentComposite,SWT.NONE);
        itemComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        GridData gd_itemComposite = new GridData(SWT.FILL,SWT.FILL,true,false,1,1);
        gd_itemComposite.heightHint = this.comboRowHeight;
        gd_itemComposite.widthHint = this.comboRowWidth;
        itemComposite.setLayoutData(gd_itemComposite);
        GridLayout gl_itemComposite = new GridLayout(2,false);
        gl_itemComposite.verticalSpacing = 0;
        gl_itemComposite.horizontalSpacing = 5;
        itemComposite.setLayout(gl_itemComposite);
        Label img = new Label(itemComposite, SWT.NONE);
        GridData gd_img = new GridData(SWT.FILL,SWT.FILL,false,false,1,1);
        gd_img.widthHint = 24;
        gd_img.heightHint = 24;
        img.setLayoutData(gd_img);
        img.setData("value", data);
        changeUnSelectCheckBox(img);
        img.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        img.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        img.addListener(SWT.MouseDown, new Listener() {
            @Override
            public void handleEvent(Event event) {
                Label img = (Label)event.widget;
                boolean select = (boolean)img.getData("checked");
                DropDownBox.Data data = (DropDownBox.Data)img.getData("value");
                if (select) {
                    rightSelectMap.remove(data);
                    changeUnSelectCheckBox(img);
                    select = false;
                } else {
                    rightSelectMap.put(data, itemComposite);
                    changeSelectCheckBox(img);
                    select = true;
                }
                img.setData("checked", select);
            }
        });

        CLabel itemLabel = new CLabel(itemComposite, SWT.NONE);
        itemLabel.setText(data.getDisplay());
        itemLabel.setData("value", data);
        itemLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        GridData gd_itemLabel= new GridData(SWT.FILL,SWT.FILL,true,true,1,1);
        itemLabel.setLayoutData(gd_itemLabel);
        itemLabel.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        itemLabel.addListener(SWT.MouseEnter, new Listener() {

            @Override
            public void handleEvent(Event event) {
                changeItemSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseExit, new Listener() {

            @Override
            public void handleEvent(Event event) {
                changeItemUnSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseDown, new Listener() {

            @Override
            public void handleEvent(Event event) {
                Event newEvent = new Event();
                newEvent.widget = img;
                img.notifyListeners(SWT.MouseDown, newEvent);
            }
        });
        itemComposite.layout(true);
        itemComposite.setData("data", data);
        relayoutRightScrollComposite();
    }

    /**
     * 绘制左侧区域每行数据
     */
    @Override
    protected void generateComboItemComposite(DropDownBox.Data data, Composite itemComposite) {
        GridLayout gl_itemComposite = new GridLayout(2,false);
        gl_itemComposite.verticalSpacing = 0;
        gl_itemComposite.horizontalSpacing = 5;
        itemComposite.setLayout(gl_itemComposite);
        Label img = new Label(itemComposite, SWT.NONE);
        GridData gd_img = new GridData(SWT.FILL,SWT.FILL,false,false,1,1);
        gd_img.widthHint = 24;
        gd_img.heightHint = 24;
        img.setLayoutData(gd_img);
        img.setData("value", data);
        changeUnSelectCheckBox(img);
        img.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        img.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        img.addListener(SWT.MouseDown, new Listener() {
            @Override
            public void handleEvent(Event event) {
                Label img = (Label)event.widget;
                boolean select = (boolean)img.getData("checked");
                DropDownBox.Data data = (DropDownBox.Data)img.getData("value");
                if (select) {
                    selectedList.remove(data);
                    selectMap.remove(data);
                    changeUnSelectCheckBox(img);
                    select = false;
                } else {
                    selectedList.add(data);
                    selectMap.put(data, itemComposite);
                    changeSelectCheckBox(img);
                    select = true;
                }
                img.setData("checked", select);
                updateLeftNum();
            }
        });

        CLabel itemLabel = new CLabel(itemComposite, SWT.NONE);
        itemLabel.setText(data.getDisplay());
        itemLabel.setData("value", data);
        itemLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        GridData gd_itemLabel= new GridData(SWT.FILL,SWT.FILL,true,true,1,1);
        itemLabel.setLayoutData(gd_itemLabel);
        itemLabel.setCursor(SWTResourceManager.getCursor(SWT.CURSOR_HAND));
        itemLabel.addListener(SWT.MouseEnter, new Listener() {
            @Override
            public void handleEvent(Event event) {
                changeItemSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseExit, new Listener() {

            @Override
            public void handleEvent(Event event) {
                changeItemUnSelection(itemLabel);
            }
        });
        itemLabel.addListener(SWT.MouseDown, new Listener() {

            @Override
            public void handleEvent(Event event) {
                Event newEvent = new Event();
                newEvent.widget = img;
                img.notifyListeners(SWT.MouseDown, newEvent);
            }
        });
        itemComposite.layout(true);
    }
}

原文地址:https://www.cnblogs.com/sandyflower/p/9750148.html

时间: 2024-10-12 22:50:54

自定义SWT控件五之自定义穿梭框的相关文章

自定义SWT控件二之自定义多选下拉框

2.自定义下拉多选框 package com.view.control.select; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import or

自定义SWT控件一之自定义单选下拉框

一.自定义下拉控件 自定义的下拉框,是自定义样式的,其中的下拉框使用的是独立的window,非复选框的下拉框双击单机其它区域或选择完之后,独立window构成的下拉框会自动消失. package com.view.control.select; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite;

自定义视图控件例:自定义正方形

自定义正方形 自定义button效果(控件皮肤): 绘制API自定义

IOS开发--自定义segment控件,方便自定义样式

系统的segment控件太封闭,想换个颜色加个背景太难了,忍不住自己写一个,以备不时之需 这个控件给出了很多自定义属性的设置,用起来还是比较方便的,需要注意的 itemWidth如果不设置,则会按照控件的宽度平均分配每一项的宽度,如果设置了,那么总宽度超过控件宽度后会有滑动效果 直接上代码吧: 头文件: #import <Foundation/Foundation.h> @protocol WCSegmentControlDelegate -(void)wcSegmentControlSele

自定义SWT控件三之搜索功能下拉框

3.搜索功能下拉弹出框 package com.view.control.select; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import log.HikLog; import org.apache.commons.lang3.StringUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLa

【转】带checkbox的ListView实现(二)——自定义Checkable控件的实现方法

原文网址:http://blog.csdn.net/harvic880925/article/details/40475367 前言:前一篇文章给大家展示了传统的Listview的写法,但有的时候我们并不想在DataHolder类中加一个标识是否选中的checked的成员变量,因为在项目开发中,大部分的ListItemLayout布局都是大家共用的,有些人根本不需要checkbox控件,所以会在初始化的时候把这个控件给隐藏掉,但我们的DataHolder在构造的时候以及ListItemAdapt

android自定义倒计时控件示例

这篇文章主要介绍了Android秒杀倒计时自定义TextView示例,大家参考使用吧 自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.content.Context;import android.content.res.TypedArray;import android.graphics.Paint;import android.text.Html;import android.util.AttributeSet;import and

自定义日历控件-CalendarView

转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/43056675 我们在开发中会遇到使用到日历控件,下面就介绍一个自定义日历控件. 思路: 1.自定义类CalendarView继承LinearLayout,使用布局文件,显示布局. 2.使用ViewFlipper,里面添加GridView,当月的日期. 3.使用手势GestureDetector,控制ViewFlipper的滑动. calen_calendar.xml <span

Android自定义控件之自定义组合控件(三)

前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发成本,以及维护成本. 使用自定义组合控件的好处? 我们在项目开发中经常会遇见很多相似或者相同的布局,比如APP的标题栏,我们从三种方式实现标题栏来对比自定义组件带来的好处,毕竟好的东西还是以提高开发效率,降低开发成本为导向的. 1.)第一种方式:直接在每个xml布局中写相同的标题栏布局代码 <?xm