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.RenderAppendable;
024 import org.crsh.text.Renderer;
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 RowRenderer extends Renderer {
032
033 /** . */
034 private final List<Renderer> 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 RowRenderer(RowElement row, BorderStyle separator, int leftCellPadding, int rightCellPadding) {
049
050 List<Renderer> cols = new ArrayList<Renderer>(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<Renderer> 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 Renderer 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 Renderer 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 (Renderer 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 (Renderer 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 Renderer 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 Renderer 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 }