/** * Calculate the actual size of each row or column based on the minimum and preferred sizes, the * size of this container, and the row or column weights. * * @param minSize the minimum size of each row/column * @param prefSize the preferred size of each row/column * @param weight the weight of each row/column * @param totalSize the total size of the container in the appropriate dimension * @return the position of the right edge of each column, or the bottom edge of each row */ private int[] calculatePositions(int minSize[], int prefSize[], double weight[], int totalSize) { int pos[] = new int[minSize.length]; int totalMin = 0, totalPref = 0; for (int i = 0; i < minSize.length; i++) { totalMin += minSize[i]; totalPref += prefSize[i]; } if (totalMin > totalSize) { // Just give every row/column its minimum size (which means that some may extend off the edge // of // the container). int current = 0; for (int i = 0; i < pos.length; i++) { current += minSize[i]; pos[i] = current; } } else if (totalPref > totalSize) { // Give each row/column its minimum size, plus a fixed fraction of the difference between its // minimum and preferred sizes. double fract = (totalSize - totalMin) / (double) (totalPref - totalMin); double current = 0.0f; for (int i = 0; i < pos.length; i++) { current += minSize[i] + fract * (prefSize[i] - minSize[i]); pos[i] = ((int) Math.round(current)); } } else { // Give each row/column its preferred size, plus a fraction of the extra size based on its // weight. double realWeight[] = new double[weight.length]; double totalWeight = 0.0; for (int i = 0; i < weight.length; i++) totalWeight += weight[i]; if (totalWeight > 0.0) for (int i = 0; i < realWeight.length; i++) realWeight[i] = weight[i] / totalWeight; double current = 0.0f; for (int i = 0; i < pos.length; i++) { current += prefSize[i] + realWeight[i] * (totalSize - totalPref); pos[i] = ((int) Math.round(current)); } } return pos; }
/** * Calculate the minimum or preferred size of every row or column. * * @param dim the minimum or preferred size of every child * @param row true if row sizes should be calculated, false if column sizes should be calculated * @return the size required for every row or column */ private int[] calculateRequiredSizes(Dimension dim[], boolean row) { // Build a linked list of size requirements of every child. LinkedList<int[]> requiredList = new LinkedList<int[]>(); for (int i = 0; i < dim.length; i++) { ChildInfo info = child.get(i); if (row) requiredList.addLast(new int[] {info.y, info.height, dim[i].height}); else requiredList.addLast(new int[] {info.x, info.width, dim[i].width}); } // Find the required size for each row or column. int width[] = new int[row ? rowWeight.length : colWeight.length]; double weight[] = (row ? rowWeight : colWeight); for (int currentWidth = 1; requiredList.size() > 0; currentWidth++) { // Apply constraints for all children which occupy currentWidth rows or columns. Iterator<int[]> iter = requiredList.iterator(); while (iter.hasNext()) { int req[] = iter.next(); if (req[1] != currentWidth) continue; iter.remove(); if (currentWidth == 1) { width[req[0]] = Math.max(width[req[0]], req[2]); continue; } // Find how much space is currently available. int total = 0; for (int i = 0; i < currentWidth; i++) total += width[req[0] + i]; if (total >= req[2]) continue; // It is already wide enough. // Allocate additional space to the rows or columns, based on their weights. double totalWeight = 0.0; for (int i = 0; i < currentWidth; i++) totalWeight += weight[req[0] + i]; int extra[] = new int[currentWidth]; int totalExtra = 0; for (int i = 0; i < currentWidth - 1; i++) { double w = (totalWeight > 0.0 ? weight[req[0] + i] / totalWeight : 1.0 / currentWidth); extra[i] += w * (req[2] - total); totalExtra += extra[i]; } extra[extra.length - 1] = req[2] - total - totalExtra; for (int i = 0; i < currentWidth; i++) width[req[0] + i] += extra[i]; } } return width; }