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.List;
029 import java.util.concurrent.atomic.AtomicInteger;
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 private final boolean header;
041
042 RowRenderer(RowElement row) {
043
044 List<Renderer> cols = new ArrayList<Renderer>(row.getCols().size());
045 for (Element col : row.getCols()) {
046 cols.add(col.renderer());
047 }
048
049 //
050 this.cols = cols;
051 this.style = row.getStyle();
052 this.header = row.header;
053 }
054
055 public boolean isHeader() {
056 return header;
057 }
058
059 int getSize() {
060 return cols.size();
061 }
062
063 public List<Renderer> getCols() {
064 return cols;
065 }
066
067 public LineReader renderer(final int width, Border border) {
068
069 //
070 int[] widths = new int[cols.size()];
071 int[] minWidths = new int[cols.size()];
072 for (int i = 0;i < cols.size();i++) {
073 Renderer renderable = cols.get(i);
074 widths[i] = Math.max(widths[i], renderable.getActualWidth());
075 minWidths[i] = Math.max(minWidths[i], renderable.getMinWidth());
076 }
077
078 //
079 widths = ColumnLayout.rightToLeft().compute(border, width, widths, minWidths);
080
081 //
082 if (widths == null) {
083 return new LineReader() {
084 public int getWidth() {
085 return width;
086 }
087 public boolean hasLine() {
088 return false;
089 }
090 public void renderLine(RenderAppendable to) throws IllegalStateException {
091 throw new IllegalStateException();
092 }
093 };
094 } else {
095 return renderer(widths, width, border);
096 }
097 }
098
099 public LineReader renderer(final int[] widths, final int width, final Border border) {
100 final AtomicInteger totalWidth = new AtomicInteger();
101 final LineReader[] renderers = new LineReader[cols.size()];
102 for (int i = 0;i < cols.size();i++) {
103 if (widths[i] > 0) {
104 renderers[i] = cols.get(i).renderer(widths[i]);
105 totalWidth.addAndGet(widths[i]);
106 }
107 }
108
109 //
110 return new LineReader() {
111 public boolean hasLine() {
112 for (LineReader renderer : renderers) {
113 if (renderer != null) {
114 if (renderer.hasLine()) {
115 return true;
116 }
117 }
118 }
119 return false;
120 }
121
122 public void renderLine(RenderAppendable to) {
123 int total = 0;
124 if (border != null) {
125 to.styleOff();
126 to.append(border.vertical);
127 to.styleOn();
128 total++;
129 }
130
131 //
132 if (style != null) {
133 to.enterStyle(style);
134 }
135
136 //
137 for (int i = 0;i < renderers.length;i++) {
138 LineReader renderer = renderers[i];
139 if (widths[i] > 0) {
140 if (i > 0) {
141 if (border != null) {
142 to.styleOff();
143 to.append(border.vertical);
144 to.styleOn();
145 total++;
146 }
147 }
148
149 total += widths[i];
150 if (renderer != null && renderer.hasLine()) {
151 renderer.renderLine(to);
152 } else {
153 renderers[i] = null;
154 for (int j = widths[i];j > 0;j--) {
155 to.append(' ');
156 }
157 }
158
159 }
160 }
161
162 //
163 if (style != null) {
164 to.leaveStyle();
165 }
166
167 //
168 if (border != null) {
169 to.styleOff();
170 to.append(border.vertical);
171 to.styleOff();
172 total++;
173 }
174 while (total++ < width) {
175 to.append(' ');
176 }
177 }
178 };
179 }
180
181 @Override
182 public LineReader renderer(int width) {
183 return renderer(width, null);
184 }
185
186 @Override
187 public int getActualWidth() {
188 int width = 0;
189 for (Renderer col : cols) {
190 width += col.getActualWidth();
191 }
192 return width;
193 }
194
195 @Override
196 public int getMinWidth() {
197 int minWidth = 0;
198 for (Renderer col : cols) {
199 minWidth += col.getMinWidth();
200 }
201 return minWidth;
202 }
203 }