Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » NatTable » Percentage size rounding
Percentage size rounding [message #1698710] Wed, 17 June 2015 11:44 Go to next message
Eugeniusz Kalafior is currently offline Eugeniusz KalafiorFriend
Messages: 9
Registered: June 2015
Junior Member
HI, I have a situation where i have about 20 columns defined for table and some of them are invisible. Invisible columns have percentage width defined as 0. When SizeConfig class calculates the percentage sizes and distributes missing pixels (fixing rounding problem) in the end of
public void calculatePercentages(int space, int positionCount) {
it increases width of first X columns (where X is number of "lost" pixels). In my case sometimes those are invisible columns, and this ends up with some weird stripe, not always refreshed on the right side of the table. In my opinion it would be better to do this rounding more precise. I've changed the implementation of this method from:
    public void calculatePercentages(int space, int positionCount) {
        if (isPercentageSizing()) {
            this.isAggregatedSizeCacheValid = false;
            this.availableSpace = space;

            int percentageSpace = calculateAvailableSpace(space);

            int sum = 0;
            int real = 0;
            int realSum = 0;
            int fixedSum = 0;
            List<Integer> noInfoPositions = new ArrayList<Integer>();
            Integer positionValue = null;
            for (int i = 0; i < positionCount; i++) {
                positionValue = this.sizeMap.get(i);
                if (positionValue != null) {
                    if (isPercentageSizing(i)) {
                        sum += positionValue;
                        real = calculatePercentageValue(positionValue,
                                percentageSpace);
                    } else {
                        real = positionValue;
                        fixedSum += real;
                    }
                    realSum += real;
                    this.realSizeMap.put(i, real);
                } else {
                    // remember the position for which no size information
                    // exists needed to calculate the size for those positions
                    // dependent on the remaining space
                    noInfoPositions.add(i);
                }
            }

            int[] correction = correctPercentageValues(sum, positionCount);
            if (correction != null) {
                sum = correction[0];
                realSum = correction[1] + fixedSum;
            }

            if (!noInfoPositions.isEmpty()) {
                // now calculate the size for the remaining columns
                double remaining = new Double(space) - realSum;
                Double remainingColSpace = remaining / noInfoPositions.size();
                for (Integer position : noInfoPositions) {
                    sum += (remainingColSpace / space) * 100;
                    this.realSizeMap.put(position, remainingColSpace.intValue());
                }
                // If there are positions for which no size information exist,
                // the size config will use 100 percent of the available space
                // on percentage sizing. To handle rounding issues just set the
                // sum to 100 for correct calculation results.
                sum = 100;
            }
            if (sum == 100) {
                // check if the sum of the calculated values is the same as the
                // given space if not distribute the missing pixels to some of
                // the other columns this is needed because of rounding issues
                // on 100% with odd-numbered pixel values
                int valueSum = 0;
                int lastPos = -1;
                for (Map.Entry<Integer, Integer> entry : this.realSizeMap.entrySet()) {
                    valueSum += entry.getValue();
                    lastPos = Math.max(lastPos, entry.getKey());
                }

                if (space > 0 && valueSum < space) {
                    // distribute the missing pixels
                    int missingPixels = (space - valueSum);
                    int pos = 0;
                    for (int i = missingPixels; i > 0; i--) {
                        if (!this.realSizeMap.containsKey(pos)) {
                            // there are more missing pixels than columns
                            // start over at position 0
                            pos = 0;
                        }
                        int posValue = this.realSizeMap.get(pos);
                        this.realSizeMap.put(pos, posValue + 1);
                        pos++;
                    }
                }
            }
        }
    }

to:
public void calculatePercentages(int space, int positionCount) {
        if (isPercentageSizing()) {
            this.isAggregatedSizeCacheValid = false;
            this.availableSpace = space;

            int percentageSpace = calculateAvailableSpace(space);

            int sum = 0;
            int real = 0;
            int realSum = 0;
            int fixedSum = 0;
            List<Integer> noInfoPositions = new ArrayList<Integer>();
            List<Double> endings = new ArrayList<Double>(positionCount);
            Integer positionValue = null;
            for (int i = 0; i < positionCount; i++) {
                positionValue = this.sizeMap.get(i);
                if (positionValue != null) {
                    if (isPercentageSizing(i)) {
                        sum += positionValue;
                        Double porcentageSize = new Double(percentageSpace) * positionValue / 100;
                        real = porcentageSize.intValue();
                        //keep the difference between int and double value of the percentage size 
                        //to add missing pixels to columns with highest differences
                        endings.add(i, porcentageSize - real);
                    } else {
                        real = positionValue;
                        fixedSum += real;
                    }
                    realSum += real;
                    this.realSizeMap.put(i, real);
                } else {
                    // remember the position for which no size information
                    // exists needed to calculate the size for those positions
                    // dependent on the remaining space
                    noInfoPositions.add(i);
                }
            }

            int[] correction = correctPercentageValues(sum, positionCount);
            if (correction != null) {
                sum = correction[0];
                realSum = correction[1] + fixedSum;
            }

            if (!noInfoPositions.isEmpty()) {
                // now calculate the size for the remaining columns
                double remaining = new Double(space) - realSum;
                Double remainingColSpace = remaining / noInfoPositions.size();
                for (Integer position : noInfoPositions) {
                    sum += (remainingColSpace / space) * 100;
                    this.realSizeMap.put(position, remainingColSpace.intValue());
                }
                // If there are positions for which no size information exist,
                // the size config will use 100 percent of the available space
                // on percentage sizing. To handle rounding issues just set the
                // sum to 100 for correct calculation results.
                sum = 100;
            }
            if (sum == 100) {
                // check if the sum of the calculated values is the same as the
                // given space if not distribute the missing pixels to columns
            	// with highest differences between double and int values
            	
                if (space > 0 && realSum < space) {
                	//sort differences between int and double values
        			List<Double> sortedEndings = new ArrayList<Double>(endings);
        			Collections.sort(sortedEndings);
        			//round up sizes of columns that have biggest differences between double and int value to have a total of 100% of table size
        			//(40.3, 20.4, 39,3) -> (40, 21, 39) 
        			for(int i = space - realSum; i > 0; i--){
        				int colIndex = endings.indexOf(sortedEndings.get(sortedEndings.size()-i));
        				realSizeMap.put(colIndex, realSizeMap.get(colIndex) + 1);
        			}
                }
            }
        }
    }

or something similar.
Re: Percentage size rounding [message #1698720 is a reply to message #1698710] Wed, 17 June 2015 12:36 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
Sorry, but why don't you use the ColumnHideShowLayer to implement hidden columns instead of setting the width of a column to 0?

Also I can't make a diff with source snippets posted on the forum. So I really don't see easily what your proposed modification is. Please open a ticket and push a solution via Gerrit so I am able to review.

But personally your use case should be solvable via column hiding instead of setting the width of a column to 0.
Re: Percentage size rounding [message #1698748 is a reply to message #1698720] Wed, 17 June 2015 14:59 Go to previous messageGo to next message
Eugeniusz Kalafior is currently offline Eugeniusz KalafiorFriend
Messages: 9
Registered: June 2015
Junior Member
I am using ColumnHideShowLayer, but I am also setting them size to 0 to I keep a total of 100% while defining columns percentage width for each of them. My proposition is actually an improvement of distributing the "lost" pixels so that if percentage calculation results in columns width like this: 50.2, 30.1, 40.8, 30.9, the final result is 50, 30, 41, 31, instead of 51, 31, 41, 30.

[Updated on: Wed, 17 June 2015 15:30]

Report message to a moderator

Re: Percentage size rounding [message #1698754 is a reply to message #1698748] Wed, 17 June 2015 15:26 Go to previous messageGo to next message
Eugeniusz Kalafior is currently offline Eugeniusz KalafiorFriend
Messages: 9
Registered: June 2015
Junior Member

Quote:
Please open a ticket and push a solution via Gerrit so I am able to review.

Currently I have no idea on how to use Gerrit Smile, I'll try to do it when I find some spare time.
Re: Percentage size rounding [message #1698763 is a reply to message #1698754] Wed, 17 June 2015 16:19 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
As far as I can see your solution doesn't take into account that there are more than one pixels that need to be distributed. And what happens if all columns have the same rounding loss?

I'm not sure if the solution is that simple and what impact on the performance this would have. Needs to be well tested for all of the possible use cases.
Re: Percentage size rounding [message #1698764 is a reply to message #1698763] Wed, 17 June 2015 16:20 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
Oh, and using Gerrit is easy. We have a contribution guide that should at least point to all relevant information.
Re: Percentage size rounding [message #1698823 is a reply to message #1698764] Thu, 18 June 2015 08:40 Go to previous message
Eugeniusz Kalafior is currently offline Eugeniusz KalafiorFriend
Messages: 9
Registered: June 2015
Junior Member
Quote:
As far as I can see your solution doesn't take into account that there are more than one pixels that need to be distributed.

The number of "lost" pixels will always be smaller than the number of columns, as it comes from rounding the double values only, so there will be no need to add more than one pixel to a column. If you ask about adding pixel to more than one column, it's handled in this loop:
for(int i = space - realSum; i > 0; i--){
    int colIndex = endings.indexOf(sortedEndings.get(sortedEndings.size()-i));
    realSizeMap.put(colIndex, realSizeMap.get(colIndex) + 1);
}

Quote:
And what happens if all columns have the same rounding loss?

From my point of view it doesn't matter which one of those columns will get the additional pixel, if there is no column that have bigger rounding loss.
Quote:
what impact on the performance this would have

I haven't tested it on a table with more than 100 columns, it could have impact on performance when using large amount of columns. However the most complex calculation here is sorting the list of doubles, so I don't think it would be that heavy.
Quote:
Needs to be well tested for all of the possible use cases.

Of course, I totally agree. From my side I can add that I'm using this solution for my application and it works correctly.

[Updated on: Thu, 18 June 2015 08:41]

Report message to a moderator

Previous Topic:Odd row spacing on large table
Next Topic:Using NatTable as a spreadsheet
Goto Forum:
  


Current Time: Wed Apr 24 20:47:15 GMT 2024

Powered by FUDForum. Page generated in 0.03091 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top