javaswtfontmetricscustom-draw

Which text margin does SWT Table use when drawing text?


I got a relatively easy question - but I cannot find anything anywhere to answer it.

I use a simple SWT table widget in my application that displays only text in the cells. I got an incremental search feature and want to highlight text snippets in all cells if they match.

So when typing "a", all "a"s should be highlighted.

To get this, I add an SWT.EraseItem listener to interfere with the background drawing. If the current cell's text contains the search string, I find the positions and calculate relative x-coordinates within the text using event.gc.stringExtent - easy.

With that I just draw rectangles "behind" the occurrences.

Now, there's a flaw in this. The table does not draw the text without a margin, so my x coordinate does not really match - it is slightly off by a few pixels! But how many?? Where do I retrieve the cell's text margins that table's own drawing will use? No clue. Cannot find anything.

Bonus question: the table's draw method also shortens text and adds "..." if it does not fit into the cell. Hmm. My occurrence finder takes the TableItem's text and thus also tries to mark occurrences that are actually not visible because they are consumed by the "...". How do I get the shortened text and not the "real" text within the EraseItem draw handler?

    @Override
    public void handleEvent( final Event event ) {
        final TableItem ti = (TableItem) event.item;
        final int index = event.index;
        final GC gc = event.gc;

        if( ti == null || currentSwyt.isEmpty() ) {
            return;
        }

        final String text = ti.getText( index );
        if( !text.contains( currentSwyt ) ) {
            return;
        }

        // search text is contained
        final String[] parts = text.split( currentSwyt );
        final int swytWidth = gc.stringExtent( currentSwyt ).x;

        // calculate positions, must be relative to the text's start
        int x = event.x; // THIS IS THE PROBLEM: event.x is not enough!
        final int[] pos = new int[parts.length - 1];
        for( int i = 0; i < parts.length - 1; i++ ) {
            x += gc.stringExtent( parts[i] ).x;
            pos[i] = x;
        }

        final Color red = event.display.getSystemColor( SWT.COLOR_RED );

        final Color oldBackground = gc.getBackground();
        gc.setBackground( red );
        for( int j = 0; j < pos.length; j++ ) {
            gc.fillRectangle( pos[j], event.y, swytWidth, event.height );
        }

        gc.setBackground( oldBackground );

        event.detail &= ~SWT.BACKGROUND;
    }

Solution

  • I think it would be quite useful for you to have a look at TableViewer and StyledCellLabelProvider. That will make your task a lot easier I think considering the kind of text formatting you require. Since the drawing is than completely handled by the label provider, you can avoid these pesky margin issues.