Skip to content

Commit 90c04e6

Browse files
committed
Additional span methods.
Fixed span repainting on row selection.
1 parent 13cd27b commit 90c04e6

File tree

2 files changed

+131
-43
lines changed

2 files changed

+131
-43
lines changed

src/org/quinto/swing/table/view/JBroTable.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
import javax.swing.table.TableColumn;
2323
import javax.swing.table.TableColumnModel;
2424
import org.apache.log4j.Logger;
25+
import org.quinto.swing.table.model.IModelFieldGroup;
2526
import org.quinto.swing.table.model.ModelData;
2627
import org.quinto.swing.table.model.ModelField;
27-
import org.quinto.swing.table.model.IModelFieldGroup;
2828
import org.quinto.swing.table.model.Utils;
2929

3030
public class JBroTable extends JTable {
@@ -546,6 +546,12 @@ public TableColumnModel getColumnModel() {
546546
public JBroTableHeader getTableHeader() {
547547
return ( JBroTableHeader )super.getTableHeader();
548548
}
549+
550+
@Override
551+
public void valueChanged( ListSelectionEvent e ) {
552+
super.valueChanged( e );
553+
getUI().onRowsSelected( e.getFirstIndex(), e.getLastIndex() );
554+
}
549555

550556
private class HeaderHeightWatcher implements TableColumnModelListener {
551557
@Override

src/org/quinto/swing/table/view/JBroTableUI.java

Lines changed: 124 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.awt.Toolkit;
1111
import java.util.Arrays;
1212
import java.util.HashMap;
13+
import java.util.IdentityHashMap;
1314
import java.util.LinkedHashMap;
1415
import java.util.Map;
1516
import java.util.Set;
@@ -439,6 +440,21 @@ void setNoDefaults( boolean noDefaults ) {
439440
this.noDefaults = noDefaults;
440441
}
441442

443+
/**
444+
* Get span bounds in pixels.
445+
* @param col any column of span
446+
* @param row any row of span
447+
* @param includeSpacing if false, return the true cell bounds
448+
* computed by subtracting the intercell spacing from the height
449+
* and widths of the column and row models
450+
* @return span bounds in pixels
451+
* @see javax.swing.JTable#getCellRect
452+
*/
453+
public Rectangle getSpanCoordinatesInPixels( int col, int row, boolean includeSpacing ) {
454+
Rectangle rect = getSpanCoordinates( col, row );
455+
return table.getCellRect( rect.y, rect.x, includeSpacing ).union( table.getCellRect( rect.y + rect.height - 1, rect.x + rect.width - 1, includeSpacing ) );
456+
}
457+
442458
/**
443459
* Find a span at position ( col, row ). Return its starting point and size in cells.
444460
* The value returned is <b>not</b> the span bounds in pixels.
@@ -449,72 +465,138 @@ void setNoDefaults( boolean noDefaults ) {
449465
*/
450466
public Rectangle getSpanCoordinates( int col, int row ) {
451467
Rectangle ret = new Rectangle( col, row, 1, 1 );
452-
if ( col < 0 || row < 0 )
468+
SpanWithId spanWithId = getSpanWithId( col, row );
469+
if ( spanWithId == null )
453470
return ret;
454471
TableColumnModel cm = table.getColumnModel();
472+
int columnCount = cm.getColumnCount();
473+
int rowCount = table.getRowCount();
474+
ModelData data = ( ( JBroTable )table ).getData();
475+
int minRow = row;
476+
for ( int i = row - 1; i >= 0; i-- ) {
477+
if ( spanWithId.id.equals( data.getValue( table.convertRowIndexToModel( i ), spanWithId.idColumnIdx ) ) )
478+
minRow = i;
479+
else
480+
break;
481+
}
482+
int maxRow = row;
483+
for ( int i = row + 1; i < rowCount; i++ ) {
484+
if ( spanWithId.id.equals( data.getValue( table.convertRowIndexToModel( i ), spanWithId.idColumnIdx ) ) )
485+
maxRow = i;
486+
else
487+
break;
488+
}
489+
Set< String > columns = spanWithId.span.getColumns();
490+
int minCol = col;
491+
for ( int i = col - 1; i >= 0; i-- ) {
492+
TableColumn spanCoveredColumn = cm.getColumn( i );
493+
if ( columns.contains( ( String )spanCoveredColumn.getIdentifier() ) )
494+
minCol = i;
495+
else
496+
break;
497+
}
498+
int maxCol = col;
499+
for ( int i = col + 1; i < columnCount; i++ ) {
500+
TableColumn spanCoveredColumn = cm.getColumn( i );
501+
if ( columns.contains( ( String )spanCoveredColumn.getIdentifier() ) )
502+
maxCol = i;
503+
else
504+
break;
505+
}
506+
ret.setBounds( minCol, minRow, maxCol - minCol + 1, maxRow - minRow + 1 );
507+
return ret;
508+
}
509+
510+
public ModelSpan getSpan( int col, int row ) {
511+
SpanWithId spanWithId = getSpanWithId( col, row );
512+
return spanWithId == null ? null : spanWithId.span;
513+
}
514+
515+
public Object getSpanValue( int col, int row ) {
516+
ModelSpan span = getSpan( col, row );
517+
if ( span == null )
518+
return table.getValueAt( col, row );
519+
int modelRow = table.convertRowIndexToModel( row );
520+
ModelData data = ( ( JBroTable )table ).getData();
521+
return data.getValue( modelRow, span.getValueColumn() );
522+
}
523+
524+
private SpanWithId getSpanWithId( int col, int row ) {
525+
if ( col < 0 || row < 0 )
526+
return null;
527+
TableColumnModel cm = table.getColumnModel();
455528
if ( cm == null )
456-
return ret;
529+
return null;
457530
int columnCount = cm.getColumnCount();
458531
if ( col >= columnCount )
459-
return ret;
532+
return null;
460533
TableColumn aColumn = cm.getColumn( col );
461534
if ( aColumn == null )
462-
return ret;
535+
return null;
463536
String columnName = ( String )aColumn.getIdentifier();
464537
Map< String, ModelSpan > columnSpans = spans.get( columnName );
465538
if ( columnSpans == null )
466-
return ret;
539+
return null;
467540
int rowCount = table.getRowCount();
468541
if ( row >= rowCount )
469-
return ret;
542+
return null;
470543
int modelRow = table.convertRowIndexToModel( row );
471544
if ( modelRow < 0 )
472-
return ret;
545+
return null;
473546
ModelData data = ( ( JBroTable )table ).getData();
474547
if ( data == null || modelRow >= data.getRowsCount() )
475-
return ret;
548+
return null;
476549
for ( Map.Entry< String, ModelSpan > spanWithId : columnSpans.entrySet() ) {
477550
int idColumnIdx = data.getIndexOfModelField( spanWithId.getKey() );
478551
if ( idColumnIdx < 0 )
479552
continue;
480553
Object id = data.getValue( modelRow, idColumnIdx );
481554
if ( id == null )
482555
continue;
483-
int minRow = row;
484-
for ( int i = row - 1; i >= 0; i-- ) {
485-
if ( id.equals( data.getValue( table.convertRowIndexToModel( i ), idColumnIdx ) ) )
486-
minRow = i;
487-
else
488-
break;
489-
}
490-
int maxRow = row;
491-
for ( int i = row + 1; i < rowCount; i++ ) {
492-
if ( id.equals( data.getValue( table.convertRowIndexToModel( i ), idColumnIdx ) ) )
493-
maxRow = i;
494-
else
495-
break;
496-
}
497-
ModelSpan span = spanWithId.getValue();
498-
Set< String > columns = span.getColumns();
499-
int minCol = col;
500-
for ( int i = col - 1; i >= 0; i-- ) {
501-
TableColumn spanCoveredColumn = cm.getColumn( i );
502-
if ( columns.contains( ( String )spanCoveredColumn.getIdentifier() ) )
503-
minCol = i;
504-
else
505-
break;
506-
}
507-
int maxCol = col;
508-
for ( int i = col + 1; i < columnCount; i++ ) {
509-
TableColumn spanCoveredColumn = cm.getColumn( i );
510-
if ( columns.contains( ( String )spanCoveredColumn.getIdentifier() ) )
511-
maxCol = i;
512-
else
513-
break;
556+
return new SpanWithId( spanWithId.getValue(), id, idColumnIdx );
557+
}
558+
return null;
559+
}
560+
561+
public Iterable< ModelSpan > getSpans() {
562+
IdentityHashMap< ModelSpan, String > ret = new IdentityHashMap< ModelSpan, String >();
563+
for ( Map< String, ModelSpan > value : spans.values() )
564+
for ( ModelSpan span : value.values() )
565+
ret.put( span, null );
566+
return ret.keySet();
567+
}
568+
569+
void onRowsSelected( int firstIndex, int lastIndex ) {
570+
if ( spans.isEmpty() )
571+
return;
572+
int rc = table.getRowCount();
573+
int cc = table.getColumnCount();
574+
firstIndex = Math.min( Math.max( firstIndex, 0 ), rc - 1 );
575+
lastIndex = Math.min( Math.max( lastIndex, 0 ), rc - 1 );
576+
Rectangle firstRowRect = table.getCellRect( firstIndex, 0, false );
577+
Rectangle lastRowRect = table.getCellRect( lastIndex, cc - 1, false );
578+
Rectangle dirtyRegion = firstRowRect.union( lastRowRect );
579+
for ( int s = 0; s < 2; s++ ) {
580+
for ( int i = cc - 1; i >= 0; i-- ) {
581+
Rectangle rect = getSpanCoordinates( i, s == 0 ? firstIndex : lastIndex );
582+
if ( rect.width > 1 || rect.height > 1 ) {
583+
dirtyRegion = dirtyRegion.union( table.getCellRect( rect.y, rect.x, false ) );
584+
dirtyRegion = dirtyRegion.union( table.getCellRect( rect.y + rect.height - 1, rect.x + rect.width - 1, false ) );
585+
}
514586
}
515-
ret.setBounds( minCol, minRow, maxCol - minCol + 1, maxRow - minRow + 1 );
516-
break;
517587
}
518-
return ret;
588+
table.repaint( dirtyRegion );
589+
}
590+
591+
private static class SpanWithId {
592+
private final ModelSpan span;
593+
private final Object id;
594+
private final int idColumnIdx;
595+
596+
public SpanWithId( ModelSpan span, Object id, int idColumnIdx ) {
597+
this.span = span;
598+
this.id = id;
599+
this.idColumnIdx = idColumnIdx;
600+
}
519601
}
520602
}

0 commit comments

Comments
 (0)