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
026 import java.util.ArrayList;
027 import java.util.Iterator;
028 import java.util.LinkedList;
029 import java.util.List;
030
031 class TreeRenderer extends Renderer {
032
033 /** . */
034 private final Renderer value;
035
036 /** . */
037 private final List<Renderer> children;
038
039 TreeRenderer(TreeElement tree) {
040
041 ArrayList<Renderer> children = new ArrayList<Renderer>(tree.children.size());
042 for (Element child : tree.children) {
043 children.add(child.renderer());
044 }
045
046 //
047 this.children = children;
048 this.value = tree.value != null ? tree.value.renderer() : null;
049 }
050
051 @Override
052 public int getActualWidth() {
053 int width = value != null ? value.getActualWidth() : 0;
054 for (Renderer child : children) {
055 width = Math.max(width, 2 + child.getActualWidth());
056 }
057 return width;
058 }
059
060 @Override
061 public int getMinWidth() {
062 int width = value != null ? value.getMinWidth() : 0;
063 for (Renderer child : children) {
064 width = Math.max(width, 2 + child.getMinWidth());
065 }
066 return width;
067 }
068
069 @Override
070 public LineReader renderer(final int width) {
071
072
073 final LinkedList<LineReader> renderers = new LinkedList<LineReader>();
074 for (Renderer child : children) {
075 renderers.addLast(child.renderer(width - 2));
076 }
077
078 //
079 return new LineReader() {
080
081 /** . */
082 LineReader value = TreeRenderer.this.value != null ? TreeRenderer.this.value.renderer(width) : null;
083
084 /** . */
085 boolean node = true;
086
087 public boolean hasLine() {
088 if (value != null) {
089 if (value.hasLine()) {
090 return true;
091 } else {
092 value = null;
093 }
094 }
095 while (renderers.size() > 0) {
096 if (renderers.peekFirst().hasLine()) {
097 return true;
098 } else {
099 renderers.removeFirst();
100 node = true;
101 }
102 }
103 return false;
104 }
105
106 public void renderLine(RenderAppendable to) {
107 if (value != null) {
108 if (value.hasLine()) {
109 value.renderLine(to);
110 } else {
111 value = null;
112 }
113 }
114 if (value == null) {
115 while (renderers.size() > 0) {
116 LineReader first = renderers.peekFirst();
117 if (first.hasLine()) {
118 if (node) {
119 to.append("+-");
120 node = false;
121 } else {
122 Iterator<LineReader> i = renderers.descendingIterator();
123 boolean rest = false;
124 while (i.hasNext()) {
125 LineReader renderer = i.next();
126 if (i.hasNext()) {
127 if (renderer.hasLine()) {
128 rest = true;
129 break;
130 }
131 }
132 }
133 if (rest) {
134 to.append("| ");
135 } else {
136 to.append(" ");
137 }
138 }
139 first.renderLine(to);
140 break;
141 }
142 }
143 }
144 }
145 };
146 }
147 }