Vaadin 8用Enum类创建一棵树

时间:2018-04-16 06:36:53

标签: java vaadin vaadin8

我仍然是Vaadin的新手,所以请耐心等待。

我们目前正在从Vaadin框架8.0迁移到8.3.2。其中一个原因是需要在菜单中使用树。由于8.0没有树,因此生成菜单的解决方法是在循环中使用Enum类实例化实例化内部Button类(用于用户权限控制):

public final class ValoMenuItemButton extends Button {

        private static final String STYLE_SELECTED = "selected";

        private final DashboardViewType view;

        public ValoMenuItemButton(final DashboardViewType view) {
            this.view = view;
            setPrimaryStyleName("valo-menu-item");
            setIcon(view.getIcon());
            setCaption(view.getViewName().substring(0, 1).toUpperCase()
                    + view.getViewName().substring(1));
            DashboardEventBus.register(this);
            addClickListener(new ClickListener() {
                @Override
                public void buttonClick(final ClickEvent event) {
                    UI.getCurrent().getNavigator()
                            .navigateTo(view.getViewName());
                }
            });

        }

        @Subscribe
        public void postViewChange(final PostViewChangeEvent event) {
            removeStyleName(STYLE_SELECTED);
            if (event.getView() == view) {
                addStyleName(STYLE_SELECTED);
            }
        }
    }

枚举类结构以这种方式构建:

AUDIT("Receipt Validation", RcptValidation.class, FontAwesome.BAR_CHART_O, false),
        AUDIT1("Matching - Receipt not in SYCARDA", RcptNotInSycarda.class, FontAwesome.BAR_CHART_O, false), 
        AUDIT2("Matching - Receipt not in POS", RcptNotInPos.class, FontAwesome.BAR_CHART_O, false), 
        AUDIT3("Missing Sequence", MissSequence.class, FontAwesome.BAR_CHART_O, false),
        AUDIT4("*Debug Purposes", LineAmtVsTotal.class, FontAwesome.BAR_CHART_O, false);
  
   
    private DashboardViewType(final String viewName,
            final Class<? extends View> viewClass, final Resource icon,
            final boolean stateful) {
        this.viewName = viewName;
        this.viewClass = viewClass;
        this.icon = icon;
        this.stateful = stateful;
    }

到目前为止,我还没有找到任何围绕v8框架编写的示例,而我见过的大部分示例代码都基于v7框架。

我试图写这样的东西,但是树子菜单没有按原样出现(我省略了展开和折叠事件,因为可以在以后处理)。

我在树上尝试的代码是这样的:

TreeData <String> treeData = new TreeData(); 
treeData.addRootItems("Dashboard","Sales","Sales Pattern","Top SKUs","Audit"); 
// The loop starts here (for DashboardViewType view: DashboardViewType.values)
        if(enabled){ 
        if(StringUtils.startsWith(view.getViewName(), "SALES")){ 
            if (StringUtils.contains(view.getViewName(),"SALES_PATTERN")){ 
                treeData.addItem( "Sales Pattern", view.getViewName()); 
            }else{ treeData.addItem( "Sales", view.getViewName());
 } 
        }else if (StringUtils.startsWith(view.getViewName(), "TOP_SKUS")){ 
            treeData.addItem( "Top SKUs", view.getViewName()); 
        }else if (StringUtils.startsWith(view.getViewName(), "AUDIT")){ 
            treeData.addItem( "Audit", view.getViewName()); 
        }else if (StringUtils.startsWith(view.getViewName(), "DASHBOARD")){ 
            treeData.addItem( "Dashboard", view.getViewName()); 
        } 
        DashboardEventBus.register(view);
            } 
// loop ends here

    Tree<String> tree = new Tree<>("Sycarda Dashboard"); 
    tree.setDataProvider(new TreeDataProvider<>(treeData)); 
    tree.setItemIconGenerator(item -> { return FontAwesome.BAR_CHART_O; }); 
    tree.expand("Sales","Sales Pattern","Top SKUs","Audit"); 
    tree.addSelectionListener(e -> new Button.ClickListener() { 
        @Override public void buttonClick(Button.ClickEvent event) { 
            DashboardEventBus.register(event); 
            UI.getCurrent().getNavigator().navigateTo(event.getClass().getName()); 
        } 
    });

在Vaadin论坛上这是posted originally,但由于没有答案,我把它放在这里。如果对此问题有任何意见或其他方法,我会很感激。

提前致谢。

2 个答案:

答案 0 :(得分:2)

在Vaadin 8中,你可以简单地定义&#34;得到孩子&#34;添加数据时的方法。在你的情况下,enum类应该提供一些像&#34; getSubItems&#34;这样的方法,你可以将它们设置为值提供者。以下示例以类似的方式显示它,其中&#34; rootItems&#34;与顶级枚举实例完全相同,MenuItem与枚举相同。

    static {
        rootItems = Arrays.asList(...);
    }

    @PostConstruct
    private void init() {
        Tree<MenuItem> tree = new Tree<>();

        tree.setItems(rootItems, MenuItem::getSubItems);
    }

    private class MenuItem {
        private String name;
        private Resource icon;
        private Collection<MenuItem> subItems;

        public Collection<MenuItem> getSubItems() {
            return subItems;
        }

        // ... other getter and constructor omitted;
    }

答案 1 :(得分:0)

有人展示了一个例子,它与Stefan提到的相似。根据我的要求,所涉及的步骤包括:

  1. 创建一个包含以下内容的包装类:

    private DashboardViewType view;
    private Resource icon;
    private boolean stateful;
    private Class<? extends View> viewClass;
    private String viewName;
    
    //Create the get / set methods for those attributes above
    //Constructor for the wrapper class is below. 
    
    public TreeMenuItem(DashboardViewType view){
        this.view = view;
    }
    
  2. 对于Enum类,添加了其他主菜单项。可以使用默认主类,因为您不能使用null。

    public enum DashboardViewType {

    SALES("Sales",DashboardView.class,FontAwesome.HOME,false),
    SALES_PATTERN("Sales Pattern",DashboardView.class,FontAwesome.HOME,false),
    TOP_SKUs("Top SKUs",DashboardView.class,FontAwesome.HOME,false),
    AUDIT("Audit",DashboardView.class,FontAwesome.HOME,false)
    

    }

  3. 树是以这种方式构建的:

    私有组件buildTree(){

    Tree<TreeMenuItem> tree = new Tree<>();
    TreeData<TreeMenuItem> treeData = new TreeData<>();
    
    
    //This is for items that have no child.                
    TreeMenuItem dashboardItem = new TreeMenuItem(DashboardViewType.DASHBOARD);
    dashboardItem.setIcon(VaadinIcons.HOME_O);
    dashboardItem.setStateful(DashboardViewType.DASHBOARD.isStateful());
    dashboardItem.setViewName(DashboardViewType.DASHBOARD.getViewName());
    treeData.addItem(null, dashboardItem);
    
    for (DashboardViewType type : DashboardViewType.values()) {
       TreeMenuItem menuItem = new TreeMenuItem(type);
       menuItem.setIcon(VaadinIcons.HOME_O);
       menuItem.setViewName(type.getViewName());
       menuItem.setStateful(false);
       treeData.addItem(null, menuItem);
       getSubMenuItems(type).forEach(subView -> {
           TreeMenuItem subItem = new TreeMenuItem(subView);
           subItem.setViewName(subView.getViewName().substring(0, 1).toUpperCase()
                                            + subView.getViewName().substring(1));
           subItem.setIcon(subView.getIcon());
           subItem.setStateful(subView.isStateful());
           subItem.setView(subView);
           subItem.setViewClass(subView.getViewClass());
           treeData.addItem(menuItem, subItem);
        }); 
        }
     }
    tree.setDataProvider(new TreeDataProvider<>(treeData));
    tree.setItemIconGenerator(TreeMenuItem::getIcon);
    tree.setItemCaptionGenerator(TreeMenuItem::getViewName);
    tree.addItemClickListener((Tree.ItemClick<TreeMenuItem> event) -> {
                DashboardEventBus.register(event.getItem().getView());           UI.getCurrent().getNavigator().navigateTo(event.getItem().getViewName());
            });
    

    }

  4. 创建子视图的逻辑:

    private List getSubMenuItems(DashboardViewType type){

        List<DashboardViewType> dashboardList;
        switch(type){
            case TOP_SKUs:
            dashboardList =  new LinkedList<>(Arrays.asList(DashboardViewType.TOP_SKUs1,
                                 DashboardViewType.TOP_SKUs2,
                                 DashboardViewType.TOP_SKUs3,
                                 DashboardViewType.TOP_SKUs4));
    
            filterByUserLevel(dashboardList,subACL4);
            return dashboardList;
    
            case AUDIT:
            dashboardList =  new LinkedList<>(Arrays.asList(DashboardViewType.AUDIT1,
                                 DashboardViewType.AUDIT2,
                                 DashboardViewType.AUDIT3,
                                 DashboardViewType.AUDIT4,
                                 DashboardViewType.AUDIT5));
    
            filterByUserLevel(dashboardList,subACL5);
            return dashboardList;    
    
            case DASHBOARD:
                break;
            default:
                break;
        }
    
        return Collections.emptyList();
    }
    
  5. 如果需要,添加其他案例。之后,函数控件将删除不属于用户级别的元素:

    private List<DashboardType> filterByUserLevel(List<DashboardType>list, String u){
    
        if(list.size() == subACL.length()){
           for(int i=0; i<list.size(); i++){
           if(StringUtils.substring(subACL, i, i+1).equalsIgnoreCase("0")){
              list.remove(i);
            }
          }
         Collections.sort(list);
         return list;
         //this removes unwanted sub-menu items according current user level.
        }
    
    }