angle-left

Создание динамических табов с использованием IceFaces 1.8.2

Разумно взять метод и испытать его. При неудаче честно
признайтесь в этом и попробуйте другой метод. Но главное,
делайте что-нибудь.

                             

ФРАНКЛИН Д. РУЗВЕЛЬТ

Dynamic tabs ( IceFaces 1.8.2 )

Создание универсальных динамических табов (разных классов), довольно не простая задача, с которой мне пришлось столкнуться.

Дело в том, что компонент panelTabSet использует в качестве табов список объектов одного класса, а от сюда следует, что либо нужно создать большой класс, который включал бы в себя поля, нужные во всех табах, либо табы кастить динамически к нужным нам классам. Что я решил и сделать.При использовании моего решения, вы можете часто ловить java.lang.ClassCastException, если не будете отслеживать текущий открытый таб.

Приступим...

Создадим абстрактный класс Tab, унаследовав его от компонента Ice Faces - PanelTab. На основе Tab мы будем создавать классы наших табов.

Tab.java

package workflow.common.controls.ui.tabs;

import com.icesoft.faces.component.paneltabset.PanelTab;
import javax.faces.event.ActionEvent;
import static workflow.common.controls.ui.tabs.TabSetBean.*;

/**
 * @author nicola
 * @version 2.1.0 (Feb 17, 2010)
 */
public abstract class Tab extends PanelTab {
    
    private int type;
    private boolean deleted;
    private String name;
    private int index;

    public Tab() {
        this(TYPE_NONE, "", "", -1);
    }

    public Tab(int tabType, String tabName, String tabTitle, int index) {
        setName(tabName);
        setTitle(tabTitle);
        this.type = tabType;
        this.index = index;
        this.deleted = false;
    }

    public void setType(int type) {
        this.type = type;
    }

    public int getType() {
        return type;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void closeTab() {
        this.deleted = true;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }
    
    @Override
    public int hashCode() {
        return super.hashCode();
    }

    public abstract void reload(ActionEvent event);

    @Override
    public boolean equals(Object object) {
       ......
    }
}

 

А теперь создадим классы наших табов.

PersonTab.java

package workflow.contactmanager.beans.tabs;

import workflow.common.controls.ui.tabs.Tab;
import javax.faces.event.ActionEvent;
import static workflow.contactmanager.beans.tabs.ContactTabSetBean.*;


/**
 * @author nicola
 * @version 2.1.0 (Feb 17, 2010)
 */
public class PersonTab extends Tab {

    private PersonTabBean personTabBean;

    public PersonTab() {
        this("", "", -1);
        this.personTabBean = new PersonTabBean();
    }

    private PersonTab(String tabName, String tabTitle, int index) {
        super(TYPE_PERSONS, tabName, tabTitle, index);
    }
    
    public PersonTabBean getPersonTabBean() {
        return personTabBean;
    }

    public void setPersonTabBean(PersonTabBean personTabBean) {
        this.personTabBean = personTabBean;
    }

    @Override
    public void reload(ActionEvent event) {
        this.personTabBean = new PersonTabBean();
    }
    
}

 

OrganizationTab.java

package workflow.contactmanager.beans.tabs;

import workflow.common.controls.ui.tabs.Tab;
import javax.faces.event.ActionEvent;

import static workflow.contactmanager.beans.tabs.ContactTabSetBean.*;


/**
 * @author nicola
 * @version 2.1.0 (Feb 17, 2010)
 */
public class OrganizationTab extends Tab {

    private OrganizationTabBean organizationTabBean;

    public OrganizationTab() {
        this("", "", -1);
        this.organizationTabBean = new OrganizationTabBean();
    }

    private OrganizationTab(String tabName, String tabTitle, int index) {
        super(TYPE_ORGANIZATIONS, tabName, tabTitle, index);
    }
    
    public OrganizationTabBean getOrganizationTabBean() {
        return organizationTabBean;
    }

    public void setOrganizationTabBean(OrganizationTabBean organizationTabBean) {
        this.organizationTabBean = organizationTabBean;
    }

    @Override
    public void reload(ActionEvent event) {
        this.organizationTabBean = new OrganizationTabBean();
    }

}

 

Теперь нам нужно создать универсальный tabSet и унаследовать от него наш класс для управления табами.

TabSetBean.java

package workflow.common.controls.ui.tabs;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * @author nicola
 * @version 2.1.0 (Feb 17, 2010)
 */
public class TabSetBean {
    private static final Logger LOG = Logger.getLogger(TabSetBean.class.getName());

    public static final int TYPE_NONE = -1;

    private int selectedTabIndex = 0;
    private List<Tab> tabs;

    public TabSetBean() {
        this.tabs = new ArrayList<Tab>();
    }

    public <T extends Tab> void addTab(T tab) {
        try {
            this.tabs.add(tab);
            this.selectedTabIndex = this.tabs != null ? this.tabs.size() - 1 : 0;
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    public List<Tab> getTabs() {
        return tabs;
    }

    public void setTabs(List<Tab> tabs) {
        this.tabs = tabs;
    }

    public int getTypeNone() {
        return TYPE_NONE;
    }

    public int getSelectedTabIndex() {
        return selectedTabIndex;
    }

    public void setSelectedTabIndex(int selectedTabIndex) {
        this.selectedTabIndex = selectedTabIndex;
    }

    public void removeDeletedTab() {
        if (this.tabs != null) {
            Iterator it = this.tabs.iterator();
            int removedTabIndex = -1;

            while (it.hasNext()) {
                Tab tab = (Tab) it.next();
                if (tab.isDeleted()) {
                    removedTabIndex = tab.getIndex();
                    it.remove();
                    if (this.selectedTabIndex == removedTabIndex) {
                        this.selectedTabIndex = (removedTabIndex == this.tabs.size()) 
                                                 ? (removedTabIndex - 1) 
                                                 : removedTabIndex;
                    } else {
                        this.selectedTabIndex--;
                    }
                }
            }

            if (this.selectedTabIndex < 0) {
                this.selectedTabIndex = 0;
            }

            reindexTabs();
        }
    }

    public void reindexTabs() {
        for (int i = 0; i < tabs.size(); i++) {
            ((Tab) tabs.get(i)).setIndex(i);
        }
    }

    public int getSizeTabs() {
        return (this.tabs != null ? this.tabs.size() : 0);
    }

    

}

 

ContactTabSetBean.java

 

	package workflow.contactmanager.beans.tabs;


import workflow.common.controls.ui.tabs.TabSetBean;
import workflow.common.controls.ui.tabs.Tab;
import workflow.common.controls.ui.FacesUtils;
import com.icesoft.faces.component.paneltabset.TabChangeEvent;
import com.icesoft.faces.component.paneltabset.TabChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.apache.log4j.Logger;

/**
 * @author nicola
 * @version 2.1.0 (Feb 17, 2010)
 */
public class ContactTabSetBean extends TabSetBean implements TabChangeListener {
    private static final Logger LOG = Logger.getLogger(ContactTabSetBean.class.getName());

    public static final int TYPE_ORGANIZATIONS = 1;
    public static final int TYPE_PERSONS = 2;

    private Tab currentTab;

    public ContactTabSetBean() {
        initTabs();
    }

    @Override
    public void processTabChange(TabChangeEvent event) {
        setSelectedTabIndex(event.getNewTabIndex());
        this.currentTab = getCurrentTab();
    }

    private void initTabs() {
         List<Tab> tabs = new ArrayList<Tab>();

         Tab organizationContactTab = new OrganizationTab();
         organizationContactTab.setType(TYPE_ORGANIZATIONS);
         organizationContactTab.setName(FacesUtils.getLocalizedMessage("menu.organizations"));
         organizationContactTab.setTitle(FacesUtils.getLocalizedMessage("menu.organizations"));
         organizationContactTab.setIndex(tabs.size());
         tabs.add(organizationContactTab);

         Tab personsContactTab = new PersonTab();
         personsContactTab.setType(TYPE_PERSONS);
         personsContactTab.setName(FacesUtils.getLocalizedMessage("menu.persons"));
         personsContactTab.setTitle(FacesUtils.getLocalizedMessage("menu.persons"));
         personsContactTab.setIndex(tabs.size());
         tabs.add(personsContactTab);

         setTabs(tabs);

    }

    @Override
    public void addTab(Tab tab) {
        boolean hasTab = false;
        try {            
            List<Tab> tabs = getTabs();
            for (Tab tabItem : tabs){
                if (tabItem != null && tabItem.equals(tab)) {
                    setSelectedTabIndex(tabItem.getIndex());
                    this.currentTab = tab;
                    hasTab = true;
                    break;
                }
            }

            if (!hasTab) {        
                tab.setIndex(getTabs().size());
                getTabs().add(tab);
                setSelectedTabIndex(tab.getIndex());
                this.currentTab = tab;
            }

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    public void addPersonTab(ActionEvent event) {
        try {
            PersonTab tab = new PersonTab();
            addTab(tab);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    public void addOrganizationTab(ActionEvent event) {
        try {            
            OrganizationTab tab = new OrganizationTab();
            addTab(tab);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

    public int getTypeOrganizations() {
        return TYPE_ORGANIZATIONS;
    }

    public int getTypePersons() {
        return TYPE_PERSONS;
    }

    public OrganizationTab getOrganizationCurrenTab() {
        return ( OrganizationTab )this.currentTab;
    }

    public PersonTab getPersonCurrenTab() {
        return ( PersonTab )this.currentTab;
    }

    private Tab getCurrentTab() {
        FacesContext context = FacesContext.getCurrentInstance();
        Tab tab = null;
        try {
            tab = ( Tab )context.getExternalContext().getRequestMap().get( "currentTab" );
            if (tab == null) {
                tab = ( Tab )getTabs().get(getSelectedTabIndex());
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }

        return tab;
    }

    public void closeTab(ActionEvent event) {
        try {
            String tabIndex = FacesUtils.getActionAttribute(event, "tabIndex");
            LOG.info("tabIndex " + tabIndex);
            Tab closingTab = null;
            closingTab = ( Tab )getTabs().get(Integer.valueOf(tabIndex).intValue());
            closingTab.closeTab();
            removeDeletedTab();
            this.currentTab = ( Tab )getTabs().get(getSelectedTabIndex());
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }
    }

}

 

Собственно, основные классы готовы. Пропишем теперь в  faces-config.xml

<managed-bean>
        <managed-bean-name>contactTabset</managed-bean-name>
        <managed-bean-class>
                workflow.contactmanager.beans.tabs.ContactTabSetBean
        </managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

 

Теперь наш jspx сможет работать с нашим бином табов. Осталось совсем немного, прописать ice faces компонент в jspx и настроить отоброжение табов.

index.jspx

	<?xml version="1.0" encoding="UTF-8" ?>
<ui:component xmlns:jsp="http://java.sun.com/JSP/Page"
          xmlns="http://www.w3.org/1999/xhtml"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:ice="http://www.icesoft.com/icefaces/component"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          version="2.0">

    <ui:composition template="/template.jspx">

        <ui:define name="title">#{msgs['menu.contacts']}</ui:define>

        <ui:define name="body">
            <ice:panelTabSet id="contactTabSet" 
                             immediate="true"
                             value="#{contactTabset.tabs}"
                             tabChangeListener="#{contactTabset.processTabChange}"
                             selectedIndex="#{contactTabset.selectedTabIndex}"
                             var="currentTab"
                             >
                
                <ice:panelTab title="#{currentTab.title}">
                    <f:facet name="label">
                        <ice:panelGrid columns="2">
                            <ice:outputText value="#{currentTab.name}"/>
                            <ice:commandButton rendered="#{contactTabset.sizeTabs gt 1}"
                                               image="#{styleBean.imageDirectory}cal_off.gif"
                                               actionListener="#{contactTabset.closeTab}">
                                <f:attribute name="tabIndex" value="#{currentTab.index}" />
                            </ice:commandButton>
                        </ice:panelGrid>
                    </f:facet>


                    <ice:panelGroup rendered="#{currentTab.type == contactTabset.typeOrganizations}">
                        <ui:include src="organizations.jspx"/>
                    </ice:panelGroup>

                    <ice:panelGroup rendered="#{currentTab.type == contactTabset.typePersons}">
                        <ui:include src="persons.jspx"/>
                    </ice:panelGroup>

                </ice:panelTab>
                    

            </ice:panelTabSet>

            
        </ui:define>
    </ui:composition>
</ui:component>

 

 

Код persons.jspx и organizations.jspx я не привожу, но покажу как добираться до бинов нужного вам класса.

Пример:

#{contactTabset.personCurrenTab.personTabBean.renderedPersonsPaginator}"

 

Собственно и все. В дальнейшем я расскажу, как повесить меню на табы и сделать их "drag and drop". В этом посте я лишь хотел показать логику создания универсальных табов, исходные классы были порезаны, поэтому могут вкраться ошибки.

Рад буду услышать Ваши отзывы.

Назад

S/N/V/      

tuneit
 

Образование:  СПБГУ ИТМО. Кафедра вычислительной техники.

Интересы: железо, софт, web-приложения (java EE, ICEfaces, LIferay, DotCMS, PHP, CSS, html, JavaScript, CMS Drupal, PostgreSQL, MySql, Oracle...)

Увлечения : активно занимаюсь спортом :  плаванием, джиу-джитсу, волейболом, бегом итд. Люблю отдыхать на природе.

Контакты:

  •   Nicola.russian
  •   Nicola.russian