Theme the web UI with different skin colors

We now offer a few of our color choices as configuration settings
in gerrit.config, so the administrator can try to style the site
to better match their header and other local website conventions.

Change-Id: I096f8a2bbdfcf1593a6efcf1031d12852b5bd255
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2010-02-25 12:10:10 -08:00
parent 7604b20a46
commit 2ba3ab4c86
6 changed files with 272 additions and 130 deletions

View File

@@ -1380,6 +1380,50 @@ Supported MACs: hmac-md5, hmac-md5-96, hmac-sha1, hmac-sha1-96.
+
By default, all supported MACs are available.
[[theme]] Section theme
~~~~~~~~~~~~~~~~~~~~~~~
[[theme.backgroundColor]]theme.backgroundColor::
+
Background color for the page, and major data tables like the all
open changes table or the account dashboard. The value must be a
valid HTML hex color code, or standard color name.
+
By default white, `FFFFFF`.
[[theme.topMenuColor]]theme.topMenuColor::
+
This is the color of the main menu bar at the top of the page.
The value must be a valid HTML hex color code, or standard color
name. The value defaults to <<theme.trimColor,trimColor>>.
[[theme.textColor]]theme.textColor::
+
Text color for the page, and major data tables like the all
open changes table or the account dashboard. The value must be a
valid HTML hex color code, or standard color name.
+
By default black, `000000`.
[[theme.trimColor]]theme.trimColor::
+
Primary color used as a background color behind text. This is
the color of the main menu bar at the top, of table headers,
and of major UI areas that we want to offset from other portions
of the page. The value must be a valid HTML hex color code, or
standard color name.
+
By default a shade of green, `D4E9A9`.
[[theme.selectionColor]]theme.selectionColor::
+
Background color used within a trimColor area to denote the currently
selected tab, or the background color used in a table to denote the
currently selected row. The value must be a valid HTML hex color
code, or standard color name.
+
By default a shade of yellow, `FFFFCC`.
[[user]] Section user
~~~~~~~~~~~~~~~~~~~~~

View File

@@ -38,6 +38,12 @@ public class GerritConfig implements Cloneable {
protected List<RegexFindReplace> commentLinks;
protected boolean documentationAvailable;
protected String backgroundColor;
protected String topMenuColor;
protected String textColor;
protected String trimColor;
protected String selectionColor;
public String getRegisterUrl() {
return registerUrl;
}
@@ -148,4 +154,44 @@ public class GerritConfig implements Cloneable {
public void setDocumentationAvailable(final boolean available) {
documentationAvailable = available;
}
public String getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(String color) {
backgroundColor = color;
}
public String getTopMenuColor() {
return topMenuColor;
}
public void setTopMenuColor(String color) {
topMenuColor = color;
}
public String getTextColor() {
return textColor;
}
public void setTextColor(String color) {
textColor = color;
}
public String getTrimColor() {
return trimColor;
}
public void setTrimColor(String color) {
trimColor = color;
}
public String getSelectionColor() {
return selectionColor;
}
public void setSelectionColor(String color) {
selectionColor = color;
}
}

View File

@@ -219,74 +219,8 @@ public class Gerrit implements EntryPoint {
/*-{ return path.replace(/%2F/g, "/"); }-*/;
});
RESOURCES.gwt_override().ensureInjected();
RESOURCES.css().ensureInjected();
final RootPanel gTopMenu = RootPanel.get("gerrit_topmenu");
final RootPanel gStarting = RootPanel.get("gerrit_startinggerrit");
final RootPanel gBody = RootPanel.get("gerrit_body");
final RootPanel gBottomMenu = RootPanel.get("gerrit_btmmenu");
gTopMenu.setStyleName(RESOURCES.css().gerritTopMenu());
gBody.setStyleName(RESOURCES.css().gerritBody());
initHostname();
Window.setTitle(M.windowTitle1(myHost));
initHistoryHooks();
populateBottomMenu(gBottomMenu);
final Grid menuLine = new Grid(1, 3);
menuLeft = new TabPanel();
menuRight = new LinkMenuBar();
searchPanel = new SearchPanel();
menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
menuLine.setStyleName(RESOURCES.css().topmenu());
gTopMenu.add(menuLine);
final FlowPanel menuRightPanel = new FlowPanel();
menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
menuRightPanel.add(menuRight);
menuRightPanel.add(searchPanel);
menuLine.setWidget(0, 0, menuLeft);
menuLine.setWidget(0, 1, new FlowPanel());
menuLine.setWidget(0, 2, menuRightPanel);
final CellFormatter fmt = menuLine.getCellFormatter();
fmt.setStyleName(0, 0, RESOURCES.css().topmenuTDmenu());
fmt.setStyleName(0, 1, RESOURCES.css().topmenuTDglue());
fmt.setStyleName(0, 2, RESOURCES.css().topmenuTDmenu());
siteHeader = RootPanel.get("gerrit_header");
siteFooter = RootPanel.get("gerrit_footer");
body = new ViewSite<Screen>() {
@Override
protected void onShowView(Screen view) {
final String token = view.getToken();
if (!token.equals(History.getToken())) {
History.newItem(token, false);
if (historyHooks != null) {
dispatchHistoryHooks(token);
}
}
super.onShowView(view);
view.onShowView();
}
};
gBody.add(body);
RpcStatus.INSTANCE = new RpcStatus(gTopMenu);
JsonUtil.addRpcStartHandler(RpcStatus.INSTANCE);
JsonUtil.addRpcCompleteHandler(RpcStatus.INSTANCE);
JsonUtil.setDefaultXsrfManager(new XsrfManager() {
@Override
public String getToken(JsonDefTarget proxy) {
return Cookies.getCookie(SESSION_COOKIE);
}
@Override
public void setToken(JsonDefTarget proxy, String token) {
// Ignore the request, we always rely upon the cookie.
}
});
final HostPageDataService hpd = GWT.create(HostPageDataService.class);
hpd.load(new GerritCallback<HostPageData>() {
@@ -296,7 +230,7 @@ public class Gerrit implements EntryPoint {
myAccount = result.account;
applyUserPreferences();
}
onModuleLoad2(gStarting);
onModuleLoad2();
}
});
}
@@ -362,11 +296,78 @@ public class Gerrit implements EntryPoint {
btmmenu.add(version);
}
private void onModuleLoad2(final RootPanel starting) {
refreshMenuBar();
private void onModuleLoad2() {
RESOURCES.gwt_override().ensureInjected();
RESOURCES.css().ensureInjected();
starting.getElement().getParentElement().removeChild(starting.getElement());
RootPanel.detachNow(starting);
final RootPanel gTopMenu = RootPanel.get("gerrit_topmenu");
final RootPanel gStarting = RootPanel.get("gerrit_startinggerrit");
final RootPanel gBody = RootPanel.get("gerrit_body");
final RootPanel gBottomMenu = RootPanel.get("gerrit_btmmenu");
gTopMenu.setStyleName(RESOURCES.css().gerritTopMenu());
gBody.setStyleName(RESOURCES.css().gerritBody());
final Grid menuLine = new Grid(1, 3);
menuLeft = new TabPanel();
menuRight = new LinkMenuBar();
searchPanel = new SearchPanel();
menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
menuLine.setStyleName(RESOURCES.css().topmenu());
gTopMenu.add(menuLine);
final FlowPanel menuRightPanel = new FlowPanel();
menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
menuRightPanel.add(menuRight);
menuRightPanel.add(searchPanel);
menuLine.setWidget(0, 0, menuLeft);
menuLine.setWidget(0, 1, new FlowPanel());
menuLine.setWidget(0, 2, menuRightPanel);
final CellFormatter fmt = menuLine.getCellFormatter();
fmt.setStyleName(0, 0, RESOURCES.css().topmenuTDmenu());
fmt.setStyleName(0, 1, RESOURCES.css().topmenuTDglue());
fmt.setStyleName(0, 2, RESOURCES.css().topmenuTDmenu());
siteHeader = RootPanel.get("gerrit_header");
siteFooter = RootPanel.get("gerrit_footer");
body = new ViewSite<Screen>() {
@Override
protected void onShowView(Screen view) {
final String token = view.getToken();
if (!token.equals(History.getToken())) {
History.newItem(token, false);
if (historyHooks != null) {
dispatchHistoryHooks(token);
}
}
super.onShowView(view);
view.onShowView();
}
};
gBody.add(body);
RpcStatus.INSTANCE = new RpcStatus(gTopMenu);
JsonUtil.addRpcStartHandler(RpcStatus.INSTANCE);
JsonUtil.addRpcCompleteHandler(RpcStatus.INSTANCE);
JsonUtil.setDefaultXsrfManager(new XsrfManager() {
@Override
public String getToken(JsonDefTarget proxy) {
return Cookies.getCookie(SESSION_COOKIE);
}
@Override
public void setToken(JsonDefTarget proxy, String token) {
// Ignore the request, we always rely upon the cookie.
}
});
gStarting.getElement().getParentElement().removeChild(
gStarting.getElement());
RootPanel.detachNow(gStarting);
initHistoryHooks();
populateBottomMenu(gBottomMenu);
refreshMenuBar();
History.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(final ValueChangeEvent<String> event) {

View File

@@ -14,6 +14,7 @@
*/
@external .gwt-Button;
@external .gwt-TabBar;
@external .gwt-TabBarFirst;
@external .gwt-TabBarItem;
@external .gwt-TabBarItem-selected;
@@ -34,10 +35,15 @@
@def black #000000;
@def white #ffffff;
@def trim-color #D4E9A9;
@def norm-font Arial Unicode MS, Arial, sans-serif;
@def mono-font 'Lucida Console', 'Lucida Sans Typewriter', Monaco, monospace;
@eval backgroundColor com.google.gerrit.client.Gerrit.getConfig().getBackgroundColor();
@eval topMenuColor com.google.gerrit.client.Gerrit.getConfig().getTopMenuColor();
@eval textColor com.google.gerrit.client.Gerrit.getConfig().getTextColor();;
@eval trimColor com.google.gerrit.client.Gerrit.getConfig().getTrimColor();
@eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
@sprite .greenCheckClass {
gwt-image: "greenCheck";
@@ -48,8 +54,17 @@
padding-top: 5px;
padding-left: 5px;
padding-right: 5px;
background: trim-color;
background: topMenuColor;
}
.gerritTopMenu .gwt-TabBar .gwt-TabBarItem,
.gerritTopMenu .gwt-TabBar .gwt-TabBarRest,
.gerritTopMenu .gwt-TabBar .gwt-TabPanelBottom {
background: topMenuColor;
}
.gerritTopMenu .gwt-TabBar .gwt-TabBarItem-selected {
background: selectionColor;
}
.gerritBody {
font-size: 11pt;
padding-left: 5px;
@@ -93,7 +108,7 @@
.blockHeader {
font-size: small;
font-weight: bold;
background: trim-color;
background: trimColor;
padding: 0.2em 0.2em 0.2em 0.5em;
}
@@ -208,16 +223,16 @@
}
.topmenuMenuLeft {
width: 300px;
border-left: 1px solid trim-color;
border-right: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-left: 1px solid topMenuColor;
border-right: 1px solid topMenuColor;
border-bottom: 1px solid topMenuColor;
}
.topmenuMenuLeft .gwt-TabBarFirst {
display: none;
}
.topmenuMenuLeft .gwt-TabBarItem {
margin: 0px;
background: trim-color;
background: topMenuColor;
padding-top: 0px;
padding-bottom: 1px;
padding-left: 1em;
@@ -225,14 +240,14 @@
border-right: 1px solid black;
}
.topmenuMenuLeft .gwt-TabBarItem-selected {
background: #ffffcc;
background: selectionColor;
}
.topmenuMenuLeft .gwt-TabBarRest {
background: trim-color;
background: topMenuColor;
padding-top: 0px;
}
.topmenuMenuLeft .gwt-TabPanelBottom {
background: trim-color;
background: topMenuColor;
border-top: none;
border-left: none;
border-right: none;
@@ -295,7 +310,7 @@
border: none;
padding: 10px;
width: 600px;
color: white;
color: backgroundColor;
font-size: 15px;
font-family: verdana;
}
@@ -356,15 +371,15 @@
width: 1px;
padding: 0px;
vertical-align: middle;
border-bottom: 1px solid trim-color;
border-bottom: 1px solid trimColor;
}
.changeTable .changeTypeCell {
width: 1px;
padding-left: 5px;
padding-right: 5px;
border-right: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-right: 1px solid trimColor;
border-bottom: 1px solid trimColor;
vertical-align: top;
}
@@ -391,14 +406,14 @@
}
.changeTable .leftMostCell {
border-left: 1px solid trim-color;
border-left: 1px solid trimColor;
}
.changeTable .dataCell {
padding-left: 5px;
padding-right: 5px;
border-right: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-right: 1px solid trimColor;
border-bottom: 1px solid trimColor;
}
.accountDashboard.changeTable tr {
@@ -409,15 +424,17 @@
color: #444444;
text-decoration: none;
}
.accountDashboard.changeTable .needsReview {
.accountDashboard.changeTable .needsReview,
.accountDashboard.changeTable .needsReview a {
font-weight: bold;
color: black;
background: white;
color: textColor;
background: backgroundColor;
}
.changeTable .activeRow,
.accountDashboard.changeTable .activeRow {
background: #ffffcc;
.accountDashboard.changeTable .activeRow,
.accountDashboard.changeTable .activeRow a {
background: selectionColor;
}
.changeTable .cID {
@@ -459,33 +476,33 @@
}
.changeTable .iconHeader {
border-top: 1px solid white;
border-bottom: 1px solid white;
background-color: trim-color;
border-top: 1px solid backgroundColor;
border-bottom: 1px solid backgroundColor;
background-color: trimColor;
}
.changeTable .dataHeader {
border: 1px solid white;
border: 1px solid backgroundColor;
padding: 2px 6px 1px;
background-color: trim-color;
background-color: trimColor;
font-style: italic;
white-space: nowrap;
color: black;
color: textColor;
}
.changeTable .sectionHeader {
border-top: 8px solid white;
border-top: 8px solid backgroundColor;
padding: 2px 6px 1px;
background-color: trim-color;
background-color: trimColor;
white-space: nowrap;
font-weight: bold;
color: black;
color: textColor;
}
.changeTable .emptySection {
border-left: 1px solid trim-color;
border-right: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-left: 1px solid trimColor;
border-right: 1px solid trimColor;
border-bottom: 1px solid trimColor;
font-style: italic;
padding-left: 25px;
}
@@ -515,6 +532,8 @@
width: 100%;
border-collapse: separate;
border-spacing: 0;
background: white;
color: black;
}
.patchContentTable td {
padding-top: 0;
@@ -598,13 +617,13 @@
border-bottom: 1px solid white;
}
.fileColumnHeader {
background: trim-color;
background: trimColor;
font-family: norm-font;
font-weight: bold;
text-align: center;
}
.lineNumber.fileColumnHeader {
border-bottom: 1px solid trim-color;
border-bottom: 1px solid trimColor;
}
.noLineLineNumber {
font-family: mono-font;
@@ -658,7 +677,7 @@
.patchContentTable .activeRow .iconCell,
.patchContentTable .activeRow .lineNumber {
background: #ffffcc;
background: selectionColor;
}
.patchContentTable .activeRow .iconCell,
.patchContentTable .activeRow .lineNumber,
@@ -725,13 +744,13 @@
}
.infoTable td {
border-left: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-left: 1px solid trimColor;
border-bottom: 1px solid trimColor;
padding: 2px 6px 1px;
}
.infoTable td.header {
background-color: trim-color;
background-color: trimColor;
font-weight: normal;
padding: 2px 4px 0 6px;
font-style: italic;
@@ -741,7 +760,7 @@
}
.rightmost {
border-right: 1px solid trim-color;
border-right: 1px solid trimColor;
}
.infoTable td.approvalrole {
@@ -780,18 +799,18 @@
.infoBlock td {
padding: 2px 4px 2px 6px;
border-right: 1px solid trim-color;
border-bottom: 1px solid trim-color;
border-right: 1px solid trimColor;
border-bottom: 1px solid trimColor;
text-align: left;
white-space: nowrap;
}
.infoBlock td.topmost {
border-top: 1px solid trim-color;
border-top: 1px solid trimColor;
}
.infoBlock td.header {
background-color: trim-color;
background-color: trimColor;
font-style: italic;
text-align: right;
}
@@ -801,7 +820,7 @@
}
.infoBlock td.bottomheader {
border-bottom: 1px solid trim-color;
border-bottom: 1px solid trimColor;
}
.infoBlock td.closedstate {
@@ -867,7 +886,7 @@ td.downloadLinkListCell {
padding: 0px;
}
.downloadLinkHeader {
background: trim-color;
background: trimColor;
white-space: nowrap;
border-bottom: 1px solid black;
}
@@ -882,7 +901,7 @@ td.downloadLinkListCell {
color: black;
text-decoration: none;
white-space: nowrap;
background: trim-color;
background: trimColor;
border-right: 1px solid black;
padding-left: 0.5em;
padding-right: 0.5em;
@@ -891,7 +910,7 @@ a:hover.downloadLink {
color: black;
}
.downloadLink_Active {
background: #ffffcc;
background: selectionColor;
}
.downloadLinkCopyLabel {
white-space: pre;
@@ -982,13 +1001,13 @@ a:hover.downloadLink {
.addSshKeyPanel {
margin-top: 10px;
background-color: trim-color;
background-color: trimColor;
padding: 5px 5px 5px 5px;
}
.sshHostKeyPanel {
margin-top: 10px;
border: 1px solid trim-color;
border: 1px solid trimColor;
padding: 5px 5px 5px 5px;
}
.sshHostKeyPanelHeading {
@@ -1084,7 +1103,7 @@ a:hover.downloadLink {
.publishCommentsScreen .approvalCategoryList {
margin-bottom: 10px;
margin-left: 10px;
background: trim-color;
background: trimColor;
width: 25em;
white-space: nowrap;
padding-top: 2px;
@@ -1139,7 +1158,7 @@ a:hover.downloadLink {
}
.abandonChangeDialog .abandonMessage {
margin-left: 10px;
background: trim-color;
background: trimColor;
padding: 5px 5px 5px 5px;
}
.abandonChangeDialog .abandonMessage textarea {
@@ -1156,7 +1175,7 @@ a:hover.downloadLink {
opacity: 0.90;
}
.patchBrowserPopupBody {
background: white;
background: backgroundColor;
margin: 4px;
opacity: 0.90;
}

View File

@@ -14,6 +14,7 @@
*/
@external .gwt-Button;
@external .gwt-DialogBox .dialogMiddleCenter;
@external .gwt-TabBar;
@external .gwt-TabBarFirst;
@external .gwt-TabBarItem;
@@ -22,8 +23,20 @@
@external .gwt-TabPanel;
@external .gwt-TabPanelBottom;
@def trim-color #D4E9A9;
@eval backgroundColor com.google.gerrit.client.Gerrit.getConfig().getBackgroundColor();
@eval textColor com.google.gerrit.client.Gerrit.getConfig().getTextColor();;
@eval trimColor com.google.gerrit.client.Gerrit.getConfig().getTrimColor();
@eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
body {
background: backgroundColor;
color: textColor;
}
.gwt-DialogBox .dialogMiddleCenter {
background: backgroundColor;
color: textColor;
}
.gwt-Button {
white-space: nowrap;
@@ -37,7 +50,7 @@
}
.gwt-TabBar .gwt-TabBarItem {
margin: 0px;
background: trim-color;
background: trimColor;
padding-top: 0.5em;
padding-bottom: 1px;
padding-left: 1em;
@@ -45,15 +58,15 @@
border-right: 1px solid black;
}
.gwt-TabBar .gwt-TabBarItem-selected {
background: #ffffcc;
background: selectionColor;
}
.gwt-TabBar .gwt-TabBarRest {
background: trim-color;
background: trimColor;
padding-top: 0.5em;
padding-bottom: 1px;
}
.gwt-TabBar .gwt-TabPanelBottom {
background: trim-color;
background: trimColor;
border-top: 1px solid black;
border-left: none;
border-right: none;

View File

@@ -142,9 +142,28 @@ class GerritConfigProvider implements Provider<GerritConfig> {
}
config.setCommentLinks(links);
config.setBackgroundColor(getThemeColor("backgroundColor", "#FFFFFF"));
config.setTextColor(getThemeColor("textColor", "#000000"));
config.setTrimColor(getThemeColor("trimColor", "#D4E9A9"));
config.setSelectionColor(getThemeColor("selectionColor", "#FFFFCC"));
config
.setTopMenuColor(getThemeColor("topMenuColor", config.getTrimColor()));
return config;
}
private String getThemeColor(String name, String defaultValue) {
String v = cfg.getString("theme", null, name);
if (v == null || v.isEmpty()) {
v = defaultValue;
}
if (!v.startsWith("#") && v.matches("^[0-9a-fA-F]{2,6}$")) {
v = "#" + v;
}
return v;
}
@Override
public GerritConfig get() {
try {