Detect if a Table's row is currently visible?

Is there a way to determine if a row in a table (or the Item backing that row) is currently visible in a Table?

My goal is determining whether I need to programmatically scroll the Table to display a row if not already displayed.

For example, say I add a row between rows # 5 & 6. If those rows are not already visible (they are scrolled above the top or below the bottom), then I want to scroll the Table to select and display the new row to the user.

–Basil Bourque

Well there nothing readymade for that, but there is somewhat of a workaround. You can use a combination of these methods to get a range of visible items:

Object	 getCurrentPageFirstItemId()
protected  int	indexOfId(Object itemId) 
 int	getPageLength() 

The range is then getCurrentPageFirstItemId() to getCurrentPageFirstItemId()+getPageLength(). The id of the item is indexOfId(itemId), and you check if that is inside the range.
the indexOfId is protected so you have to extend table to get it or, as a better suggestion, read it straight from the container. The method is visible in the Container.Indexed -interface, which most containers implement.

Thanks to Jens Jansson for sharing that idea.

Using that suggestion, I added this method to a subclass of Table. See further below for entire Table subclass, and for an example Vaadin application demonstrating the Table in action.

/**
 * Returns True if the desired item is currently displayed amongs the rows currently scrolled into viewing range in a Table.
 * Only rows showing entirely are reported as showing. If they are partially scrolled off the top or bottom, they are reported as 'not showing'.
 * 
 * @param itemId
 * @return
 */
public boolean [color=#00940e]
itemIsShowing
[/color]( Object itemId ) {
    // Get index of the desired item.
   [color=#00940e]
 int targetIndex = this.indexOfId( itemId );
[/color]
    // Get the index of the first item showing.
   [color=#008e0e]
 int firstIndexShown = this.getCurrentPageFirstItemIndex();
[/color]
   [color=#008a0d]
 int lastIndexShown = firstIndexShown + this.getPageLength() - 1;
[/color] [color=#5c0084]
// Minus one, to ignore rows partially scrolling off the bottom.
[/color]
    // Determine if the desired item's index lies within the range of displayed indices, inclusively.
    boolean targetIsShowing = [color=#008a0d]
( targetIndex >= firstIndexShown ) && ( ( targetIndex < lastIndexShown ) )
[/color];
    return targetIsShowing;
}

Table subclass, including method shown above:

/**
 * 
 */
package com.example;

import com.vaadin.data.Container;
import com.vaadin.ui.Table;

/**
 * <p>
 * Extends Table class, to provide a method that tells whether a particular itemId's Item is currently showing or whether the Item is scrolled off the top or bottom of the Table (out of sight).
 * </p>
 * 
 * <p>
 * Designed to tell if the entire height of the row is shown. If the row is partially scrolled off the top or the bottom, it is considered 'not showing'.
 * </p>
 * 
 * <p>
 * Based on <a href='https://vaadin.com/forum/-/message_boards/view_message/1547679'>this posting</a> in the Vaadin.com forum.
 * </p>
 * 
 * © 2012 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
 * 
 * @author Basil Bourque
 * 
 */
public class Table_IsRowShown extends Table {

    public static final String version = "2012-07-01T23:38:55.853Z";

    /**
     * <p>
     * Returns True if the desired item is currently displayed amongs the rows currently scrolled into viewing range in a Table.
     * Only rows showing entirely are reported as showing. If they are partially scrolled off the top or bottom, they are reported as 'not showing'.
     * </p>
     * @param itemId
     * @return
     */
    public boolean itemIsShowing( Object itemId ) {
        // Get index of the desired item.
        int targetIndex = this.indexOfId( itemId );
        // Get the index of the first item showing.
        int firstIndexShown = this.getCurrentPageFirstItemIndex();
        int lastIndexShown = firstIndexShown + this.getPageLength() - 1; // Minus one, to ignore rows partially scrolling off the bottom.
        // Determine if the desired item's index lies within the range of displayed indices, inclusively.
        boolean targetIsShowing = ( targetIndex >= firstIndexShown ) && ( ( targetIndex < lastIndexShown ) );
        return targetIsShowing;
    }

    /**
     * 
     */
    public Table_IsRowShown() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @param caption
     * @param dataSource
     */
    public Table_IsRowShown( String caption, Container dataSource ) {
        super( caption, dataSource );
        // TODO Auto-generated constructor stub
    }

    /**
     * @param caption
     */
    public Table_IsRowShown( String caption ) {
        super( caption );
        // TODO Auto-generated constructor stub
    }

}

Vaadin app showing this Table subclass in action. Of many rows in a table, 3 have the word “Cat”, “Dog”, or “Bird”. Scroll the table up and down to reveal any of the rows with those words. You can ignore the other rows; they were added simply to have enough rows to cause scrolling.

package com.example;

import com.vaadin.Application;
import com.vaadin.ui.*;
import com.vaadin.ui.Button.ClickEvent;

/**
 * <p>
 * A Vaadin application demonstrating the "Table_IsRowShown" class, a subclass of Table.
 * </p>
 * <p>
 * Of many rows in a table, three rows have the word "Cat", "Dog", or "Bird". Scroll the table up and down to reveal any of the rows with those words. 
 * Click the button to display a message indicating which of those three rows are showing or not showing.
 * You may ignore the other rows; they were added as filler to cause scrolling.
 * </p>
 * 
 * 
 * © 2012 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
 * 
 * @author Basil Bourque
 * 
 */
public class TableisnowshownApplication extends Application {

    Table_IsRowShown table;

    @Override
    public void init() {
        Window mainWindow = new Window( "Table_IsRowShown Example" );
        Label label = new Label( "Hello Vaadin user. " + new java.util.Date() );
        mainWindow.addComponent( label );

        this.table = new Table_IsRowShown( "Table_IsRowShown example:" );
        table.addContainerProperty( "Animal_Or_Uuid", String.class, null );
        table.addContainerProperty( "NanoTime", Long.class, null );
        // table.addContainerProperty( "SomeNumber", Integer.class, null );

        /* Add a few items in the table. */
        table.addItem( new Object[] { "Cat", new Long( System.nanoTime() ) }, "cat" );
        for ( int i = 1; i < 13; i++ ) {
            table.addItem( new Object[] { java.util.UUID.randomUUID().toString(), new Long( System.nanoTime() ) }, null );
        }
        table.addItem( new Object[] { "Dog", new Long( System.nanoTime() ) }, "dog" );
        for ( int i = 1; i < 13; i++ ) {
            table.addItem( new Object[] { java.util.UUID.randomUUID().toString(), new Long( System.nanoTime() ) }, null );
        }
        table.addItem( new Object[] { "Bird", new Long( System.nanoTime() ) }, "bird" );
        for ( int i = 1; i < 13; i++ ) {
            table.addItem( new Object[] { java.util.UUID.randomUUID().toString(), new Long( System.nanoTime() ) }, null );
        }
        mainWindow.addComponent( table );

        Button button = new Button( "Peek-a-boo" );
        button.addListener( new Button.ClickListener() {

            @Override
            public void buttonClick( ClickEvent event ) {
                tellWhichAnimalsAreShowing();
            }

        } );
        mainWindow.addComponent( button );

        setMainWindow( mainWindow );
    }

    public void tellWhichAnimalsAreShowing() {
        // Build a statement about each animal being display or not.
        String cat = ( this.table.itemIsShowing( "cat" ) ) ? "" : "not";
        String dog = ( this.table.itemIsShowing( "dog" ) ) ? "" : "not";
        String bird = ( this.table.itemIsShowing( "bird" ) ) ? "" : "not";
        getMainWindow().showNotification( "Peek-a-boo",
                "<br/>Cat is " + cat + " showing" + "<br/>Dog is " + dog + " showing" + "<br/>Bird is " + bird + " showing",
                Window.Notification.TYPE_HUMANIZED_MESSAGE );

    }
}