Beispiel #1
0
  public void doListDataChange(ListDataEvent event) {
    // when this is called _model is never null
    final ListModel _model = _listbox.getModel();
    final int newsz = _model.getSize(), oldsz = _listbox.getItemCount();
    int min = event.getIndex0(), max = event.getIndex1(), cnt;

    switch (event.getType()) {
      case ListDataEvent.INTERVAL_ADDED:
        cnt = newsz - oldsz;
        if (cnt <= 0) throw new UiException("Adding causes a smaller list?");
        if ((oldsz <= 0 || cnt > INVALIDATE_THRESHOLD) && !inPagingMold()) _listbox.invalidate();
        // Bug 3147518: avoid memory leak
        // Also better performance (outer better than remove a lot)
        if (min < 0)
          if (max < 0) min = 0;
          else min = max - cnt + 1;
        if (min > oldsz) min = oldsz;

        ListitemRenderer renderer = null;
        final Component next = min < oldsz ? _listbox.getItemAtIndex(min) : null;
        while (--cnt >= 0) {
          if (renderer == null) renderer = (ListitemRenderer) getRealRenderer();
          _listbox.insertBefore(newUnloadedItem(renderer, min++), next);
        }
        break;

      case ListDataEvent.INTERVAL_REMOVED:
        cnt = oldsz - newsz;
        if (cnt <= 0) throw new UiException("Removal causes a larger list?");
        if (min >= 0) max = min + cnt - 1;
        else if (max < 0) max = cnt - 1; // 0 ~ cnt - 1		
        if (max > oldsz - 1) max = oldsz - 1;

        if ((newsz <= 0 || cnt > INVALIDATE_THRESHOLD) && !inPagingMold()) _listbox.invalidate();
        // Bug 3147518: avoid memory leak
        // Also better performance (outer better than remove a lot)

        // detach from end (due to groopfoot issue)
        Component comp = _listbox.getItemAtIndex(max);
        while (--cnt >= 0) {
          Component p = comp.getPreviousSibling();
          comp.detach();
          comp = p;
        }
        break;

      default: // CONTENTS_CHANGED
        syncModel(min, max);
    }
  }
  public void render(final Comboitem item, final Object data, final int index) throws Exception {
    final Combobox cb = (Combobox) item.getParent();
    final ListModel<?> model = cb.getModel();
    final int size = model.getSize();
    final Template tm = resoloveTemplate(cb, item, data, index, size, "model");
    if (tm == null) {
      item.setLabel(Objects.toString(data));
      item.setValue(data);
    } else {
      final ForEachStatus iterStatus =
          new AbstractForEachStatus() { // provide iteration status in this context
            private static final long serialVersionUID = 1L;

            public int getIndex() {
              return index;
            }

            public Object getEach() {
              return data;
            }

            public Integer getEnd() {
              return size;
            }
          };

      final String var = (String) tm.getParameters().get(EACH_ATTR);
      final String varnm = var == null ? EACH_VAR : var; // var is not specified, default to "each"
      final String itervar = (String) tm.getParameters().get(STATUS_ATTR);
      final String itervarnm =
          itervar == null
              ? (var == null ? EACH_STATUS_VAR : varnm + STATUS_POST_VAR)
              : itervar; // provide default value if not specified

      // bug 1188, EL when nested var and itervar
      Object oldVar = cb.getAttribute(varnm);
      Object oldIter = cb.getAttribute(itervarnm);
      cb.setAttribute(varnm, data);
      cb.setAttribute(itervarnm, iterStatus);

      final Component[] items = tm.create(cb, item, null, null);

      cb.setAttribute(varnm, oldVar);
      cb.setAttribute(itervarnm, oldIter);

      if (items.length != 1)
        throw new UiException("The model template must have exactly one item, not " + items.length);

      final Comboitem nci = (Comboitem) items[0];
      nci.setAttribute(BinderImpl.VAR, varnm); // for the converter to get the value

      if (model instanceof ListSubModel) {
        // ZK-992 wrong item when binding to combbox with submodel implementation
        // combobox has a internal model as the submodel,
        // I don't have way to access the submodel, and user doesn't has info to notify model[index]
        // changed.
        // so I set the value directly.
        nci.setAttribute(varnm, data);
      } else {
        addItemReference(
            cb, nci, index, varnm); // kept the reference to the data, before ON_BIND_INIT
      }

      nci.setAttribute(itervarnm, iterStatus);

      // add template dependency
      addTemplateTracking(cb, nci, data, index, size);

      if (nci.getValue() == null) // template might set it
      nci.setValue(data);
      item.setAttribute("org.zkoss.zul.model.renderAs", nci);
      // indicate a new item is created to replace the existent one
      item.detach();

      // bug #ZK-677: combobox selection is lost after reload model
      // binding Comboitem immediately, @see BindUiLifeCycle#afterComponentAttached
      Events.sendEvent(new Event(BinderImpl.ON_BIND_INIT, nci));
    }
  }
Beispiel #3
0
 public int getTotalSize() {
   final ListModel model = _listbox.getModel();
   return model != null ? model.getSize() : _listbox.getVisibleItemCount();
 }
Beispiel #4
0
  private void syncModel0(int offset, int limit) {
    int min = offset;
    int max = offset + limit - 1;

    final ListModel _model = _listbox.getModel();
    final int newsz = _model.getSize();
    final int oldsz = _listbox.getItemCount();
    final Paginal _pgi = _listbox.getPaginal();
    final boolean inPaging = inPagingMold();
    final boolean shallInvalidated = // Bug 3147518: avoid memory leak
        (min < 0 || min == 0) && (max < 0 || max >= newsz || max >= oldsz);

    int newcnt = newsz - oldsz;
    int atg = _pgi != null ? _listbox.getActivePage() : 0;
    ListitemRenderer renderer = null;
    Component next = null;
    if (oldsz > 0) {
      if (min < 0) min = 0;
      else if (min > oldsz - 1) min = oldsz - 1;
      if (max < 0) max = oldsz - 1;
      else if (max > oldsz - 1) max = oldsz - 1;
      if (min > max) {
        int t = min;
        min = max;
        max = t;
      }

      int cnt = max - min + 1; // # of affected
      if (_model instanceof GroupsListModel) {
        // detach all from end to front since groupfoot
        // must be detached before group
        newcnt += cnt; // add affected later
        if ((shallInvalidated || newcnt > INVALIDATE_THRESHOLD) && !inPaging) _listbox.invalidate();
        // Bug 3147518: avoid memory leak
        // Also better performance (outer better than remove a lot)

        Component comp = _listbox.getItemAtIndex(max);
        next = comp.getNextSibling();
        while (--cnt >= 0) {
          Component p = comp.getPreviousSibling();
          comp.detach();
          comp = p;
        }
      } else { // ListModel
        int addcnt = 0;
        Component item = _listbox.getItemAtIndex(min);
        while (--cnt >= 0) {
          next = item.getNextSibling();

          if (cnt < -newcnt) { // if shrink, -newcnt > 0
            item.detach(); // remove extra
          } else if (((Listitem) item).isLoaded()) {
            if (renderer == null) renderer = (ListitemRenderer) getRealRenderer();
            item.detach(); // always detach
            _listbox.insertBefore(newUnloadedItem(renderer, min), next);
            ++addcnt;
          }
          ++min;
          item = next; // B2100338.,next item could be Paging, don't use Listitem directly
        }

        if ((shallInvalidated
                || addcnt > INVALIDATE_THRESHOLD
                || addcnt + newcnt > INVALIDATE_THRESHOLD)
            && !inPagingMold()) _listbox.invalidate();
        // Bug 3147518: avoid memory leak
        // Also better performance (outer better than remove a lot)
      }
    } else {
      min = 0;
    }

    for (; --newcnt >= 0; ++min) {
      if (renderer == null) renderer = (ListitemRenderer) getRealRenderer();
      _listbox.insertBefore(newUnloadedItem(renderer, min), next);
    }
    if (_pgi != null) {
      if (atg >= _pgi.getPageCount()) atg = _pgi.getPageCount() - 1;
      _pgi.setActivePage(atg);
    }
  }