Source Code Cross Referenced for Grid.java in  » Ajax » zk » org » zkoss » zul » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » zk » org.zkoss.zul 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Grid.java
0002:
0003:        {{IS_NOTE
0004:        	Purpose:
0005:        		
0006:        	Description:
0007:        		
0008:        	History:
0009:        		Tue Oct 25 15:40:35     2005, Created by tomyeh
0010:        }}IS_NOTE
0011:
0012:        Copyright (C) 2005 Potix Corporation. All Rights Reserved.
0013:
0014:        {{IS_RIGHT
0015:        	This program is distributed under GPL Version 2.0 in the hope that
0016:        	it will be useful, but WITHOUT ANY WARRANTY.
0017:        }}IS_RIGHT
0018:         */
0019:        package org.zkoss.zul;
0020:
0021:        import java.util.Collection;
0022:        import java.util.AbstractCollection;
0023:        import java.util.List;
0024:        import java.util.ArrayList;
0025:        import java.util.LinkedList;
0026:        import java.util.ListIterator;
0027:        import java.util.Iterator;
0028:        import java.util.Set;
0029:
0030:        import org.zkoss.lang.D;
0031:        import org.zkoss.lang.Objects;
0032:        import org.zkoss.lang.Classes;
0033:        import org.zkoss.lang.Exceptions;
0034:        import org.zkoss.util.logging.Log;
0035:        import org.zkoss.xml.HTMLs;
0036:
0037:        import org.zkoss.zk.ui.Component;
0038:        import org.zkoss.zk.ui.UiException;
0039:        import org.zkoss.zk.ui.ext.client.RenderOnDemand;
0040:        import org.zkoss.zk.ui.ext.client.InnerWidth;
0041:        import org.zkoss.zk.ui.event.Event;
0042:        import org.zkoss.zk.ui.event.EventListener;
0043:        import org.zkoss.zk.ui.event.Events;
0044:
0045:        import org.zkoss.zul.impl.XulElement;
0046:        import org.zkoss.zul.ext.Paginal;
0047:        import org.zkoss.zul.event.ListDataEvent;
0048:        import org.zkoss.zul.event.ListDataListener;
0049:        import org.zkoss.zul.event.ZulEvents;
0050:        import org.zkoss.zul.event.PagingEvent;
0051:
0052:        /**
0053:         * A grid is an element that contains both rows and columns elements.
0054:         * It is used to create a grid of elements.
0055:         * Both the rows and columns are displayed at once although only one will
0056:         * typically contain content, while the other may provide size information.
0057:         *
0058:         * <p>Besides creating {@link Row} programmingly, you can assign
0059:         * a data model (a {@link ListModel} instance) to a grid via
0060:         * {@link #setModel} and then the grid will retrieve data
0061:         * by calling {@link ListModel#getElementAt} when necessary.
0062:         *
0063:         * <p>Besides assign a list model, you could assign a renderer
0064:         * (a {@link RowRenderer} instance) to a grid, such that
0065:         * the grid will use this
0066:         * renderer to render the data returned by {@link ListModel#getElementAt}.
0067:         * If not assigned, the default renderer, which assumes a label per row,
0068:         * is used.
0069:         * In other words, the default renderer adds a label to
0070:         * a row by calling toString against the object returned
0071:         * by {@link ListModel#getElementAt}
0072:         * 
0073:         * <p>There are two ways to handle long content: scrolling and paging.
0074:         * If {@link #getMold} is "default", scrolling is used if {@link #setHeight}
0075:         * is called and too much content to display.
0076:         * If {@link #getMold} is "paging", paging is used if two or more pages are
0077:         * required. To control the number of rows to display in a page, use
0078:         * {@link #setPageSize}.
0079:         *
0080:         * <p>If paging is used, the page controller is either created automatically
0081:         * or assigned explicity by {@link #setPaginal}.
0082:         * The paging controller specified explicitly by {@link #setPaginal} is called
0083:         * the external page controller. It is useful if you want to put the paging
0084:         * controller at different location (other than as a child component), or
0085:         * you want to use the same controller to control multiple grids.
0086:         *
0087:         * <p>Default {@link #getSclass}: grid.
0088:         *
0089:         * <p>To have a grid without stripping, you can specify a non-existent
0090:         * style class to {@link #setOddRowSclass}.
0091:         * If you want to disable all striping, you can specify the style:
0092:         * <pre><code>
0093:         tr.odd td.gc {
0094:         background: white;
0095:         }
0096:         * </code></pre>
0097:         *
0098:         * @author tomyeh
0099:         * @see ListModel
0100:         * @see RowRenderer
0101:         * @see RowRendererExt
0102:         */
0103:        public class Grid extends XulElement {
0104:            private static final Log log = Log.lookup(Grid.class);
0105:
0106:            private transient Rows _rows;
0107:            private transient Columns _cols;
0108:            private transient Foot _foot;
0109:            private transient Collection _heads;
0110:            private String _align;
0111:            private ListModel _model;
0112:            private RowRenderer _renderer;
0113:            private transient ListDataListener _dataListener;
0114:            /** The paging controller, used only if mold = "paging". */
0115:            private transient Paginal _pgi;
0116:            /** The paging controller, used only if mold = "paging" and user
0117:             * doesn't assign a controller via {@link #setPaginal}.
0118:             * If exists, it is the last child.
0119:             */
0120:            private transient Paging _paging;
0121:            private transient EventListener _pgListener, _pgImpListener;
0122:            /** The style class of the odd row. */
0123:            private String _scOddRow = "odd";
0124:            /** the # of rows to preload. */
0125:            private int _preloadsz = 7;
0126:            private String _innerWidth = "100%";
0127:
0128:            public Grid() {
0129:                setSclass("grid");
0130:                init();
0131:            }
0132:
0133:            private void init() {
0134:                _heads = new AbstractCollection() {
0135:                    public int size() {
0136:                        int sz = getChildren().size();
0137:                        if (_rows != null)
0138:                            --sz;
0139:                        if (_foot != null)
0140:                            --sz;
0141:                        if (_paging != null)
0142:                            --sz;
0143:                        return sz;
0144:                    }
0145:
0146:                    public Iterator iterator() {
0147:                        return new Iter();
0148:                    }
0149:                };
0150:            }
0151:
0152:            /** Returns the rows.
0153:             */
0154:            public Rows getRows() {
0155:                return _rows;
0156:            }
0157:
0158:            /** Returns the columns.
0159:             */
0160:            public Columns getColumns() {
0161:                return _cols;
0162:            }
0163:
0164:            /** Returns the foot.
0165:             */
0166:            public Foot getFoot() {
0167:                return _foot;
0168:            }
0169:
0170:            /** Returns a collection of heads, including {@link #getColumns}
0171:             * and auxiliary heads ({@link Auxhead}) (never null).
0172:             *
0173:             * @since 3.0.0
0174:             */
0175:            public Collection getHeads() {
0176:                return _heads;
0177:            }
0178:
0179:            /** Returns the specified cell, or null if not available.
0180:             * @param row which row to fetch (starting at 0).
0181:             * @param col which column to fetch (starting at 0).
0182:             */
0183:            public Component getCell(int row, int col) {
0184:                final Rows rows = getRows();
0185:                if (rows == null)
0186:                    return null;
0187:
0188:                List children = rows.getChildren();
0189:                if (children.size() <= row)
0190:                    return null;
0191:
0192:                children = ((Row) children.get(row)).getChildren();
0193:                return children.size() <= col ? null : (Component) children
0194:                        .get(col);
0195:            }
0196:
0197:            /** Returns the horizontal alignment of the whole grid.
0198:             * <p>Default: null (system default: left unless CSS specified).
0199:             */
0200:            public String getAlign() {
0201:                return _align;
0202:            }
0203:
0204:            /** Sets the horizontal alignment of the whole grid.
0205:             * <p>Allowed: "left", "center", "right"
0206:             */
0207:            public void setAlign(String align) {
0208:                if (!Objects.equals(_align, align)) {
0209:                    _align = align;
0210:                    smartUpdate("align", _align);
0211:                }
0212:            }
0213:
0214:            //--Paging--//
0215:            /** Returns the paging controller, or null if not available.
0216:             * Note: the paging controller is used only if {@link #getMold} is "paging".
0217:             *
0218:             * <p>If mold is "paging", this method never returns null, because
0219:             * a child paging controller is created automcatically (if not specified
0220:             * by developers with {@link #setPaginal}).
0221:             *
0222:             * <p>If a paging controller is specified (either by {@link #setPaginal},
0223:             * or by {@link #setMold} with "paging"),
0224:             * the grid will rely on the paging controller to handle long-content
0225:             * instead of scrolling.
0226:             */
0227:            public Paginal getPaginal() {
0228:                return _pgi;
0229:            }
0230:
0231:            /* Specifies the paging controller.
0232:             * Note: the paging controller is used only if {@link #getMold} is "paging".
0233:             *
0234:             * <p>It is OK, though without any effect, to specify a paging controller
0235:             * even if mold is not "paging".
0236:             *
0237:             * @param pgi the paging controller. If null and {@link #getMold} is "paging",
0238:             * a paging controller is created automatically as a child component
0239:             * (see {@link #getPaging}).
0240:             */
0241:            public void setPaginal(Paginal pgi) {
0242:                if (!Objects.equals(pgi, _pgi)) {
0243:                    final Paginal old = _pgi;
0244:                    _pgi = pgi;
0245:
0246:                    if (inPagingMold()) {
0247:                        if (old != null)
0248:                            removePagingListener(old);
0249:                        if (_pgi == null) {
0250:                            if (_paging != null)
0251:                                _pgi = _paging;
0252:                            else
0253:                                newInternalPaging();
0254:                        } else { //_pgi != null
0255:                            if (_pgi != _paging) {
0256:                                if (_paging != null)
0257:                                    _paging.detach();
0258:                                _pgi.setTotalSize(_rows != null ? _rows
0259:                                        .getChildren().size() : 0);
0260:                                addPagingListener(_pgi);
0261:                            }
0262:                        }
0263:                    }
0264:                }
0265:            }
0266:
0267:            /** Creates the internal paging component.
0268:             */
0269:            private void newInternalPaging() {
0270:                assert D.OFF || inPagingMold() : "paging mold only";
0271:                assert D.OFF || (_paging == null && _pgi == null);
0272:
0273:                final Paging paging = new Paging();
0274:                paging.setAutohide(true);
0275:                paging.setDetailed(true);
0276:                paging.setTotalSize(_rows != null ? _rows.getChildren().size()
0277:                        : 0);
0278:                paging.setParent(this );
0279:                addPagingListener(_pgi);
0280:            }
0281:
0282:            /** Adds the event listener for the onPaging event. */
0283:            private void addPagingListener(Paginal pgi) {
0284:                if (_pgListener == null)
0285:                    _pgListener = new EventListener() {
0286:                        public void onEvent(Event event) {
0287:                            final PagingEvent evt = (PagingEvent) event;
0288:                            Events.postEvent(new PagingEvent(evt.getName(),
0289:                                    Grid.this , evt.getPageable(), evt
0290:                                            .getActivePage()));
0291:                        }
0292:                    };
0293:                pgi.addEventListener(ZulEvents.ON_PAGING, _pgListener);
0294:
0295:                if (_pgImpListener == null)
0296:                    _pgImpListener = new EventListener() {
0297:                        public void onEvent(Event event) {
0298:                            if (_rows != null && _model != null
0299:                                    && inPagingMold()) {
0300:                                //theorectically, _rows shall not be null if _model is not null when
0301:                                //this method is called. But, just in case -- if sent manually
0302:                                final Renderer renderer = new Renderer();
0303:                                try {
0304:                                    final Paginal pgi = getPaginal();
0305:                                    int pgsz = pgi.getPageSize();
0306:                                    final int ofs = pgi.getActivePage() * pgsz;
0307:                                    for (final Iterator it = _rows
0308:                                            .getChildren().listIterator(ofs); --pgsz >= 0
0309:                                            && it.hasNext();)
0310:                                        renderer.render((Row) it.next());
0311:                                } catch (Throwable ex) {
0312:                                    renderer.doCatch(ex);
0313:                                } finally {
0314:                                    renderer.doFinally();
0315:                                }
0316:                            }
0317:
0318:                            if (_rows != null)
0319:                                _rows.invalidate();
0320:                        }
0321:                    };
0322:                pgi.addEventListener("onPagingImpl", _pgImpListener);
0323:            }
0324:
0325:            /** Removes the event listener for the onPaging event. */
0326:            private void removePagingListener(Paginal pgi) {
0327:                pgi.removeEventListener(ZulEvents.ON_PAGING, _pgListener);
0328:                pgi.removeEventListener("onPagingImpl", _pgImpListener);
0329:            }
0330:
0331:            /** Returns the child paging controller that is created automatically,
0332:             * or null if mold is not "paging", or the controller is specified externally
0333:             * by {@link #setPaginal}.
0334:             */
0335:            public Paging getPaging() {
0336:                return _paging;
0337:            }
0338:
0339:            /** Returns the page size, aka., the number rows per page.
0340:             * @exception IllegalStateException if {@link #getPaginal} returns null,
0341:             * i.e., mold is not "paging" and no external controller is specified.
0342:             */
0343:            public int getPageSize() {
0344:                if (_pgi == null)
0345:                    throw new IllegalStateException(
0346:                            "Available only the paging mold");
0347:                return _pgi.getPageSize();
0348:            }
0349:
0350:            /** Sets the page size, aka., the number rows per page.
0351:             * @exception IllegalStateException if {@link #getPaginal} returns null,
0352:             * i.e., mold is not "paging" and no external controller is specified.
0353:             */
0354:            public void setPageSize(int pgsz) {
0355:                if (_pgi == null)
0356:                    throw new IllegalStateException(
0357:                            "Available only the paging mold");
0358:                _pgi.setPageSize(pgsz);
0359:            }
0360:
0361:            /** Returns whether this grid is in the paging mold.
0362:             */
0363:            /*package*/boolean inPagingMold() {
0364:                return "paging".equals(getMold());
0365:            }
0366:
0367:            //-- ListModel dependent codes --//
0368:            /** Returns the list model associated with this grid, or null
0369:             * if this grid is not associated with any list data model.
0370:             */
0371:            public ListModel getModel() {
0372:                return _model;
0373:            }
0374:
0375:            /** Sets the list model associated with this grid.
0376:             * If a non-null model is assigned, no matter whether it is the same as
0377:             * the previous, it will always cause re-render.
0378:             *
0379:             * @param model the list model to associate, or null to dis-associate
0380:             * any previous model.
0381:             * @exception UiException if failed to initialize with the model
0382:             */
0383:            public void setModel(ListModel model) {
0384:                if (model != null) {
0385:                    if (_model != model) {
0386:                        if (_model != null) {
0387:                            _model.removeListDataListener(_dataListener);
0388:                        } else {
0389:                            if (_rows != null)
0390:                                _rows.getChildren().clear(); //Bug 1807414
0391:                            smartUpdate("z.model", "true");
0392:                        }
0393:
0394:                        initDataListener();
0395:                        _model = model;
0396:                        _model.addListDataListener(_dataListener);
0397:                    }
0398:
0399:                    //Always syncModel because it is easier for user to enfore reload
0400:                    syncModel(-1, -1); //create rows if necessary
0401:                    postOnInitRender();
0402:                    //Since user might setModel and setRender separately or repeatedly,
0403:                    //we don't handle it right now until the event processing phase
0404:                    //such that we won't render the same set of data twice
0405:                    //--
0406:                    //For better performance, we shall load the first few row now
0407:                    //(to save a roundtrip)
0408:                } else if (_model != null) {
0409:                    _model.removeListDataListener(_dataListener);
0410:                    _model = null;
0411:                    if (_rows != null)
0412:                        _rows.getChildren().clear();
0413:                    smartUpdate("z.model", null);
0414:                }
0415:            }
0416:
0417:            private void initDataListener() {
0418:                if (_dataListener == null)
0419:                    _dataListener = new ListDataListener() {
0420:                        public void onChange(ListDataEvent event) {
0421:                            onListDataChange(event);
0422:                        }
0423:                    };
0424:            }
0425:
0426:            /** Returns the renderer to render each row, or null if the default
0427:             * renderer is used.
0428:             */
0429:            public RowRenderer getRowRenderer() {
0430:                return _renderer;
0431:            }
0432:
0433:            /** Sets the renderer which is used to render each row
0434:             * if {@link #getModel} is not null.
0435:             *
0436:             * <p>Note: changing a render will not cause the grid to re-render.
0437:             * If you want it to re-render, you could assign the same model again 
0438:             * (i.e., setModel(getModel())), or fire an {@link ListDataEvent} event.
0439:             *
0440:             * @param renderer the renderer, or null to use the default.
0441:             * @exception UiException if failed to initialize with the model
0442:             */
0443:            public void setRowRenderer(RowRenderer renderer) {
0444:                _renderer = renderer;
0445:            }
0446:
0447:            /** Sets the renderer by use of a class name.
0448:             * It creates an instance automatically.
0449:             */
0450:            public void setRowRenderer(String clsnm)
0451:                    throws ClassNotFoundException, NoSuchMethodException,
0452:                    IllegalAccessException, InstantiationException,
0453:                    java.lang.reflect.InvocationTargetException {
0454:                if (clsnm != null)
0455:                    setRowRenderer((RowRenderer) Classes
0456:                            .newInstanceByThread(clsnm));
0457:            }
0458:
0459:            /** Returns the number of rows to preload when receiving
0460:             * the rendering request from the client.
0461:             *
0462:             * <p>Default: 7.
0463:             *
0464:             * <p>It is used only if live data ({@link #setModel} and
0465:             * not paging ({@link #getPaging}.
0466:             *
0467:             * @since 2.4.1
0468:             */
0469:            public int getPreloadSize() {
0470:                return _preloadsz;
0471:            }
0472:
0473:            /** Sets the number of rows to preload when receiving
0474:             * the rendering request from the client.
0475:             * <p>It is used only if live data ({@link #setModel} and
0476:             * not paging ({@link #getPaging}.
0477:             *
0478:             * @param sz the number of rows to preload. If zero, no preload
0479:             * at all.
0480:             * @exception UiException if sz is negative
0481:             * @since 2.4.1
0482:             */
0483:            public void setPreloadSize(int sz) {
0484:                if (sz < 0)
0485:                    throw new UiException("nonnegative is required: " + sz);
0486:                _preloadsz = sz;
0487:            }
0488:
0489:            /**
0490:             * Sets the inner width of this component.
0491:             * The inner width is the width of the inner table.
0492:             * By default, it is 100%. That is, it is the same as the width
0493:             * of this component. However, it is changed when the user
0494:             * is sizing the column's width.
0495:             *
0496:             * <p>Application developers rarely call this method, unless
0497:             * they want to preserve the widths of sizable columns
0498:             * changed by the user.
0499:             * To preserve the widths, the developer have to store the widths of
0500:             * all columns and the inner width ({@link #getInnerWidth}),
0501:             * and then restore them when re-creating this component.
0502:             *
0503:             * @param innerWidth the inner width. If null, "100%" is assumed.
0504:             * @since 3.0.0
0505:             */
0506:            public void setInnerWidth(String innerWidth) {
0507:                if (innerWidth == null)
0508:                    innerWidth = "100%";
0509:                if (!_innerWidth.equals(innerWidth)) {
0510:                    _innerWidth = innerWidth;
0511:                    smartUpdate("z.innerWidth", innerWidth);
0512:                }
0513:            }
0514:
0515:            /**
0516:             * Returns the inner width of this component.
0517:             * The inner width is the width of the inner table.
0518:             * <p>Default: "100%"
0519:             * @see #setInnerWidth
0520:             * @since 3.0.0
0521:             */
0522:            public String getInnerWidth() {
0523:                return _innerWidth;
0524:            }
0525:
0526:            /** Synchronizes the grid to be consistent with the specified model.
0527:             *
0528:             * @param min the lower index that a range of invalidated rows
0529:             * @param max the higher index that a range of invalidated rows
0530:             */
0531:            private void syncModel(int min, int max) {
0532:                RowRenderer renderer = null;
0533:                final int newsz = _model.getSize();
0534:                final int oldsz = _rows != null ? _rows.getChildren().size()
0535:                        : 0;
0536:                if (oldsz > 0) {
0537:                    if (newsz > 0 && min < oldsz) {
0538:                        if (max < 0 || max >= oldsz)
0539:                            max = oldsz - 1;
0540:                        if (max >= newsz)
0541:                            max = newsz - 1;
0542:                        if (min < 0)
0543:                            min = 0;
0544:
0545:                        //unloadRow() might detach and insert row into _rows, must make a copy for iterate.
0546:                        for (Iterator it = new ArrayList(_rows.getChildren())
0547:                                .listIterator(min); min <= max && it.hasNext(); ++min) {
0548:                            final Row row = (Row) it.next();
0549:                            if (row.isLoaded()) {
0550:                                if (renderer == null)
0551:                                    renderer = getRealRenderer();
0552:                                unloadRow(renderer, row);
0553:                            }
0554:                        }
0555:                    }
0556:
0557:                    //detach and remove
0558:                    if (oldsz > newsz) {
0559:                        for (Iterator it = _rows.getChildren().listIterator(
0560:                                newsz); it.hasNext();) {
0561:                            it.next();
0562:                            it.remove();
0563:                        }
0564:                    }
0565:                }
0566:
0567:                //auto create but it means <grid model="xx"><rows/>... will fail
0568:                if (_rows == null)
0569:                    new Rows().setParent(this );
0570:
0571:                for (int j = oldsz; j < newsz; ++j) {
0572:                    if (renderer == null)
0573:                        renderer = getRealRenderer();
0574:                    newUnloadedRow(renderer).setParent(_rows);
0575:                }
0576:            }
0577:
0578:            /** Creates an new and unloaded row. */
0579:            private final Row newUnloadedRow(RowRenderer renderer) {
0580:                Row row = null;
0581:                if (renderer instanceof  RowRendererExt)
0582:                    row = ((RowRendererExt) renderer).newRow(this );
0583:
0584:                if (row == null) {
0585:                    row = new Row();
0586:                    row.applyProperties();
0587:                }
0588:                row.setLoaded(false);
0589:
0590:                newUnloadedCell(renderer, row);
0591:                return row;
0592:            }
0593:
0594:            private Component newUnloadedCell(RowRenderer renderer, Row row) {
0595:                Component cell = null;
0596:                if (renderer instanceof  RowRendererExt)
0597:                    cell = ((RowRendererExt) renderer).newCell(row);
0598:
0599:                if (cell == null) {
0600:                    cell = newRenderLabel(null);
0601:                    cell.applyProperties();
0602:                }
0603:                cell.setParent(row);
0604:                return cell;
0605:            }
0606:
0607:            /** Returns the label for the cell generated by the default renderer.
0608:             */
0609:            private static Label newRenderLabel(String value) {
0610:                final Label label = new Label(value != null
0611:                        && value.length() > 0 ? value : " ");
0612:                label.setPre(true); //to make sure &nbsp; is generated, and then occupies some space
0613:                return label;
0614:            }
0615:
0616:            /** Clears a row as if it is not loaded. */
0617:            private final void unloadRow(RowRenderer renderer, Row row) {
0618:                if (!(renderer instanceof  RowRendererExt)
0619:                        || (((RowRendererExt) renderer).getControls() & RowRendererExt.DETACH_ON_UNLOAD) == 0) { //re-use (default)
0620:                    final List cells = row.getChildren();
0621:                    boolean bNewCell = cells.isEmpty();
0622:                    if (!bNewCell) {
0623:                        //detach and remove all but the first cell
0624:                        for (Iterator it = cells.listIterator(1); it.hasNext();) {
0625:                            it.next();
0626:                            it.remove();
0627:                        }
0628:
0629:                        final Component cell = (Component) cells.get(0);
0630:                        bNewCell = !(cell instanceof  Label);
0631:                        if (bNewCell) {
0632:                            cell.detach();
0633:                        } else {
0634:                            ((Label) cell).setValue("");
0635:                        }
0636:                    }
0637:
0638:                    if (bNewCell)
0639:                        newUnloadedCell(renderer, row);
0640:                    row.setLoaded(false);
0641:                } else { //detach
0642:                    _rows.insertBefore(newUnloadedRow(renderer), row);
0643:                    row.detach();
0644:                }
0645:            }
0646:
0647:            /** Handles a private event, onInitRender. It is used only for
0648:             * implementation, and you rarely need to invoke it explicitly.
0649:             */
0650:            public void onInitRender() {
0651:                final Renderer renderer = new Renderer();
0652:                try {
0653:                    int pgsz, ofs;
0654:                    if (inPagingMold()) {
0655:                        pgsz = _pgi.getPageSize();
0656:                        ofs = _pgi.getActivePage() * pgsz;
0657:                        final int cnt = _rows.getChildren().size();
0658:                        if (ofs >= cnt) { //not possible; just in case
0659:                            ofs = cnt - pgsz;
0660:                            if (ofs < 0)
0661:                                ofs = 0;
0662:                        }
0663:                    } else {
0664:                        pgsz = 20;
0665:                        ofs = 0;
0666:                        //we don't know # of visible rows, so a 'smart' guess
0667:                        //It is OK since client will send back request if not enough
0668:                    }
0669:
0670:                    int j = 0;
0671:                    for (Iterator it = _rows.getChildren().listIterator(ofs); j < pgsz
0672:                            && it.hasNext(); ++j)
0673:                        renderer.render((Row) it.next());
0674:
0675:                    if (!inPagingMold()
0676:                            && getRows().getChildren().size() > pgsz)
0677:                        ((Row) getRows().getChildren().get(pgsz)).setAttribute(
0678:                                Attributes.SKIP_SIBLING, Boolean.TRUE);
0679:                } catch (Throwable ex) {
0680:                    renderer.doCatch(ex);
0681:                } finally {
0682:                    renderer.doFinally();
0683:                }
0684:            }
0685:
0686:            private void postOnInitRender() {
0687:                Events.postEvent("onInitRender", this , null);
0688:                smartUpdate("z.render", true);
0689:            }
0690:
0691:            /** Handles when the list model's content changed.
0692:             */
0693:            private void onListDataChange(ListDataEvent event) {
0694:                //when this is called _model is never null
0695:                final int newsz = _model.getSize(), oldsz = _rows.getChildren()
0696:                        .size();
0697:                int min = event.getIndex0(), max = event.getIndex1();
0698:                if (min < 0)
0699:                    min = 0;
0700:
0701:                boolean done = false;
0702:                switch (event.getType()) {
0703:                case ListDataEvent.INTERVAL_ADDED:
0704:                    if (max < 0)
0705:                        max = newsz - 1;
0706:                    if ((max - min + 1) != (newsz - oldsz)) {
0707:                        log
0708:                                .warning("Conflict event: number of added rows not matched: "
0709:                                        + event);
0710:                        break; //handle it as CONTENTS_CHANGED
0711:                    }
0712:
0713:                    RowRenderer renderer = null;
0714:                    final Row before = min < oldsz ? (Row) _rows.getChildren()
0715:                            .get(min) : null;
0716:                    for (int j = min; j <= max; ++j) {
0717:                        if (renderer == null)
0718:                            renderer = getRealRenderer();
0719:                        _rows.insertBefore(newUnloadedRow(renderer), before);
0720:                    }
0721:
0722:                    done = true;
0723:                    break;
0724:
0725:                case ListDataEvent.INTERVAL_REMOVED:
0726:                    if (max < 0)
0727:                        max = oldsz - 1;
0728:                    int cnt = max - min + 1;
0729:                    if (cnt != (oldsz - newsz)) {
0730:                        log
0731:                                .warning("Conflict event: number of removed rows not matched: "
0732:                                        + event);
0733:                        break; //handle it as CONTENTS_CHANGED
0734:                    }
0735:
0736:                    //detach and remove
0737:                    for (Iterator it = _rows.getChildren().listIterator(min); --cnt >= 0
0738:                            && it.hasNext();) {
0739:                        it.next();
0740:                        it.remove();
0741:                    }
0742:
0743:                    done = true;
0744:                    break;
0745:                }
0746:
0747:                if (!done) //CONTENTS_CHANGED
0748:                    syncModel(min, max);
0749:
0750:                postOnInitRender(); //to improve performance
0751:            }
0752:
0753:            private static final RowRenderer getDefaultRowRenderer() {
0754:                return _defRend;
0755:            }
0756:
0757:            private static final RowRenderer _defRend = new RowRenderer() {
0758:                public void render(Row row, Object data) {
0759:                    final Label label = newRenderLabel(Objects.toString(data));
0760:                    label.applyProperties();
0761:                    label.setParent(row);
0762:                    row.setValue(data);
0763:                }
0764:            };
0765:
0766:            /** Returns the renderer used to render rows.
0767:             */
0768:            private RowRenderer getRealRenderer() {
0769:                return _renderer != null ? _renderer : getDefaultRowRenderer();
0770:            }
0771:
0772:            /** Used to render row if _model is specified. */
0773:            private class Renderer implements  java.io.Serializable {
0774:                private final RowRenderer _renderer;
0775:                private boolean _rendered, _ctrled;
0776:
0777:                private Renderer() {
0778:                    _renderer = getRealRenderer();
0779:                }
0780:
0781:                private void render(Row row) throws Throwable {
0782:                    if (row.isLoaded())
0783:                        return; //nothing to do
0784:
0785:                    if (!_rendered && (_renderer instanceof  RendererCtrl)) {
0786:                        ((RendererCtrl) _renderer).doTry();
0787:                        _ctrled = true;
0788:                    }
0789:
0790:                    final Component cell = row.getFirstChild();
0791:                    if (!(_renderer instanceof  RowRendererExt)
0792:                            || (((RowRendererExt) _renderer).getControls() & RowRendererExt.DETACH_ON_RENDER) != 0) { //detach (default)
0793:                        cell.detach();
0794:                    }
0795:
0796:                    try {
0797:                        _renderer.render(row, _model.getElementAt(row
0798:                                .getIndex()));
0799:                    } catch (Throwable ex) {
0800:                        try {
0801:                            final Label label = newRenderLabel(Exceptions
0802:                                    .getMessage(ex));
0803:                            label.applyProperties();
0804:                            label.setParent(row);
0805:                        } catch (Throwable t) {
0806:                            log.error(t);
0807:                        }
0808:                        row.setLoaded(true);
0809:                        throw ex;
0810:                    } finally {
0811:                        if (row.getChildren().isEmpty())
0812:                            cell.setParent(row);
0813:                    }
0814:
0815:                    row.setLoaded(true);
0816:                    _rendered = true;
0817:                }
0818:
0819:                private void doCatch(Throwable ex) {
0820:                    if (_ctrled) {
0821:                        try {
0822:                            ((RendererCtrl) _renderer).doCatch(ex);
0823:                        } catch (Throwable t) {
0824:                            throw UiException.Aide.wrap(t);
0825:                        }
0826:                    } else {
0827:                        throw UiException.Aide.wrap(ex);
0828:                    }
0829:                }
0830:
0831:                private void doFinally() {
0832:                    if (_ctrled)
0833:                        ((RendererCtrl) _renderer).doFinally();
0834:                }
0835:            }
0836:
0837:            /** Renders the specified {@link Row} if not loaded yet,
0838:             * with {@link #getRowRenderer}.
0839:             *
0840:             * <p>It does nothing if {@link #getModel} returns null.
0841:             * In other words, it is meaningful only if live data model is used.
0842:             */
0843:            public void renderRow(Row row) {
0844:                if (_model == null)
0845:                    return;
0846:
0847:                final Renderer renderer = new Renderer();
0848:                try {
0849:                    renderer.render(row);
0850:                } catch (Throwable ex) {
0851:                    renderer.doCatch(ex);
0852:                } finally {
0853:                    renderer.doFinally();
0854:                }
0855:            }
0856:
0857:            /** Renders all {@link Row} if not loaded yet,
0858:             * with {@link #getRowRenderer}.
0859:             */
0860:            public void renderAll() {
0861:                if (_model == null)
0862:                    return;
0863:
0864:                final Renderer renderer = new Renderer();
0865:                try {
0866:                    for (Iterator it = _rows.getChildren().iterator(); it
0867:                            .hasNext();)
0868:                        renderer.render((Row) it.next());
0869:                } catch (Throwable ex) {
0870:                    renderer.doCatch(ex);
0871:                } finally {
0872:                    renderer.doFinally();
0873:                }
0874:            }
0875:
0876:            /** Renders a set of specified rows.
0877:             * It is the same as {@link #renderItems}.
0878:             */
0879:            public void renderRows(Set rows) {
0880:                renderItems(rows);
0881:            }
0882:
0883:            public void renderItems(Set rows) {
0884:                if (_model == null) { //just in case that app dev might change it
0885:                    if (log.debugable())
0886:                        log.debug("No model no render");
0887:                    return;
0888:                }
0889:
0890:                if (rows.isEmpty())
0891:                    return; //nothing to do
0892:
0893:                final Renderer renderer = new Renderer();
0894:                try {
0895:                    for (Iterator it = rows.iterator(); it.hasNext();)
0896:                        renderer.render((Row) it.next());
0897:                } catch (Throwable ex) {
0898:                    renderer.doCatch(ex);
0899:                } finally {
0900:                    renderer.doFinally();
0901:                }
0902:            }
0903:
0904:            /** Returns the style class for the odd rows.
0905:             *
0906:             * <p>Default: odd.
0907:             *
0908:             * @since 3.0.0
0909:             */
0910:            public String getOddRowSclass() {
0911:                return _scOddRow;
0912:            }
0913:
0914:            /** Sets the style class for the odd rows.
0915:             * If the style class doesn't exist, the striping effect disappears.
0916:             * You can provide different effects by providing the proper style
0917:             * classes.
0918:             * @since 3.0.0
0919:             */
0920:            public void setOddRowSclass(String scls) {
0921:                if (scls != null && scls.length() == 0)
0922:                    scls = null;
0923:                if (!Objects.equals(_scOddRow, scls)) {
0924:                    _scOddRow = scls;
0925:                    smartUpdate("z.scOddRow", scls);
0926:                }
0927:            }
0928:
0929:            //-- super --//
0930:            public void setMold(String mold) {
0931:                final String old = getMold();
0932:                if (!Objects.equals(old, mold)) {
0933:                    super .setMold(mold);
0934:
0935:                    if ("paging".equals(old)) { //change from paging
0936:                        if (_paging != null) {
0937:                            removePagingListener(_paging);
0938:                            _paging.detach();
0939:                        } else if (_pgi != null) {
0940:                            removePagingListener(_pgi);
0941:                        }
0942:                    } else if (inPagingMold()) { //change to paging
0943:                        if (_pgi != null)
0944:                            addPagingListener(_pgi);
0945:                        else
0946:                            newInternalPaging();
0947:                    }
0948:                }
0949:            }
0950:
0951:            public String getOuterAttrs() {
0952:                final StringBuffer sb = new StringBuffer(80).append(super 
0953:                        .getOuterAttrs());
0954:                if (_align != null)
0955:                    HTMLs.appendAttribute(sb, "align", _align);
0956:                if (_model != null) {
0957:                    HTMLs.appendAttribute(sb, "z.model", true);
0958:                    final List rows = getRows().getChildren();
0959:                    int index = rows.size();
0960:                    for (final ListIterator it = rows.listIterator(index); it
0961:                            .hasPrevious(); --index)
0962:                        if (((Row) it.previous()).isLoaded())
0963:                            break;
0964:                    HTMLs.appendAttribute(sb, "z.lastLoadIdx", index);
0965:                }
0966:                if (_scOddRow != null)
0967:                    HTMLs.appendAttribute(sb, "z.scOddRow", _scOddRow);
0968:                return sb.toString();
0969:            }
0970:
0971:            //-- Component --//
0972:            public boolean insertBefore(Component newChild, Component refChild) {
0973:                if (newChild instanceof  Rows) {
0974:                    if (_rows != null && _rows != newChild)
0975:                        throw new UiException(
0976:                                "Only one rows child is allowed: "
0977:                                        + this 
0978:                                        + "\nNote: rows is created automatically if live data");
0979:                    _rows = (Rows) newChild;
0980:                } else if (newChild instanceof  Columns) {
0981:                    if (_cols != null && _cols != newChild)
0982:                        throw new UiException(
0983:                                "Only one columns child is allowed: " + this );
0984:                    _cols = (Columns) newChild;
0985:                } else if (newChild instanceof  Foot) {
0986:                    if (_foot != null && _foot != newChild)
0987:                        throw new UiException(
0988:                                "Only one foot child is allowed: " + this );
0989:                    _foot = (Foot) newChild;
0990:                } else if (newChild instanceof  Paging) {
0991:                    if (_pgi != null)
0992:                        throw new UiException(
0993:                                "External paging cannot coexist with child paging");
0994:                    if (_paging != null && _paging != newChild)
0995:                        throw new UiException("Only one paging is allowed: "
0996:                                + this );
0997:                    if (!inPagingMold())
0998:                        throw new UiException(
0999:                                "The child paging is allowed only in the paging mold");
1000:                    _pgi = _paging = (Paging) newChild;
1001:                } else if (!(newChild instanceof  Auxhead)) {
1002:                    throw new UiException("Unsupported child for grid: "
1003:                            + newChild);
1004:                }
1005:
1006:                if (super .insertBefore(newChild, refChild)) {
1007:                    //not need to invalidate since auxhead visible only with _cols
1008:                    if (!(newChild instanceof  Auxhead))
1009:                        invalidate();
1010:                    return true;
1011:                }
1012:                return false;
1013:            }
1014:
1015:            public boolean removeChild(Component child) {
1016:                if (!super .removeChild(child))
1017:                    return false;
1018:
1019:                if (_rows == child)
1020:                    _rows = null;
1021:                else if (_cols == child)
1022:                    _cols = null;
1023:                else if (_foot == child)
1024:                    _foot = null;
1025:                else if (_paging == child) {
1026:                    _paging = null;
1027:                    if (_pgi == child)
1028:                        _pgi = null;
1029:                }
1030:                invalidate();
1031:                return true;
1032:            }
1033:
1034:            //Cloneable//
1035:            public Object clone() {
1036:                final Grid clone = (Grid) super .clone();
1037:                clone.init();
1038:
1039:                int cnt = 0;
1040:                if (clone._rows != null)
1041:                    ++cnt;
1042:                if (clone._cols != null)
1043:                    ++cnt;
1044:                if (clone._foot != null)
1045:                    ++cnt;
1046:                if (clone._paging != null)
1047:                    ++cnt;
1048:                if (cnt > 0)
1049:                    clone.afterUnmarshal(cnt);
1050:
1051:                return clone;
1052:            }
1053:
1054:            /** @param cnt # of children that need special handling (used for optimization).
1055:             * -1 means process all of them
1056:             */
1057:            private void afterUnmarshal(int cnt) {
1058:                for (Iterator it = getChildren().iterator(); it.hasNext();) {
1059:                    final Object child = it.next();
1060:                    if (child instanceof  Rows) {
1061:                        _rows = (Rows) child;
1062:                        if (--cnt == 0)
1063:                            break;
1064:                    } else if (child instanceof  Columns) {
1065:                        _cols = (Columns) child;
1066:                        if (--cnt == 0)
1067:                            break;
1068:                    } else if (child instanceof  Foot) {
1069:                        _foot = (Foot) child;
1070:                        if (--cnt == 0)
1071:                            break;
1072:                    } else if (child instanceof  Paging) {
1073:                        _pgi = _paging = (Paging) child;
1074:                        if (--cnt == 0)
1075:                            break;
1076:                    }
1077:                }
1078:            }
1079:
1080:            //Serializable//
1081:            private synchronized void readObject(java.io.ObjectInputStream s)
1082:                    throws java.io.IOException, ClassNotFoundException {
1083:                s.defaultReadObject();
1084:                init();
1085:                afterUnmarshal(-1);
1086:                //TODO: how to marshal _pgi if _pgi != _paging
1087:                //TODO: re-register event listener for onPaging
1088:
1089:                if (_model != null)
1090:                    initDataListener();
1091:            }
1092:
1093:            //-- ComponentCtrl --//
1094:            protected Object newExtraCtrl() {
1095:                return new ExtraCtrl();
1096:            }
1097:
1098:            /** A utility class to implement {@link #getExtraCtrl}.
1099:             * It is used only by component developers.
1100:             */
1101:            protected class ExtraCtrl extends XulElement.ExtraCtrl implements 
1102:                    InnerWidth, RenderOnDemand {
1103:                //InnerWidth//
1104:                public void setInnerWidthByClient(String width) {
1105:                    _innerWidth = width == null ? "100%" : width;
1106:                }
1107:
1108:                //RenderOnDemand//
1109:                public void renderItems(Set items) {
1110:                    int cnt = items.size();
1111:                    if (cnt == 0)
1112:                        return; //nothing to do
1113:                    cnt = 20 - cnt;
1114:                    if (cnt > 0 && _preloadsz > 0) { //Feature 1740072: pre-load
1115:                        if (cnt > _preloadsz)
1116:                            cnt = _preloadsz;
1117:
1118:                        //1. locate the first item found in items
1119:                        final List toload = new LinkedList();
1120:                        Iterator it = getRows().getChildren().iterator();
1121:                        while (it.hasNext()) {
1122:                            final Row row = (Row) it.next();
1123:                            if (items.contains(row)) //found
1124:                                break;
1125:                            if (!row.isLoaded())
1126:                                toload.add(0, row); //reverse order
1127:                        }
1128:
1129:                        //2. add unload items before the found one
1130:                        if (!toload.isEmpty()) {
1131:                            int bfcnt = cnt / 3;
1132:                            for (Iterator e = toload.iterator(); bfcnt > 0
1133:                                    && e.hasNext(); --bfcnt, --cnt) {
1134:                                items.add(e.next());
1135:                            }
1136:                        }
1137:
1138:                        //3. add unloaded after the found one
1139:                        while (cnt > 0 && it.hasNext()) {
1140:                            final Row row = (Row) it.next();
1141:                            if (!row.isLoaded() && items.add(row))
1142:                                --cnt;
1143:                        }
1144:                    }
1145:
1146:                    Grid.this .renderItems(items);
1147:                }
1148:            }
1149:
1150:            /** An iterator used by _heads.
1151:             */
1152:            private class Iter implements  Iterator {
1153:                private final ListIterator _it = getChildren().listIterator();
1154:
1155:                public boolean hasNext() {
1156:                    while (_it.hasNext()) {
1157:                        Object o = _it.next();
1158:                        if (o instanceof  Columns || o instanceof  Auxhead) {
1159:                            _it.previous();
1160:                            return true;
1161:                        }
1162:                    }
1163:                    return false;
1164:                }
1165:
1166:                public Object next() {
1167:                    for (;;) {
1168:                        Object o = _it.next();
1169:                        if (o instanceof  Columns || o instanceof  Auxhead)
1170:                            return o;
1171:                    }
1172:                }
1173:
1174:                public void remove() {
1175:                    throw new UnsupportedOperationException();
1176:                }
1177:            }
1178:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.