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 int getActualHeight(int width) {
071 throw new UnsupportedOperationException("Implement me");
072 }
073
074 @Override
075 public int getMinHeight(int width) {
076 throw new UnsupportedOperationException("Implement me");
077 }
078
079 @Override
080 public LineReader reader(final int width) {
081
082
083 final LinkedList<LineReader> readers = new LinkedList<LineReader>();
084 for (Renderer child : children) {
085 readers.addLast(child.reader(width - 2));
086 }
087
088 //
089 return new LineReader() {
090
091 /** . */
092 LineReader value = TreeRenderer.this.value != null ? TreeRenderer.this.value.reader(width) : null;
093
094 /** . */
095 boolean node = true;
096
097 public boolean hasLine() {
098 if (value != null) {
099 if (value.hasLine()) {
100 return true;
101 } else {
102 value = null;
103 }
104 }
105 while (readers.size() > 0) {
106 if (readers.peekFirst().hasLine()) {
107 return true;
108 } else {
109 readers.removeFirst();
110 node = true;
111 }
112 }
113 return false;
114 }
115
116 public void renderLine(RenderAppendable to) {
117 if (value != null) {
118 if (value.hasLine()) {
119 value.renderLine(to);
120 } else {
121 value = null;
122 }
123 }
124 if (value == null) {
125 while (readers.size() > 0) {
126 LineReader first = readers.peekFirst();
127 if (first.hasLine()) {
128 if (node) {
129 to.append("+-");
130 node = false;
131 } else {
132 Iterator<LineReader> i = readers.descendingIterator();
133 boolean rest = false;
134 while (i.hasNext()) {
135 LineReader renderer = i.next();
136 if (i.hasNext()) {
137 if (renderer.hasLine()) {
138 rest = true;
139 break;
140 }
141 }
142 }
143 if (rest) {
144 to.append("| ");
145 } else {
146 to.append(" ");
147 }
148 }
149 first.renderLine(to);
150 break;
151 }
152 }
153 }
154 }
155 };
156 }
157 }