@Override public void listChanged(ListEvent<Object> listChanges) { updates.beginEvent(true); while (listChanges.next()) { int index = listChanges.getIndex(); int type = listChanges.getType(); if (type == ListEvent.INSERT || type == ListEvent.UPDATE) { Match<Object, File> match = getMatch(index); // create new future final FormattedFuture future = new FormattedFuture(match, getFormatter(match), getMatchContext()); // update data if (type == ListEvent.INSERT) { futures.add(index, future); updates.elementInserted(index, future); } else if (type == ListEvent.UPDATE) { // set new future, dispose old future FormattedFuture obsolete = futures.set(index, future); cancel(obsolete); // Don't update view immediately, to avoid irritating flickering, // caused by a rapid succession of change events. // The worker may only need a couple of milliseconds to complete, // so the view will be notified of the change soon enough. SwingUI.invokeLater( 50, new Runnable() { @Override public void run() { // task has not been started, no change events have been sent as of yet, // fire change event now if (future.getState() == StateValue.PENDING) { future.firePropertyChange("state", null, StateValue.PENDING); } } }); } // observe and enqueue worker task submit(future); } else if (type == ListEvent.DELETE) { // remove future from data and formatter queue FormattedFuture obsolete = futures.remove(index); cancel(obsolete); updates.elementDeleted(index, obsolete); } } updates.commitEvent(); }
/** * Updates the value of this Calculation in response to the <code>listChanges</code>. * * @param listChanges describes the changes to the backing EventList */ @Override public void listChanged(ListEvent<E> listChanges) { // store the value for later when we fire a PropertyChangeEvent final N oldValue = getValue(); final List<E> source = listChanges.getSourceList(); if (listChanges.isReordering()) { final int[] reorderMap = listChanges.getReorderMap(); for (int i = 0; i < reorderMap.length; i++) { final int oldIndex = reorderMap[i]; // if the element has changed indexes it must be processed like an update if (oldIndex != i) { final E newElement = source.get(i); final E oldElement = snapshot.set(i, newElement); updated(oldElement, newElement); } } } else { // update our snapshot and update the value of this Calculation by // delegating to the abstract methods which provide that updating logic while (listChanges.next()) { final int index = listChanges.getIndex(); switch (listChanges.getType()) { case ListEvent.INSERT: { final E element = source.get(index); snapshot.add(index, element); inserted(element); break; } case ListEvent.DELETE: { deleted(snapshot.remove(index)); break; } case ListEvent.UPDATE: { final E newElement = source.get(index); final E oldElement = snapshot.set(index, newElement); updated(oldElement, newElement); break; } } } } // fetch the new value of this Calculation and try to fire an event final N newValue = getValue(); fireValueChange(oldValue, newValue); }
/** * Gets invoked when changes occur to the contents of the list, and updates the nodes of the tree * model accordingly. It the invokes <code>reload(node)</code> on the tree model for the affected * node so changes are reflected in the <code>JTree</code> * * @see ca.odell.glazedlists.event.ListEventListener#listChanged * (ca.odell.glazedlists.event.ListEvent) */ public void listChanged(ListEvent listChanges) { while (listChanges.next()) { int type = listChanges.getType(); int index = listChanges.getIndex(); if (type == ListEvent.INSERT) { Object element = listChanges.getSourceList().get(index); DefaultMutableTreeNode newNode = createChildNode(node, element); node.insert(newNode, index); } else { if (type == ListEvent.UPDATE) { node.remove(index); Object element = listChanges.getSourceList().get(index); DefaultMutableTreeNode newNode = createChildNode(node, element); node.insert(newNode, index); } else { if (type == ListEvent.DELETE) { node.remove(index); } } } } treeModel.reload(node); }
public void listChanged(ListEvent<ReportHolder> listChanges) { // all of these changes to this list happen "atomically" updates.beginEvent(true); // handle reordering events if (!listChanges.isReordering()) { // for all changes, one index at a time while (listChanges.next()) { // get the current change info int changeType = listChanges.getType(); EventList<ReportHolder> sourceList = listChanges.getSourceList(); // handle delete events if (changeType == ListEvent.UPDATE) { throw new UnsupportedOperationException(); } else if (changeType == ListEvent.DELETE) { // assume a delete all since this is the only thing supported. clear(); updates.commitEvent(); return; } else if (changeType == ListEvent.INSERT) { ReportHolder deltaReportHolder = sourceList.get(listChanges.getIndex()); Message deltaMessage = deltaReportHolder.getMessage(); ReportBase deltaReport = deltaReportHolder.getReport(); quickfix.field.Side orderSide = new quickfix.field.Side(); try { deltaMessage.getField(orderSide); } catch (FieldNotFound e) { orderSide.setValue(quickfix.field.Side.UNDISCLOSED); } String side = String.valueOf(orderSide.getValue()); Instrument instrument = InstrumentFromMessage.SELECTOR.forValue(deltaMessage).extract(deltaMessage); SymbolSide symbolSide = new SymbolSide(instrument, side); if (deltaReport instanceof ExecutionReport) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Considering {}", //$NON-NLS-1$ deltaReport); ExecutionReport execReport = (ExecutionReport) deltaReport; ExecutionType execType = execReport.getExecutionType(); if (execType == null) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because the execType was null", //$NON-NLS-1$ execReport); continue; } if (execType == null || !execType.isFill()) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because its execution type {} is not a fill", //$NON-NLS-1$ execReport, execReport.getExecutionType()); continue; } if (!execReport.getOriginator().forOrders() || !execReport.getHierarchy().forOrders()) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because it's not appropriate for FIX Message Views", //$NON-NLS-1$ execReport); continue; } BigDecimal lastQuantity = execReport.getLastQuantity(); BigDecimal lastPrice = execReport.getLastPrice(); if (lastQuantity == null || !(lastQuantity.compareTo(BigDecimal.ZERO) > 0)) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because the last quantity was null/zero", //$NON-NLS-1$ execReport); continue; } if (lastPrice == null) { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because the last price was null", //$NON-NLS-1$ execReport); continue; } Integer averagePriceIndex = mAveragePriceIndexes.get(symbolSide); // decide if we've seen this symbol/side combination in the list of ERs before. if we // have, averagePriceIndex will be non-null if (averagePriceIndex != null) { // we have already processed at least one ER with this symbol/side combination. that // means the math must take into account the existing // ERs as well as the current ER ReportHolder averagePriceReportHolder = mAveragePricesList.get(averagePriceIndex); Message averagePriceMessage = averagePriceReportHolder.getMessage(); ExecutionReport averagePriceReport = (ExecutionReport) averagePriceReportHolder.getReport(); BigDecimal existingCumQty = averagePriceReport.getCumulativeQuantity(); BigDecimal existingAvgPx = averagePriceReport.getAveragePrice(); BigDecimal newLastQty = lastQuantity; BigDecimal newTotal = existingCumQty.add(newLastQty); if (!newTotal.equals(ZERO)) { BigDecimal numerator = existingCumQty.multiply(existingAvgPx).add(newLastQty.multiply(lastPrice)); BigDecimal newAvgPx = numerator.divide(newTotal, 4, RoundingMode.HALF_UP); averagePriceMessage.setDecimal(AvgPx.FIELD, newAvgPx); averagePriceMessage.setDecimal(CumQty.FIELD, newTotal); updates.elementUpdated( averagePriceIndex, averagePriceReportHolder, averagePriceReportHolder); } } else { // we have not seen an ER with this instrument/side combination, make a new average // price entry Message averagePriceMessage = mMessageFactory.createMessage(MsgType.EXECUTION_REPORT); averagePriceMessage.setField(orderSide); InstrumentToMessage.SELECTOR .forInstrument(instrument) .set(instrument, mMessageFactory.getBeginString(), averagePriceMessage); averagePriceMessage.setField(new CumQty(lastQuantity)); averagePriceMessage.setField(new AvgPx(lastPrice.setScale(4, RoundingMode.HALF_UP))); try { ReportHolder newReport = new ReportHolder( Factory.getInstance() .createExecutionReport( averagePriceMessage, execReport.getBrokerID(), Originator.Broker, execReport.getActorID(), execReport.getViewerID()), deltaReportHolder.getUnderlying()); mAveragePricesList.add(newReport); averagePriceIndex = mAveragePricesList.size() - 1; mAveragePriceIndexes.put(symbolSide, averagePriceIndex); updates.elementInserted(averagePriceIndex, newReport); } catch (MessageCreationException e) { Messages.UNEXPECTED_ERROR.error(this, e); } } } else { SLF4JLoggerProxy.debug( AveragePriceReportList.class, "Skipping {} because it's not an ExecutionReport", //$NON-NLS-1$ deltaReport); } } } } // commit the changes and notify listeners updates.commitEvent(); }