blob: 5a6e96c913a509bec9b7b3ff36625afce5e67b23 [file] [log] [blame]
// Copyright (C) 2008 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.client.changes;
import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.change.RelatedChanges;
import com.google.gerrit.client.change.RelatedChanges.ChangeAndCommit;
import com.google.gerrit.client.changes.ChangeInfo.CommitInfo;
import com.google.gerrit.client.diff.DiffApi;
import com.google.gerrit.client.diff.FileInfo;
import com.google.gerrit.client.projects.ConfigInfoCache;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.CommentPanel;
import com.google.gerrit.client.ui.ComplexDisclosurePanel;
import com.google.gerrit.client.ui.ExpandAllCommand;
import com.google.gerrit.client.ui.LinkMenuBar;
import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ChangeInfo;
import com.google.gerrit.common.data.SubmitTypeRecord;
import com.google.gerrit.extensions.common.ListChangesOption;
import com.google.gerrit.extensions.common.SubmitType;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.CommentVisibilityStrategy;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.Patch.ChangeType;
import com.google.gerrit.reviewdb.client.Patch.PatchType;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ChangeScreen extends Screen
implements ValueChangeHandler<ChangeDetail> {
private final Change.Id changeId;
private final PatchSet.Id openPatchSetId;
private ChangeDetailCache detailCache;
private com.google.gerrit.client.changes.ChangeInfo changeInfo;
private ChangeDescriptionBlock descriptionBlock;
private ApprovalTable approvals;
private IncludedInTable includedInTable;
private DisclosurePanel includedInPanel;
private ComplexDisclosurePanel dependenciesPanel;
private ChangeTable dependencies;
private ChangeTable.Section dependsOn;
private ChangeTable.Section neededBy;
private PatchSetsBlock patchSetsBlock;
private Panel comments;
private CommentLinkProcessor commentLinkProcessor;
private KeyCommandSet keysNavigation;
private KeyCommandSet keysAction;
private HandlerRegistration regNavigation;
private HandlerRegistration regAction;
private HandlerRegistration regDetailCache;
private Grid patchesGrid;
private ListBox patchesList;
/**
* The change id for which the old version history is valid.
*/
private static Change.Id currentChangeId;
/**
* Which patch set id is the diff base.
*/
private static PatchSet.Id diffBaseId;
public ChangeScreen(final Change.Id toShow) {
changeId = toShow;
openPatchSetId = null;
}
public ChangeScreen(final PatchSet.Id toShow) {
changeId = toShow.getParentKey();
openPatchSetId = toShow;
}
public ChangeScreen(final ChangeInfo c) {
this(c.getId());
}
@Override
protected void onLoad() {
super.onLoad();
detailCache.refresh();
}
@Override
protected void onUnload() {
if (regNavigation != null) {
regNavigation.removeHandler();
regNavigation = null;
}
if (regAction != null) {
regAction.removeHandler();
regAction = null;
}
if (regDetailCache != null) {
regDetailCache.removeHandler();
regDetailCache = null;
}
super.onUnload();
}
@Override
public void registerKeys() {
super.registerKeys();
regNavigation = GlobalKey.add(this, keysNavigation);
regAction = GlobalKey.add(this, keysAction);
if (openPatchSetId != null) {
patchSetsBlock.activate(openPatchSetId);
}
}
@Override
protected void onInitUI() {
super.onInitUI();
ChangeCache cache = ChangeCache.get(changeId);
detailCache = cache.getChangeDetailCache();
regDetailCache = detailCache.addValueChangeHandler(this);
addStyleName(Gerrit.RESOURCES.css().changeScreen());
addStyleName(Gerrit.RESOURCES.css().screenNoHeader());
keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
keysNavigation.add(new UpToListKeyCommand(0, 'u', Util.C.upToChangeList()));
keysNavigation.add(new ExpandCollapseDependencySectionKeyCommand(0, 'd', Util.C.expandCollapseDependencies()));
if (Gerrit.isSignedIn()) {
keysAction.add(new PublishCommentsKeyCommand(0, 'r', Util.C
.keyPublishComments()));
}
descriptionBlock = new ChangeDescriptionBlock(keysAction);
add(descriptionBlock);
approvals = new ApprovalTable();
add(approvals);
includedInPanel = new DisclosurePanel(Util.C.changeScreenIncludedIn());
includedInTable = new IncludedInTable(changeId);
includedInPanel.setContent(includedInTable);
add(includedInPanel);
dependencies = new ChangeTable() {
{
table.setWidth("auto");
}
};
dependsOn = new ChangeTable.Section(Util.C.changeScreenDependsOn());
dependsOn.setChangeRowFormatter(new ChangeTable.ChangeRowFormatter() {
@Override
public String getRowStyle(ChangeInfo c) {
if (! c.isLatest() || Change.Status.ABANDONED.equals(c.getStatus())) {
return Gerrit.RESOURCES.css().outdated();
}
return null;
}
@Override
public String getDisplayText(final ChangeInfo c, final String displayText) {
if (! c.isLatest()) {
return displayText + " [OUTDATED]";
}
return displayText;
}
});
neededBy = new ChangeTable.Section(Util.C.changeScreenNeededBy());
dependencies.addSection(dependsOn);
dependencies.addSection(neededBy);
dependenciesPanel = new ComplexDisclosurePanel(
Util.C.changeScreenDependencies(), false);
dependenciesPanel.setContent(dependencies);
add(dependenciesPanel);
patchesList = new ListBox();
patchesList.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
final int index = patchesList.getSelectedIndex();
final String selectedPatchSet = patchesList.getValue(index);
if (index == 0) {
diffBaseId = null;
} else {
diffBaseId = PatchSet.Id.parse(selectedPatchSet);
}
if (patchSetsBlock != null) {
patchSetsBlock.refresh(diffBaseId);
}
}
});
patchesGrid = new Grid(1, 2);
patchesGrid.setStyleName(Gerrit.RESOURCES.css().selectPatchSetOldVersion());
patchesGrid.setText(0, 0, Util.C.referenceVersion());
patchesGrid.setWidget(0, 1, patchesList);
add(patchesGrid);
patchSetsBlock = new PatchSetsBlock();
add(patchSetsBlock);
comments = new FlowPanel();
comments.setStyleName(Gerrit.RESOURCES.css().changeComments());
add(comments);
}
private void displayTitle(final Change.Key changeId, final String subject) {
final StringBuilder titleBuf = new StringBuilder();
if (LocaleInfo.getCurrentLocale().isRTL()) {
if (subject != null) {
titleBuf.append(subject);
titleBuf.append(" :");
}
titleBuf.append(Util.M.changeScreenTitleId(changeId.abbreviate()));
} else {
titleBuf.append(Util.M.changeScreenTitleId(changeId.abbreviate()));
if (subject != null) {
titleBuf.append(": ");
titleBuf.append(subject);
}
}
setPageTitle(titleBuf.toString());
setHeaderVisible(false);
}
@Override
public void onValueChange(final ValueChangeEvent<ChangeDetail> event) {
if (isAttached() && isLastValueChangeHandler()) {
// Until this screen is fully migrated to the new API, these calls must
// happen sequentially after the ChangeDetail lookup, because we can't
// start an async get at the source of every call that might trigger a
// value change.
CallbackGroup cbs1 = new CallbackGroup();
final CallbackGroup cbs2 = new CallbackGroup();
final PatchSet.Id psId = event.getValue().getCurrentPatchSet().getId();
final Map<String, Patch> patches = new HashMap<>();
String revId =
event.getValue().getCurrentPatchSetDetail().getInfo().getRevId();
if (event.getValue().getChange().getStatus().isOpen()) {
ChangeApi.revision(changeId.get(), "current")
.view("submit_type")
.get(cbs1.add(new GerritCallback<NativeString>() {
@Override
public void onSuccess(NativeString result) {
event.getValue().setSubmitTypeRecord(SubmitTypeRecord.OK(
SubmitType.valueOf(result.asString())));
}
public void onFailure(Throwable caught) {}
}));
}
if (Gerrit.isSignedIn()) {
ChangeApi.revision(changeId.get(), "" + psId.get())
.view("related")
.get(cbs1.add(new AsyncCallback<RelatedChanges.RelatedInfo>() {
@Override
public void onSuccess(RelatedChanges.RelatedInfo info) {
if (info.changes() != null) {
dependsOn(info);
neededBy(info);
}
}
private void dependsOn(RelatedChanges.RelatedInfo info) {
ChangeAndCommit self = null;
Map<String, ChangeAndCommit> m = new HashMap<>();
for (int i = 0; i < info.changes().length(); i++) {
ChangeAndCommit c = info.changes().get(i);
if (changeId.equals(c.legacy_id())) {
self = c;
}
if (c.commit() != null && c.commit().commit() != null) {
m.put(c.commit().commit(), c);
}
}
if (self != null && self.commit() != null
&& self.commit().parents() != null) {
List<ChangeInfo> d = new ArrayList<>();
for (CommitInfo p : Natives.asList(self.commit().parents())) {
ChangeAndCommit pc = m.get(p.commit());
if (pc != null && pc.has_change_number()) {
ChangeInfo i = new ChangeInfo();
load(pc, i);
d.add(i);
}
}
event.getValue().setDependsOn(d);
}
}
private void neededBy(RelatedChanges.RelatedInfo info) {
Set<String> mine = new HashSet<>();
for (PatchSet ps : event.getValue().getPatchSets()) {
mine.add(ps.getRevision().get());
}
List<ChangeInfo> n = new ArrayList<>();
for (int i = 0; i < info.changes().length(); i++) {
ChangeAndCommit c = info.changes().get(i);
if (c.has_change_number()
&& c.commit() != null
&& c.commit().parents() != null) {
for (int j = 0; j < c.commit().parents().length(); j++) {
CommitInfo p = c.commit().parents().get(j);
if (mine.contains(p.commit())) {
ChangeInfo u = new ChangeInfo();
load(c, u);
n.add(u);
break;
}
}
}
}
event.getValue().setNeededBy(n);
}
private void load(final ChangeAndCommit pc, final ChangeInfo i) {
RestApi call = ChangeApi.change(pc.legacy_id().get());
ChangeList.addOptions(call, EnumSet.of(
ListChangesOption.DETAILED_ACCOUNTS,
ListChangesOption.CURRENT_REVISION));
call.get(cbs2.add(new AsyncCallback<
com.google.gerrit.client.changes.ChangeInfo>() {
public void onFailure(Throwable caught) {}
public void onSuccess(
com.google.gerrit.client.changes.ChangeInfo result) {
i.set(ChangeDetailCache.toChange(result),
pc.patch_set_id());
i.setStarred(result.starred());
event.getValue().getAccounts()
.merge(ChangeDetailCache.users(result));
}}));
}
public void onFailure(Throwable caught) {}
}));
ChangeApi.revision(changeId.get(), revId)
.view("files")
.addParameterTrue("reviewed")
.get(cbs1.add(new AsyncCallback<JsArrayString>() {
@Override
public void onSuccess(JsArrayString result) {
for(int i = 0; i < result.length(); i++) {
String path = result.get(i);
Patch p = patches.get(path);
if (p == null) {
p = new Patch(new Patch.Key(psId, path));
patches.put(path, p);
}
p.setReviewedByCurrentUser(true);
}
}
public void onFailure(Throwable caught) {}
}));
final Set<PatchSet.Id> withDrafts = new HashSet<>();
event.getValue().setPatchSetsWithDraftComments(withDrafts);
for (PatchSet ps : event.getValue().getPatchSets()) {
if (!ps.getId().equals(psId)) {
final PatchSet.Id id = ps.getId();
ChangeApi.revision(changeId.get(), "" + id.get())
.view("drafts")
.get(cbs1.add(new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
@Override
public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
if (!result.isEmpty()) {
withDrafts.add(id);
}
}
public void onFailure(Throwable caught) {}
}));
}
}
ChangeApi.revision(changeId.get(), "" + psId.get())
.view("drafts")
.get(cbs1.add(new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
@Override
public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
for (String path : result.keySet()) {
Patch p = patches.get(path);
if (p == null) {
p = new Patch(new Patch.Key(psId, path));
patches.put(path, p);
}
p.setDraftCount(result.get(path).length());
}
if (!result.isEmpty()) {
withDrafts.add(psId);
}
}
public void onFailure(Throwable caught) {}
}));
}
ChangeApi.revision(changeId.get(), revId)
.view("comments")
.get(cbs1.add(new AsyncCallback<NativeMap<JsArray<CommentInfo>>>() {
@Override
public void onSuccess(NativeMap<JsArray<CommentInfo>> result) {
for (String path : result.keySet()) {
Patch p = patches.get(path);
if (p == null) {
p = new Patch(new Patch.Key(psId, path));
patches.put(path, p);
}
p.setCommentCount(result.get(path).length());
}
}
public void onFailure(Throwable caught) {}
}));
DiffApi.list(changeId.get(), null, revId,
new AsyncCallback<NativeMap<FileInfo>>() {
@Override
public void onSuccess(NativeMap<FileInfo> result) {
JsArray<FileInfo> fileInfos = result.values();
FileInfo.sortFileInfoByPath(fileInfos);
List<Patch> list = new ArrayList<>(fileInfos.length());
for (FileInfo f : Natives.asList(fileInfos)) {
Patch p = patches.get(f.path());
if (p == null) {
p = new Patch(new Patch.Key(psId, f.path()));
patches.put(f.path(), p);
}
p.setInsertions(f.lines_inserted());
p.setDeletions(f.lines_deleted());
p.setPatchType(f.binary() ? PatchType.BINARY : PatchType.UNIFIED);
if (f.status() == null) {
p.setChangeType(ChangeType.MODIFIED);
} else {
p.setChangeType(ChangeType.forCode(f.status().charAt(0)));
}
list.add(p);
}
event.getValue().getCurrentPatchSetDetail().setPatches(list);
}
public void onFailure(Throwable caught) {}
});
ConfigInfoCache.get(
event.getValue().getChange().getProject(),
cbs1.add(new GerritCallback<ConfigInfoCache.Entry>() {
@Override
public void onSuccess(ConfigInfoCache.Entry result) {
commentLinkProcessor = result.getCommentLinkProcessor();
setTheme(result.getTheme());
}
@Override
public void onFailure(Throwable caught) {
// Handled by last callback's onFailure.
}
}));
ChangeApi.detail(changeId.get(), cbs1.addFinal(
new GerritCallback<com.google.gerrit.client.changes.ChangeInfo>() {
@Override
public void onSuccess(
com.google.gerrit.client.changes.ChangeInfo result) {
changeInfo = result;
cbs2.addFinal(new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
display(event.getValue());
}
public void onFailure(Throwable caught) {}
}).onSuccess(null);
}
}));
}
}
// Find the last attached screen.
// When DialogBox is used (i. e. CommentedActionDialog) then the original
// ChangeScreen is still in attached state.
// Use here the fact, that the handlers (ChangeScreen) are sorted.
private boolean isLastValueChangeHandler() {
int count = detailCache.getHandlerCount();
return count > 0 && detailCache.getHandler(count - 1) == this;
}
private void display(final ChangeDetail detail) {
displayTitle(detail.getChange().getKey(), detail.getChange().getSubject());
discardDiffBaseIfNotApplicable(detail.getChange().getId());
if (Status.MERGED == detail.getChange().getStatus()) {
includedInPanel.setVisible(true);
includedInPanel.addOpenHandler(includedInTable);
} else {
includedInPanel.setVisible(false);
}
dependencies.setAccountInfoCache(detail.getAccounts());
descriptionBlock.display(detail,
detail.isStarred(),
detail.canEditCommitMessage(),
detail.getCurrentPatchSetDetail().getInfo(),
detail.getAccounts(), detail.getSubmitTypeRecord(),
commentLinkProcessor);
dependsOn.display(detail.getDependsOn());
neededBy.display(detail.getNeededBy());
approvals.display(changeInfo);
patchesList.clear();
if (detail.getCurrentPatchSetDetail().getInfo().getParents().size() > 1) {
patchesList.addItem(Util.C.autoMerge());
} else {
patchesList.addItem(Util.C.baseDiffItem());
}
for (PatchSet pId : detail.getPatchSets()) {
patchesList.addItem(Util.M.patchSetHeader(pId.getPatchSetId()), pId
.getId().toString());
}
if (diffBaseId != null) {
patchesList.setSelectedIndex(diffBaseId.get());
}
patchSetsBlock.display(detail, diffBaseId);
addComments(detail);
// If any dependency change is still open, or is outdated,
// or the change is needed by a change that is new or submitted,
// show our dependency list.
//
boolean depsOpen = false;
int outdated = 0;
if (!detail.getChange().getStatus().isClosed()) {
final List<ChangeInfo> dependsOn = detail.getDependsOn();
if (dependsOn != null) {
for (final ChangeInfo ci : dependsOn) {
if (!ci.isLatest()) {
depsOpen = true;
outdated++;
} else if (ci.getStatus() != Change.Status.MERGED) {
depsOpen = true;
}
}
}
}
final List<ChangeInfo> neededBy = detail.getNeededBy();
if (neededBy != null) {
for (final ChangeInfo ci : neededBy) {
if ((ci.getStatus() == Change.Status.NEW) ||
(ci.getStatus() == Change.Status.SUBMITTED) ||
(ci.getStatus() == Change.Status.DRAFT)) {
depsOpen = true;
}
}
}
dependenciesPanel.setOpen(depsOpen);
dependenciesPanel.getHeader().clear();
if (outdated > 0) {
dependenciesPanel.getHeader().add(new InlineLabel(
Util.M.outdatedHeader(outdated)));
}
if (!isCurrentView()) {
display();
}
patchSetsBlock.setRegisterKeys(true);
}
private static void discardDiffBaseIfNotApplicable(final Change.Id toShow) {
if (currentChangeId != null && !currentChangeId.equals(toShow)) {
diffBaseId = null;
}
currentChangeId = toShow;
}
private void addComments(final ChangeDetail detail) {
comments.clear();
final AccountInfoCache accts = detail.getAccounts();
final List<ChangeMessage> msgList = detail.getMessages();
HorizontalPanel title = new HorizontalPanel();
title.setWidth("100%");
title.add(new Label(Util.C.changeScreenComments()));
if (msgList.size() > 1) {
title.add(messagesMenuBar());
}
title.setStyleName(Gerrit.RESOURCES.css().blockHeader());
comments.add(title);
final long AGE = 7 * 24 * 60 * 60 * 1000L;
final Timestamp aged = new Timestamp(System.currentTimeMillis() - AGE);
CommentVisibilityStrategy commentVisibilityStrategy =
CommentVisibilityStrategy.EXPAND_RECENT;
if (Gerrit.isSignedIn()) {
commentVisibilityStrategy = Gerrit.getUserAccount()
.getGeneralPreferences().getCommentVisibilityStrategy();
}
for (int i = 0; i < msgList.size(); i++) {
final ChangeMessage msg = msgList.get(i);
AccountInfo author;
if (msg.getAuthor() != null) {
author = FormatUtil.asInfo(accts.get(msg.getAuthor()));
} else {
author = AccountInfo.create(0, Util.C.messageNoAuthor(), null, null);
}
boolean isRecent;
if (i == msgList.size() - 1) {
isRecent = true;
} else {
// TODO Instead of opening messages by strict age, do it by "unread"?
isRecent = msg.getWrittenOn().after(aged);
}
final CommentPanel cp = new CommentPanel(author, msg.getWrittenOn(),
msg.getMessage(), commentLinkProcessor);
cp.setRecent(isRecent);
cp.addStyleName(Gerrit.RESOURCES.css().commentPanelBorder());
if (i == msgList.size() - 1) {
cp.addStyleName(Gerrit.RESOURCES.css().commentPanelLast());
}
boolean isOpen = false;
switch (commentVisibilityStrategy) {
case COLLAPSE_ALL:
break;
case EXPAND_ALL:
isOpen = true;
break;
case EXPAND_MOST_RECENT:
isOpen = i == msgList.size() - 1;
break;
case EXPAND_RECENT:
default:
isOpen = isRecent;
break;
}
cp.setOpen(isOpen);
comments.add(cp);
}
final Button b = new Button(Util.C.changeScreenAddComment());
b.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
PatchSet.Id currentPatchSetId = patchSetsBlock.getCurrentPatchSet().getId();
Gerrit.display(Dispatcher.toPublish(currentPatchSetId));
}
});
comments.add(b);
comments.setVisible(msgList.size() > 0);
}
private LinkMenuBar messagesMenuBar() {
final Panel c = comments;
final LinkMenuBar menuBar = new LinkMenuBar();
menuBar.addItem(Util.C.messageExpandRecent(), new ExpandAllCommand(c, true) {
@Override
protected void expand(final CommentPanel w) {
w.setOpen(w.isRecent());
}
});
menuBar.addItem(Util.C.messageExpandAll(), new ExpandAllCommand(c, true));
menuBar.addItem(Util.C.messageCollapseAll(), new ExpandAllCommand(c, false));
menuBar.addStyleName(Gerrit.RESOURCES.css().commentPanelMenuBar());
return menuBar;
}
public class UpToListKeyCommand extends KeyCommand {
public UpToListKeyCommand(int mask, char key, String help) {
super(mask, key, help);
}
@Override
public void onKeyPress(final KeyPressEvent event) {
Gerrit.displayLastChangeList();
}
}
public class ExpandCollapseDependencySectionKeyCommand extends KeyCommand {
public ExpandCollapseDependencySectionKeyCommand(int mask, char key, String help) {
super(mask, key, help);
}
@Override
public void onKeyPress(KeyPressEvent event) {
dependenciesPanel.setOpen(!dependenciesPanel.isOpen());
}
}
public class PublishCommentsKeyCommand extends NeedsSignInKeyCommand {
public PublishCommentsKeyCommand(int mask, char key, String help) {
super(mask, key, help);
}
@Override
public void onKeyPress(final KeyPressEvent event) {
PatchSet.Id currentPatchSetId = patchSetsBlock.getCurrentPatchSet().getId();
Gerrit.display(Dispatcher.toPublish(currentPatchSetId));
}
}
}