/* MeshElement.java {{IS_NOTE Purpose: Description: History: Feb 11, 2011 5:48:26 PM, Created by henrichen }}IS_NOTE Copyright (C) 2011 Potix Corporation. All Rights Reserved. */ package org.zkoss.zul.impl; import javax.servlet.ServletRequest; import org.zkoss.lang.Objects; import org.zkoss.web.servlet.Servlets; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zul.Paging; import org.zkoss.zul.ext.Paginal; import org.zkoss.zul.ext.Paginated; /** * The fundamental class for mesh elements such as {@link org.zkoss.zul.Grid}, {@link org.zkoss.zul.Listbox}, and {@link org.zkoss.zul.Tree}. * @author henrichen * @since 5.0.6 */ public abstract class MeshElement extends XulElement implements Paginated { private String _span; private boolean _sizedByContent; private boolean _autopaging; private String _pagingPosition = "bottom"; /** * Return column span hint of this component. * <p>Default: null * @return column span hint of this component. * @since 5.0.6 * @see #setSpan */ public String getSpan() { return _span; } /** * Sets column span hint of this component. * <p>String number span indicates how this component distributes remaining empty space to the * specified column(0-based). "0" means distribute remaining empty space to the 1st column; "1" means * distribute remaining empty space to the 2nd column, etc.. The spanning column will grow to * fit the extra remaining space.</p> * <p>Special span hint with "true" means span ALL columns proportionally per their * original widths while null or "false" means NOT spanning any column.</p> * <p>Default: null. That is, NOT span any column.</p> * <p>Note span is meaningful only if there is remaining empty space for columns.</p> * * @param span the column span hint. * @since 5.0.6 * @see #getSpan * @see #setSpan(boolean) */ public void setSpan(String span) { if (!Objects.equals(_span, span)) { _span = span; smartUpdate("span", span); } } /** * Sets whether distributes remaining empty space of this component to ALL columns proportionally. * <p>Default: false. That is, NOT span any column.</p> * <p>Note span is meaningful only if there is remaining empty space for columns.</p> * @param span whether to span the width of ALL columns to occupy the whole mesh element(grid/listbox/tree). * @since 5.0.5 */ public void setSpan(boolean span) { if ((span && !"true".equals(_span)) || (!span && _span != null && !"false".equals(_span))) { _span = span ? "true" : "false"; smartUpdate("span", span); } } /** * Returns whether distributes remaining empty space of this component to ANY column. * <p>Default: false.</p> * @return whether distributes remaining empty space of this component to ANY column. * @since 5.0.5 * @see #getSpan * @see #setSpan(boolean) * @see #setSpan(String) */ public boolean isSpan() { return _span != null && !"false".equals(_span); } /** * Sets whether sizing grid/listbox/tree column width by its content; it equals set hflex="min" on each column. * <p>Default: false. * @param byContent * @since 5.0.0 */ public void setSizedByContent(boolean byContent) { if (_sizedByContent != byContent) { _sizedByContent = byContent; smartUpdate("sizedByContent", byContent); } } /** * Returns whether sizing grid/listbox/tree column width by its content. Default is false. * @since 5.0.0 * @see #setSizedByContent */ public boolean isSizedByContent() { String s = (String) getAttribute("sized-by-content"); //backward-compatibility if (s == null) { s = (String) getAttribute("fixed-layout"); //backward-compatibility return s != null ? !"true".equalsIgnoreCase(s) : _sizedByContent; } else return "true".equalsIgnoreCase(s); } /** * Sets whether the auto-paging facility is turned on when mold is * "paging". If it is set to true, the {@link #setPageSize} is ignored; * rather, the page size is automatically determined by the height of the * Listbox dynamically. Note: Due to performance concern, Autopaging * functionality does not support {@link org.zkoss.zul.Detail} components. * @param autopaging true to turn on the auto-paging facility. * @since 5.0.2 */ public void setAutopaging(boolean autopaging) { if (_autopaging != autopaging) { _autopaging = autopaging; smartUpdate("autopaging", autopaging); } } /** * Returns whether the auto-paging facility is turned on when mold is * "paging". If it is set to true, the {@link #setPageSize} is ignored; * rather, the page size is automatically determined by the height of the * Listbox dynamically. * @return whether the "autopaging" facility is turned on. * @since 5.0.2 */ public boolean isAutopaging() { return _autopaging; } /** * Sets how to position the paging of mesh element at the client screen. * It is meaningless if the mold is not in "paging". * @param pagingPosition how to position. It can only be "bottom" (the default), or * "top", or "both". * @since 3.0.4 */ public void setPagingPosition(String pagingPosition) { if (pagingPosition == null || (!pagingPosition.equals("top") && !pagingPosition.equals("bottom") && !pagingPosition.equals("both"))) throw new WrongValueException("Unsupported position : " + pagingPosition); if (!Objects.equals(_pagingPosition, pagingPosition)) { _pagingPosition = pagingPosition; smartUpdate("pagingPosition", pagingPosition); } } protected class InternalPaging extends Paging { private boolean autohideModify = false; public InternalPaging() { } public boolean isAutohide() { if (!autohideModify) return isAutohidePaging(); else return super.isAutohide(); } public void setAutohide(boolean autohide) { autohideModify = true; super.setAutohide(autohide); } public boolean isAutohideModify() { return autohideModify; } } protected abstract boolean isAutohidePaging(); /** * Returns how to position the paging of mesh element at the client screen. * It is meaningless if the mold is not in "paging". * @since 3.0.4 */ public String getPagingPosition() { return _pagingPosition; } /** Returns the instance of the @{link Paginal} */ protected abstract Paginal pgi(); /** Returns the page size, a.k.a., the number rows per page. * @exception IllegalStateException if {@link #pgi} returns null, * i.e., mold is not "paging" and no external controller is specified. */ public int getPageSize() { return pgi().getPageSize(); } /** Sets the page size, a.k.a., the number rows per page. * @exception IllegalStateException if {@link #pgi} returns null, * i.e., mold is not "paging" and no external controller is specified. */ public void setPageSize(int pgsz) throws WrongValueException { pgi().setPageSize(pgsz); } /** Returns the number of pages. * Note: there is at least one page even no item at all. * @since 3.0.4 */ public int getPageCount() { return pgi().getPageCount(); } /** Returns the active page (starting from 0). * @since 3.0.4 */ public int getActivePage() { return pgi().getActivePage(); } /** Sets the active page (starting from 0). * @since 3.0.4 */ public void setActivePage(int pg) throws WrongValueException { pgi().setActivePage(pg); } /*package*/ boolean isNativeScrollbar() { ServletRequest request = (ServletRequest) Executions.getCurrent().getNativeRequest(); // B70-ZK-2489: Set org.zkoss.zul.nativebar's default to false when using a mobile device if (Servlets.isBrowser(request, "ie8-")) { return true; } else { return Utils.testAttribute(this, "org.zkoss.zul.nativebar", true, true); } } /** * @return whether the paging component of this component is disabled * @since 8.0.3 */ public boolean isPagingDisabled() { return pgi().isDisabled(); } /** * Sets whether to disable the Paging component of this component * @param pagingDisabled * @since 8.0.3 */ public void setPagingDisabled(boolean pagingDisabled) { pgi().setDisabled(pagingDisabled); } protected void renderProperties(org.zkoss.zk.ui.sys.ContentRenderer renderer) throws java.io.IOException { super.renderProperties(renderer); if (isSizedByContent()) renderer.render("sizedByContent", true); if (_span != null) renderer.render("span", _span); if (isAutopaging()) renderer.render("autopaging", true); if (!"bottom".equals(_pagingPosition)) render(renderer, "pagingPosition", _pagingPosition); if (isNativeScrollbar()) renderer.render("_nativebar", true); } }