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 }