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    }