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
025 class TableRowReader implements LineReader {
026
027 /** . */
028 private final TableRowRenderer renderer;
029
030 /** . */
031 private final int[] widths;
032
033 /** . */
034 private final RowRenderer row;
035
036 /** . */
037 private LineReader reader;
038
039 /** . */
040 private TableRowReader previous;
041
042 /** . */
043 private TableRowReader next;
044
045 /** . */
046 private BorderStyle top;
047
048 /** . */
049 private BorderStyle bottom;
050
051 /** . */
052 private final int height;
053
054 /**
055 * 0 -> render top
056 * 1 -> render cells
057 * 2 -> render bottom
058 * 3 -> done
059 */
060 private int status;
061
062 TableRowReader(TableRowRenderer renderer, RowRenderer row, int[] widths, int height) {
063
064 //
065 this.renderer = renderer;
066 this.row = row;
067 this.widths = widths;
068 this.reader = null;
069 this.top = null;
070 this.bottom = null;
071 this.height = height;
072 this.status = 1;
073 }
074
075 TableRowReader add(TableRowReader next) {
076 next.previous = this;
077 this.next = next;
078 bottom = renderer.header ? (renderer.table.separator != null ? renderer.table.separator : BorderStyle.DASHED) : null;
079 next.top = next.renderer.header && !renderer.header ? (next.renderer.table.separator != null ? next.renderer.table.separator : BorderStyle.DASHED) : null;
080 next.status = next.top != null ? 0 : 1;
081 return next;
082 }
083
084 TableRowReader previous() {
085 return previous;
086 }
087
088 TableRowReader next() {
089 return next;
090 }
091
092 boolean hasTop() {
093 return renderer.header && previous != null;
094 }
095
096 boolean hasBottom() {
097 return renderer.header && next != null && !next.renderer.header;
098 }
099
100 boolean isSeparator() {
101 return status == 0 || status == 2;
102 }
103
104 public boolean hasLine() {
105 return 0 <= status && status <= 2;
106 }
107
108 public void renderLine(RenderAppendable to) throws IllegalStateException {
109 if (!hasLine()) {
110 throw new IllegalStateException();
111 }
112 switch (status) {
113 case 0:
114 case 2: {
115 BorderStyle b = status == 0 ? top : bottom;
116 to.styleOff();
117 for (int i = 0;i < widths.length;i++) {
118 if (i > 0 && renderer.table.separator != null) {
119 to.append(b.horizontal);
120 }
121 for (int j = 0;j < widths[i];j++) {
122 to.append(b.horizontal);
123 }
124 }
125 to.styleOn();
126 status++;
127 break;
128 }
129 case 1: {
130
131 //
132 if (reader == null) {
133 if (height > 0 && renderer.table.overflow == Overflow.WRAP) {
134 int h = height;
135 if (hasTop()) {
136 h--;
137 }
138 if (hasBottom()) {
139 h--;
140 }
141 reader = row.renderer(widths, h);
142 } else {
143 reader = row.renderer(widths, -1);
144 }
145 }
146
147 //
148 reader.renderLine(to);
149
150 //
151 if (renderer.table.overflow == Overflow.HIDDEN) {
152 status = bottom != null ? 2 : 3;
153 } else {
154 if (!reader.hasLine()) {
155 status = bottom != null ? 2 : 3;
156 }
157 }
158
159 //
160 break;
161 }
162 default:
163 throw new AssertionError();
164 }
165 }
166 }