<configuration>
<modules>
<module>org.sonar.plugins.design.ui.page.DesignPage${gwt.permutationSuffix}</module>
- <module>org.sonar.plugins.design.ui.dependencies.DependenciesTab${gwt.permutationSuffix}</module>
<module>org.sonar.plugins.design.ui.libraries.LibrariesPage${gwt.permutationSuffix}</module>
</modules>
<skip>${skipGwt}</skip>
*/
package org.sonar.plugins.design;
-import com.google.common.collect.Lists;
+import java.util.List;
+
import org.sonar.api.SonarPlugin;
-import org.sonar.plugins.design.batch.*;
-import org.sonar.plugins.design.ui.dependencies.GwtDependenciesTab;
+import org.sonar.plugins.design.batch.FileTangleIndexDecorator;
+import org.sonar.plugins.design.batch.MavenDependenciesSensor;
+import org.sonar.plugins.design.batch.PackageTangleIndexDecorator;
+import org.sonar.plugins.design.batch.ProjectDsmDecorator;
+import org.sonar.plugins.design.batch.SuspectLcom4DensityDecorator;
+import org.sonar.plugins.design.ui.dependencies.DependenciesViewer;
import org.sonar.plugins.design.ui.libraries.GwtLibrariesPage;
import org.sonar.plugins.design.ui.page.GwtDesignPage;
import org.sonar.plugins.design.ui.widgets.ChidamberKemererWidget;
import org.sonar.plugins.design.ui.widgets.FileDesignWidget;
import org.sonar.plugins.design.ui.widgets.PackageDesignWidget;
-import java.util.List;
+import com.google.common.collect.Lists;
public class DesignPlugin extends SonarPlugin {
+ @SuppressWarnings({"unchecked", "rawtypes"})
public List getExtensions() {
List extensions = Lists.newArrayList();
// UI
extensions.add(GwtDesignPage.class);
- extensions.add(GwtDependenciesTab.class);
+ extensions.add(DependenciesViewer.class);
extensions.add(FileDesignWidget.class);
extensions.add(PackageDesignWidget.class);
extensions.add(ChidamberKemererWidget.class);
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.plugins.design.ui.dependencies;
+
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.web.AbstractRubyTemplate;
+import org.sonar.api.web.DefaultTab;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.RequiredMeasures;
+import org.sonar.api.web.ResourceQualifier;
+import org.sonar.api.web.RubyRailsPage;
+import org.sonar.api.web.UserRole;
+
+@RequiredMeasures(allOf = {CoreMetrics.AFFERENT_COUPLINGS_KEY, CoreMetrics.EFFERENT_COUPLINGS_KEY})
+@ResourceQualifier({Qualifiers.FILE, Qualifiers.CLASS, Qualifiers.PACKAGE, Qualifiers.PROJECT, Qualifiers.MODULE})
+@DefaultTab(metrics = {CoreMetrics.AFFERENT_COUPLINGS_KEY, CoreMetrics.EFFERENT_COUPLINGS_KEY})
+@NavigationSection({NavigationSection.RESOURCE_TAB})
+@UserRole(UserRole.USER)
+public class DependenciesViewer extends AbstractRubyTemplate implements RubyRailsPage {
+
+ public String getId() {
+ return "dependencies_viewer";
+ }
+
+ public String getTitle() {
+ return "Dependencies";
+ }
+
+ @Override
+ protected String getTemplatePath() {
+ return "/org/sonar/plugins/design/ui/dependencies/dependencies_viewer.html.erb";
+ }
+}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.plugins.design.ui.dependencies;
-
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.web.DefaultTab;
-import org.sonar.api.web.GwtPage;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.RequiredMeasures;
-import org.sonar.api.web.ResourceQualifier;
-import org.sonar.api.web.UserRole;
-import org.sonar.plugins.design.ui.dependencies.client.DependenciesTab;
-
-@RequiredMeasures(allOf = {CoreMetrics.AFFERENT_COUPLINGS_KEY, CoreMetrics.EFFERENT_COUPLINGS_KEY})
-@ResourceQualifier({Qualifiers.FILE, Qualifiers.CLASS, Qualifiers.PACKAGE, Qualifiers.PROJECT, Qualifiers.MODULE})
-@DefaultTab(metrics = {CoreMetrics.AFFERENT_COUPLINGS_KEY, CoreMetrics.EFFERENT_COUPLINGS_KEY})
-@NavigationSection({NavigationSection.RESOURCE_TAB})
-@UserRole(UserRole.USER)
-public class GwtDependenciesTab extends GwtPage {
-
- public String getTitle() {
- return "Dependencies";
- }
-
- public String getGwtId() {
- return DependenciesTab.GWT_ID;
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.plugins.design.ui.dependencies.client;
-
-import org.sonar.wsclient.services.Dependency;
-import org.sonar.wsclient.services.Resource;
-
-import java.util.List;
-
-public class Data {
-
- private long resourceId;
- private List<Dependency> dependencies = null;
- private Resource resource = null;
-
- public Data(long resourceId) {
- this.resourceId = resourceId;
- }
-
- public long getResourceId() {
- return resourceId;
- }
-
- public boolean isLoaded() {
- return dependencies!=null && resource!=null;
- }
-
- public boolean canDisplay() {
- return resource.getMeasure("ca")!=null && resource.getMeasure("ce")!=null;
- }
-
- public List<Dependency> getDependencies() {
- return dependencies;
- }
-
- public void setDependencies(List<Dependency> dependencies) {
- this.dependencies = dependencies;
- }
-
- public Resource getResource() {
- return resource;
- }
-
- public void setMeasures(Resource resource) {
- this.resource = resource;
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.plugins.design.ui.dependencies.client;
-
-import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.Widget;
-import org.sonar.gwt.Metrics;
-import org.sonar.gwt.ui.Loading;
-import org.sonar.gwt.ui.Page;
-import org.sonar.wsclient.gwt.AbstractCallback;
-import org.sonar.wsclient.gwt.AbstractListCallback;
-import org.sonar.wsclient.gwt.Sonar;
-import org.sonar.wsclient.services.Dependency;
-import org.sonar.wsclient.services.DependencyQuery;
-import org.sonar.wsclient.services.Resource;
-import org.sonar.wsclient.services.ResourceQuery;
-
-import java.util.List;
-
-public class DependenciesTab extends Page {
- public static final String GWT_ID = "org.sonar.plugins.design.ui.dependencies.DependenciesTab";
-
- private FlowPanel panel = null;
- private DependenciesTable dependenciesTable = null;
- private Loading loading;
-
- @Override
- protected Widget doOnResourceLoad(Resource resource) {
- prepare();
- Data data = new Data(resource.getId());
- loadMeasures(data);
- loadDependencies(data);
- return panel;
- }
-
- private void prepare() {
- if (panel == null) {
- panel = new FlowPanel();
- panel.getElement().setId("deps");
- loading = new Loading();
- dependenciesTable = new DependenciesTable();
- panel.setWidth("100%");
- }
- panel.clear();
- panel.add(loading);
- }
-
- private void loadMeasures(final Data data) {
- ResourceQuery query = new ResourceQuery(data.getResourceId());
- query.setMetrics(Metrics.EFFERENT_COUPLINGS, Metrics.AFFERENT_COUPLINGS);
- query.setVerbose(true);
- Sonar.getInstance().find(query, new AbstractCallback<org.sonar.wsclient.services.Resource>() {
- @Override
- protected void doOnResponse(org.sonar.wsclient.services.Resource resource) {
- data.setMeasures(resource);
- displayMeasures(data);
- }
- });
- }
-
- private void loadDependencies(final Data data) {
- DependencyQuery query = DependencyQuery.createForResource(data.getResourceId());
- Sonar.getInstance().findAll(query, new AbstractListCallback<Dependency>() {
-
- @Override
- protected void doOnResponse(List<Dependency> dependencies) {
- data.setDependencies(dependencies);
- displayMeasures(data);
- }
- });
- }
-
-
- private void displayMeasures(Data data) {
- if (data.isLoaded()) {
- panel.clear();
- dependenciesTable.display(data);
- panel.add(dependenciesTable);
- }
- }
-}
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.plugins.design.ui.dependencies.client;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.i18n.client.Dictionary;
-import com.google.gwt.user.client.ui.*;
-import org.sonar.gwt.Links;
-import org.sonar.gwt.ui.Icons;
-import org.sonar.wsclient.services.Dependency;
-
-public class DependenciesTable extends Composite {
-
- private HorizontalPanel panel;
-
- public DependenciesTable() {
- panel = new HorizontalPanel();
- panel.setStylePrimaryName("dependencies");
- initWidget(panel);
- }
-
-
- public void display(final Data data) {
- panel.clear();
- if (data.canDisplay()) {
- panel.add(createIncomingColumn(data));
- panel.add(createOutgoingColumn(data));
- } else {
- panel.add(new Label(Dictionary.getDictionary("l10n").get("noData")));
- }
- }
-
-
- private Panel createIncomingColumn(Data data) {
- FlexTable grid = new FlexTable();
- grid.setStyleName("col");
- grid.setWidget(0, 1, new HTML(Dictionary.getDictionary("l10n").get("depsTab.afferentCouplings") + ": <b>" + data.getResource().getMeasureIntValue("ca") + "</b>"));
- grid.getRowFormatter().setStyleName(0, "coltitle");
-
- int row = 1;
- for (Dependency dependency : data.getDependencies()) {
- if (data.getResourceId() == dependency.getToId()) {
- addDependencyRow(grid, row, dependency.getFromId(), dependency.getFromName() + " (" + dependency.getWeight() + ")");
- grid.setWidget(row, 0, Icons.forQualifier(dependency.getFromQualifier()).createImage());
- row++;
- }
- }
-
- return grid;
- }
-
- private Panel createOutgoingColumn(Data data) {
- FlexTable grid = new FlexTable();
- grid.setStyleName("col");
- grid.setWidget(0, 1, new HTML(Dictionary.getDictionary("l10n").get("depsTab.efferentCouplings") + ": <b>" + data.getResource().getMeasureIntValue("ce") + "</b>"));
- grid.getRowFormatter().setStyleName(0, "coltitle");
-
- int row = 1;
- for (Dependency dependency : data.getDependencies()) {
- if (data.getResourceId() == dependency.getFromId()) {
- addDependencyRow(grid, row, dependency.getToId(), dependency.getToName() + " (" + dependency.getWeight() + ")");
- grid.setWidget(row, 0, Icons.forQualifier(dependency.getToQualifier()).createImage());
- row++;
- }
- }
-
- return grid;
- }
-
- private void addDependencyRow(final FlexTable grid, final int row, final long resourceId, final String name) {
- Label link = new Label(name);
- link.setStyleName("link");
- link.addClickHandler(new ClickHandler() {
- public void onClick(ClickEvent clickEvent) {
- Links.openResourcePopup(String.valueOf(resourceId));
- }
- });
- grid.setWidget(row, 1, link);
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.plugins.design.ui.dependencies.client;
-
-import com.google.gwt.i18n.client.Dictionary;
-import com.google.gwt.user.client.ui.*;
-import org.sonar.wsclient.services.Measure;
-import org.sonar.wsclient.services.Resource;
-
-public class Header extends Composite {
- private FlowPanel header;
-
- public Header() {
- header = new FlowPanel();
- header.setStyleName("gwt-ViewerHeader");
- initWidget(header);
- }
-
- private void addMeasure(Panel panel, Resource resource, String key, String label) {
- Measure measure = resource.getMeasure(key);
- if (measure != null) {
- HTML html = new HTML(label + ": ");
- html.setStyleName("metric");
- panel.add(html);
-
- html = new HTML(measure.getFormattedValue("-"));
- html.setStyleName("value");
- panel.add(html);
- }
- }
-
- public void display(Data data) {
- header.clear();
- HorizontalPanel panel = new HorizontalPanel();
- header.add(panel);
- Dictionary l10n = Dictionary.getDictionary("l10n");
- addMeasure(panel, data.getResource(), "classes", l10n.get("depsTab.classes"));
- addMeasure(panel, data.getResource(), "dit", l10n.get("depsTab.dit"));
- addMeasure(panel, data.getResource(), "noc", l10n.get("depsTab.noc"));
- addMeasure(panel, data.getResource(), "rfc", l10n.get("depsTab.rfc"));
- addLcom4(data, panel);
- }
-
- private void addLcom4(Data data, HorizontalPanel panel) {
- Measure lcom4 = data.getResource().getMeasure("lcom4");
- if (lcom4 != null && lcom4.getIntValue()!=null) {
- HTML html = new HTML(Dictionary.getDictionary("l10n").get("depsTab.lcom4") + ": ");
- html.setStyleName("metric");
- panel.add(html);
-
- html = new HTML(lcom4.getIntValue() + "");
- html.setStyleName("value");
- if (lcom4.getIntValue()>1) {
- html.addStyleName("red bold");
- }
-
- panel.add(html);
- }
- }
-}
+++ /dev/null
-<module>
- <inherits name="com.google.gwt.user.User"/>
- <inherits name="com.google.gwt.json.JSON"/>
- <inherits name="com.google.gwt.http.HTTP"/>
- <inherits name="org.sonar.Sonar"/>
-
- <stylesheet src='dependencies-tab.css'/>
- <entry-point class="org.sonar.plugins.design.ui.dependencies.client.DependenciesTab"/>
-</module>
+++ /dev/null
-<module rename-to="org.sonar.plugins.design.ui.dependencies.DependenciesTab">
- <inherits name="org.sonar.plugins.design.ui.dependencies.DependenciesTab"/>
- <inherits name="org.sonar.SonarDev"/>
-
- <entry-point class="org.sonar.plugins.design.ui.dependencies.client.DependenciesTab"/>
-</module>
--- /dev/null
+<div id="dependencies" class="drilldown_col">
+
+<%
+ ca = @snapshot.measure('ca')
+ ce = @snapshot.measure('ce')
+ dependencies = Dependency.find(:all,
+ :include => ['from','to'],
+ :conditions => ['(dependencies.from_snapshot_id=? OR dependencies.to_snapshot_id=?)', @snapshot.id, @snapshot.id])
+
+ resource_id = @resource.id
+ dependencies_by_measure = []
+ dependencies_by_measure << {:metric => 'ca', :measure => ca,
+ :dependencies => dependencies.select {|dep| dep.to_resource_id == resource_id}}
+ dependencies_by_measure << {:metric => 'ce', :measure => ce,
+ :dependencies => dependencies.select {|dep| dep.from_resource_id == resource_id}}
+
+ dependencies_by_measure.each do |deps_by_m|
+ metric_name = deps_by_m[:metric]
+ measure = deps_by_m[:measure]
+ deps = deps_by_m[:dependencies]
+%>
+
+ <div id="<%= metric_name -%>-deps" style="float: left">
+ <table class="col">
+ <thead>
+ <tr class="coltitle">
+ <th class="thin"></th>
+ <th><%= message('dependencies_viewer.' + metric_name) -%>: <b><%= format_measure(measure) -%></b></th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <%
+ deps.each do |dep|
+ resource = metric_name=='ca' ? dep.from : dep.to
+ %>
+ <tr>
+ <td class="thin"><%= image_tag 'q/CLA.png'-%></td>
+ <td><%= link_to_resource resource, resource.long_name -%> (<%= dep.weight -%>)</td>
+ </tr>
+ <% end %>
+ </tbody>
+
+ </table>
+ </div>
+<% end %>
+
+</div>
+++ /dev/null
-#deps {
- padding: 10px;
-}
-
-#deps .data {
- min-width: 380px;
-}
-#deps .col {
- margin: 0 10px 0 0;
- border-right: 1px solid #ccc;
- border-left: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
-}
-#deps .col td {
- padding: 3px 5px;
-}
-
-#deps .coltitle {
- background-color: #efefef;
- padding: 3px;
- border-top: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
-}
+++ /dev/null
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
-
-<html>
-<head>
- <meta http-equiv="content-type" content="text/html; charset=UTF-8">
- <title>Sources</title>
- <link href="http://localhost:9000/stylesheets/sonar.css" media="all" rel="Stylesheet" type="text/css" />
- <script src="http://localhost:9000/javascripts/sonar.js" type="text/javascript"></script>
-</head>
-
-<body>
-<script type="text/javascript">
-var registeredTabs = [];
-var config = {
- "sonar_url": "http://localhost:9000",
- "viewer_resource_key" : "org.apache.struts:struts-core:org.apache.struts.action.ActionServlet"
-};
-</script>
-<div class="error" id="error" style="display:none"><span id="errormsg"></span> [<a href="test.html#" onclick="javascript:$('error').hide();return false;">hide</a>]</div>
-<div class="warning" id="warning" style="display:none"><span id="warningmsg"></span> [<a href="test.html#" onclick="javascript:$('warning').hide();return false;">hide</a>]</div>
-<div class="notice" id="info" style="display:none"><span id="infomsg"></span> [<a href="test.html#" onclick="javascript:$('info').hide();return false;">hide</a>]</div>
-
-<div id="resource_viewers">
- <div id='loading'></div>
-</div>
-<script type="text/javascript" language="javascript" src="org.sonar.plugins.design.ui.dependencies.DependenciesTab.nocache.js"></script>
-
-<a href="test.html#" onclick="load_org_sonar_plugins_design_ui_dependencies_DependenciesTab();">load</a>
-</body>
-</html>
\ No newline at end of file
violations_drilldown.page=Violations Drilldown
update_center.page=Update Center
lcom4_viewer.page=LCOM4
+dependencies_viewer.page=Dependencies
# GWT pages
code_viewer.create_violation.unit_test_not_supported=Users can not create their own violations on unit test files.
+#------------------------------------------------------------------------------
+#
+# DEPENDENCIES VIEWER
+#
+#------------------------------------------------------------------------------
+dependencies_viewer.ca=Afferent (incoming) couplings
+dependencies_viewer.ce=Efferent (outgoing) couplings
+
+
#------------------------------------------------------------------------------
#
# MANUAL MEASURES
background-repeat: no-repeat;
margin-right: 8px;
padding-right: 8px;
+}
+
+/* Dependencies */
+#dependencies {
+ padding: 10px;
+}
+
+#dependencies .coltitle {
+ background-color: #efefef;
+ padding: 3px;
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+#dependencies .col {
+ margin: 0 10px 0 0;
+ border-right: 1px solid #ccc;
+ border-left: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+#dependencies .col td, #dependencies .col th {
+ padding: 3px 5px;
}
\ No newline at end of file