In this section a
To obtain the bins filled with the referring row IDs, an array with empty bins must be passed to the
Note that the panel might be null. If this is the case, the view displays a message that no data is available by default. Another situation might be that the view is open and the model changes (due to a different input, or a different configuration). Then the view has to be updated. This is realized by the
The
NodeView
for our node is implemented. In order to display information about the work of this node we display the bins in a histogram, where the height of each bin indicates the number of rows in this bin.
Internal Representation:
A model is required to represent the outcome of our algorithm. Obviously a model representing a bin is appropriate. A bin contains a number of rows and is graphically represented by a rectangle. Therefore, we create this data structure.public class
NumericBin {private final
Setm_containedRowIds; public NumericBin() { m_containedRowIds = new
HashSet(); } /** * Adds another row to this bin. * @param rowId the row to add to this bin. */ public void
addRowToBin(final
DataCell rowId) { m_containedRowIds.add(rowId); } /** * * @return the number of rows in this bin. */public int
getSize() {return
m_containedRowIds.size(); }
NumericBinnerCellFactory
, which adds the row to the referring bin in the getCell
method:
/** * @see de.unikn.knime.core.data.container.SingleCellFactory#getCell( * de.unikn.knime.core.data.DataRow) */ @Overridepublic
DataCell getCell(DataRow row) { DataCell currCell = row.getCell(m_colIndex); ...int
binNr = 0;for
(Double intervalBound : m_intervalUpperBounds) {if
(currValue <= intervalBound) { m_bins[binNr].addRowToBin(row.getKey().getId());return new
IntCell(binNr); } binNr++; } ...
Drawing Component:
Before we can start to implement theNodeView
we have to implement a component that actually draws our bins. For this purpose we create our own JPanel
using a quite simple paint method:
public class
NumericBinnerViewPanelextends
JPanel ... /** * @see javax.swing.JComponent#paint(java.awt.Graphics) */ @Overridepublic void
paint(Graphics g) {super
.paint(g);if
(m_bins !=null
&& m_bins.length > 0) {int
maxNr = 0; // determine the largest binfor
(int
i = 0; i < m_bins.length; i++) { maxNr = Math.max(m_bins[i].getSize(), maxNr); } // if no size information available (creation) set default sizeint
width = getWidth();if
(width == 0) { width = SIZE; }int
height = getHeight();if
(height == 0) { height = SIZE; } // calculate the bin widthint
binWidth = width / m_bins.length;for
(int
i = 0; i < m_bins.length; i++) { // the left side of the rectangleint
x = i * binWidth; // the height of the binint
binHeight = height; // the larger the bin the higher the rectdouble
sizeFactor = ((double
)(maxNr - m_bins[i].getSize()) / (double
)maxNr); // since y-axis starts on top subtract binHeight -= sizeFactor * height; Rectangle rect =new
Rectangle(x, height - binHeight, binWidth, binHeight); m_bins[i].setViewRepresentation(rect); // draw the bin in black g.setColor(Color.BLACK); g.fillRect(rect.x, rect.y, rect.width, rect.height); // draw a border in white to make the bins distinguishable g.setColor(Color.WHITE); g.drawRect(rect.x, rect.y, rect.width, rect.height); } } }
NodeView:
Implementation of theNodeView
is very simple. In the constructor we create the drawing component (our NumericBinnerViewPanel
) using the bins retrieved from the model. We set it as our view content via the setComponent
method:
public class
NumericBinnerNodeViewextends
NodeView { // panel which actually paints the binsprivate
NumericBinnerViewPanel m_panel; /** * Creates a new view. * * @param nodeModel the model class: {@link NumericBinnerNodeModel} */protected
NumericBinnerNodeView(final
NodeModel nodeModel) {super
(nodeModel); // get the bins NumericBin[] bins = ((NumericBinnerNodeModel)getNodeModel()) .getBinRepresentations();if
(bins !=null
&& bins.length >0) { // create the panel that draws the bins m_panel =new
NumericBinnerViewPanel(bins); } // sets the view content in the node view setComponent(m_panel); }
modelChanged
method in the NodeView
:
protected void
modelChanged() {
// if the model had changed get the new bins
NumericBin[] bins = ((NumericBinnerNodeModel)getNodeModel())
.getBinRepresentations();
if
(bins != null
&& bins.length > 0 && m_panel != null
) {
// and paint the bins
((NumericBinnerViewPanel)m_panel).updateView(bins);
}
}
NumericBinnerViewPanel
also needs an update method, as follows:
/** * If the view is updated the new bins are set and then painted. * * @param bins the new bins to display. */public void
updateView(final
NumericBin[] bins) { m_bins = bins; repaint(); }