Allow plugins to extend Gerrit screens with GWT controls
Gerrit screens can now define extension points where plugins can add GWT panels with custom controls. For now only 2 extension points are provided, one on change screen below the change info block and one on the user profile screen below the grid with the profile data. Gerrit screens can also pass some values to the plugin panels, e.g. the change screen passes the numeric change ID to the plugin panels. Plugins must register extension panels early at plugin module load. The way how extension panels are registered and embedded in Gerrit screens is similar to how plugins can add custom screens. Errors on loading the extension panels are ignored and logged to the browser console so that in case of errors the Gerrit screen still loads without the extension panels. In the cookbook plugin, examples for both UI extension points were implemented. Change-Id: I5e0c93b2ab0cd130dd35ee8b32c37db6ba251d48 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
|
||||
package com.google.gerrit.plugin.client;
|
||||
|
||||
import com.google.gerrit.client.GerritUiExtensionPoint;
|
||||
import com.google.gerrit.plugin.client.extension.Panel;
|
||||
import com.google.gerrit.plugin.client.screen.Screen;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
@@ -91,6 +93,20 @@ public final class Plugin extends JavaScriptObject {
|
||||
private final native void screenRegex(String p, JavaScriptObject e)
|
||||
/*-{ this.screen(new $wnd.RegExp(p), e) }-*/;
|
||||
|
||||
/**
|
||||
* Register a panel for a UI extension point.
|
||||
*
|
||||
* @param extensionPoint the UI extension point for which the panel should be
|
||||
* registered.
|
||||
* @param entry callback function invoked to create the panel widgets.
|
||||
*/
|
||||
public final void panel(GerritUiExtensionPoint extensionPoint, Panel.EntryPoint entry) {
|
||||
panel(extensionPoint.name(), wrap(entry));
|
||||
}
|
||||
|
||||
private final native void panel(String i, JavaScriptObject e)
|
||||
/*-{ this.panel(i, e) }-*/;
|
||||
|
||||
protected Plugin() {
|
||||
}
|
||||
|
||||
@@ -105,4 +121,11 @@ public final class Plugin extends JavaScriptObject {
|
||||
@com.google.gerrit.plugin.client.screen.Screen::new(Lcom/google/gerrit/plugin/client/screen/Screen$Context;)(c));
|
||||
});
|
||||
}-*/;
|
||||
|
||||
private static final native JavaScriptObject wrap(Panel.EntryPoint b) /*-{
|
||||
return $entry(function(c){
|
||||
b.@com.google.gerrit.plugin.client.extension.Panel.EntryPoint::onLoad(Lcom/google/gerrit/plugin/client/extension/Panel;)(
|
||||
@com.google.gerrit.plugin.client.extension.Panel::new(Lcom/google/gerrit/plugin/client/extension/Panel$Context;)(c));
|
||||
});
|
||||
}-*/;
|
||||
}
|
||||
|
@@ -0,0 +1,104 @@
|
||||
// Copyright (C) 2015 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.plugin.client.extension;
|
||||
|
||||
import com.google.gerrit.client.GerritUiExtensionPoint;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
|
||||
/**
|
||||
* Panel that extends a Gerrit core screen contributed by this plugin.
|
||||
*
|
||||
* Panel should be registered early at module load:
|
||||
*
|
||||
* <pre>
|
||||
* @Override
|
||||
* public void onModuleLoad() {
|
||||
* Plugin.get().panel(GerritUiExtensionPoint.CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK,
|
||||
* new Panel.EntryPoint() {
|
||||
* @Override
|
||||
* public void onLoad(Panel panel) {
|
||||
* panel.setWidget(new Label("World"));
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public class Panel extends SimplePanel {
|
||||
/** Initializes a panel for display. */
|
||||
public interface EntryPoint {
|
||||
/**
|
||||
* Invoked when the panel has been created.
|
||||
* <p>
|
||||
* The implementation should create a single widget to define the content of
|
||||
* this panel and add it to the passed panel instance.
|
||||
* <p>
|
||||
* To use multiple widgets, compose them in panels such as {@code FlowPanel}
|
||||
* and add only the top level widget to the panel.
|
||||
* <p>
|
||||
* The panel is already attached to the browser DOM.
|
||||
* Any widgets added to the screen will immediately receive {@code onLoad()}.
|
||||
* GWT will fire {@code onUnload()} when the panel is removed from the UI,
|
||||
* generally caused by the user navigating to another screen.
|
||||
*
|
||||
* @param panel panel that will contain the panel widget.
|
||||
*/
|
||||
public void onLoad(Panel panel);
|
||||
}
|
||||
|
||||
static final class Context extends JavaScriptObject {
|
||||
final native Element body() /*-{ return this.body }-*/;
|
||||
|
||||
final native String get(String k) /*-{ return this.p[k]; }-*/;
|
||||
final native int getInt(String k, int d) /*-{
|
||||
return this.p.hasOwnProperty(k) ? this.p[k] : d
|
||||
}-*/;
|
||||
final native int getBoolean(String k, boolean d) /*-{
|
||||
return this.p.hasOwnProperty(k) ? this.p[k] : d
|
||||
}-*/;
|
||||
|
||||
|
||||
final native void detach(Panel p) /*-{
|
||||
this.onUnload($entry(function(){
|
||||
p.@com.google.gwt.user.client.ui.Widget::onDetach()();
|
||||
}));
|
||||
}-*/;
|
||||
|
||||
protected Context() {
|
||||
}
|
||||
}
|
||||
|
||||
private final Context ctx;
|
||||
|
||||
Panel(Context ctx) {
|
||||
super(ctx.body());
|
||||
this.ctx = ctx;
|
||||
onAttach();
|
||||
ctx.detach(this);
|
||||
}
|
||||
|
||||
public String get(GerritUiExtensionPoint.Key key) {
|
||||
return ctx.get(key.name());
|
||||
}
|
||||
|
||||
public int getInt(GerritUiExtensionPoint.Key key, int defaultValue) {
|
||||
return ctx.getInt(key.name(), defaultValue);
|
||||
}
|
||||
|
||||
public int getBoolean(GerritUiExtensionPoint.Key key, boolean defaultValue) {
|
||||
return ctx.getBoolean(key.name(), defaultValue);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user