001 /* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 020 package org.crsh.text.ui; 021 022 import org.crsh.text.LineReader; 023 import org.crsh.text.LineRenderer; 024 import org.crsh.text.RenderAppendable; 025 import org.crsh.text.Style; 026 027 import java.util.ArrayList; 028 import java.util.Arrays; 029 import java.util.List; 030 031 class RowLineRenderer extends LineRenderer { 032 033 /** . */ 034 private final List<LineRenderer> cols; 035 036 /** . */ 037 private final Style.Composite style; 038 039 /** . */ 040 final int leftCellPadding; 041 042 /** . */ 043 final int rightCellPadding; 044 045 /** . */ 046 private final BorderStyle separator; 047 048 RowLineRenderer(RowElement row, BorderStyle separator, int leftCellPadding, int rightCellPadding) { 049 050 List<LineRenderer> cols = new ArrayList<LineRenderer>(row.cols.size()); 051 for (Element col : row.cols) { 052 cols.add(col.renderer()); 053 } 054 055 // 056 this.cols = cols; 057 this.style = row.getStyle(); 058 this.separator = separator; 059 this.leftCellPadding = leftCellPadding; 060 this.rightCellPadding = rightCellPadding; 061 } 062 063 int getSize() { 064 return cols.size(); 065 } 066 067 public List<LineRenderer> getCols() { 068 return cols; 069 } 070 071 @Override 072 public int getActualWidth() { 073 int actualWidth = 0; 074 for (int i = 0;i < cols.size();i++) { 075 LineRenderer col = cols.get(i); 076 actualWidth += col.getActualWidth(); 077 actualWidth += leftCellPadding; 078 actualWidth += rightCellPadding; 079 if (separator != null && i > 0) { 080 actualWidth++; 081 } 082 } 083 return actualWidth; 084 } 085 086 @Override 087 public int getMinWidth() { 088 int minWidth = 0; 089 for (int i = 0;i < cols.size();i++) { 090 LineRenderer col = cols.get(i); 091 minWidth += col.getMinWidth(); 092 minWidth += leftCellPadding; 093 minWidth += rightCellPadding; 094 if (separator != null && i > 0) { 095 minWidth++; 096 } 097 } 098 return minWidth; 099 } 100 101 @Override 102 public int getActualHeight(int width) { 103 int actualHeight = 0; 104 for (LineRenderer col : cols) { 105 actualHeight = Math.max(actualHeight, col.getActualHeight(width)); 106 } 107 return actualHeight; 108 } 109 110 @Override 111 public int getMinHeight(int width) { 112 int minHeight = 0; 113 for (LineRenderer col : cols) { 114 minHeight = Math.max(minHeight, col.getMinHeight(width)); 115 } 116 return minHeight; 117 } 118 119 // todo look at : 120 // if (i > 0) { 121 // to.append(b.horizontal); 122 // } 123 // in relation to widths array that can contain (should?) 0 value 124 LineReader renderer(final int[] widths, int height) { 125 final LineReader[] readers = new LineReader[widths.length]; 126 for (int i = 0;i < readers.length;i++) { 127 LineRenderer renderer = cols.get(i); 128 LineReader reader = renderer.reader(widths[i] - leftCellPadding - rightCellPadding, height); 129 readers[i] = reader; 130 } 131 132 // 133 return new LineReader() { 134 135 /** . */ 136 private boolean done = false; 137 138 public boolean hasLine() { 139 return !done; 140 } 141 142 public void renderLine(RenderAppendable to) { 143 if (!hasLine()) { 144 throw new IllegalStateException(); 145 } 146 147 // 148 if (style != null) { 149 to.enterStyle(style); 150 } 151 152 // 153 for (int i = 0;i < readers.length;i++) { 154 LineReader reader = readers[i]; 155 156 // 157 if (i > 0) { 158 if (separator != null) { 159 to.styleOff(); 160 to.append(separator.vertical); 161 to.styleOn(); 162 } 163 } 164 if (reader != null && reader.hasLine()) { 165 // Left padding 166 if (leftCellPadding > 0) { 167 for (int j = 0;j < leftCellPadding;j++) { 168 to.append(' '); 169 } 170 } 171 reader.renderLine(to); 172 // Right padding 173 if (rightCellPadding > 0) { 174 for (int j = 0;j < rightCellPadding;j++) { 175 to.append(' '); 176 } 177 } 178 } else { 179 readers[i] = null; 180 for (int j = widths[i];j > 0;j--) { 181 to.append(' '); 182 } 183 } 184 } 185 186 // 187 if (style != null) { 188 to.leaveStyle(); 189 } 190 191 192 // Update status 193 done = true; 194 for (LineReader reader : readers) { 195 if (reader != null) { 196 if (reader.hasLine()) { 197 done = false; 198 break; 199 } 200 } 201 } 202 } 203 }; 204 } 205 206 @Override 207 public LineReader reader(int width) { 208 int[] widths = new int[cols.size()]; 209 int[] minWidths = new int[cols.size()]; 210 for (int i = 0;i < cols.size();i++) { 211 LineRenderer renderable = cols.get(i); 212 widths[i] = Math.max(widths[i], renderable.getActualWidth()); 213 minWidths[i] = Math.max(minWidths[i], renderable.getMinWidth()); 214 } 215 widths = Layout.flow().compute(false, width, widths, minWidths); 216 if (widths == null) { 217 return null; 218 } else { 219 // Size could be smaller and lead to ArrayIndexOutOfBounds later 220 widths = Arrays.copyOf(widths, minWidths.length); 221 return renderer(widths, -1); 222 } 223 } 224 }