001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.api.web.gwt.client.widgets;
021
022 import com.google.gwt.core.client.JavaScriptObject;
023 import com.google.gwt.user.client.ui.Composite;
024 import com.google.gwt.user.client.ui.HTML;
025 import com.google.gwt.user.client.ui.Panel;
026 import com.google.gwt.user.client.ui.VerticalPanel;
027 import com.google.gwt.widgetideas.table.client.PreloadedTable;
028 import org.sonar.api.web.gwt.client.webservices.BaseQueryCallback;
029 import org.sonar.api.web.gwt.client.webservices.FileSource;
030 import org.sonar.api.web.gwt.client.webservices.Resource;
031 import org.sonar.api.web.gwt.client.webservices.SourcesQuery;
032
033 import java.util.Arrays;
034 import java.util.List;
035 import java.util.Map;
036
037 public abstract class AbstractSourcePanel extends Composite {
038
039 private final Panel panel = new VerticalPanel();
040 private FileSource sourceLines;
041 private final LoadingLabel loading = new LoadingLabel();
042 private int from = 0;
043 private int length = 0;
044
045 private boolean started = false;
046 private Resource resource;
047 private boolean hasNoSources = false;
048
049 public AbstractSourcePanel(Resource resource) {
050 this(resource, 0, 0);
051 }
052
053 public Resource getResource() {
054 return resource;
055 }
056
057 public AbstractSourcePanel(Resource resource, int from, int length) {
058 this.from = from;
059 this.length = length;
060 this.resource = resource;
061
062 panel.add(loading);
063 panel.getElement().setId("sourcePanel");
064 initWidget(panel);
065 setStyleName("gwt-SourcePanel");
066
067 loadSources();
068 }
069
070 private void loadSources() {
071 SourcesQuery.get(resource.getId().toString())
072 .setFrom(from)
073 .setLength(length)
074 .execute(new BaseQueryCallback<FileSource>(loading) {
075 public void onResponse(FileSource response, JavaScriptObject jsonResponse) {
076 sourceLines = response;
077 decorate();
078 }
079
080 @Override
081 public void onError(int errorCode, String errorMessage) {
082 if (errorCode == 404) {
083 panel.add(new HTML("No sources"));
084 hasNoSources = true;
085 loading.removeFromParent();
086 } else {
087 super.onError(errorCode, errorMessage);
088 }
089 }
090 });
091 }
092
093 protected void setStarted() {
094 started = true;
095 decorate();
096 }
097
098 public void refresh() {
099 if (!hasNoSources) {
100 panel.clear();
101 panel.add(loading);
102 decorate();
103 }
104 }
105
106 private void decorate() {
107 if (started && sourceLines != null) {
108 PreloadedTable table = new PreloadedTable();
109 table.setStyleName("sources");
110
111 int rowIndex = 0;
112 if (shouldDecorateLine(0)) {
113 List<Row> rows = decorateLine(0, null);
114 if (rows != null) {
115 for (Row row : rows) {
116 table.setPendingHTML(rowIndex, 0, row.getColumn1());
117 table.setPendingHTML(rowIndex, 1, row.getColumn2());
118 table.setPendingHTML(rowIndex, 2, row.getColumn3());
119 table.setPendingHTML(rowIndex, 3, row.getColumn4());
120 rowIndex++;
121 }
122 }
123 }
124
125 Map<Integer, String> lines = sourceLines.getLines();
126 boolean previousLineIsDecorated = true;
127 boolean firstDecoratedLine = true;
128 for (Map.Entry<Integer, String> entry : lines.entrySet()) {
129 Integer lineIndex = entry.getKey();
130 if (shouldDecorateLine(lineIndex)) {
131 if (!previousLineIsDecorated && !firstDecoratedLine) {
132 table.setPendingHTML(rowIndex, 0, "<div class='src' style='background-color: #fff;height: 3em; border-top: 1px dashed silver;border-bottom: 1px dashed silver;'> </div>");
133 table.setPendingHTML(rowIndex, 1, " ");
134 table.setPendingHTML(rowIndex, 2, " ");
135 table.setPendingHTML(rowIndex, 3, "<div class='src' style='background-color: #fff;height: 3em; border-top: 1px dashed silver;border-bottom: 1px dashed silver;'> </div>");
136 rowIndex++;
137 }
138
139 List<Row> rows = decorateLine(lineIndex, entry.getValue());
140 if (rows != null) {
141 for (Row row : rows) {
142 table.setPendingHTML(rowIndex, 0, row.getColumn1());
143 table.setPendingHTML(rowIndex, 1, row.getColumn2());
144 table.setPendingHTML(rowIndex, 2, row.getColumn3());
145 table.setPendingHTML(rowIndex, 3, row.getColumn4());
146 rowIndex++;
147 }
148 previousLineIsDecorated = true;
149 firstDecoratedLine = false;
150 }
151
152 } else {
153 previousLineIsDecorated = false;
154 }
155 }
156 panel.clear();
157 panel.add(table);
158 }
159 }
160
161 protected boolean shouldDecorateLine(int index) {
162 return true;
163 }
164
165 protected List<Row> decorateLine(int index, String source) {
166 if (index > 0) {
167 return Arrays.asList(new Row(index, source));
168 }
169 return null;
170 }
171
172 public static class Row {
173 protected String column1;
174 protected String column2;
175 protected String column3;
176 protected String column4;
177
178 public Row(String column1, String column2, String column3) {
179 this.column1 = column1;
180 this.column2 = column2;
181 this.column3 = column3;
182 this.column4 = "";
183 }
184
185 public Row(String column1, String column2, String column3, String column4) {
186 this.column1 = column1;
187 this.column2 = column2;
188 this.column3 = column3;
189 this.column4 = column4;
190 }
191
192 public Row(int lineIndex, String source) {
193 setLineIndex(lineIndex, "");
194 unsetValue();
195 setSource(source, "");
196 }
197
198 public Row() {
199 }
200
201 public Row setLineIndex(int index, String style) {
202 column1 = "<div class='ln " + style + "'>" + index + "</div>";
203 return this;
204 }
205
206 public Row setValue(String value, String style) {
207 column2 = "<div class='val " + style + "'>" + value + "</div>";
208 return this;
209 }
210
211 public Row setValue2(String value, String style) {
212 column3 = "<div class='val " + style + "'>" + value + "</div>";
213 return this;
214 }
215
216 public Row unsetValue() {
217 column2 = "";
218 column3 = "";
219 return this;
220 }
221
222 public Row setSource(String source, String style) {
223 column4 = "<div class='src " + style + "'><pre>" + source + "</pre></div>";
224 return this;
225 }
226
227 public String getColumn1() {
228 return column1;
229 }
230
231 public void setColumn1(String column1) {
232 this.column1 = column1;
233 }
234
235 public String getColumn2() {
236 return column2;
237 }
238
239 public void setColumn2(String column2) {
240 this.column2 = column2;
241 }
242
243 public String getColumn3() {
244 return column3;
245 }
246
247 public void setColumn3(String column3) {
248 this.column3 = column3;
249 }
250
251 public String getColumn4() {
252 return column4;
253 }
254
255 public void setColumn4(String column4) {
256 this.column4 = column4;
257 }
258 }
259 }