/** * Copyright 2010 the original author or authors. * * This file is part of Zksample2. http://zksample2.sourceforge.net/ * * Zksample2 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Zksample2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Zksample2. If not, see <http://www.gnu.org/licenses/gpl.html>. */ package de.forsthaus.webui.article; import java.io.Serializable; import org.apache.log4j.Logger; import org.zkoss.util.resource.Labels; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Path; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventQueues; import org.zkoss.zk.ui.event.Events; import org.zkoss.zkplus.databind.AnnotateDataBinder; import org.zkoss.zkplus.databind.BindingListModelList; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.FieldComparator; import org.zkoss.zul.Intbox; import org.zkoss.zul.Listbox; import org.zkoss.zul.Listheader; import org.zkoss.zul.Paging; import org.zkoss.zul.Textbox; import org.zkoss.zul.Window; import de.forsthaus.UserWorkspace; import de.forsthaus.backend.model.Article; import de.forsthaus.backend.service.ArticleService; import de.forsthaus.backend.util.HibernateSearchObject; import de.forsthaus.webui.util.GFCBaseListCtrl; /** * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br> * This is the controller class for the /WEB-INF/pages/article/articleList.zul * file.<br> * <b>WORKS with the annotated databinding mechanism.</b><br> * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br> * * @changes 05/15/2009: sge Migrating the list models for paging. <br> * 07/24/2009: sge changings for clustering.<br> * 11/07/2009: bbr changed to extending from GFCBaseCtrl<br> * (GenericForwardComposer) for spring-managed creation.<br> * 03/09/2009: sge changed for allow repainting after resizing.<br> * with the refresh button.<br> * 07/03/2010: sge modified for zk5.x with complete Annotated * Databinding.<br> * * @author bbruhns * @author Stephan Gerth */ public class ArticleListCtrl extends GFCBaseListCtrl<Article> implements Serializable { private static final long serialVersionUID = 2038742641853727975L; private static final Logger logger = Logger.getLogger(ArticleListCtrl.class); /* * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * All the components that are defined here and have a corresponding * component with the same 'id' in the zul-file are getting autowired by our * 'extends GFCBaseCtrl' GenericForwardComposer. * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ protected Window windowArticlesList; // autowired // listbox articles protected Borderlayout borderLayout_articleList; // autowired protected Paging paging_ArticleList; // autowired protected Listbox listBoxArticle; // autowired protected Listheader listheader_ArticleList_No; // autowired protected Listheader listheader_ArticleList_ShortDescr; // autowired protected Listheader listheader_ArticleList_SinglePrice; // autowired // textbox long description protected Textbox longBoxArt_LangBeschreibung; // autowired // count of rows in the listbox private int countRows; // NEEDED for ReUse in a SearchWindow private HibernateSearchObject<Article> searchObj; // Databinding private AnnotateDataBinder binder; private ArticleMainCtrl articleMainCtrl; // ServiceDAOs / Domain Classes private transient ArticleService articleService; /** * default constructor.<br> */ public ArticleListCtrl() { super(); } @Override public void doAfterCompose(Component window) throws Exception { super.doAfterCompose(window); /** * 1. Set an 'alias' for this composer name to access it in the * zul-file.<br> * 2. Set the parameter 'recurse' to 'false' to avoid problems with * managing more than one zul-file in one page. Otherwise it would be * overridden and can ends in curious error messages. */ this.self.setAttribute("controller", this, false); /** * 1. Get the overhanded MainController.<br> * 2. Set this controller in the MainController.<br> * 3. Check if a 'selectedObject' exists yet in the MainController.<br> */ if (arg.containsKey("ModuleMainController")) { setArticleMainCtrl((ArticleMainCtrl) arg.get("ModuleMainController")); // SET THIS CONTROLLER TO THE module's Parent/MainController getArticleMainCtrl().setArticleListCtrl(this); // Get the selected object. // Check if this Controller if created on first time. If so, // than the selectedXXXBean should be null if (getArticleMainCtrl().getSelectedArticle() != null) { setSelectedArticle(getArticleMainCtrl().getSelectedArticle()); } else setSelectedArticle(null); } else { setSelectedArticle(null); } } // +++++++++++++++++++++++++++++++++++++++++++++++++ // // +++++++++++++++ Component Events ++++++++++++++++ // // +++++++++++++++++++++++++++++++++++++++++++++++++ // public void onCreate$windowArticlesList(Event event) throws Exception { binder = (AnnotateDataBinder) event.getTarget().getAttribute("binder", true); doFillListbox(); binder.loadAll(); } public void doFillListbox() { doFitSize(); // set the paging params paging_ArticleList.setPageSize(getCountRows()); paging_ArticleList.setDetailed(true); // not used listheaders must be declared like -> // lh.setSortAscending(""); lh.setSortDescending("") listheader_ArticleList_No.setSortAscending(new FieldComparator("artNr", true)); listheader_ArticleList_No.setSortDescending(new FieldComparator("artNr", false)); listheader_ArticleList_ShortDescr.setSortAscending(new FieldComparator("artKurzbezeichnung", true)); listheader_ArticleList_ShortDescr.setSortDescending(new FieldComparator("artKurzbezeichnung", false)); listheader_ArticleList_SinglePrice.setSortAscending(new FieldComparator("artPreis", true)); listheader_ArticleList_SinglePrice.setSortDescending(new FieldComparator("artPreis", false)); // ++ create the searchObject and init sorting ++// // get customers and only their latest address searchObj = new HibernateSearchObject<Article>(Article.class, getCountRows()); searchObj.addSort("artNr", false); setSearchObj(this.searchObj); // Set the BindingListModel getPagedBindingListWrapper().init(searchObj, getListBoxArticle(), paging_ArticleList); BindingListModelList lml = (BindingListModelList) getListBoxArticle().getModel(); setArticles(lml); // Now we would select and show the text of the first entry in the list. // We became not the first item FROM the listbox because it's NOT // RENDERED AT THIS TIME. // So we take the first entry from the MODEL (ListModelList) and set as // selected. // check if first time opened and init databinding for selectedBean if (getSelectedArticle() == null) { // init the bean with the first record in the List if (lml.getSize() > 0) { final int rowIndex = 0; // only for correct showing after Rendering. No effect as an // Event // yet. getListBoxArticle().setSelectedIndex(rowIndex); // get the first entry and cast them to the needed object setSelectedArticle((Article) lml.get(0)); // call the onSelect Event for showing the objects data in the // statusBar Events.sendEvent(new Event("onSelect", getListBoxArticle(), getSelectedArticle())); } } } /** * Selects the object in the listbox and change the tab.<br> * Event is forwarded in the corresponding listbox. */ public void onDoubleClickedArticleItem(Event event) { // logger.debug(event.toString()); Article anArticle = getSelectedArticle(); if (anArticle != null) { setSelectedArticle(anArticle); setArticle(anArticle); // check first, if the tabs are created if (getArticleMainCtrl().getArticleDetailCtrl() == null) { Events.sendEvent(new Event("onSelect", getArticleMainCtrl().tabArticleDetail, null)); // if we work with spring beanCreation than we must check a // little bit deeper, because the Controller are preCreated ? } else if (getArticleMainCtrl().getArticleDetailCtrl().getBinder() == null) { Events.sendEvent(new Event("onSelect", getArticleMainCtrl().tabArticleDetail, null)); } Events.sendEvent(new Event("onSelect", getArticleMainCtrl().tabArticleDetail, anArticle)); } } /** * When a listItem in the corresponding listbox is selected.<br> * Event is forwarded in the corresponding listbox. * * @param event */ public void onSelect$listBoxArticle(Event event) { // logger.debug(event.toString()); // selectedArticle is filled by annotated databinding mechanism Article anArticle = getSelectedArticle(); if (anArticle == null) { return; } // check first, if the tabs are created if (getArticleMainCtrl().getArticleDetailCtrl() == null) { Events.sendEvent(new Event("onSelect", getArticleMainCtrl().tabArticleDetail, null)); // if we work with spring beanCreation than we must check a little // bit deeper, because the Controller are preCreated ? } else if (getArticleMainCtrl().getArticleDetailCtrl().getBinder() == null) { Events.sendEvent(new Event("onSelect", getArticleMainCtrl().tabArticleDetail, null)); } // INIT ALL RELATED Queries/OBJECTS/LISTS NEW getArticleMainCtrl().getArticleDetailCtrl().setSelectedArticle(anArticle); getArticleMainCtrl().getArticleDetailCtrl().setArticle(anArticle); // store the selected bean values as current getArticleMainCtrl().doStoreInitValues(); // show the objects data in the statusBar final String str = Labels.getLabel("common.Article") + ": " + anArticle.getArtKurzbezeichnung(); EventQueues.lookup("selectedObjectEventQueue", EventQueues.DESKTOP, true).publish(new Event("onChangeSelectedObject", null, str)); } // +++++++++++++++++++++++++++++++++++++++++++++++++ // // +++++++++++++++++ Business Logic ++++++++++++++++ // // +++++++++++++++++++++++++++++++++++++++++++++++++ // // +++++++++++++++++++++++++++++++++++++++++++++++++ // // ++++++++++++++++++++ Helpers ++++++++++++++++++++ // // +++++++++++++++++++++++++++++++++++++++++++++++++ // /** * Recalculates the container size for this controller and resize them. * * Calculate how many rows have been place in the listbox. Get the * currentDesktopHeight from a hidden Intbox from the index.zul that are * filled by onClientInfo() in the indexCtroller. */ public void doFitSize() { // normally 0 ! Or we have a i.e. a toolBar on top of the listBox. final int specialSize = 0; final int menuOffset = UserWorkspace.getInstance().getMenuOffset(); int height = ((Intbox) Path.getComponent("/outerIndexWindow/currentDesktopHeight")).getValue().intValue(); height = height - menuOffset; final int maxListBoxHeight = height - specialSize - 152; setCountRows((int) Math.round(maxListBoxHeight / 18.4)); borderLayout_articleList.setHeight(String.valueOf(maxListBoxHeight) + "px"); windowArticlesList.invalidate(); } // ++++++++++++++++++++++++++++++++++++++++++++++++++++++// // ++++++++++++++++++ getter / setter +++++++++++++++++++// // ++++++++++++++++++++++++++++++++++++++++++++++++++++++// /** * Best Pratice Hint:<br> * The setters/getters for the local annotated data binded Beans/Sets are * administered in the module's mainController. Working in this way you have * clean line to share this beans/sets with other controllers. */ /* Master BEANS */ public Article getArticle() { // STORED IN THE module's MainController return getArticleMainCtrl().getSelectedArticle(); } public void setArticle(Article article) { // STORED IN THE module's MainController getArticleMainCtrl().setSelectedArticle(article); } public void setSelectedArticle(Article selectedArticle) { // STORED IN THE module's MainController getArticleMainCtrl().setSelectedArticle(selectedArticle); } public Article getSelectedArticle() { // STORED IN THE module's MainController return getArticleMainCtrl().getSelectedArticle(); } public void setArticles(BindingListModelList articles) { // STORED IN THE module's MainController getArticleMainCtrl().setArticles(articles); } public BindingListModelList getArticles() { // STORED IN THE module's MainController return getArticleMainCtrl().getArticles(); } public void setBinder(AnnotateDataBinder binder) { this.binder = binder; } public AnnotateDataBinder getBinder() { return this.binder; } /* CONTROLLERS */ public void setArticleMainCtrl(ArticleMainCtrl articleMainCtrl) { this.articleMainCtrl = articleMainCtrl; } public ArticleMainCtrl getArticleMainCtrl() { return this.articleMainCtrl; } /* SERVICES */ public void setArticleService(ArticleService articleService) { this.articleService = articleService; } public ArticleService getArticleService() { return this.articleService; } /* COMPONENTS and OTHERS */ public int getCountRows() { return this.countRows; } public void setCountRows(int countRows) { this.countRows = countRows; } public HibernateSearchObject<Article> getSearchObj() { return this.searchObj; } public void setSearchObj(HibernateSearchObject<Article> searchObj) { this.searchObj = searchObj; } public Listbox getListBoxArticle() { return this.listBoxArticle; } public void setListBoxArticle(Listbox listBoxArticle) { this.listBoxArticle = listBoxArticle; } }