📄 listbox.java
字号:
throws ClassNotFoundException, NoSuchMethodException, InstantiationException, java.lang.reflect.InvocationTargetException { if (clsnm != null) setItemRenderer((ListitemRenderer)Classes.newInstanceByThread(clsnm)); } /** Synchronizes the listbox to be consistent with the specified model. * @param min the lower index that a range of invalidated items * @param max the higher index that a range of invalidated items */ private void syncModel(int min, int max) { final int newsz = _model.getSize(); final int oldsz = getItemCount(); if (oldsz > 0) { if (newsz > 0 && min < oldsz) { if (max < 0 || max >= oldsz) max = oldsz - 1; if (max >= newsz) max = newsz - 1; if (min < 0) min = 0; for (Iterator it = _items.listIterator(min); min <= max && it.hasNext(); ++min) clearItemAsUnloaded((Listitem)it.next()); } for (int j = newsz; j < oldsz; ++j) getItemAtIndex(newsz).detach(); //detach and remove } for (int j = oldsz; j < newsz; ++j) newUnloadedItem().setParent(this); } /** Creates an new and unloaded listitem. */ private static Listitem newUnloadedItem() { final Listitem item = new Listitem(); item.applyProperties(); item.setLoaded(false); final Listcell cell = new Listcell(); cell.applyProperties(); cell.setParent(item); //an empty listheader return item; } /** Clears a listitem as if it is not loaded. */ private static void clearItemAsUnloaded(Listitem item) { final List cells = item.getChildren(); if (cells.isEmpty()) { final Listcell cell = new Listcell(); cell.applyProperties(); cell.setParent(item); } else { final Listcell listcell = (Listcell)cells.get(0); listcell.setLabel(null); listcell.setImage(null); for (int k = cells.size(); --k > 0;) ((Component)cells.get(1)).detach(); //detach and remove } item.setLoaded(false); } /** Handles a private event, onInitRender. It is used only for * implementation, and you rarely need to invoke it explicitly. */ public void onInitRender() { final Renderer renderer = new Renderer(); try { final int pgsz = inSelectMold() ? getItemCount(): inPagingMold() ? _pgi.getPageSize(): _rows; int j = 0; for (Iterator it = getItems().iterator(); j < pgsz && it.hasNext(); ++j) renderer.render((Listitem)it.next()); } catch (Throwable ex) { renderer.doCatch(ex); } finally { renderer.doFinally(); } } /** Handles when the list model's content changed. */ private void onListDataChange(ListDataEvent event) { if (inSelectMold()) { invalidate(); syncModel(-1, -1); Events.postEvent("onInitRender", this, null); return; } //when this is called _model is never null final int newsz = _model.getSize(), oldsz = getItemCount(); int min = event.getIndex0(), max = event.getIndex1(); if (min < 0) min = 0; boolean done = false; switch (event.getType()) { case ListDataEvent.INTERVAL_ADDED: if (max < 0) max = newsz - 1; if ((max - min + 1) != (newsz - oldsz)) { log.warning("Conflict event: number of added items not matched: "+event); break; //handle it as CONTENTS_CHANGED } final Listitem before = min < oldsz ? getItemAtIndex(min): null; for (int j = min; j <= max; ++j) insertBefore(newUnloadedItem(), before); done = true; break; case ListDataEvent.INTERVAL_REMOVED: if (max < 0) max = oldsz - 1; if ((max - min + 1) != (oldsz - newsz)) { log.warning("Conflict event: number of removed items not matched: "+event); break; //handle it as CONTENTS_CHANGED } for (int j = min; j <= max; ++j) getItemAtIndex(min).detach(); //detach and remove done = true; break; } if (!done) //CONTENTS_CHANGED syncModel(min, max); initAtClient(); //client have to send back for what have to reload } private static final ListitemRenderer getDefaultItemRenderer() { return _defRend; } private static final ListitemRenderer _defRend = new ListitemRenderer() { public void render(Listitem item, Object data) { item.setLabel(Objects.toString(data)); item.setValue(data); } }; /** Used to render listitem if _model is specified. */ private class Renderer implements java.io.Serializable { private final ListitemRenderer _renderer; private boolean _rendered, _ctrled; private Renderer() { _renderer = Listbox.this._renderer != null ? Listbox.this._renderer: getDefaultItemRenderer(); } private void render(Listitem item) throws Throwable { if (item.isLoaded()) return; //nothing to do if (!_rendered && (_renderer instanceof RendererCtrl)) { ((RendererCtrl)_renderer).doTry(); _ctrled = true; } final Listcell cell = (Listcell)item.getChildren().get(0); cell.detach(); try { _renderer.render(item, _model.getElementAt(item.getIndex())); } catch (Throwable ex) { try { item.setLabel(Exceptions.getMessage(ex)); } catch (Throwable t) { log.error(t); } item.setLoaded(true); throw ex; } finally { if (item.getChildren().isEmpty()) cell.setParent(item); } item.setLoaded(true); _rendered = true; } private void doCatch(Throwable ex) { if (_ctrled) { try { ((RendererCtrl)_renderer).doCatch(ex); } catch (Throwable t) { throw UiException.Aide.wrap(t); } } else { throw UiException.Aide.wrap(ex); } } private void doFinally() { if (_rendered) initAtClient(); //reason: after rendering, the column width might change //Also: Mozilla remembers scrollTop when user's pressing //RELOAD, it makes init more desirable. if (_ctrled) ((RendererCtrl)_renderer).doFinally(); } } /** Renders the specified {@link Listitem} if not loaded yet, * with {@link #getItemRenderer}. * * <p>It does nothing if {@link #getModel} returns null. * In other words, it is meaningful only if live data model is used. */ public void renderItem(Listitem li) { if (_model == null) return; final Renderer renderer = new Renderer(); try { renderer.render(li); } catch (Throwable ex) { renderer.doCatch(ex); } finally { renderer.doFinally(); } } /** Renders all {@link Listitem} if not loaded yet, * with {@link #getItemRenderer}. */ public void renderAll() { if (_model == null) return; final Renderer renderer = new Renderer(); try { for (Iterator it = getItems().iterator(); it.hasNext();) renderer.render((Listitem)it.next()); } catch (Throwable ex) { renderer.doCatch(ex); } finally { renderer.doFinally(); } } //-- RenderOnDemand --// public void renderItems(Set items) { if (_model == null) { //just in case that app dev might change it if (log.debugable()) log.debug("No model no render"); return; } if (items.isEmpty()) return; //nothing to do final Renderer renderer = new Renderer(); try { for (Iterator it = items.iterator(); it.hasNext();) renderer.render((Listitem)it.next()); } catch (Throwable ex) { renderer.doCatch(ex); } finally { renderer.doFinally(); } } //-- super --// public void setMold(String mold) { final String old = getMold(); if (!Objects.equals(old, mold)) { super.setMold(mold); if ("paging".equals(old)) { //change from paging if (_paging != null) { removePagingListener(_paging); _paging.detach(); } else if (_pgi != null) { removePagingListener(_pgi); } } else if (inPagingMold()) { //change to paging if (_pgi != null) addPagingListener(_pgi); else newInternalPaging(); } } } public void setHeight(String height) { if (!Objects.equals(height, getHeight())) { super.setHeight(height); if (!inSelectMold()) initAtClient(); } } public String getOuterAttrs() { final StringBuffer sb = new StringBuffer(80).append(super.getOuterAttrs()); if (inSelectMold()) { HTMLs.appendAttribute(sb, "name", _name); HTMLs.appendAttribute(sb, "size", getRows()); if (isMultiple()) HTMLs.appendAttribute(sb, "multiple", "multiple"); if (_disabled) HTMLs.appendAttribute(sb, "disabled", "disabled"); if (_readonly) HTMLs.appendAttribute(sb, "readonly", "readonly"); } else { HTMLs.appendAttribute(sb, "z.name", _name); HTMLs.appendAttribute(sb, "z.size", _rows); if (_disabled) HTMLs.appendAttribute(sb, "z.disabled", true); if (_readonly) HTMLs.appendAttribute(sb, "z.readonly", true); if (_multiple) HTMLs.appendAttribute(sb, "z.multiple", true); HTMLs.appendAttribute(sb, "z.selId", getSelectedId()); //if (_checkmark) // HTMLs.appendAttribute(sb, "z.checkmark", true); if (_vflex) HTMLs.appendAttribute(sb, "z.vflex", true); if (_model != null) HTMLs.appendAttribute(sb, "z.model", true); } appendAsapAttr(sb, Events.ON_SELECT); return sb.toString(); } private class ItemIter implements ListIterator, java.io.Serializable { private ListIterator _it; private int _j; private boolean _bNxt; private ItemIter(int index) { _j = index; } public void add(Object o) { prepare(); _it.add(o); ++_j; } public boolean hasNext() { return _j < _items.size(); } public boolean hasPrevious() { return _j > 0; } public Object next() { if (!hasNext()) throw new NoSuchElementException(); prepare(); final Object o = _it.next(); ++_j; _bNxt = true; return o; } public Object previous() { if (!hasPrevious()) throw new NoSuchElementException(); prepare(); final Object o = _it.previous(); --_j; _bNxt = false; return o; } public int nextIndex() { return _j; } public int previousIndex() { return _j - 1; } public void remove() { if (_it == null) throw new IllegalStateException(); _it.remove(); if (_bNxt) --_j; } public void set(Object o) { if (_it == null) throw new IllegalStateException(); _it.set(o); } private void prepare() { if (_it == null) { int v = _j; if (_listhead != null) ++v; _it = getChildren().listIterator(v); } } } //Cloneable// public Object clone() { final Listbox clone = (Listbox)super.clone(); int cnt = clone._selItems.size(); clone.init(); if (clone._listhead != null) ++cnt; if (clone._listfoot != null) ++cnt; if (cnt > 0) clone.afterUnmarshal(cnt); return clone; } /** @param cnt # of children that need special handling (used for optimization). * -1 means process all of them */ private void afterUnmarshal(int cnt) { int index = 0; for (Iterator it = getChildren().iterator(); it.hasNext();) { final Object child = it.next(); if (child instanceof Listitem) { final Listitem li = (Listitem)child; li.setIndex(index ++); //since Listitem.clone() resets index if (li.isSelected()) { _selItems.add(li); if (--cnt == 0) break; } } else if (child instanceof Listhead) { _listhead = (Listhead)child; if (--cnt == 0) break; } else if (child instanceof Listfoot) { _listfoot = (Listfoot)child; if (--cnt == 0) break; } else if (child instanceof Paging) { _pgi = _paging = (Paging)child; if (--cnt == 0) break; } } } //-- Serializable --// private synchronized void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); init(); afterUnmarshal(-1); //TODO: how to marshal _pgi if _pgi != _paging //TODO: re-register event listener for onPaging if (_model != null) initDataListener(); } //-- ComponentCtrl --// protected Object newExtraCtrl() { return new ExtraCtrl(); } /** A utility class to implement {@link #getExtraCtrl}. * It is used only by component developers. */ protected class ExtraCtrl extends XulElement.ExtraCtrl implements Selectable, ChildChangedAware, Cropper { //ChildChangedAware// public boolean isChildChangedAware() { return !inSelectMold(); } //--Cropper--// public boolean isCropper() { return inPagingMold(); } public Set getAvailableAtClient() { if (!inPagingMold()) return null; final Set avail = new HashSet(37); if (_listhead != null) avail.add(_listhead); if (_listfoot != null) avail.add(_listfoot); if (_paging != null) avail.add(_paging); final Paginal pgi = getPaginal(); int pgsz = pgi.getPageSize(); final int ofs = pgi.getActivePage() * pgsz; for (final Iterator it = getItems().listIterator(ofs); --pgsz >= 0 && it.hasNext();) avail.add(it.next()); return avail; } //-- Selectable --// public void selectItemsByClient(Set selItems) { _noSmartUpdate = true; try { final boolean paging = inPagingMold(); if (!_multiple || (!paging && (selItems == null || selItems.size() <= 1))) { final Listitem item = selItems != null && selItems.size() > 0 ? (Listitem)selItems.iterator().next(): null; selectItem(item); } else { int from, to; if (paging) { final Paginal pgi = getPaginal(); int pgsz = pgi.getPageSize(); from = pgi.getActivePage() * pgsz; to = from + pgsz; //excluded } else { from = to = 0; } int j = 0; for (Iterator it = _items.iterator(); it.hasNext(); ++j) { final Listitem item = (Listitem)it.next(); if (selItems.contains(item)) { addItemToSelection(item); } else if (!paging) { removeItemFromSelection(item); } else { final int index = item.getIndex(); if (index >= from && index < to) removeItemFromSelection(item); } } } } finally { _noSmartUpdate = false; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -