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
020package org.crsh.text.ui;
021
022import org.crsh.text.LineReader;
023import org.crsh.text.RenderAppendable;
024
025class TableRowReader implements LineReader {
026
027  /** . */
028  private final TableRowLineRenderer renderer;
029
030  /** . */
031  private final int[] widths;
032
033  /** . */
034  private final RowLineRenderer 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(TableRowLineRenderer renderer, RowLineRenderer 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}