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 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 }