Remove old unified diff screen
The functionality of skipping deleted or uncommented files when navigating using the prev / next links will be implemented in a following change. Note that the diff preferences dialog box currently doesn't render these settings. Change-Id: If7549cdd986a5e5dd26b1cbc4b4cfdb7ca48f880
This commit is contained in:

committed by
Michael Zhou

parent
7a9dca2b33
commit
ff4ee1a494
@@ -1,33 +0,0 @@
|
||||
// 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.common.data;
|
||||
|
||||
import com.google.gerrit.common.audit.Audit;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.common.RemoteJsonService;
|
||||
import com.google.gwtjsonrpc.common.RpcImpl;
|
||||
import com.google.gwtjsonrpc.common.RpcImpl.Version;
|
||||
|
||||
@RpcImpl(version = Version.V2_0)
|
||||
public interface ChangeDetailService extends RemoteJsonService {
|
||||
@Audit
|
||||
void patchSetDetail(PatchSet.Id key, AsyncCallback<PatchSetDetail> callback);
|
||||
|
||||
@Audit
|
||||
void patchSetDetail2(PatchSet.Id baseId, PatchSet.Id key,
|
||||
DiffPreferencesInfo diffPrefs, AsyncCallback<PatchSetDetail> callback);
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
// 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.common.data;
|
||||
|
||||
import com.google.gerrit.common.audit.Audit;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.common.RemoteJsonService;
|
||||
import com.google.gwtjsonrpc.common.RpcImpl;
|
||||
import com.google.gwtjsonrpc.common.RpcImpl.Version;
|
||||
|
||||
@RpcImpl(version = Version.V2_0)
|
||||
public interface PatchDetailService extends RemoteJsonService {
|
||||
@Audit
|
||||
void patchScript(Patch.Key key, PatchSet.Id a, PatchSet.Id b,
|
||||
DiffPreferencesInfo diffPrefs, AsyncCallback<PatchScript> callback);
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
// 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.common.data;
|
||||
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.PatchSetInfo;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PatchSetDetail {
|
||||
protected PatchSet patchSet;
|
||||
protected PatchSetInfo info;
|
||||
protected List<Patch> patches;
|
||||
protected Project.NameKey project;
|
||||
|
||||
public PatchSetDetail() {
|
||||
}
|
||||
|
||||
public PatchSet getPatchSet() {
|
||||
return patchSet;
|
||||
}
|
||||
|
||||
public void setPatchSet(final PatchSet ps) {
|
||||
patchSet = ps;
|
||||
}
|
||||
|
||||
public PatchSetInfo getInfo() {
|
||||
return info;
|
||||
}
|
||||
|
||||
public void setInfo(final PatchSetInfo i) {
|
||||
info = i;
|
||||
}
|
||||
|
||||
public List<Patch> getPatches() {
|
||||
return patches;
|
||||
}
|
||||
|
||||
public void setPatches(final List<Patch> p) {
|
||||
patches = p;
|
||||
}
|
||||
|
||||
public Project.NameKey getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public void setProject(final Project.NameKey p) {
|
||||
project = p;
|
||||
}
|
||||
}
|
@@ -15,7 +15,7 @@
|
||||
package com.google.gerrit.extensions.client;
|
||||
|
||||
public enum GerritTopMenu {
|
||||
ALL, MY, DIFFERENCES, PROJECTS, PEOPLE, PLUGINS, DOCUMENTATION;
|
||||
ALL, MY, PROJECTS, PEOPLE, PLUGINS, DOCUMENTATION;
|
||||
|
||||
public final String menuName;
|
||||
|
||||
|
@@ -88,7 +88,6 @@ import com.google.gerrit.client.documentation.DocScreen;
|
||||
import com.google.gerrit.client.editor.EditScreen;
|
||||
import com.google.gerrit.client.groups.GroupApi;
|
||||
import com.google.gerrit.client.groups.GroupInfo;
|
||||
import com.google.gerrit.client.patches.UnifiedPatchScreen;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.rpc.RestApi;
|
||||
import com.google.gerrit.client.ui.Screen;
|
||||
@@ -481,8 +480,6 @@ public class Dispatcher {
|
||||
codemirror(token, baseId, id, side, line, false);
|
||||
} else if ("unified".equals(panel)) {
|
||||
unified(token, baseId, id, side, line);
|
||||
} else if ("unified1".equals(panel)) {
|
||||
unified1(token, baseId, id);
|
||||
} else if ("edit".equals(panel)) {
|
||||
codemirror(token, null, id, side, line, true);
|
||||
} else {
|
||||
@@ -505,18 +502,6 @@ public class Dispatcher {
|
||||
});
|
||||
}
|
||||
|
||||
private static void unified1(final String token,
|
||||
final PatchSet.Id baseId,
|
||||
final Patch.Key id) {
|
||||
GWT.runAsync(new AsyncSplit(token) {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
UnifiedPatchScreen.TopView top = Gerrit.getPatchScreenTopView();
|
||||
Gerrit.display(token, new UnifiedPatchScreen(id, top, baseId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void codemirror(final String token, final PatchSet.Id baseId,
|
||||
final Patch.Key id, final DisplaySide side, final int line,
|
||||
final boolean edit) {
|
||||
|
@@ -37,7 +37,6 @@ import com.google.gerrit.client.info.ServerInfo;
|
||||
import com.google.gerrit.client.info.TopMenu;
|
||||
import com.google.gerrit.client.info.TopMenuItem;
|
||||
import com.google.gerrit.client.info.TopMenuList;
|
||||
import com.google.gerrit.client.patches.UnifiedPatchScreen;
|
||||
import com.google.gerrit.client.rpc.CallbackGroup;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.rpc.Natives;
|
||||
@@ -56,7 +55,6 @@ import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gwt.aria.client.Roles;
|
||||
import com.google.gwt.core.client.EntryPoint;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.AnchorElement;
|
||||
import com.google.gwt.dom.client.Document;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
@@ -138,7 +136,6 @@ public class Gerrit implements EntryPoint {
|
||||
private static SearchPanel searchPanel;
|
||||
private static final Dispatcher dispatcher = new Dispatcher();
|
||||
private static ViewSite<Screen> body;
|
||||
private static UnifiedPatchScreen patchScreen;
|
||||
private static String lastChangeListToken;
|
||||
private static String lastViewToken;
|
||||
|
||||
@@ -152,13 +149,6 @@ public class Gerrit implements EntryPoint {
|
||||
Window.Location.reload();
|
||||
}
|
||||
|
||||
public static UnifiedPatchScreen.TopView getPatchScreenTopView() {
|
||||
if (patchScreen == null) {
|
||||
return null;
|
||||
}
|
||||
return patchScreen.getTopView();
|
||||
}
|
||||
|
||||
public static void displayLastChangeList() {
|
||||
if (lastChangeListToken != null) {
|
||||
display(lastChangeListToken);
|
||||
@@ -214,26 +204,6 @@ public class Gerrit implements EntryPoint {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update any top level menus which can vary based on the view which was
|
||||
* loaded.
|
||||
* @param view the loaded view.
|
||||
*/
|
||||
public static void updateMenus(Screen view) {
|
||||
LinkMenuBar diffBar = menuBars.get(GerritTopMenu.DIFFERENCES.menuName);
|
||||
if (view instanceof UnifiedPatchScreen) {
|
||||
patchScreen = (UnifiedPatchScreen) view;
|
||||
menuLeft.setVisible(diffBar, true);
|
||||
menuLeft.selectTab(menuLeft.getWidgetIndex(diffBar));
|
||||
} else {
|
||||
if (patchScreen != null && menuLeft.getSelectedWidget() == diffBar) {
|
||||
menuLeft.selectTab(isSignedIn() ? 1 : 0);
|
||||
}
|
||||
patchScreen = null;
|
||||
menuLeft.setVisible(diffBar, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void selectMenu(LinkMenuBar bar) {
|
||||
menuLeft.selectTab(menuLeft.getWidgetIndex(bar));
|
||||
}
|
||||
@@ -718,15 +688,6 @@ public class Gerrit implements EntryPoint {
|
||||
menuLeft.selectTab(0);
|
||||
}
|
||||
|
||||
patchScreen = null;
|
||||
LinkMenuBar diffBar = new LinkMenuBar();
|
||||
menuBars.put(GerritTopMenu.DIFFERENCES.menuName, diffBar);
|
||||
menuLeft.addInvisible(diffBar, C.menuDiff());
|
||||
addDiffLink(diffBar, C.menuDiffCommit(), UnifiedPatchScreen.TopView.COMMIT);
|
||||
addDiffLink(diffBar, C.menuDiffPreferences(), UnifiedPatchScreen.TopView.PREFERENCES);
|
||||
addDiffLink(diffBar, C.menuDiffPatchSets(), UnifiedPatchScreen.TopView.PATCH_SETS);
|
||||
addDiffLink(diffBar, C.menuDiffFiles(), UnifiedPatchScreen.TopView.FILES);
|
||||
|
||||
final LinkMenuBar projectsBar = new LinkMenuBar();
|
||||
menuBars.put(GerritTopMenu.PROJECTS.menuName, projectsBar);
|
||||
addLink(projectsBar, C.menuProjectsList(), PageLinks.ADMIN_PROJECTS);
|
||||
@@ -1018,19 +979,6 @@ public class Gerrit implements EntryPoint {
|
||||
m.insertItem(new LinkMenuItem(text, historyToken), beforeIndex);
|
||||
}
|
||||
|
||||
private static void addDiffLink(final LinkMenuBar m, final String text,
|
||||
final UnifiedPatchScreen.TopView tv) {
|
||||
m.addItem(new LinkMenuItem(text, "") {
|
||||
@Override
|
||||
public void go() {
|
||||
if (patchScreen != null) {
|
||||
patchScreen.setTopView(tv);
|
||||
}
|
||||
AnchorElement.as(getElement()).blur();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static LinkMenuItem addProjectLink(LinkMenuBar m, TopMenuItem item) {
|
||||
LinkMenuItem i = new ProjectLinkMenuItem(item.getName(), item.getUrl()) {
|
||||
@Override
|
||||
|
@@ -111,9 +111,6 @@ public interface ChangeConstants extends Constants {
|
||||
String reviewed();
|
||||
String submitFailed();
|
||||
|
||||
String diffAllSideBySide();
|
||||
String diffAllUnified();
|
||||
|
||||
String votable();
|
||||
|
||||
String pushCertMissing();
|
||||
|
@@ -94,9 +94,6 @@ nextPatchLinkIcon = ⇨
|
||||
reviewed = Reviewed
|
||||
submitFailed = Submit Failed
|
||||
|
||||
diffAllSideBySide = All Side-by-Side
|
||||
diffAllUnified = All Unified
|
||||
|
||||
votable = Votable:
|
||||
|
||||
pushCertMissing = This patch set was created without a push certificate
|
||||
|
@@ -477,8 +477,8 @@ abstract class DiffScreen extends Screen {
|
||||
new NoOpKeyCommand(0, 'j', PatchUtil.C.lineNext()),
|
||||
new NoOpKeyCommand(0, 'k', PatchUtil.C.linePrev()));
|
||||
keysNavigation.add(
|
||||
new NoOpKeyCommand(0, 'n', PatchUtil.C.chunkNext2()),
|
||||
new NoOpKeyCommand(0, 'p', PatchUtil.C.chunkPrev2()));
|
||||
new NoOpKeyCommand(0, 'n', PatchUtil.C.chunkNext()),
|
||||
new NoOpKeyCommand(0, 'p', PatchUtil.C.chunkPrev()));
|
||||
keysNavigation.add(
|
||||
new NoOpKeyCommand(KeyCommand.M_SHIFT, 'n', PatchUtil.C.commentNext()),
|
||||
new NoOpKeyCommand(KeyCommand.M_SHIFT, 'p', PatchUtil.C.commentPrev()));
|
||||
|
@@ -1,970 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
import com.google.gerrit.client.FormatUtil;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.CommentApi;
|
||||
import com.google.gerrit.client.changes.CommentInfo;
|
||||
import com.google.gerrit.client.info.AccountInfo;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.CommentLinkProcessor;
|
||||
import com.google.gerrit.client.ui.CommentPanel;
|
||||
import com.google.gerrit.client.ui.NavigationTable;
|
||||
import com.google.gerrit.client.ui.NeedsSignInKeyCommand;
|
||||
import com.google.gerrit.common.data.AccountInfoCache;
|
||||
import com.google.gerrit.common.data.CommentDetail;
|
||||
import com.google.gerrit.common.data.PatchScript;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.prettify.client.ClientSideFormatter;
|
||||
import com.google.gerrit.prettify.client.PrettyFormatter;
|
||||
import com.google.gerrit.prettify.client.SparseHtmlFile;
|
||||
import com.google.gerrit.prettify.common.SparseFileContent;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.event.dom.client.BlurEvent;
|
||||
import com.google.gwt.event.dom.client.BlurHandler;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.DoubleClickEvent;
|
||||
import com.google.gwt.event.dom.client.DoubleClickHandler;
|
||||
import com.google.gwt.event.dom.client.FocusEvent;
|
||||
import com.google.gwt.event.dom.client.FocusHandler;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.user.client.DOM;
|
||||
import com.google.gwt.user.client.History;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Focusable;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
import com.google.gwt.user.client.ui.UIObject;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwtexpui.globalkey.client.GlobalKey;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommand;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
import com.google.gwtorm.client.KeyUtil;
|
||||
|
||||
import org.eclipse.jgit.diff.Edit;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
abstract class AbstractPatchContentTable extends NavigationTable<Object>
|
||||
implements CommentEditorContainer, FocusHandler, BlurHandler {
|
||||
public static final int R_HEAD = 0;
|
||||
static final short FILE_SIDE_A = (short) 0;
|
||||
static final short FILE_SIDE_B = (short) 1;
|
||||
protected PatchTable fileList;
|
||||
protected AccountInfoCache accountCache = AccountInfoCache.empty();
|
||||
protected Patch.Key patchKey;
|
||||
protected PatchSet.Id idSideA;
|
||||
protected PatchSet.Id idSideB;
|
||||
protected boolean onlyOneHunk;
|
||||
protected PatchSetSelectBox headerSideA;
|
||||
protected PatchSetSelectBox headerSideB;
|
||||
protected Image iconA;
|
||||
protected Image iconB;
|
||||
|
||||
private final KeyCommandSet keysComment;
|
||||
private HandlerRegistration regComment;
|
||||
private final KeyCommandSet keysOpenByEnter;
|
||||
private HandlerRegistration regOpenByEnter;
|
||||
private CommentLinkProcessor commentLinkProcessor;
|
||||
boolean isDisplayBinary;
|
||||
|
||||
protected AbstractPatchContentTable() {
|
||||
keysNavigation.add(new PrevKeyCommand(0, 'k', PatchUtil.C.linePrev()));
|
||||
keysNavigation.add(new NextKeyCommand(0, 'j', PatchUtil.C.lineNext()));
|
||||
keysNavigation.add(new PrevChunkKeyCmd(0, 'p', PatchUtil.C.chunkPrev()));
|
||||
keysNavigation.add(new NextChunkKeyCmd(0, 'n', PatchUtil.C.chunkNext()));
|
||||
keysNavigation.add(new PrevCommentCmd(0, 'P', PatchUtil.C.commentPrev()));
|
||||
keysNavigation.add(new NextCommentCmd(0, 'N', PatchUtil.C.commentNext()));
|
||||
|
||||
keysAction.add(new OpenKeyCommand(0, 'o', PatchUtil.C.expandComment()));
|
||||
keysOpenByEnter = new KeyCommandSet(Gerrit.C.sectionNavigation());
|
||||
keysOpenByEnter.add(new OpenKeyCommand(0, KeyCodes.KEY_ENTER, PatchUtil.C.expandComment()));
|
||||
|
||||
if (Gerrit.isSignedIn()) {
|
||||
keysAction.add(new InsertCommentCommand(0, 'c', PatchUtil.C
|
||||
.commentInsert()));
|
||||
|
||||
// See CommentEditorPanel
|
||||
//
|
||||
keysComment = new KeyCommandSet(PatchUtil.C.commentEditorSet());
|
||||
keysComment.add(new NoOpKeyCommand(KeyCommand.M_CTRL, 's', PatchUtil.C
|
||||
.commentSaveDraft()));
|
||||
keysComment.add(new NoOpKeyCommand(0, KeyCodes.KEY_ESCAPE, PatchUtil.C
|
||||
.commentCancelEdit()));
|
||||
} else {
|
||||
keysComment = null;
|
||||
}
|
||||
|
||||
table.setStyleName(Gerrit.RESOURCES.css().patchContentTable());
|
||||
}
|
||||
|
||||
abstract void createFileCommentEditorOnSideA();
|
||||
|
||||
abstract void createFileCommentEditorOnSideB();
|
||||
|
||||
protected void initHeaders(PatchScript script, PatchSetDetail detail) {
|
||||
headerSideA = new PatchSetSelectBox(PatchSetSelectBox.Side.A);
|
||||
headerSideA.display(detail, script, patchKey, idSideA, idSideB);
|
||||
headerSideA.addDoubleClickHandler(new DoubleClickHandler() {
|
||||
@Override
|
||||
public void onDoubleClick(DoubleClickEvent event) {
|
||||
if (headerSideA.isFileOrCommitMessage()) {
|
||||
createFileCommentEditorOnSideA();
|
||||
}
|
||||
}
|
||||
});
|
||||
headerSideB = new PatchSetSelectBox(PatchSetSelectBox.Side.B);
|
||||
headerSideB.display(detail, script, patchKey, idSideA, idSideB);
|
||||
headerSideB.addDoubleClickHandler(new DoubleClickHandler() {
|
||||
@Override
|
||||
public void onDoubleClick(DoubleClickEvent event) {
|
||||
if (headerSideB.isFileOrCommitMessage()) {
|
||||
createFileCommentEditorOnSideB();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Prepare icons.
|
||||
iconA = new Image(Gerrit.RESOURCES.addFileComment());
|
||||
iconA.setTitle(PatchUtil.C.addFileCommentToolTip());
|
||||
iconA.addStyleName(Gerrit.RESOURCES.css().link());
|
||||
iconA.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
createFileCommentEditorOnSideA();
|
||||
}
|
||||
});
|
||||
iconB = new Image(Gerrit.RESOURCES.addFileComment());
|
||||
iconB.setTitle(PatchUtil.C.addFileCommentToolTip());
|
||||
iconB.addStyleName(Gerrit.RESOURCES.css().link());
|
||||
iconB.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
createFileCommentEditorOnSideB();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDraftDelta(final int delta) {
|
||||
if (fileList != null) {
|
||||
fileList.notifyDraftDelta(patchKey, delta);
|
||||
}
|
||||
|
||||
Widget p = getParent();
|
||||
while (p != null) {
|
||||
if (p instanceof CommentEditorContainer) {
|
||||
((CommentEditorContainer) p).notifyDraftDelta(delta);
|
||||
break;
|
||||
}
|
||||
p = p.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(CommentEditorPanel panel) {
|
||||
final int nRows = table.getRowCount();
|
||||
for (int row = 0; row < nRows; row++) {
|
||||
final int nCells = table.getCellCount(row);
|
||||
for (int cell = 0; cell < nCells; cell++) {
|
||||
if (table.getWidget(row, cell) == panel) {
|
||||
destroyEditor(row, cell);
|
||||
Widget p = table;
|
||||
while (p != null) {
|
||||
if (p instanceof Focusable) {
|
||||
((Focusable) p).setFocus(true);
|
||||
break;
|
||||
}
|
||||
p = p.getParent();
|
||||
}
|
||||
|
||||
if (table.getCellFormatter().getStyleName(row - 1, cell)
|
||||
.contains(Gerrit.RESOURCES.css().commentHolder())) {
|
||||
table.getCellFormatter().addStyleName(row - 1, cell,
|
||||
Gerrit.RESOURCES.css().commentPanelLast());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRegisterKeys(final boolean on) {
|
||||
super.setRegisterKeys(on);
|
||||
if (on && keysComment != null && regComment == null) {
|
||||
regComment = GlobalKey.add(this, keysComment);
|
||||
} else if (!on && regComment != null) {
|
||||
regComment.removeHandler();
|
||||
regComment = null;
|
||||
}
|
||||
|
||||
if (on && keysOpenByEnter != null && regOpenByEnter == null) {
|
||||
regOpenByEnter = GlobalKey.add(this, keysOpenByEnter);
|
||||
} else if (!on && regOpenByEnter != null) {
|
||||
regOpenByEnter.removeHandler();
|
||||
regOpenByEnter = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void display(final Patch.Key k, final PatchSet.Id a,
|
||||
final PatchSet.Id b, final PatchScript s, final PatchSetDetail d) {
|
||||
patchKey = k;
|
||||
idSideA = a;
|
||||
idSideB = b;
|
||||
|
||||
render(s, d);
|
||||
}
|
||||
|
||||
void setCommentLinkProcessor(CommentLinkProcessor commentLinkProcessor) {
|
||||
this.commentLinkProcessor = commentLinkProcessor;
|
||||
}
|
||||
|
||||
protected boolean hasDifferences(PatchScript script) {
|
||||
return hasEdits(script) || hasMeta(script) || hasComments(script);
|
||||
}
|
||||
|
||||
public boolean isPureMetaChange(PatchScript script) {
|
||||
return !hasEdits(script) && hasMeta(script);
|
||||
}
|
||||
|
||||
// True if there are differences between the two patch sets
|
||||
private boolean hasEdits(PatchScript script) {
|
||||
for (Edit e : script.getEdits()) {
|
||||
if (e.getType() != Edit.Type.EMPTY) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// True if one of the two patch sets has comments
|
||||
private boolean hasComments(PatchScript script) {
|
||||
return !script.getCommentDetail().getCommentsA().isEmpty()
|
||||
|| !script.getCommentDetail().getCommentsB().isEmpty();
|
||||
}
|
||||
|
||||
// True if this change is a mode change or a pure rename/copy
|
||||
private boolean hasMeta(PatchScript script) {
|
||||
return !script.getPatchHeader().isEmpty();
|
||||
}
|
||||
|
||||
protected void appendNoDifferences(SafeHtmlBuilder m) {
|
||||
m.openTr();
|
||||
m.openTd();
|
||||
m.setAttribute("colspan", 5);
|
||||
m.openDiv();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchNoDifference());
|
||||
m.append(PatchUtil.C.noDifference());
|
||||
m.closeDiv();
|
||||
m.closeTd();
|
||||
m.closeTr();
|
||||
}
|
||||
|
||||
protected SparseHtmlFile getSparseHtmlFileA(PatchScript s) {
|
||||
DiffPreferencesInfo dp = s.getDiffPrefs();
|
||||
dp.showWhitespaceErrors = false;
|
||||
|
||||
PrettyFormatter f = ClientSideFormatter.FACTORY.get();
|
||||
f.setDiffPrefs(dp);
|
||||
f.setFileName(s.getA().getPath());
|
||||
f.setEditFilter(PrettyFormatter.A);
|
||||
f.setEditList(s.getEdits());
|
||||
f.format(s.getA());
|
||||
return f;
|
||||
}
|
||||
|
||||
protected SparseHtmlFile getSparseHtmlFileB(PatchScript s) {
|
||||
DiffPreferencesInfo dp = s.getDiffPrefs();
|
||||
|
||||
SparseFileContent b = s.getB();
|
||||
PrettyFormatter f = ClientSideFormatter.FACTORY.get();
|
||||
f.setDiffPrefs(dp);
|
||||
f.setFileName(b.getPath());
|
||||
f.setEditFilter(PrettyFormatter.B);
|
||||
f.setEditList(s.getEdits());
|
||||
|
||||
if (s.getA().isWholeFile() && !b.isWholeFile()) {
|
||||
b = b.apply(s.getA(), s.getEdits());
|
||||
}
|
||||
f.format(b);
|
||||
return f;
|
||||
}
|
||||
|
||||
protected String getUrlA() {
|
||||
final String rawBase = GWT.getHostPageBaseURL() + "cat/";
|
||||
final String url;
|
||||
if (idSideA == null) {
|
||||
url = rawBase + KeyUtil.encode(patchKey.toString()) + "^1";
|
||||
} else {
|
||||
Patch.Key k = new Patch.Key(idSideA, patchKey.get());
|
||||
url = rawBase + KeyUtil.encode(k.toString()) + "^0";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
protected String getUrlB() {
|
||||
final String rawBase = GWT.getHostPageBaseURL() + "cat/";
|
||||
return rawBase + KeyUtil.encode(patchKey.toString()) + "^0";
|
||||
}
|
||||
|
||||
protected abstract void render(PatchScript script, final PatchSetDetail detail);
|
||||
|
||||
protected abstract void onInsertComment(PatchLine pl);
|
||||
|
||||
public abstract void display(CommentDetail comments, boolean expandComments);
|
||||
|
||||
@Override
|
||||
protected Object getRowItemKey(final Object item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void initScript(final PatchScript script) {
|
||||
if (script.getEdits().size() == 1) {
|
||||
final SparseFileContent a = script.getA();
|
||||
final SparseFileContent b = script.getB();
|
||||
onlyOneHunk = a.size() == 0 || b.size() == 0;
|
||||
} else {
|
||||
onlyOneHunk = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChunk(final int row) {
|
||||
final Object o = getRowItem(row);
|
||||
if (!onlyOneHunk && o instanceof PatchLine) {
|
||||
final PatchLine pl = (PatchLine) o;
|
||||
switch (pl.getType()) {
|
||||
case DELETE:
|
||||
case INSERT:
|
||||
case REPLACE:
|
||||
return true;
|
||||
case CONTEXT:
|
||||
break;
|
||||
}
|
||||
} else if (o instanceof CommentList) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int findChunkStart(int row) {
|
||||
while (0 <= row && isChunk(row)) {
|
||||
row--;
|
||||
}
|
||||
return row + 1;
|
||||
}
|
||||
|
||||
private int findChunkEnd(int row) {
|
||||
final int max = table.getRowCount();
|
||||
while (row < max && isChunk(row)) {
|
||||
row++;
|
||||
}
|
||||
return row - 1;
|
||||
}
|
||||
|
||||
private static int oneBefore(final int begin) {
|
||||
return 1 <= begin ? begin - 1 : begin;
|
||||
}
|
||||
|
||||
private int oneAfter(final int end) {
|
||||
return end + 1 < table.getRowCount() ? end + 1 : end;
|
||||
}
|
||||
|
||||
private void moveToPrevChunk(int row) {
|
||||
while (0 <= row && isChunk(row)) {
|
||||
row--;
|
||||
}
|
||||
for (; 0 <= row; row--) {
|
||||
if (isChunk(row)) {
|
||||
final int start = findChunkStart(row);
|
||||
movePointerTo(start, false);
|
||||
scrollIntoView(oneBefore(start), oneAfter(row));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No prior hunk found? Try to hit the first line in the file.
|
||||
//
|
||||
for (row = 0; row < table.getRowCount(); row++) {
|
||||
if (getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToNextChunk(int row) {
|
||||
final int max = table.getRowCount();
|
||||
while (row < max && isChunk(row)) {
|
||||
row++;
|
||||
}
|
||||
for (; row < max; row++) {
|
||||
if (isChunk(row)) {
|
||||
movePointerTo(row, false);
|
||||
scrollIntoView(oneBefore(row), oneAfter(findChunkEnd(row)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No next hunk found? Try to hit the last line in the file.
|
||||
//
|
||||
for (row = max - 1; row >= 0; row--) {
|
||||
if (getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToPrevComment(int row) {
|
||||
while (0 <= row && isComment(row)) {
|
||||
row--;
|
||||
}
|
||||
for (; 0 <= row; row--) {
|
||||
if (isComment(row)) {
|
||||
movePointerTo(row, false);
|
||||
scrollIntoView(oneBefore(row), oneAfter(row));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No prior comment found? Try to hit the first line in the file.
|
||||
//
|
||||
for (row = 0; row < table.getRowCount(); row++) {
|
||||
if (getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToNextComment(int row) {
|
||||
final int max = table.getRowCount();
|
||||
while (row < max && isComment(row)) {
|
||||
row++;
|
||||
}
|
||||
for (; row < max; row++) {
|
||||
if (isComment(row)) {
|
||||
movePointerTo(row, false);
|
||||
scrollIntoView(oneBefore(row), oneAfter(row));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No next comment found? Try to hit the last line in the file.
|
||||
//
|
||||
for (row = max - 1; row >= 0; row--) {
|
||||
if (getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isComment(int row) {
|
||||
return getRowItem(row) instanceof CommentList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes createCommentEditor() with an empty string as value for the comment
|
||||
* parent UUID. This method is invoked by callers that want to create an
|
||||
* editor for a comment that is not a reply.
|
||||
*/
|
||||
protected void createCommentEditor(final int suggestRow, final int column,
|
||||
final int line, final short file) {
|
||||
if (Gerrit.isSignedIn()) {
|
||||
if (R_HEAD <= line) {
|
||||
final Patch.Key parentKey;
|
||||
final short side;
|
||||
switch (file) {
|
||||
case 0:
|
||||
if (idSideA == null) {
|
||||
parentKey = new Patch.Key(idSideB, patchKey.get());
|
||||
side = (short) 0;
|
||||
} else {
|
||||
parentKey = new Patch.Key(idSideA, patchKey.get());
|
||||
side = (short) 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
parentKey = new Patch.Key(idSideB, patchKey.get());
|
||||
side = (short) 1;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("unexpected file id " + file);
|
||||
}
|
||||
|
||||
final PatchLineComment newComment = new PatchLineComment(
|
||||
new PatchLineComment.Key(parentKey, null), line,
|
||||
Gerrit.getUserAccount().getId(), null,
|
||||
new Timestamp(System.currentTimeMillis()));
|
||||
newComment.setSide(side);
|
||||
newComment.setMessage("");
|
||||
|
||||
findOrCreateCommentEditor(suggestRow, column, newComment, true)
|
||||
.setFocus(true);
|
||||
}
|
||||
} else {
|
||||
Gerrit.doSignIn(History.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cursor after selecting a comment.
|
||||
*
|
||||
* @param newComment comment that was selected.
|
||||
*/
|
||||
protected void updateCursor(final PatchLineComment newComment) {
|
||||
}
|
||||
|
||||
abstract void insertFileCommentRow(final int row);
|
||||
|
||||
private CommentEditorPanel findOrCreateCommentEditor(final int suggestRow,
|
||||
final int column, final PatchLineComment newComment, final boolean create) {
|
||||
int row = suggestRow;
|
||||
int[] spans = new int[column + 1];
|
||||
FIND_ROW: while (row < table.getRowCount()) {
|
||||
int col = 0;
|
||||
for (int cell = 0; row < table.getRowCount()
|
||||
&& cell < table.getCellCount(row); cell++) {
|
||||
while (col < column && 0 < spans[col]) {
|
||||
spans[col++]--;
|
||||
}
|
||||
spans[col] = table.getFlexCellFormatter().getRowSpan(row, cell);
|
||||
if (col == column) {
|
||||
final Widget w = table.getWidget(row, cell);
|
||||
if (w instanceof CommentEditorPanel
|
||||
&& ((CommentEditorPanel) w).getComment().getKey().getParentKey()
|
||||
.equals(newComment.getKey().getParentKey())) {
|
||||
// Don't insert two editors on the same position, it doesn't make
|
||||
// any sense to the user.
|
||||
//
|
||||
return ((CommentEditorPanel) w);
|
||||
|
||||
} else if (w instanceof CommentPanel) {
|
||||
if (newComment != null && newComment.getParentUuid() != null) {
|
||||
// If we are a reply, we were given the exact row to insert
|
||||
// ourselves at. We should be before this panel so break.
|
||||
//
|
||||
break FIND_ROW;
|
||||
}
|
||||
row++;
|
||||
cell--;
|
||||
} else {
|
||||
break FIND_ROW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newComment == null || !create) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CommentEditorPanel ed =
|
||||
new CommentEditorPanel(newComment, commentLinkProcessor);
|
||||
ed.addFocusHandler(this);
|
||||
ed.addBlurHandler(this);
|
||||
boolean isCommentRow = false;
|
||||
boolean needInsert = false;
|
||||
if (row < table.getRowCount()) {
|
||||
for (int cell = 0; cell < table.getCellCount(row); cell++) {
|
||||
final Widget w = table.getWidget(row, cell);
|
||||
if (w instanceof CommentEditorPanel || w instanceof CommentPanel) {
|
||||
if (column == cell) {
|
||||
needInsert = true;
|
||||
}
|
||||
isCommentRow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needInsert || !isCommentRow) {
|
||||
if (newComment.getLine() == R_HEAD) {
|
||||
insertFileCommentRow(row);
|
||||
} else {
|
||||
insertRow(row);
|
||||
}
|
||||
styleCommentRow(row);
|
||||
}
|
||||
table.setWidget(row, column, ed);
|
||||
styleLastCommentCell(row, column);
|
||||
|
||||
int span = 1;
|
||||
for (int r = row + 1; r < table.getRowCount(); r++) {
|
||||
boolean hasComment = false;
|
||||
for (int c = 0; c < table.getCellCount(r); c++) {
|
||||
final Widget w = table.getWidget(r, c);
|
||||
if (w instanceof CommentPanel || w instanceof CommentEditorPanel) {
|
||||
if (c != column) {
|
||||
hasComment = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasComment) {
|
||||
table.removeCell(r, column);
|
||||
span++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (span > 1) {
|
||||
table.getFlexCellFormatter().setRowSpan(row, column, span);
|
||||
}
|
||||
|
||||
for (int r = row - 1; r > 0; r--) {
|
||||
if (getRowItem(r) instanceof CommentList) {
|
||||
continue;
|
||||
} else if (getRowItem(r) != null) {
|
||||
movePointerTo(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateCursor(newComment);
|
||||
return ed;
|
||||
}
|
||||
|
||||
protected void insertRow(final int row) {
|
||||
table.insertRow(row);
|
||||
table.getCellFormatter().setStyleName(row, 0,
|
||||
Gerrit.RESOURCES.css().iconCell());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOpenRow(final int row) {
|
||||
final Object item = getRowItem(row);
|
||||
if (item instanceof CommentList) {
|
||||
for (final CommentPanel p : ((CommentList) item).panels) {
|
||||
p.setOpen(!p.isOpen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setAccountInfoCache(final AccountInfoCache aic) {
|
||||
assert aic != null;
|
||||
accountCache = aic;
|
||||
}
|
||||
|
||||
private void destroyEditor(final int row, final int col) {
|
||||
table.clearCell(row, col);
|
||||
final int span = table.getFlexCellFormatter().getRowSpan(row, col);
|
||||
boolean removeRow = true;
|
||||
final int nCells = table.getCellCount(row);
|
||||
for (int cell = 0; cell < nCells; cell++) {
|
||||
if (table.getWidget(row, cell) != null) {
|
||||
removeRow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (removeRow) {
|
||||
destroyCommentRow(row);
|
||||
} else {
|
||||
destroyComment(row, col, span);
|
||||
}
|
||||
}
|
||||
|
||||
protected void destroyCommentRow(int row) {
|
||||
for (int r = row - 1; 0 <= r; r--) {
|
||||
boolean data = false;
|
||||
for (int c = 0; c < table.getCellCount(r); c++) {
|
||||
data |= table.getWidget(r, c) != null;
|
||||
final int s = table.getFlexCellFormatter().getRowSpan(r, c) - 1;
|
||||
if (r + s == row) {
|
||||
table.getFlexCellFormatter().setRowSpan(r, c, s);
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
table.removeRow(row);
|
||||
}
|
||||
|
||||
private void destroyComment(int row, int col, int span) {
|
||||
table.getFlexCellFormatter().setStyleName(//
|
||||
row, col, Gerrit.RESOURCES.css().diffText());
|
||||
|
||||
if (span != 1) {
|
||||
table.getFlexCellFormatter().setRowSpan(row, col, 1);
|
||||
for (int r = row + 1; r < row + span; r++) {
|
||||
table.insertCell(r, col);
|
||||
|
||||
table.getFlexCellFormatter().setStyleName(//
|
||||
r, col, Gerrit.RESOURCES.css().diffText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void bindComment(final int row, final int col,
|
||||
final PatchLineComment line, boolean expandComment) {
|
||||
if (line.getStatus() == PatchLineComment.Status.DRAFT) {
|
||||
final CommentEditorPanel plc =
|
||||
new CommentEditorPanel(line, commentLinkProcessor);
|
||||
plc.addFocusHandler(this);
|
||||
plc.addBlurHandler(this);
|
||||
table.setWidget(row, col, plc);
|
||||
styleLastCommentCell(row, col);
|
||||
|
||||
} else {
|
||||
final AccountInfo author = FormatUtil.asInfo(accountCache.get(line.getAuthor()));
|
||||
final PublishedCommentPanel panel =
|
||||
new PublishedCommentPanel(author, line);
|
||||
panel.setOpen(expandComment);
|
||||
panel.addFocusHandler(this);
|
||||
panel.addBlurHandler(this);
|
||||
table.setWidget(row, col, panel);
|
||||
styleLastCommentCell(row, col);
|
||||
|
||||
CommentList l = (CommentList) getRowItem(row);
|
||||
if (l == null) {
|
||||
l = new CommentList();
|
||||
setRowItem(row, l);
|
||||
}
|
||||
l.comments.add(line);
|
||||
l.panels.add(panel);
|
||||
}
|
||||
|
||||
styleCommentRow(row);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocus(FocusEvent event) {
|
||||
// when the comment panel gets focused (actually when a button inside the
|
||||
// comment panel gets focused) we have to unregister the key binding for
|
||||
// ENTER that expands/collapses the comment panel, if we don't do this the
|
||||
// focused button in the comment panel cannot be triggered by pressing ENTER
|
||||
// since ENTER would then be already consumed by this key binding
|
||||
if (regOpenByEnter != null) {
|
||||
regOpenByEnter.removeHandler();
|
||||
regOpenByEnter = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlur(BlurEvent event) {
|
||||
// when the comment panel gets blurred (actually when a button inside the
|
||||
// comment panel gets blurred) we have to re-register the key binding for
|
||||
// ENTER that expands/collapses the comment panel
|
||||
if (keysOpenByEnter != null && regOpenByEnter == null) {
|
||||
regOpenByEnter = GlobalKey.add(this, keysOpenByEnter);
|
||||
}
|
||||
}
|
||||
|
||||
private void styleCommentRow(final int row) {
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
final Element iconCell = fmt.getElement(row, 0);
|
||||
UIObject.setStyleName(DOM.getParent(iconCell), Gerrit.RESOURCES.css()
|
||||
.commentHolder(), true);
|
||||
}
|
||||
|
||||
private void styleLastCommentCell(final int row, final int col) {
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
fmt.removeStyleName(row - 1, col, //
|
||||
Gerrit.RESOURCES.css().commentPanelLast());
|
||||
fmt.setStyleName(row, col, Gerrit.RESOURCES.css().commentHolder());
|
||||
fmt.addStyleName(row, col, Gerrit.RESOURCES.css().commentPanelLast());
|
||||
if (!fmt.getStyleName(row, col - 1).contains(Gerrit.RESOURCES.css().commentHolder())) {
|
||||
fmt.addStyleName(row, col, Gerrit.RESOURCES.css().commentHolderLeftmost());
|
||||
}
|
||||
}
|
||||
|
||||
protected static class CommentList {
|
||||
final List<PatchLineComment> comments = new ArrayList<>();
|
||||
final List<PublishedCommentPanel> panels = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static class NoOpKeyCommand extends NeedsSignInKeyCommand {
|
||||
public NoOpKeyCommand(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
}
|
||||
}
|
||||
|
||||
public class InsertCommentCommand extends NeedsSignInKeyCommand {
|
||||
public InsertCommentCommand(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
ensurePointerVisible();
|
||||
for (int row = getCurrentRow(); 0 <= row; row--) {
|
||||
final Object item = getRowItem(row);
|
||||
if (item instanceof PatchLine) {
|
||||
onInsertComment((PatchLine) item);
|
||||
return;
|
||||
} else if (item instanceof CommentList) {
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PrevChunkKeyCmd extends KeyCommand {
|
||||
public PrevChunkKeyCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
ensurePointerVisible();
|
||||
moveToPrevChunk(getCurrentRow());
|
||||
}
|
||||
}
|
||||
|
||||
public class NextChunkKeyCmd extends KeyCommand {
|
||||
public NextChunkKeyCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
ensurePointerVisible();
|
||||
moveToNextChunk(getCurrentRow());
|
||||
}
|
||||
}
|
||||
|
||||
public class PrevCommentCmd extends KeyCommand {
|
||||
public PrevCommentCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
ensurePointerVisible();
|
||||
moveToPrevComment(getCurrentRow());
|
||||
}
|
||||
}
|
||||
|
||||
public class NextCommentCmd extends KeyCommand {
|
||||
public NextCommentCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
ensurePointerVisible();
|
||||
moveToNextComment(getCurrentRow());
|
||||
}
|
||||
}
|
||||
|
||||
private class PublishedCommentPanel extends CommentPanel implements
|
||||
ClickHandler {
|
||||
final PatchLineComment comment;
|
||||
final Button reply;
|
||||
final Button replyDone;
|
||||
|
||||
PublishedCommentPanel(final AccountInfo author, final PatchLineComment c) {
|
||||
super(author, c.getWrittenOn(), c.getMessage(), commentLinkProcessor);
|
||||
this.comment = c;
|
||||
|
||||
reply = new Button(PatchUtil.C.buttonReply());
|
||||
reply.addClickHandler(this);
|
||||
addButton(reply);
|
||||
|
||||
replyDone = new Button(PatchUtil.C.buttonReplyDone());
|
||||
replyDone.addClickHandler(this);
|
||||
addButton(replyDone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
if (Gerrit.isSignedIn()) {
|
||||
if (reply == event.getSource()) {
|
||||
createReplyEditor();
|
||||
} else if (replyDone == event.getSource()) {
|
||||
cannedReply(PatchUtil.C.cannedReplyDone());
|
||||
}
|
||||
|
||||
} else {
|
||||
Gerrit.doSignIn(History.getToken());
|
||||
}
|
||||
}
|
||||
|
||||
private void createReplyEditor() {
|
||||
final PatchLineComment newComment = newComment();
|
||||
newComment.setMessage("");
|
||||
findOrCreateEditor(newComment, true).setFocus(true);
|
||||
}
|
||||
|
||||
private void cannedReply(String message) {
|
||||
final PatchLineComment newComment = newComment();
|
||||
newComment.setMessage(message);
|
||||
CommentEditorPanel p = findOrCreateEditor(newComment, false);
|
||||
if (p == null) {
|
||||
enableButtons(false);
|
||||
final PatchSet.Id psId = newComment.getKey().getParentKey().getParentKey();
|
||||
CommentInfo in = CommentEditorPanel.toInput(newComment);
|
||||
CommentApi.createDraft(psId, in,
|
||||
new GerritCallback<CommentInfo>() {
|
||||
@Override
|
||||
public void onSuccess(CommentInfo result) {
|
||||
enableButtons(true);
|
||||
notifyDraftDelta(1);
|
||||
findOrCreateEditor(CommentEditorPanel.toComment(
|
||||
psId, newComment.getKey().getParentKey().get(), result),
|
||||
true).setOpen(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
enableButtons(true);
|
||||
super.onFailure(caught);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (!p.isOpen()) {
|
||||
p.setOpen(true);
|
||||
}
|
||||
p.setFocus(true);
|
||||
}
|
||||
}
|
||||
|
||||
private CommentEditorPanel findOrCreateEditor(
|
||||
PatchLineComment newComment, boolean create) {
|
||||
int row = rowOf(getElement());
|
||||
int column = columnOf(getElement());
|
||||
return findOrCreateCommentEditor(row + 1, column, newComment, create);
|
||||
}
|
||||
|
||||
private PatchLineComment newComment() {
|
||||
PatchLineComment newComment =
|
||||
new PatchLineComment(new PatchLineComment.Key(comment.getKey()
|
||||
.getParentKey(), null), comment.getLine(), Gerrit
|
||||
.getUserAccount().getId(), comment.getKey().get(),
|
||||
new Timestamp(System.currentTimeMillis()));
|
||||
newComment.setSide(comment.getSide());
|
||||
return newComment;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
// Copyright (C) 2010 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.patches;
|
||||
|
||||
public interface CommentEditorContainer {
|
||||
void notifyDraftDelta(int delta);
|
||||
|
||||
void remove(CommentEditorPanel panel);
|
||||
}
|
@@ -1,371 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.change.LocalComments;
|
||||
import com.google.gerrit.client.changes.CommentApi;
|
||||
import com.google.gerrit.client.changes.CommentInfo;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.CommentLinkProcessor;
|
||||
import com.google.gerrit.client.ui.CommentPanel;
|
||||
import com.google.gerrit.extensions.client.Side;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.DoubleClickEvent;
|
||||
import com.google.gwt.event.dom.client.DoubleClickHandler;
|
||||
import com.google.gwt.event.dom.client.KeyDownEvent;
|
||||
import com.google.gwt.event.dom.client.KeyDownHandler;
|
||||
import com.google.gwt.user.client.Timer;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwtexpui.globalkey.client.NpTextArea;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.common.VoidResult;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class CommentEditorPanel extends CommentPanel implements ClickHandler,
|
||||
DoubleClickHandler {
|
||||
private static final int INITIAL_COLS = 60;
|
||||
private static final int INITIAL_LINES = 5;
|
||||
private static final int MAX_LINES = 30;
|
||||
private static final AsyncCallback<VoidResult> NULL_CALLBACK =
|
||||
new AsyncCallback<VoidResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
}
|
||||
};
|
||||
|
||||
private PatchLineComment comment;
|
||||
|
||||
private final NpTextArea text;
|
||||
private final Button edit;
|
||||
private final Button save;
|
||||
private final Button cancel;
|
||||
private final Button discard;
|
||||
private final Timer expandTimer;
|
||||
|
||||
public CommentEditorPanel(final PatchLineComment plc,
|
||||
final CommentLinkProcessor commentLinkProcessor) {
|
||||
super(commentLinkProcessor);
|
||||
comment = plc;
|
||||
|
||||
addStyleName(Gerrit.RESOURCES.css().commentEditorPanel());
|
||||
setAuthorNameText(Gerrit.getUserAccount(), PatchUtil.C.draft());
|
||||
setMessageText(plc.getMessage());
|
||||
addDoubleClickHandler(this);
|
||||
|
||||
expandTimer = new Timer() {
|
||||
@Override
|
||||
public void run() {
|
||||
expandText();
|
||||
}
|
||||
};
|
||||
text = new NpTextArea();
|
||||
text.setText(comment.getMessage());
|
||||
text.setCharacterWidth(INITIAL_COLS);
|
||||
text.setVisibleLines(INITIAL_LINES);
|
||||
text.setSpellCheck(true);
|
||||
text.addKeyDownHandler(new KeyDownHandler() {
|
||||
@Override
|
||||
public void onKeyDown(final KeyDownEvent event) {
|
||||
if ((event.isControlKeyDown() || event.isMetaKeyDown())
|
||||
&& !event.isAltKeyDown() && !event.isShiftKeyDown()) {
|
||||
switch (event.getNativeKeyCode()) {
|
||||
case 's':
|
||||
case 'S':
|
||||
event.preventDefault();
|
||||
onSave(NULL_CALLBACK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
expandTimer.schedule(250);
|
||||
}
|
||||
});
|
||||
addContent(text);
|
||||
|
||||
edit = new Button();
|
||||
edit.setText(PatchUtil.C.buttonEdit());
|
||||
edit.addClickHandler(this);
|
||||
addButton(edit);
|
||||
|
||||
save = new Button();
|
||||
save.setText(PatchUtil.C.buttonSave());
|
||||
save.addClickHandler(this);
|
||||
addButton(save);
|
||||
|
||||
cancel = new Button();
|
||||
cancel.setText(PatchUtil.C.buttonCancel());
|
||||
cancel.addClickHandler(this);
|
||||
addButton(cancel);
|
||||
|
||||
discard = new Button();
|
||||
discard.setText(PatchUtil.C.buttonDiscard());
|
||||
discard.addClickHandler(this);
|
||||
addButton(discard);
|
||||
|
||||
setOpen(true);
|
||||
if (isNew()) {
|
||||
edit();
|
||||
} else {
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
private void expandText() {
|
||||
final double cols = text.getCharacterWidth();
|
||||
int rows = 2;
|
||||
for (final String line : text.getText().split("\n")) {
|
||||
rows += Math.ceil((1.0 + line.length()) / cols);
|
||||
}
|
||||
rows = Math.max(INITIAL_LINES, Math.min(rows, MAX_LINES));
|
||||
if (text.getVisibleLines() != rows) {
|
||||
text.setVisibleLines(rows);
|
||||
}
|
||||
}
|
||||
|
||||
private void edit() {
|
||||
if (!isOpen()) {
|
||||
setOpen(true);
|
||||
}
|
||||
text.setText(comment.getMessage());
|
||||
expandText();
|
||||
stateEdit(true);
|
||||
text.setFocus(true);
|
||||
}
|
||||
|
||||
private void render() {
|
||||
final Timestamp on = comment.getWrittenOn();
|
||||
setDateText(PatchUtil.M.draftSaved(new java.util.Date(on.getTime())));
|
||||
setMessageText(comment.getMessage());
|
||||
stateEdit(false);
|
||||
}
|
||||
|
||||
private void stateEdit(final boolean inEdit) {
|
||||
expandTimer.cancel();
|
||||
setMessageTextVisible(!inEdit);
|
||||
edit.setVisible(!inEdit);
|
||||
|
||||
if (inEdit) {
|
||||
text.setVisible(true);
|
||||
} else {
|
||||
text.setFocus(false);
|
||||
text.setVisible(false);
|
||||
}
|
||||
|
||||
save.setVisible(inEdit);
|
||||
cancel.setVisible(inEdit && !isNew());
|
||||
discard.setVisible(inEdit);
|
||||
}
|
||||
|
||||
void setFocus(final boolean take) {
|
||||
if (take && !isOpen()) {
|
||||
setOpen(true);
|
||||
}
|
||||
if (text.isVisible()) {
|
||||
text.setFocus(take);
|
||||
} else if (take) {
|
||||
edit();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isNew() {
|
||||
return comment.getKey().get() == null;
|
||||
}
|
||||
|
||||
public PatchLineComment getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDoubleClick(final DoubleClickEvent event) {
|
||||
edit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
final Widget sender = (Widget) event.getSource();
|
||||
if (sender == edit) {
|
||||
edit();
|
||||
|
||||
} else if (sender == save) {
|
||||
onSave(NULL_CALLBACK);
|
||||
|
||||
} else if (sender == cancel) {
|
||||
render();
|
||||
|
||||
} else if (sender == discard) {
|
||||
onDiscard();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveDraft(AsyncCallback<VoidResult> onSave) {
|
||||
if (isOpen() && text.isVisible()) {
|
||||
onSave(onSave);
|
||||
} else {
|
||||
onSave.onSuccess(VoidResult.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSave(final AsyncCallback<VoidResult> onSave) {
|
||||
expandTimer.cancel();
|
||||
final String txt = text.getText().trim();
|
||||
if ("".equals(txt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
comment.setMessage(txt);
|
||||
text.setFocus(false);
|
||||
text.setReadOnly(true);
|
||||
save.setEnabled(false);
|
||||
cancel.setEnabled(false);
|
||||
discard.setEnabled(false);
|
||||
|
||||
final PatchSet.Id psId = comment.getKey().getParentKey().getParentKey();
|
||||
final LocalComments lc = new LocalComments(psId);
|
||||
final boolean wasNew = isNew();
|
||||
GerritCallback<CommentInfo> cb = new GerritCallback<CommentInfo>() {
|
||||
@Override
|
||||
public void onSuccess(CommentInfo result) {
|
||||
notifyDraftDelta(wasNew ? 1 : 0);
|
||||
comment = toComment(psId, comment.getKey().getParentKey().get(), result);
|
||||
text.setReadOnly(false);
|
||||
save.setEnabled(true);
|
||||
cancel.setEnabled(true);
|
||||
discard.setEnabled(true);
|
||||
render();
|
||||
onSave.onSuccess(VoidResult.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
text.setReadOnly(false);
|
||||
text.setFocus(true);
|
||||
save.setEnabled(true);
|
||||
cancel.setEnabled(true);
|
||||
discard.setEnabled(true);
|
||||
lc.setInlineComment(toInput(comment));
|
||||
super.onFailure(caught);
|
||||
onSave.onFailure(caught);
|
||||
}
|
||||
};
|
||||
CommentInfo input = toInput(comment);
|
||||
if (wasNew) {
|
||||
CommentApi.createDraft(psId, input, cb);
|
||||
} else {
|
||||
CommentApi.updateDraft(psId, input.id(), input, cb);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyDraftDelta(final int delta) {
|
||||
CommentEditorContainer c = getContainer();
|
||||
if (c != null) {
|
||||
c.notifyDraftDelta(delta);
|
||||
}
|
||||
}
|
||||
|
||||
private void onDiscard() {
|
||||
expandTimer.cancel();
|
||||
if (isNew()) {
|
||||
text.setFocus(false);
|
||||
removeUI();
|
||||
return;
|
||||
}
|
||||
|
||||
text.setFocus(false);
|
||||
text.setReadOnly(true);
|
||||
save.setEnabled(false);
|
||||
cancel.setEnabled(false);
|
||||
discard.setEnabled(false);
|
||||
|
||||
CommentApi.deleteDraft(
|
||||
comment.getKey().getParentKey().getParentKey(),
|
||||
comment.getKey().get(),
|
||||
new GerritCallback<JavaScriptObject>() {
|
||||
@Override
|
||||
public void onSuccess(JavaScriptObject result) {
|
||||
notifyDraftDelta(-1);
|
||||
removeUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
text.setReadOnly(false);
|
||||
text.setFocus(true);
|
||||
save.setEnabled(true);
|
||||
cancel.setEnabled(true);
|
||||
discard.setEnabled(true);
|
||||
super.onFailure(caught);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeUI() {
|
||||
CommentEditorContainer c = getContainer();
|
||||
if (c != null) {
|
||||
c.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
private CommentEditorContainer getContainer() {
|
||||
Widget p = getParent();
|
||||
while (p != null) {
|
||||
if (p instanceof CommentEditorContainer) {
|
||||
return (CommentEditorContainer) p;
|
||||
}
|
||||
p = p.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static CommentInfo toInput(PatchLineComment c) {
|
||||
CommentInfo i = CommentInfo.createObject().cast();
|
||||
i.id(c.getKey().get());
|
||||
i.path(c.getKey().getParentKey().get());
|
||||
i.side(c.getSide() == 0 ? Side.PARENT : Side.REVISION);
|
||||
if (c.getLine() > 0) {
|
||||
i.line(c.getLine());
|
||||
}
|
||||
i.inReplyTo(c.getParentUuid());
|
||||
i.message(c.getMessage());
|
||||
return i;
|
||||
}
|
||||
|
||||
public static PatchLineComment toComment(PatchSet.Id ps,
|
||||
String path,
|
||||
CommentInfo i) {
|
||||
PatchLineComment p = new PatchLineComment(
|
||||
new PatchLineComment.Key(
|
||||
new Patch.Key(ps, path),
|
||||
i.id()),
|
||||
i.line(),
|
||||
Gerrit.getUserAccount().getId(),
|
||||
i.inReplyTo(),
|
||||
i.updated());
|
||||
p.setMessage(i.message());
|
||||
p.setSide((short) (i.side() == Side.PARENT ? 0 : 1));
|
||||
return p;
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
// Copyright (C) 2010 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.StarredChanges;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.ui.ChangeLink;
|
||||
import com.google.gerrit.client.ui.CommentLinkProcessor;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.PreElement;
|
||||
import com.google.gwt.dom.client.Style.Display;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.SimplePanel;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
|
||||
class CommitMessageBlock extends Composite {
|
||||
interface Binder extends UiBinder<HTMLPanel, CommitMessageBlock> {}
|
||||
private static final Binder uiBinder = GWT.create(Binder.class);
|
||||
|
||||
private KeyCommandSet keysAction;
|
||||
|
||||
@UiField
|
||||
SimplePanel starPanel;
|
||||
@UiField
|
||||
FlowPanel permalinkPanel;
|
||||
@UiField
|
||||
PreElement commitSummaryPre;
|
||||
@UiField
|
||||
PreElement commitBodyPre;
|
||||
|
||||
CommitMessageBlock() {
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
CommitMessageBlock(KeyCommandSet keysAction) {
|
||||
this.keysAction = keysAction;
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
void display(String commitMessage,
|
||||
CommentLinkProcessor commentLinkProcessor) {
|
||||
display(null, null, null, commitMessage, commentLinkProcessor);
|
||||
}
|
||||
|
||||
void display(final PatchSet.Id patchSetId, final String revision,
|
||||
Boolean starred, final String commitMessage,
|
||||
CommentLinkProcessor commentLinkProcessor) {
|
||||
starPanel.clear();
|
||||
if (patchSetId != null && starred != null && Gerrit.isSignedIn()) {
|
||||
Change.Id changeId = patchSetId.getParentKey();
|
||||
StarredChanges.Icon star = StarredChanges.createIcon(changeId, starred);
|
||||
star.setStyleName(Gerrit.RESOURCES.css().changeScreenStarIcon());
|
||||
starPanel.add(star);
|
||||
|
||||
if (keysAction != null) {
|
||||
keysAction.add(StarredChanges.newKeyCommand(star));
|
||||
}
|
||||
}
|
||||
|
||||
permalinkPanel.clear();
|
||||
if (patchSetId != null && revision != null) {
|
||||
final Change.Id changeId = patchSetId.getParentKey();
|
||||
permalinkPanel.add(new ChangeLink(Util.C.changePermalink(), changeId));
|
||||
permalinkPanel.add(new CopyableLabel(ChangeLink.permalink(changeId),
|
||||
false));
|
||||
}
|
||||
|
||||
String[] splitCommitMessage = commitMessage.split("\n", 2);
|
||||
|
||||
String commitSummary = splitCommitMessage[0];
|
||||
String commitBody = "";
|
||||
if (splitCommitMessage.length > 1) {
|
||||
commitBody = splitCommitMessage[1];
|
||||
}
|
||||
|
||||
// Linkify commit summary
|
||||
SafeHtml commitSummaryLinkified = new SafeHtmlBuilder().append(commitSummary);
|
||||
commitSummaryLinkified = commitSummaryLinkified.linkify();
|
||||
commitSummaryLinkified = commentLinkProcessor.apply(commitSummaryLinkified);
|
||||
commitSummaryPre.setInnerHTML(commitSummaryLinkified.asString());
|
||||
|
||||
// Hide commit body if there is no body
|
||||
if (commitBody.trim().isEmpty()) {
|
||||
commitBodyPre.getStyle().setDisplay(Display.NONE);
|
||||
} else {
|
||||
// Linkify commit body
|
||||
SafeHtml commitBodyLinkified = new SafeHtmlBuilder().append(commitBody);
|
||||
commitBodyLinkified = commitBodyLinkified.linkify();
|
||||
commitBodyLinkified = commentLinkProcessor.apply(commitBodyLinkified);
|
||||
commitBodyLinkified = commitBodyLinkified.replaceAll("\n\n", "<p></p>");
|
||||
commitBodyLinkified = commitBodyLinkified.replaceAll("\n", "<br />");
|
||||
commitBodyPre.setInnerHTML(commitBodyLinkified.asString());
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2012 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.
|
||||
-->
|
||||
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
|
||||
|
||||
<ui:with field='res' type='com.google.gerrit.client.GerritResources'/>
|
||||
<ui:style gss='false'>
|
||||
@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
|
||||
@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
|
||||
@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
|
||||
|
||||
.commitMessageTable {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: trimColor;
|
||||
white-space: nowrap;
|
||||
color: textColor;
|
||||
font-size: 10pt;
|
||||
font-style: italic;
|
||||
padding: 2px 6px 1px;
|
||||
}
|
||||
|
||||
.contents {
|
||||
border-bottom: 1px solid trimColor;
|
||||
border-left: 1px solid trimColor;
|
||||
border-right: 1px solid trimColor;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.contents span {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.contents pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.commitSummary {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.commitBody p {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.starPanel {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.boxTitle {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.permalinkPanel {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.permalinkPanel a {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.permalinkPanel div {
|
||||
display: inline;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:HTMLPanel>
|
||||
<table class='{style.commitMessageTable}'>
|
||||
<tr><td class='{style.header}'>
|
||||
<g:SimplePanel styleName='{style.starPanel}' ui:field='starPanel'></g:SimplePanel>
|
||||
<div class='{style.boxTitle}'>Commit Message</div>
|
||||
<g:FlowPanel styleName='{style.permalinkPanel}' ui:field='permalinkPanel'></g:FlowPanel>
|
||||
</td></tr>
|
||||
<tr><td class='{style.contents}'>
|
||||
<pre class='{style.commitSummary} {res.css.changeScreenDescription}' ui:field='commitSummaryPre'/>
|
||||
<pre class='{style.commitBody} {res.css.changeScreenDescription}' ui:field='commitBodyPre'/>
|
||||
</td></tr>
|
||||
</table>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
|
@@ -1,155 +0,0 @@
|
||||
// Copyright (C) 2009 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Dispatcher;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.ui.FancyFlexTable;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.user.client.DOM;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.RadioButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A table used to specify which two patch sets should be diff'ed.
|
||||
*/
|
||||
class HistoryTable extends FancyFlexTable<Patch> {
|
||||
private final UnifiedPatchScreen screen;
|
||||
final List<HistoryRadio> all = new ArrayList<>();
|
||||
|
||||
HistoryTable(final UnifiedPatchScreen parent) {
|
||||
setStyleName(Gerrit.RESOURCES.css().patchHistoryTable());
|
||||
screen = parent;
|
||||
table.setWidth("auto");
|
||||
table.addStyleName(Gerrit.RESOURCES.css().changeTable());
|
||||
}
|
||||
|
||||
void onClick(final HistoryRadio b) {
|
||||
PatchSet.Id sideA = screen.idSideA;
|
||||
PatchSet.Id sideB = screen.idSideB;
|
||||
switch (b.file) {
|
||||
case 0:
|
||||
sideA = b.patchSetId;
|
||||
break;
|
||||
case 1:
|
||||
sideB = b.patchSetId;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
enableAll(false);
|
||||
Patch.Key k = new Patch.Key(sideB, screen.getPatchKey().get());
|
||||
Gerrit.display(Dispatcher.toUnified(sideA, k));
|
||||
}
|
||||
|
||||
void enableAll(final boolean on) {
|
||||
for (final HistoryRadio a : all) {
|
||||
a.setEnabled(on);
|
||||
}
|
||||
}
|
||||
|
||||
void display(final List<Patch> result) {
|
||||
all.clear();
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
table.setText(0, 0, PatchUtil.C.patchHeaderPatchSet());
|
||||
fmt.setStyleName(0, 0, Gerrit.RESOURCES.css().dataHeader());
|
||||
table.setText(1, 0, PatchUtil.C.patchHeaderOld());
|
||||
fmt.setStyleName(1, 0, Gerrit.RESOURCES.css().dataHeader());
|
||||
table.setText(2, 0, PatchUtil.C.patchHeaderNew());
|
||||
fmt.setStyleName(2, 0, Gerrit.RESOURCES.css().dataHeader());
|
||||
table.setText(3, 0, Util.C.patchTableColumnComments());
|
||||
fmt.setStyleName(3, 0, Gerrit.RESOURCES.css().dataHeader());
|
||||
|
||||
if (screen.getPatchSetDetail().getInfo().getParents().size() > 1) {
|
||||
table.setText(0, 1, PatchUtil.C.patchBaseAutoMerge());
|
||||
} else {
|
||||
table.setText(0, 1, PatchUtil.C.patchBase());
|
||||
}
|
||||
fmt.setStyleName(0, 1, Gerrit.RESOURCES.css().dataCell());
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topMostCell());
|
||||
fmt.setStyleName(1, 1, Gerrit.RESOURCES.css().dataCell());
|
||||
fmt.setStyleName(2, 1, Gerrit.RESOURCES.css().dataCell());
|
||||
fmt.setStyleName(3, 1, Gerrit.RESOURCES.css().dataCell());
|
||||
|
||||
installRadio(1, 1, null, screen.idSideA, 0);
|
||||
|
||||
int col=2;
|
||||
for (final Patch k : result) {
|
||||
final PatchSet.Id psId = k.getKey().getParentKey();
|
||||
table.setText(0, col, String.valueOf(psId.get()));
|
||||
fmt.setStyleName(0, col, Gerrit.RESOURCES.css().patchHistoryTablePatchSetHeader());
|
||||
fmt.addStyleName(0, col, Gerrit.RESOURCES.css().dataCell());
|
||||
fmt.addStyleName(0, col, Gerrit.RESOURCES.css().topMostCell());
|
||||
|
||||
installRadio(1, col, psId, screen.idSideA, 0);
|
||||
installRadio(2, col, psId, screen.idSideB, 1);
|
||||
|
||||
fmt.setStyleName(3, col, Gerrit.RESOURCES.css().dataCell());
|
||||
if (k.getCommentCount() > 0) {
|
||||
table.setText(3, col, Integer.toString(k.getCommentCount()));
|
||||
}
|
||||
col++;
|
||||
}
|
||||
}
|
||||
|
||||
private void installRadio(final int row, final int col, final PatchSet.Id psId,
|
||||
final PatchSet.Id cur, final int file) {
|
||||
final HistoryRadio b = new HistoryRadio(psId, file);
|
||||
b.setValue(eq(cur, psId));
|
||||
|
||||
table.setWidget(row, col, b);
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
fmt.setHorizontalAlignment(row, col, HasHorizontalAlignment.ALIGN_CENTER);
|
||||
fmt.setStyleName(row, col, Gerrit.RESOURCES.css().dataCell());
|
||||
all.add(b);
|
||||
}
|
||||
|
||||
private boolean eq(final PatchSet.Id cur, final PatchSet.Id psid) {
|
||||
if (cur == null && psid == null) {
|
||||
return true;
|
||||
}
|
||||
return psid != null && psid.equals(cur);
|
||||
}
|
||||
|
||||
private class HistoryRadio extends RadioButton {
|
||||
final PatchSet.Id patchSetId;
|
||||
final int file;
|
||||
|
||||
HistoryRadio(final PatchSet.Id ps, final int f) {
|
||||
super(String.valueOf(f));
|
||||
sinkEvents(Event.ONCLICK);
|
||||
patchSetId = ps;
|
||||
file = f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowserEvent(final Event event) {
|
||||
switch (DOM.eventGetType(event)) {
|
||||
case Event.ONCLICK:
|
||||
onClick(this);
|
||||
break;
|
||||
default:
|
||||
super.onBrowserEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,135 +0,0 @@
|
||||
// Copyright (C) 2010 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.info.WebLinkInfo;
|
||||
import com.google.gerrit.client.ui.ChangeLink;
|
||||
import com.google.gerrit.client.ui.InlineHyperlink;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommand;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class NavLinks extends Composite {
|
||||
public enum Nav {
|
||||
PREV (0, '[', PatchUtil.C.previousFileHelp(), 0),
|
||||
NEXT (4, ']', PatchUtil.C.nextFileHelp(), 1);
|
||||
|
||||
public int col; // Table Cell column to display link in
|
||||
public int key; // key code shortcut to activate link
|
||||
public String help; // help string for '?' popup
|
||||
public int cmd; // index into cmds array
|
||||
|
||||
Nav(int c, int k, String h, int i) {
|
||||
this.col = c;
|
||||
this.key = k;
|
||||
this.help = h;
|
||||
this.cmd = i;
|
||||
}
|
||||
}
|
||||
|
||||
private final PatchSet.Id patchSetId;
|
||||
private final KeyCommandSet keys;
|
||||
private final Grid table;
|
||||
|
||||
private KeyCommand[] cmds = new KeyCommand[2];
|
||||
|
||||
NavLinks(KeyCommandSet kcs, PatchSet.Id forPatch) {
|
||||
patchSetId = forPatch;
|
||||
keys = kcs;
|
||||
table = new Grid(1, 5);
|
||||
initWidget(table);
|
||||
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
table.setStyleName(Gerrit.RESOURCES.css().sideBySideScreenLinkTable());
|
||||
fmt.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT);
|
||||
fmt.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
|
||||
fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
fmt.setHorizontalAlignment(0, 3, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
fmt.setHorizontalAlignment(0, 4, HasHorizontalAlignment.ALIGN_RIGHT);
|
||||
|
||||
final ChangeLink up = new ChangeLink("", patchSetId);
|
||||
SafeHtml.set(up, SafeHtml.asis(Util.C.upToChangeIconLink()));
|
||||
table.setWidget(0, 1, up);
|
||||
}
|
||||
|
||||
void display(int patchIndex, PatchTable fileList,
|
||||
List<InlineHyperlink> links, List<WebLinkInfo> webLinks) {
|
||||
if (fileList != null) {
|
||||
Label fileCountLabel =
|
||||
new Label(Gerrit.M.fileCount(patchIndex + 1, fileList.size()));
|
||||
fileCountLabel.setStyleName(Gerrit.RESOURCES.css().nowrap());
|
||||
table.setWidget(0, 3, fileCountLabel);
|
||||
setupNav(Nav.PREV, fileList.getPreviousPatchLink(patchIndex));
|
||||
setupNav(Nav.NEXT, fileList.getNextPatchLink(patchIndex));
|
||||
} else {
|
||||
setupNav(Nav.PREV, null);
|
||||
setupNav(Nav.NEXT, null);
|
||||
}
|
||||
|
||||
FlowPanel linkPanel = new FlowPanel();
|
||||
linkPanel.setStyleName(Gerrit.RESOURCES.css().linkPanel());
|
||||
for (InlineHyperlink link : links) {
|
||||
linkPanel.add(link);
|
||||
}
|
||||
for (WebLinkInfo webLink : webLinks) {
|
||||
linkPanel.add(webLink.toAnchor());
|
||||
}
|
||||
table.setWidget(0, 2, linkPanel);
|
||||
}
|
||||
|
||||
protected void setupNav(final Nav nav, final InlineHyperlink link) {
|
||||
|
||||
/* setup the cells */
|
||||
if (link != null) {
|
||||
link.addStyleName(Gerrit.RESOURCES.css().nowrap());
|
||||
table.setWidget(0, nav.col, link);
|
||||
} else {
|
||||
table.clearCell(0, nav.col);
|
||||
}
|
||||
|
||||
/* setup the keys */
|
||||
if (keys != null) {
|
||||
|
||||
if (cmds[nav.cmd] != null) {
|
||||
keys.remove(cmds[nav.cmd]);
|
||||
}
|
||||
|
||||
if (link != null) {
|
||||
cmds[nav.cmd] = new KeyCommand(0, nav.key, nav.help) {
|
||||
@Override
|
||||
public void onKeyPress(KeyPressEvent event) {
|
||||
link.go();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
cmds[nav.cmd] = new UpToChangeCommand(patchSetId, 0, nav.key);
|
||||
}
|
||||
|
||||
keys.add(cmds[nav.cmd]);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,119 +0,0 @@
|
||||
// Copyright (C) 2009 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gwt.event.logical.shared.ResizeEvent;
|
||||
import com.google.gwt.event.logical.shared.ResizeHandler;
|
||||
import com.google.gwt.event.shared.HandlerRegistration;
|
||||
import com.google.gwt.user.client.Command;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.DialogBox;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
|
||||
import com.google.gwt.user.client.ui.ScrollPanel;
|
||||
import com.google.gwtexpui.globalkey.client.GlobalKey;
|
||||
import com.google.gwtexpui.globalkey.client.HidePopupPanelCommand;
|
||||
|
||||
class PatchBrowserPopup extends DialogBox implements
|
||||
PositionCallback, ResizeHandler {
|
||||
private final Patch.Key callerKey;
|
||||
private final PatchTable fileList;
|
||||
private final ScrollPanel sp;
|
||||
private HandlerRegistration regWindowResize;
|
||||
|
||||
PatchBrowserPopup(final Patch.Key pk, final PatchTable fl) {
|
||||
super(true/* autohide */, false/* modal */);
|
||||
|
||||
callerKey = pk;
|
||||
fileList = fl;
|
||||
sp = new ScrollPanel(fileList);
|
||||
|
||||
final FlowPanel body = new FlowPanel();
|
||||
body.setStyleName(Gerrit.RESOURCES.css().patchBrowserPopupBody());
|
||||
body.add(sp);
|
||||
|
||||
setText(Util.M.patchSetHeader(callerKey.getParentKey().get()));
|
||||
setWidget(body);
|
||||
addStyleName(Gerrit.RESOURCES.css().patchBrowserPopup());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPosition(final int myWidth, int myHeight) {
|
||||
final int dLeft = (Window.getClientWidth() - myWidth) >> 1;
|
||||
final int cHeight = Window.getClientHeight();
|
||||
final int cHeight2 = 2 * cHeight / 3;
|
||||
final int sLeft = Window.getScrollLeft();
|
||||
final int sTop = Window.getScrollTop();
|
||||
|
||||
if (myHeight > cHeight2) {
|
||||
sp.setHeight((cHeight2 - 50) + "px");
|
||||
myHeight = getOffsetHeight();
|
||||
}
|
||||
setPopupPosition(sLeft + dLeft, (sTop + cHeight) - (myHeight + 10));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResize(final ResizeEvent event) {
|
||||
sp.setWidth((Window.getClientWidth() - 60) + "px");
|
||||
setPosition(getOffsetWidth(), getOffsetHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hide() {
|
||||
if (regWindowResize != null) {
|
||||
regWindowResize.removeHandler();
|
||||
regWindowResize = null;
|
||||
}
|
||||
super.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
super.show();
|
||||
if (regWindowResize == null) {
|
||||
regWindowResize = Window.addResizeHandler(this);
|
||||
}
|
||||
|
||||
GlobalKey.dialog(this);
|
||||
GlobalKey.addApplication(this, new HidePopupPanelCommand(0, 'f', this));
|
||||
|
||||
if (!fileList.isLoaded()) {
|
||||
fileList.onTableLoaded(new Command() {
|
||||
@Override
|
||||
public void execute() {
|
||||
sp.setHeight("");
|
||||
setPosition(getOffsetWidth(), getOffsetHeight());
|
||||
fileList.setRegisterKeys(true);
|
||||
fileList.movePointerTo(callerKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void open() {
|
||||
if (!fileList.isLoaded()) {
|
||||
sp.setHeight("22px");
|
||||
}
|
||||
sp.setWidth((Window.getClientWidth() - 60) + "px");
|
||||
setPopupPositionAndShow(this);
|
||||
if (fileList.isLoaded()) {
|
||||
fileList.setRegisterKeys(true);
|
||||
fileList.movePointerTo(callerKey);
|
||||
}
|
||||
}
|
||||
}
|
@@ -17,49 +17,25 @@ package com.google.gerrit.client.patches;
|
||||
import com.google.gwt.i18n.client.Constants;
|
||||
|
||||
public interface PatchConstants extends Constants {
|
||||
String draft();
|
||||
|
||||
String buttonReply();
|
||||
String buttonEdit();
|
||||
String buttonSave();
|
||||
String buttonCancel();
|
||||
String buttonDiscard();
|
||||
|
||||
String noDifference();
|
||||
String patchBase();
|
||||
String patchBaseAutoMerge();
|
||||
String patchHeaderPatchSet();
|
||||
String patchHeaderOld();
|
||||
String patchHeaderNew();
|
||||
String patchSet();
|
||||
|
||||
String patchHistoryTitle();
|
||||
String disabledOnLargeFiles();
|
||||
String intralineFailure();
|
||||
String intralineTimeout();
|
||||
String illegalNumberOfColumns();
|
||||
|
||||
String upToChange();
|
||||
String openReply();
|
||||
String linePrev();
|
||||
String lineNext();
|
||||
String chunkPrev();
|
||||
String chunkNext();
|
||||
String chunkPrev2();
|
||||
String chunkNext2();
|
||||
String commentPrev();
|
||||
String commentNext();
|
||||
String focusSideA();
|
||||
String focusSideB();
|
||||
String fileList();
|
||||
String expandComment();
|
||||
String expandAllCommentsOnCurrentLine();
|
||||
String toggleSideA();
|
||||
String toggleIntraline();
|
||||
String showPreferences();
|
||||
|
||||
String openEditScreen();
|
||||
|
||||
String toggleReviewed();
|
||||
String markAsReviewedAndGoToNext();
|
||||
|
||||
@@ -76,22 +52,12 @@ public interface PatchConstants extends Constants {
|
||||
String previousFileHelp();
|
||||
String nextFileHelp();
|
||||
|
||||
String reviewedAnd();
|
||||
String next();
|
||||
String download();
|
||||
String edit();
|
||||
String addFileCommentToolTip();
|
||||
String addFileCommentByDoubleClick();
|
||||
|
||||
String buttonReplyDone();
|
||||
String cannedReplyDone();
|
||||
|
||||
String fileTypeSymlink();
|
||||
String fileTypeGitlink();
|
||||
|
||||
String patchSkipRegionStart();
|
||||
String patchSkipRegionEnd();
|
||||
|
||||
String sideBySideDiff();
|
||||
String unifiedDiff();
|
||||
}
|
||||
|
@@ -1,46 +1,24 @@
|
||||
draft = (Draft)
|
||||
|
||||
buttonReply = Reply ...
|
||||
buttonReplyDone = Reply 'Done'
|
||||
cannedReplyDone = Done
|
||||
buttonEdit = Edit
|
||||
buttonSave = Save
|
||||
buttonCancel = Cancel
|
||||
buttonDiscard = Discard
|
||||
|
||||
noDifference = No Differences
|
||||
patchBase = Base
|
||||
patchBaseAutoMerge = Auto Merge
|
||||
patchHeaderPatchSet = Patch Set
|
||||
patchHeaderOld = Old Version
|
||||
patchHeaderNew = New Version
|
||||
patchHistoryTitle = Patch History
|
||||
patchSet = Patch Set
|
||||
disabledOnLargeFiles = Disabled on very large source files.
|
||||
intralineFailure = Intraline difference not available due to server error.
|
||||
intralineTimeout = Intraline difference not available due to timeout.
|
||||
illegalNumberOfColumns = The number of columns cannot be zero or negative
|
||||
|
||||
upToChange = Up to change
|
||||
openReply = Reply and score
|
||||
linePrev = Previous line
|
||||
lineNext = Next line
|
||||
chunkPrev = Previous diff chunk or comment
|
||||
chunkNext = Next diff chunk or comment
|
||||
chunkPrev2 = Previous diff chunk
|
||||
chunkNext2 = Next diff chunk or search result
|
||||
chunkPrev = Previous diff chunk
|
||||
chunkNext = Next diff chunk or search result
|
||||
commentPrev = Previous comment
|
||||
commentNext = Next comment
|
||||
focusSideA = Focus left side
|
||||
focusSideB = Focus right side
|
||||
fileList = Browse files in patch set
|
||||
expandComment = Expand or collapse comment
|
||||
expandAllCommentsOnCurrentLine = Expand or collapse all comments on current line
|
||||
toggleSideA = Toggle left side
|
||||
toggleIntraline = Toggle intraline difference
|
||||
showPreferences = Show diff preferences
|
||||
|
||||
openEditScreen = Edit file in browser
|
||||
toggleReviewed = Toggle the reviewed flag
|
||||
markAsReviewedAndGoToNext = Mark patch as reviewed and go to next unreviewed patch
|
||||
|
||||
@@ -57,18 +35,9 @@ whitespaceIGNORE_ALL=All
|
||||
previousFileHelp = Previous file
|
||||
nextFileHelp = Next file
|
||||
|
||||
reviewedAnd = Reviewed &
|
||||
next = next
|
||||
download = Download
|
||||
edit = Edit
|
||||
addFileCommentToolTip = Click to add file comment
|
||||
addFileCommentByDoubleClick = Double click to add file comment
|
||||
|
||||
fileTypeSymlink = Type: Symbolic Link
|
||||
fileTypeGitlink = Type: Git Commit in Subproject
|
||||
|
||||
patchSkipRegionStart = ... skipped
|
||||
patchSkipRegionEnd = common lines ...
|
||||
|
||||
sideBySideDiff = Side-by-side diff
|
||||
unifiedDiff = Unified diff
|
||||
|
@@ -1,43 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
class PatchLine {
|
||||
static enum Type {
|
||||
DELETE, INSERT, REPLACE, CONTEXT
|
||||
}
|
||||
|
||||
private PatchLine.Type type;
|
||||
private int lineA;
|
||||
private int lineB;
|
||||
|
||||
PatchLine(final PatchLine.Type t, final int a, final int b) {
|
||||
type = t;
|
||||
lineA = a;
|
||||
lineB = b;
|
||||
}
|
||||
|
||||
PatchLine.Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
int getLineA() {
|
||||
return lineA;
|
||||
}
|
||||
|
||||
int getLineB() {
|
||||
return lineB;
|
||||
}
|
||||
}
|
@@ -16,12 +16,9 @@ package com.google.gerrit.client.patches;
|
||||
|
||||
import com.google.gwt.i18n.client.Messages;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface PatchMessages extends Messages {
|
||||
String expandBefore(int cnt);
|
||||
String expandAfter(int cnt);
|
||||
String draftSaved(Date when);
|
||||
String patchSkipRegion(String lineNumber);
|
||||
String fileNameWithShortcutKey(String file, String key);
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
expandBefore = +{0}⇧
|
||||
expandAfter = +{0}⇩
|
||||
draftSaved = Draft saved at {0,time,short}
|
||||
patchSkipRegion = ... skipped {0} common lines ...
|
||||
fileNameWithShortcutKey = {0} (Shortcut: {1})
|
||||
|
@@ -1,3 +1,4 @@
|
||||
expandBefore = +{0}⇧
|
||||
expandAfter = +{0}⇩
|
||||
patchSkipRegion = ... skipped {0} common lines ...
|
||||
fileNameWithShortcutKey = {0} (Shortcut: {1})
|
||||
|
@@ -1,347 +0,0 @@
|
||||
// Copyright (C) 2010 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.patches;
|
||||
|
||||
import com.google.gerrit.client.ErrorDialog;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.account.Util;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
|
||||
import com.google.gerrit.client.ui.NpIntTextBox;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.NodeList;
|
||||
import com.google.gwt.dom.client.OptionElement;
|
||||
import com.google.gwt.dom.client.SelectElement;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.event.dom.client.KeyPressHandler;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.uibinder.client.UiHandler;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FocusWidget;
|
||||
import com.google.gwt.user.client.ui.HasWidgets;
|
||||
import com.google.gwt.user.client.ui.ListBox;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwtjsonrpc.common.VoidResult;
|
||||
|
||||
public class PatchScriptSettingsPanel extends Composite {
|
||||
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
|
||||
|
||||
interface MyUiBinder extends UiBinder<Widget, PatchScriptSettingsPanel> {
|
||||
}
|
||||
|
||||
private final ListenableAccountDiffPreference listenablePrefs;
|
||||
private boolean enableIntralineDifference = true;
|
||||
private boolean enableSmallFileFeatures = true;
|
||||
|
||||
@UiField
|
||||
ListBox ignoreWhitespace;
|
||||
|
||||
@UiField
|
||||
NpIntTextBox tabWidth;
|
||||
|
||||
@UiField
|
||||
NpIntTextBox colWidth;
|
||||
|
||||
@UiField
|
||||
CheckBox syntaxHighlighting;
|
||||
|
||||
@UiField
|
||||
CheckBox intralineDifference;
|
||||
|
||||
@UiField
|
||||
ListBox context;
|
||||
|
||||
@UiField
|
||||
CheckBox whitespaceErrors;
|
||||
|
||||
@UiField
|
||||
CheckBox showLineEndings;
|
||||
|
||||
@UiField
|
||||
CheckBox showTabs;
|
||||
|
||||
@UiField
|
||||
CheckBox manualReview;
|
||||
|
||||
@UiField
|
||||
CheckBox skipDeleted;
|
||||
|
||||
@UiField
|
||||
CheckBox skipUncommented;
|
||||
|
||||
@UiField
|
||||
CheckBox expandAllComments;
|
||||
|
||||
@UiField
|
||||
CheckBox retainHeader;
|
||||
|
||||
@UiField
|
||||
Button update;
|
||||
|
||||
@UiField
|
||||
Button save;
|
||||
|
||||
/**
|
||||
* Counts +1 for every setEnabled(true) and -1 for every setEnabled(false)
|
||||
*
|
||||
* The purpose is to prevent enabling widgets too early. It might happen that
|
||||
* setEnabled(false) is called from this class and from an event handler
|
||||
* of ValueChangeEvent in another class. The first setEnabled(true) would then
|
||||
* enable widgets too early i.e. before the second setEnabled(true) is called.
|
||||
*
|
||||
* With this counter the setEnabled(true) will enable widgets only when
|
||||
* setEnabledCounter == 0. Until it is less than zero setEnabled(true) will
|
||||
* not enable the widgets.
|
||||
*/
|
||||
private int setEnabledCounter;
|
||||
|
||||
public PatchScriptSettingsPanel(ListenableAccountDiffPreference prefs) {
|
||||
listenablePrefs = prefs;
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
initIgnoreWhitespace(ignoreWhitespace);
|
||||
initContext(context);
|
||||
if (!Gerrit.isSignedIn()) {
|
||||
save.setVisible(false);
|
||||
}
|
||||
|
||||
KeyPressHandler onEnter = new KeyPressHandler() {
|
||||
@Override
|
||||
public void onKeyPress(KeyPressEvent event) {
|
||||
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
};
|
||||
tabWidth.addKeyPressHandler(onEnter);
|
||||
colWidth.addKeyPressHandler(onEnter);
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean on) {
|
||||
if (on) {
|
||||
setEnabledCounter++;
|
||||
} else {
|
||||
setEnabledCounter--;
|
||||
}
|
||||
if (on && setEnabledCounter == 0 || !on) {
|
||||
for (Widget w : (HasWidgets) getWidget()) {
|
||||
if (w instanceof FocusWidget) {
|
||||
((FocusWidget) w).setEnabled(on);
|
||||
}
|
||||
}
|
||||
toggleEnabledStatus(on);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnableSmallFileFeatures(final boolean on) {
|
||||
enableSmallFileFeatures = on;
|
||||
if (enableSmallFileFeatures) {
|
||||
syntaxHighlighting.setValue(getValue().syntaxHighlighting);
|
||||
} else {
|
||||
syntaxHighlighting.setValue(false);
|
||||
}
|
||||
|
||||
NodeList<OptionElement> options =
|
||||
context.getElement().<SelectElement>cast().getOptions();
|
||||
// WHOLE_FILE_CONTEXT is the last option in the list.
|
||||
int lastIndex = options.getLength() - 1;
|
||||
OptionElement currOption = options.getItem(lastIndex);
|
||||
if (enableSmallFileFeatures) {
|
||||
currOption.setDisabled(false);
|
||||
} else {
|
||||
currOption.setDisabled(true);
|
||||
if (context.getSelectedIndex() == lastIndex) {
|
||||
// Select the next longest context from WHOLE_FILE_CONTEXT
|
||||
context.setSelectedIndex(lastIndex - 1);
|
||||
}
|
||||
}
|
||||
toggleEnabledStatus(save.isEnabled());
|
||||
}
|
||||
|
||||
public void setEnableIntralineDifference(final boolean on) {
|
||||
enableIntralineDifference = on;
|
||||
if (enableIntralineDifference) {
|
||||
intralineDifference.setValue(getValue().intralineDifference);
|
||||
} else {
|
||||
intralineDifference.setValue(false);
|
||||
}
|
||||
toggleEnabledStatus(save.isEnabled());
|
||||
}
|
||||
|
||||
private void toggleEnabledStatus(final boolean on) {
|
||||
intralineDifference.setEnabled(on & enableIntralineDifference);
|
||||
syntaxHighlighting.setEnabled(on & enableSmallFileFeatures);
|
||||
|
||||
final String title =
|
||||
enableSmallFileFeatures ? null : PatchUtil.C.disabledOnLargeFiles();
|
||||
syntaxHighlighting.setTitle(title);
|
||||
}
|
||||
|
||||
public DiffPreferencesInfo getValue() {
|
||||
return listenablePrefs.get();
|
||||
}
|
||||
|
||||
public void setValue(final DiffPreferencesInfo dp) {
|
||||
listenablePrefs.set(dp);
|
||||
display();
|
||||
}
|
||||
|
||||
protected void display() {
|
||||
final DiffPreferencesInfo dp = getValue();
|
||||
setIgnoreWhitespace(dp.ignoreWhitespace);
|
||||
if (enableSmallFileFeatures) {
|
||||
syntaxHighlighting.setValue(dp.syntaxHighlighting);
|
||||
} else {
|
||||
syntaxHighlighting.setValue(false);
|
||||
}
|
||||
setContext(dp.context);
|
||||
|
||||
tabWidth.setIntValue(dp.tabSize);
|
||||
colWidth.setIntValue(dp.lineLength);
|
||||
intralineDifference.setValue(dp.intralineDifference);
|
||||
whitespaceErrors.setValue(dp.showWhitespaceErrors);
|
||||
showLineEndings.setValue(dp.showLineEndings);
|
||||
showTabs.setValue(dp.showTabs);
|
||||
skipDeleted.setValue(dp.skipDeleted);
|
||||
skipUncommented.setValue(dp.skipUncommented);
|
||||
expandAllComments.setValue(dp.expandAllComments);
|
||||
retainHeader.setValue(dp.retainHeader);
|
||||
manualReview.setValue(dp.manualReview);
|
||||
}
|
||||
|
||||
@UiHandler("update")
|
||||
void onUpdate(@SuppressWarnings("unused") ClickEvent event) {
|
||||
update();
|
||||
}
|
||||
|
||||
@UiHandler("save")
|
||||
void onSave(@SuppressWarnings("unused") ClickEvent event) {
|
||||
save();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (colWidth.getIntValue() <= 0) {
|
||||
new ErrorDialog(PatchUtil.C.illegalNumberOfColumns()).center();
|
||||
return;
|
||||
}
|
||||
DiffPreferencesInfo dp = getValue();
|
||||
dp.ignoreWhitespace = getIgnoreWhitespace();
|
||||
dp.context = getContext();
|
||||
dp.tabSize = tabWidth.getIntValue();
|
||||
dp.lineLength = colWidth.getIntValue();
|
||||
dp.syntaxHighlighting = syntaxHighlighting.getValue();
|
||||
dp.intralineDifference = intralineDifference.getValue();
|
||||
dp.showWhitespaceErrors = whitespaceErrors.getValue();
|
||||
dp.showLineEndings = showLineEndings.getValue();
|
||||
dp.showTabs = showTabs.getValue();
|
||||
dp.skipDeleted = skipDeleted.getValue();
|
||||
dp.skipUncommented = skipUncommented.getValue();
|
||||
dp.expandAllComments = expandAllComments.getValue();
|
||||
dp.retainHeader = retainHeader.getValue();
|
||||
dp.manualReview = manualReview.getValue();
|
||||
|
||||
listenablePrefs.set(dp);
|
||||
}
|
||||
|
||||
private void save() {
|
||||
update();
|
||||
if (Gerrit.isSignedIn()) {
|
||||
persistDiffPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
private void persistDiffPreferences() {
|
||||
setEnabled(false);
|
||||
listenablePrefs.save(new GerritCallback<VoidResult>() {
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
setEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initIgnoreWhitespace(ListBox ws) {
|
||||
ws.addItem(PatchUtil.C.whitespaceIGNORE_NONE(), //
|
||||
Whitespace.IGNORE_NONE.name());
|
||||
ws.addItem(PatchUtil.C.whitespaceIGNORE_TRAILING(), //
|
||||
Whitespace.IGNORE_TRAILING.name());
|
||||
ws.addItem(PatchUtil.C.whitespaceIGNORE_LEADING_AND_TRAILING(), //
|
||||
Whitespace.IGNORE_LEADING_AND_TRAILING.name());
|
||||
ws.addItem(PatchUtil.C.whitespaceIGNORE_ALL(), //
|
||||
Whitespace.IGNORE_ALL.name());
|
||||
}
|
||||
|
||||
private void initContext(ListBox context) {
|
||||
for (final short v : DiffPreferencesInfo.CONTEXT_CHOICES) {
|
||||
final String label;
|
||||
if (v == DiffPreferencesInfo.WHOLE_FILE_CONTEXT) {
|
||||
label = Util.C.contextWholeFile();
|
||||
} else {
|
||||
label = Util.M.lines(v);
|
||||
}
|
||||
context.addItem(label, String.valueOf(v));
|
||||
}
|
||||
}
|
||||
|
||||
private Whitespace getIgnoreWhitespace() {
|
||||
final int sel = ignoreWhitespace.getSelectedIndex();
|
||||
if (0 <= sel) {
|
||||
return Whitespace.valueOf(ignoreWhitespace.getValue(sel));
|
||||
}
|
||||
return getValue().ignoreWhitespace;
|
||||
}
|
||||
|
||||
private void setIgnoreWhitespace(Whitespace s) {
|
||||
for (int i = 0; i < ignoreWhitespace.getItemCount(); i++) {
|
||||
if (ignoreWhitespace.getValue(i).equals(s.name())) {
|
||||
ignoreWhitespace.setSelectedIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ignoreWhitespace.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
private int getContext() {
|
||||
final int sel = context.getSelectedIndex();
|
||||
if (0 <= sel) {
|
||||
return Short.parseShort(context.getValue(sel));
|
||||
}
|
||||
return getValue().context;
|
||||
}
|
||||
|
||||
private void setContext(int ctx) {
|
||||
String v = String.valueOf(ctx);
|
||||
for (int i = 0; i < context.getItemCount(); i++) {
|
||||
if (context.getValue(i).equals(v)) {
|
||||
context.setSelectedIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
context.setSelectedIndex(0);
|
||||
}
|
||||
}
|
@@ -1,209 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2010 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.
|
||||
-->
|
||||
<ui:UiBinder
|
||||
xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:my='urn:import:com.google.gerrit.client.ui'
|
||||
ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
|
||||
ui:generateKeys='com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator'
|
||||
ui:generateLocales='default,en'
|
||||
>
|
||||
<ui:style gss='false'>
|
||||
@external .gwt-TextBox;
|
||||
@external .gwt-ListBox;
|
||||
|
||||
@def fontSize 8pt;
|
||||
|
||||
.controls {
|
||||
border: none;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.controls td {
|
||||
font-size: fontSize;
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.controls .gwt-TextBox {
|
||||
font-size: fontSize;
|
||||
padding: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.controls .gwt-ListBox {
|
||||
font-size: fontSize;
|
||||
padding: 0;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.updateButton {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
font-size: fontSize;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:HTMLPanel>
|
||||
<table class='{style.controls}'>
|
||||
<tr valign='top'>
|
||||
<ui:msg>
|
||||
<td align='right'>Ignore Whitespace:</td>
|
||||
<td align='right'>
|
||||
<g:ListBox
|
||||
ui:field='ignoreWhitespace'
|
||||
visibleItemCount='1'
|
||||
tabIndex='1'/>
|
||||
</td>
|
||||
</ui:msg>
|
||||
|
||||
<td align='right'>
|
||||
<ui:msg>Tab Width:
|
||||
<my:NpIntTextBox
|
||||
ui:field='tabWidth'
|
||||
width='2em'
|
||||
visibleLength='2'
|
||||
maxLength='2'
|
||||
tabIndex='3'/>
|
||||
</ui:msg>
|
||||
</td>
|
||||
|
||||
<td rowspan='2'>
|
||||
<g:CheckBox
|
||||
ui:field='syntaxHighlighting'
|
||||
text='Syntax Coloring'
|
||||
tabIndex='5'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
<br/>
|
||||
<g:CheckBox
|
||||
ui:field='intralineDifference'
|
||||
text='Intraline Difference'
|
||||
tabIndex='6'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
</td>
|
||||
|
||||
<td rowspan='2'>
|
||||
<g:CheckBox
|
||||
ui:field='whitespaceErrors'
|
||||
text='Whitespace Errors'
|
||||
tabIndex='7'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
<br/>
|
||||
<g:CheckBox
|
||||
ui:field='showLineEndings'
|
||||
text='Show Line Endings'
|
||||
tabIndex='8'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
</td>
|
||||
|
||||
<td rowspan='2'>
|
||||
<g:CheckBox
|
||||
ui:field='showTabs'
|
||||
text='Show Tabs'
|
||||
tabIndex='9'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
<br/>
|
||||
<g:CheckBox
|
||||
ui:field='expandAllComments'
|
||||
text='Expand All Comments'
|
||||
tabIndex='10'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
</td>
|
||||
|
||||
<td rowspan='2'>
|
||||
<g:CheckBox
|
||||
ui:field='retainHeader'
|
||||
text='Retain Header On File Switch'
|
||||
tabIndex='11'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
<br/>
|
||||
<g:CheckBox
|
||||
ui:field='skipUncommented'
|
||||
text='Skip Uncommented Files'
|
||||
tabIndex='12'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
</td>
|
||||
|
||||
<td valign='bottom' rowspan='2'>
|
||||
<g:CheckBox
|
||||
ui:field='skipDeleted'
|
||||
text='Skip Deleted Files'
|
||||
tabIndex='13'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
<br/>
|
||||
<g:CheckBox
|
||||
ui:field='manualReview'
|
||||
text='Manual Review'
|
||||
tabIndex='14'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:CheckBox>
|
||||
</td>
|
||||
|
||||
<td rowspan='2'>
|
||||
<br/>
|
||||
<g:Button
|
||||
ui:field='update'
|
||||
text='Update'
|
||||
styleName='{style.updateButton}'
|
||||
tabIndex='15'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:Button>
|
||||
<g:Button
|
||||
ui:field='save'
|
||||
text='Save'
|
||||
styleName='{style.updateButton}'
|
||||
tabIndex='16'>
|
||||
<ui:attribute name='text'/>
|
||||
</g:Button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr valign='top'>
|
||||
<ui:msg>
|
||||
<td align='right'>Context:</td>
|
||||
<td align='right'>
|
||||
<g:ListBox
|
||||
ui:field='context'
|
||||
visibleItemCount='1'
|
||||
tabIndex='2'/>
|
||||
</td>
|
||||
</ui:msg>
|
||||
|
||||
<td align='right'>
|
||||
<ui:msg>Columns:
|
||||
<my:NpIntTextBox
|
||||
ui:field='colWidth'
|
||||
width='2.5em'
|
||||
visibleLength='3'
|
||||
maxLength='3'
|
||||
tabIndex='4'/>
|
||||
</ui:msg>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
@@ -1,188 +0,0 @@
|
||||
// Copyright (C) 2012 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Dispatcher;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.common.data.PatchScript;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.DoubleClickEvent;
|
||||
import com.google.gwt.event.dom.client.DoubleClickHandler;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.DOM;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HTMLPanel;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwtorm.client.KeyUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PatchSetSelectBox extends Composite {
|
||||
interface Binder extends UiBinder<HTMLPanel, PatchSetSelectBox> {}
|
||||
private static final Binder uiBinder = GWT.create(Binder.class);
|
||||
|
||||
interface BoxStyle extends CssResource {
|
||||
String selected();
|
||||
String hidden();
|
||||
String sideMarker();
|
||||
String patchSetLabel();
|
||||
}
|
||||
|
||||
public enum Side {
|
||||
A, B
|
||||
}
|
||||
|
||||
PatchScript script;
|
||||
Patch.Key patchKey;
|
||||
PatchSet.Id idSideA;
|
||||
PatchSet.Id idSideB;
|
||||
PatchSet.Id idActive;
|
||||
Side side;
|
||||
Map<Integer, Anchor> links;
|
||||
private Label patchSet;
|
||||
|
||||
@UiField
|
||||
HTMLPanel linkPanel;
|
||||
|
||||
@UiField
|
||||
BoxStyle style;
|
||||
|
||||
public PatchSetSelectBox(Side side) {
|
||||
this.side = side;
|
||||
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
}
|
||||
|
||||
public void display(final PatchSetDetail detail, final PatchScript script,
|
||||
Patch.Key key, PatchSet.Id idSideA, PatchSet.Id idSideB) {
|
||||
this.script = script;
|
||||
this.patchKey = key;
|
||||
this.idSideA = idSideA;
|
||||
this.idSideB = idSideB;
|
||||
this.idActive = (side == Side.A) ? idSideA : idSideB;
|
||||
this.links = new HashMap<>();
|
||||
|
||||
linkPanel.clear();
|
||||
|
||||
if (isFileOrCommitMessage()) {
|
||||
linkPanel.setTitle(PatchUtil.C.addFileCommentByDoubleClick());
|
||||
}
|
||||
|
||||
patchSet = new Label(PatchUtil.C.patchSet());
|
||||
patchSet.addStyleName(style.patchSetLabel());
|
||||
linkPanel.add(patchSet);
|
||||
|
||||
Label sideMarker = new Label((side == Side.A) ? "(-)" : "(+)");
|
||||
sideMarker.addStyleName(style.sideMarker());
|
||||
linkPanel.add(sideMarker);
|
||||
|
||||
Anchor baseLink;
|
||||
if (detail.getInfo().getParents().size() > 1) {
|
||||
baseLink = createLink(PatchUtil.C.patchBaseAutoMerge(), null);
|
||||
} else {
|
||||
baseLink = createLink(PatchUtil.C.patchBase(), null);
|
||||
}
|
||||
|
||||
links.put(0, baseLink);
|
||||
linkPanel.add(baseLink);
|
||||
|
||||
if (side == Side.B) {
|
||||
links.get(0).setStyleName(style.hidden());
|
||||
}
|
||||
|
||||
for (Patch patch : script.getHistory()) {
|
||||
PatchSet.Id psId = patch.getKey().getParentKey();
|
||||
Anchor anchor = createLink(psId.getId(), psId);
|
||||
links.put(psId.get(), anchor);
|
||||
linkPanel.add(anchor);
|
||||
}
|
||||
|
||||
if (idActive == null && side == Side.A) {
|
||||
links.get(0).setStyleName(style.selected());
|
||||
} else if (idActive != null) {
|
||||
links.get(idActive.get()).setStyleName(style.selected());
|
||||
}
|
||||
|
||||
Anchor downloadLink = createDownloadLink();
|
||||
if (downloadLink != null) {
|
||||
linkPanel.add(downloadLink);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDoubleClickHandler(DoubleClickHandler handler) {
|
||||
linkPanel.sinkEvents(Event.ONDBLCLICK);
|
||||
linkPanel.addHandler(handler, DoubleClickEvent.getType());
|
||||
patchSet.addDoubleClickHandler(handler);
|
||||
}
|
||||
|
||||
private Anchor createLink(String label, final PatchSet.Id id) {
|
||||
final Anchor anchor = new Anchor(label);
|
||||
anchor.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
if (side == Side.A) {
|
||||
idSideA = id;
|
||||
} else {
|
||||
idSideB = id;
|
||||
}
|
||||
|
||||
Patch.Key keySideB = new Patch.Key(idSideB, patchKey.get());
|
||||
Gerrit.display(Dispatcher.toUnified(idSideA, keySideB));
|
||||
}
|
||||
});
|
||||
return anchor;
|
||||
}
|
||||
|
||||
public boolean isFileOrCommitMessage() {
|
||||
return !((side == Side.A && 0 >= script.getA().size()) || //
|
||||
(side == Side.B && 0 >= script.getB().size()));
|
||||
}
|
||||
|
||||
private Anchor createDownloadLink() {
|
||||
boolean isCommitMessage = Patch.COMMIT_MSG.equals(script.getNewName());
|
||||
if (isCommitMessage || //
|
||||
(side == Side.A && 0 >= script.getA().size()) || //
|
||||
(side == Side.B && 0 >= script.getB().size())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Patch.Key key = (idActive == null) ? //
|
||||
patchKey : (new Patch.Key(idActive, patchKey.get()));
|
||||
|
||||
String sideURL = (idActive == null) ? "1" : "0";
|
||||
final String base = GWT.getHostPageBaseURL() + "cat/";
|
||||
|
||||
Image image = new Image(Gerrit.RESOURCES.downloadIcon());
|
||||
|
||||
final Anchor anchor = new Anchor();
|
||||
anchor.setHref(base + KeyUtil.encode(key.toString()) + "^" + sideURL);
|
||||
anchor.setTitle(PatchUtil.C.download());
|
||||
DOM.insertBefore(anchor.getElement(), image.getElement(),
|
||||
DOM.getFirstChild(anchor.getElement()));
|
||||
|
||||
return anchor;
|
||||
}
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2012 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.
|
||||
-->
|
||||
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
|
||||
<ui:with field='res' type='com.google.gerrit.client.GerritResources'/>
|
||||
<ui:style gss='false' type='com.google.gerrit.client.patches.PatchSetSelectBox.BoxStyle'>
|
||||
@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
|
||||
@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
|
||||
|
||||
.linkPanel {
|
||||
font-size: 12px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.linkPanel > div {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.patchSetLabel {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sideMarker {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.linkPanel > a {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.selected {
|
||||
font-weight: bold;
|
||||
background-color: selectionColor;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:HTMLPanel>
|
||||
<g:HTMLPanel styleName='{style.linkPanel}' ui:field='linkPanel'/>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
|
@@ -1,901 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Dispatcher;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.ui.InlineHyperlink;
|
||||
import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
|
||||
import com.google.gerrit.client.ui.NavigationTable;
|
||||
import com.google.gerrit.client.ui.PatchLink;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
|
||||
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.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwt.user.client.Command;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.Cell;
|
||||
import com.google.gwt.user.client.ui.Image;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommand;
|
||||
import com.google.gwtexpui.progress.client.ProgressBar;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
class PatchTable extends Composite {
|
||||
interface PatchValidator {
|
||||
/**
|
||||
* @param patch
|
||||
* @return true if patch is valid.
|
||||
*/
|
||||
boolean isValid(Patch patch);
|
||||
}
|
||||
|
||||
final PatchValidator PREFERENCE_VALIDATOR =
|
||||
new PatchValidator() {
|
||||
@Override
|
||||
public boolean isValid(Patch patch) {
|
||||
return !((listenablePrefs.get().skipDeleted
|
||||
&& patch.getChangeType().equals(ChangeType.DELETED))
|
||||
|| (listenablePrefs.get().skipUncommented
|
||||
&& patch.getCommentCount() == 0));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private final FlowPanel myBody;
|
||||
private PatchSetDetail detail;
|
||||
private Command onLoadCommand;
|
||||
private MyTable myTable;
|
||||
private String savePointerId;
|
||||
private PatchSet.Id base;
|
||||
private List<Patch> patchList;
|
||||
private Map<Patch.Key, Integer> patchMap;
|
||||
private ListenableAccountDiffPreference listenablePrefs;
|
||||
|
||||
private List<ClickHandler> clickHandlers;
|
||||
private boolean active;
|
||||
private boolean registerKeys;
|
||||
|
||||
PatchTable(ListenableAccountDiffPreference prefs) {
|
||||
listenablePrefs = prefs;
|
||||
myBody = new FlowPanel();
|
||||
initWidget(myBody);
|
||||
}
|
||||
|
||||
PatchTable() {
|
||||
this(new ListenableAccountDiffPreference());
|
||||
}
|
||||
|
||||
int indexOf(Patch.Key patch) {
|
||||
Integer i = patchMap().get(patch);
|
||||
return i != null ? i : -1;
|
||||
}
|
||||
|
||||
int size() {
|
||||
return patchMap.size();
|
||||
}
|
||||
|
||||
private Map<Patch.Key, Integer> patchMap() {
|
||||
if (patchMap == null) {
|
||||
patchMap = new HashMap<>();
|
||||
for (int i = 0; i < patchList.size(); i++) {
|
||||
patchMap.put(patchList.get(i).getKey(), i);
|
||||
}
|
||||
}
|
||||
return patchMap;
|
||||
}
|
||||
|
||||
void display(PatchSet.Id base, PatchSetDetail detail) {
|
||||
this.base = base;
|
||||
this.detail = detail;
|
||||
this.patchList = detail.getPatches();
|
||||
this.patchMap = null;
|
||||
myTable = null;
|
||||
|
||||
final DisplayCommand cmd = new DisplayCommand(patchList, base);
|
||||
if (cmd.execute()) {
|
||||
cmd.initMeter();
|
||||
Scheduler.get().scheduleIncremental(cmd);
|
||||
} else {
|
||||
cmd.showTable();
|
||||
}
|
||||
}
|
||||
|
||||
PatchSet.Id getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
void setSavePointerId(final String id) {
|
||||
savePointerId = id;
|
||||
}
|
||||
|
||||
boolean isLoaded() {
|
||||
return myTable != null;
|
||||
}
|
||||
|
||||
void onTableLoaded(final Command cmd) {
|
||||
if (myTable != null) {
|
||||
cmd.execute();
|
||||
} else {
|
||||
onLoadCommand = cmd;
|
||||
}
|
||||
}
|
||||
|
||||
void addClickHandler(final ClickHandler clickHandler) {
|
||||
if (myTable != null) {
|
||||
myTable.addClickHandler(clickHandler);
|
||||
} else {
|
||||
if (clickHandlers == null) {
|
||||
clickHandlers = new ArrayList<>(2);
|
||||
}
|
||||
clickHandlers.add(clickHandler);
|
||||
}
|
||||
}
|
||||
|
||||
void setRegisterKeys(final boolean on) {
|
||||
registerKeys = on;
|
||||
if (myTable != null) {
|
||||
myTable.setRegisterKeys(on);
|
||||
}
|
||||
}
|
||||
|
||||
void movePointerTo(final Patch.Key k) {
|
||||
if (myTable != null) {
|
||||
myTable.movePointerTo(k);
|
||||
}
|
||||
}
|
||||
|
||||
void setActive(boolean active) {
|
||||
this.active = active;
|
||||
if (myTable != null) {
|
||||
myTable.setActive(active);
|
||||
}
|
||||
}
|
||||
|
||||
void notifyDraftDelta(final Patch.Key k, final int delta) {
|
||||
if (myTable != null) {
|
||||
myTable.notifyDraftDelta(k, delta);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMyTable(MyTable table) {
|
||||
myBody.clear();
|
||||
myBody.add(table);
|
||||
myTable = table;
|
||||
|
||||
if (clickHandlers != null) {
|
||||
for (ClickHandler ch : clickHandlers) {
|
||||
myTable.addClickHandler(ch);
|
||||
}
|
||||
clickHandlers = null;
|
||||
}
|
||||
|
||||
if (active) {
|
||||
myTable.setActive(true);
|
||||
active = false;
|
||||
}
|
||||
|
||||
if (registerKeys) {
|
||||
myTable.setRegisterKeys(registerKeys);
|
||||
registerKeys = false;
|
||||
}
|
||||
|
||||
myTable.finishDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a link to the previous file in this patch set, or null.
|
||||
*/
|
||||
InlineHyperlink getPreviousPatchLink(int index) {
|
||||
int previousPatchIndex = getPreviousPatch(index, PREFERENCE_VALIDATOR);
|
||||
if (previousPatchIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return createLink(previousPatchIndex,
|
||||
SafeHtml.asis(Util.C.prevPatchLinkIcon()), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a link to the next file in this patch set, or null.
|
||||
*/
|
||||
InlineHyperlink getNextPatchLink(int index) {
|
||||
int nextPatchIndex = getNextPatch(index, false, PREFERENCE_VALIDATOR);
|
||||
if (nextPatchIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
return createLink(nextPatchIndex, null,
|
||||
SafeHtml.asis(Util.C.nextPatchLinkIcon()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a link to the the given patch.
|
||||
* @param index The patch to link to
|
||||
* @param before A string to display at the beginning of the href text
|
||||
* @param after A string to display at the end of the href text
|
||||
*/
|
||||
PatchLink createLink(int index, SafeHtml before, SafeHtml after) {
|
||||
Patch patch = patchList.get(index);
|
||||
Patch.Key thisKey = patch.getKey();
|
||||
PatchLink link;
|
||||
|
||||
if (isUnifiedPatchLink(patch)) {
|
||||
link = new PatchLink.Unified("", base, thisKey);
|
||||
} else {
|
||||
link = new PatchLink.SideBySide("", base, thisKey);
|
||||
}
|
||||
|
||||
SafeHtmlBuilder text = new SafeHtmlBuilder();
|
||||
text.append(before);
|
||||
text.append(getFileNameOnly(patch));
|
||||
text.append(after);
|
||||
SafeHtml.set(link, text);
|
||||
return link;
|
||||
}
|
||||
|
||||
private static boolean isUnifiedPatchLink(final Patch patch) {
|
||||
return (patch.getPatchType().equals(PatchType.BINARY)
|
||||
|| (Gerrit.isSignedIn()
|
||||
&& Gerrit.getUserPreferences().diffView()
|
||||
.equals(DiffView.UNIFIED_DIFF)));
|
||||
}
|
||||
|
||||
private static String getFileNameOnly(Patch patch) {
|
||||
// Note: use '/' here and not File.pathSeparator since git paths
|
||||
// are always separated by /
|
||||
//
|
||||
String fileName = getDisplayFileName(patch);
|
||||
int s = fileName.lastIndexOf('/');
|
||||
if (s >= 0) {
|
||||
fileName = fileName.substring(s + 1);
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
||||
static String getDisplayFileName(Patch patch) {
|
||||
return getDisplayFileName(patch.getKey());
|
||||
}
|
||||
|
||||
static String getDisplayFileName(Patch.Key patchKey) {
|
||||
if (Patch.COMMIT_MSG.equals(patchKey.get())) {
|
||||
return Util.C.commitMessage();
|
||||
}
|
||||
return patchKey.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the reviewed status for the given patch.
|
||||
*/
|
||||
void updateReviewedStatus(Patch.Key patchKey, boolean reviewed) {
|
||||
if (myTable != null) {
|
||||
myTable.updateReviewedStatus(patchKey, reviewed);
|
||||
}
|
||||
}
|
||||
|
||||
ListenableAccountDiffPreference getPreferences() {
|
||||
return listenablePrefs;
|
||||
}
|
||||
|
||||
private class MyTable extends NavigationTable<Patch> {
|
||||
private static final int C_PATH = 2;
|
||||
private static final int C_DRAFT = 3;
|
||||
private static final int C_SIZE = 4;
|
||||
private static final int C_SIDEBYSIDE = 5;
|
||||
private int activeRow = -1;
|
||||
|
||||
MyTable() {
|
||||
keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.patchTablePrev()));
|
||||
keysNavigation.add(new NextKeyCommand(0, 'j', Util.C.patchTableNext()));
|
||||
keysNavigation.add(new OpenKeyCommand(0, 'o', Util.C.patchTableOpenDiff()));
|
||||
keysNavigation.add(new OpenKeyCommand(0, KeyCodes.KEY_ENTER, Util.C
|
||||
.patchTableOpenDiff()));
|
||||
keysNavigation.add(new OpenUnifiedDiffKeyCommand(0, 'O', Util.C
|
||||
.patchTableOpenUnifiedDiff()));
|
||||
|
||||
table.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(final ClickEvent event) {
|
||||
final Cell cell = table.getCellForEvent(event);
|
||||
if (cell != null && cell.getRowIndex() > 0) {
|
||||
movePointerTo(cell.getRowIndex());
|
||||
}
|
||||
}
|
||||
});
|
||||
setSavePointerId(PatchTable.this.savePointerId);
|
||||
}
|
||||
|
||||
public void addClickHandler(final ClickHandler clickHandler) {
|
||||
table.addClickHandler(clickHandler);
|
||||
}
|
||||
|
||||
void updateReviewedStatus(final Patch.Key patchKey, boolean reviewed) {
|
||||
int idx = patchMap().get(patchKey);
|
||||
if (0 <= idx) {
|
||||
Patch patch = patchList.get(idx);
|
||||
if (patch.isReviewedByCurrentUser() != reviewed) {
|
||||
int row = idx + 1;
|
||||
int col = C_SIDEBYSIDE + 2;
|
||||
if (patch.getPatchType() == Patch.PatchType.BINARY) {
|
||||
col = C_SIDEBYSIDE + 3;
|
||||
}
|
||||
if (reviewed) {
|
||||
table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
|
||||
} else {
|
||||
table.clearCell(row, col);
|
||||
}
|
||||
patch.setReviewedByCurrentUser(reviewed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notifyDraftDelta(final Patch.Key key, final int delta) {
|
||||
int idx = patchMap().get(key);
|
||||
if (0 <= idx) {
|
||||
Patch p = patchList.get(idx);
|
||||
p.setDraftCount(p.getDraftCount() + delta);
|
||||
SafeHtmlBuilder m = new SafeHtmlBuilder();
|
||||
appendCommentCount(m, p);
|
||||
SafeHtml.set(table, idx + 1, C_DRAFT, m);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetHtml(final SafeHtml html) {
|
||||
super.resetHtml(html);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void movePointerTo(Object oldId) {
|
||||
super.movePointerTo(oldId);
|
||||
}
|
||||
|
||||
/** Activates / Deactivates the key navigation and the highlighting of the current row for this table */
|
||||
void setActive(boolean active) {
|
||||
if (active) {
|
||||
if(activeRow > 0 && getCurrentRow() != activeRow) {
|
||||
super.movePointerTo(activeRow);
|
||||
activeRow = -1;
|
||||
}
|
||||
} else {
|
||||
if(getCurrentRow() > 0) {
|
||||
activeRow = getCurrentRow();
|
||||
super.movePointerTo(-1);
|
||||
}
|
||||
}
|
||||
setRegisterKeys(active);
|
||||
}
|
||||
|
||||
void initializeRow(int row) {
|
||||
Patch patch = PatchTable.this.patchList.get(row - 1);
|
||||
setRowItem(row, patch);
|
||||
|
||||
Widget nameCol = new PatchLink.SideBySide(getDisplayFileName(patch), base,
|
||||
patch.getKey());
|
||||
|
||||
if (patch.getSourceFileName() != null) {
|
||||
final String text;
|
||||
if (patch.getChangeType() == Patch.ChangeType.RENAMED) {
|
||||
text = Util.M.renamedFrom(patch.getSourceFileName());
|
||||
} else if (patch.getChangeType() == Patch.ChangeType.COPIED) {
|
||||
text = Util.M.copiedFrom(patch.getSourceFileName());
|
||||
} else {
|
||||
text = Util.M.otherFrom(patch.getSourceFileName());
|
||||
}
|
||||
final Label line = new Label(text);
|
||||
line.setStyleName(Gerrit.RESOURCES.css().sourceFilePath());
|
||||
final FlowPanel cell = new FlowPanel();
|
||||
cell.add(nameCol);
|
||||
cell.add(line);
|
||||
nameCol = cell;
|
||||
}
|
||||
table.setWidget(row, C_PATH, nameCol);
|
||||
|
||||
int C_UNIFIED = C_SIDEBYSIDE + 1;
|
||||
|
||||
PatchLink sideBySide = new PatchLink.SideBySide(
|
||||
Util.C.patchTableDiffSideBySide(), base, patch.getKey());
|
||||
sideBySide.setStyleName("gwt-Anchor");
|
||||
|
||||
PatchLink unified = new PatchLink.Unified(Util.C.patchTableDiffUnified(),
|
||||
base, patch.getKey());
|
||||
unified.setStyleName("gwt-Anchor");
|
||||
|
||||
table.setWidget(row, C_SIDEBYSIDE, sideBySide);
|
||||
table.setWidget(row, C_UNIFIED, unified);
|
||||
}
|
||||
|
||||
void initializeLastRow(int row) {
|
||||
Anchor sideBySide = new Anchor(Util.C.diffAllSideBySide());
|
||||
sideBySide.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
for (Patch p : detail.getPatches()) {
|
||||
openWindow(Dispatcher.toSideBySide(base, p.getKey()));
|
||||
}
|
||||
}
|
||||
});
|
||||
table.setWidget(row, C_SIDEBYSIDE - 2, sideBySide);
|
||||
|
||||
int C_UNIFIED = C_SIDEBYSIDE - 2 + 1;
|
||||
Anchor unified = new Anchor(Util.C.diffAllUnified());
|
||||
unified.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
for (Patch p : detail.getPatches()) {
|
||||
openWindow(Dispatcher.toUnified(base, p.getKey()));
|
||||
}
|
||||
}
|
||||
});
|
||||
table.setWidget(row, C_UNIFIED, unified);
|
||||
}
|
||||
|
||||
private void openWindow(String token) {
|
||||
String url = Window.Location.getPath() + "#" + token;
|
||||
Window.open(url, "_blank", null);
|
||||
}
|
||||
|
||||
void appendHeader(final SafeHtmlBuilder m) {
|
||||
m.openTr();
|
||||
|
||||
// Cursor
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().iconHeader());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
|
||||
m.nbsp();
|
||||
m.closeTd();
|
||||
|
||||
// Mode
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().iconHeader());
|
||||
m.nbsp();
|
||||
m.closeTd();
|
||||
|
||||
// "File path"
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
|
||||
m.append(Util.C.patchTableColumnName());
|
||||
m.closeTd();
|
||||
|
||||
// "Comments"
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
|
||||
m.append(Util.C.patchTableColumnComments());
|
||||
m.closeTd();
|
||||
|
||||
// "Size"
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
|
||||
m.append(Util.C.patchTableColumnSize());
|
||||
m.closeTd();
|
||||
|
||||
// "Diff"
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
|
||||
m.setAttribute("colspan", 3);
|
||||
m.append(Util.C.patchTableColumnDiff());
|
||||
m.closeTd();
|
||||
|
||||
// "Reviewed"
|
||||
if (Gerrit.isSignedIn()) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().iconHeader());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataHeader());
|
||||
m.append(Util.C.reviewed());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
m.closeTr();
|
||||
}
|
||||
|
||||
void appendRow(final SafeHtmlBuilder m, final Patch p,
|
||||
final boolean isReverseDiff) {
|
||||
m.openTr();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().iconCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
|
||||
m.nbsp();
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().changeTypeCell());
|
||||
if (isReverseDiff) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
|
||||
}
|
||||
|
||||
if (Patch.COMMIT_MSG.equals(p.getFileName())) {
|
||||
m.nbsp();
|
||||
} else {
|
||||
m.append(p.getChangeType().getCode());
|
||||
}
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().filePathCell());
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().commentCell());
|
||||
appendCommentCount(m, p);
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
|
||||
if (isReverseDiff) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
|
||||
}
|
||||
|
||||
appendSize(m, p);
|
||||
m.closeTd();
|
||||
|
||||
// Diff
|
||||
openlink(m, 2);
|
||||
m.closeTd();
|
||||
openlink(m, 1);
|
||||
m.closeTd();
|
||||
|
||||
// Green check mark if the user is logged in and they reviewed that file
|
||||
if (Gerrit.isSignedIn()) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
if (p.isReviewedByCurrentUser()) {
|
||||
m.openDiv();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().greenCheckClass());
|
||||
m.closeSelf();
|
||||
}
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
m.closeTr();
|
||||
}
|
||||
|
||||
void appendLastRow(final SafeHtmlBuilder m, int ins, int dels,
|
||||
final boolean isReverseDiff) {
|
||||
m.openTr();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().iconCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().noborder());
|
||||
m.nbsp();
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.setAttribute("colspan", C_SIZE - 1);
|
||||
m.closeTd();
|
||||
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
|
||||
|
||||
if (isReverseDiff) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
|
||||
}
|
||||
|
||||
m.append(Util.M.patchTableSize_Modify(ins, dels));
|
||||
m.closeTd();
|
||||
|
||||
openlink(m, 2);
|
||||
m.closeTd();
|
||||
|
||||
openlink(m, 1);
|
||||
m.closeTd();
|
||||
|
||||
m.closeTr();
|
||||
}
|
||||
|
||||
void appendCommentCount(final SafeHtmlBuilder m, final Patch p) {
|
||||
if (p.getCommentCount() > 0) {
|
||||
m.append(Util.M.patchTableComments(p.getCommentCount()));
|
||||
}
|
||||
if (p.getDraftCount() > 0) {
|
||||
if (p.getCommentCount() > 0) {
|
||||
m.append(", ");
|
||||
}
|
||||
m.openSpan();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().drafts());
|
||||
m.append(Util.M.patchTableDrafts(p.getDraftCount()));
|
||||
m.closeSpan();
|
||||
}
|
||||
}
|
||||
|
||||
void appendSize(final SafeHtmlBuilder m, final Patch p) {
|
||||
if (Patch.COMMIT_MSG.equals(p.getFileName())) {
|
||||
m.nbsp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.getPatchType() == PatchType.UNIFIED) {
|
||||
int ins = p.getInsertions();
|
||||
int dels = p.getDeletions();
|
||||
|
||||
switch (p.getChangeType()) {
|
||||
case ADDED:
|
||||
m.append(Util.M.patchTableSize_Lines(ins));
|
||||
break;
|
||||
|
||||
case DELETED:
|
||||
m.nbsp();
|
||||
break;
|
||||
|
||||
case MODIFIED:
|
||||
case COPIED:
|
||||
case RENAMED:
|
||||
m.append(Util.M.patchTableSize_Modify(ins, dels));
|
||||
break;
|
||||
|
||||
case REWRITE:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
m.nbsp();
|
||||
}
|
||||
}
|
||||
|
||||
private void openlink(final SafeHtmlBuilder m, final int colspan) {
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().dataCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffLinkCell());
|
||||
m.setAttribute("colspan", colspan);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getRowItemKey(final Patch item) {
|
||||
return item.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOpenRow(final int row) {
|
||||
Widget link = table.getWidget(row, C_PATH);
|
||||
if (link instanceof FlowPanel) {
|
||||
link = ((FlowPanel) link).getWidget(0);
|
||||
}
|
||||
if (link instanceof InlineHyperlink) {
|
||||
((InlineHyperlink) link).go();
|
||||
}
|
||||
}
|
||||
|
||||
private final class OpenUnifiedDiffKeyCommand extends KeyCommand {
|
||||
|
||||
public OpenUnifiedDiffKeyCommand(int mask, char key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(KeyPressEvent event) {
|
||||
Widget link = table.getWidget(getCurrentRow(), C_PATH);
|
||||
if (link instanceof FlowPanel) {
|
||||
link = ((FlowPanel) link).getWidget(0);
|
||||
}
|
||||
if (link instanceof PatchLink.Unified) {
|
||||
((InlineHyperlink) link).go();
|
||||
} else {
|
||||
link = table.getWidget(getCurrentRow(), C_SIDEBYSIDE + 1);
|
||||
if (link instanceof PatchLink.Unified) {
|
||||
((InlineHyperlink) link).go();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class DisplayCommand implements RepeatingCommand {
|
||||
private final MyTable table;
|
||||
private final List<Patch> list;
|
||||
private boolean attached;
|
||||
private SafeHtmlBuilder nc = new SafeHtmlBuilder();
|
||||
private int stage = 0;
|
||||
private int row;
|
||||
private double start;
|
||||
private ProgressBar meter;
|
||||
|
||||
private int insertions;
|
||||
private int deletions;
|
||||
|
||||
private final PatchSet.Id psIdToCompareWith;
|
||||
|
||||
private DisplayCommand(final List<Patch> list, final PatchSet.Id psIdToCompareWith) {
|
||||
this.table = new MyTable();
|
||||
this.list = list;
|
||||
this.psIdToCompareWith = psIdToCompareWith;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the files contained in the list of patches to the table, one per row.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public boolean execute() {
|
||||
final boolean attachedNow = isAttached();
|
||||
if (!attached && attachedNow) {
|
||||
// Remember that we have been attached at least once. If
|
||||
// later we find we aren't attached we should stop running.
|
||||
//
|
||||
attached = true;
|
||||
} else if (attached && !attachedNow) {
|
||||
// If the user navigated away, we aren't in the DOM anymore.
|
||||
// Don't continue to render.
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isReverseDiff = false;
|
||||
|
||||
if (psIdToCompareWith != null
|
||||
&& list.get(0).getKey().getParentKey().get() < psIdToCompareWith.get()) {
|
||||
isReverseDiff = true;
|
||||
}
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
switch (stage) {
|
||||
case 0:
|
||||
if (row == 0) {
|
||||
table.appendHeader(nc);
|
||||
table.appendRow(nc, list.get(row++), isReverseDiff);
|
||||
}
|
||||
while (row < list.size()) {
|
||||
Patch p = list.get(row);
|
||||
insertions += p.getInsertions();
|
||||
deletions += p.getDeletions();
|
||||
table.appendRow(nc, p, isReverseDiff);
|
||||
if ((++row % 10) == 0 && longRunning()) {
|
||||
updateMeter();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
table.appendLastRow(nc, insertions, deletions, isReverseDiff);
|
||||
table.resetHtml(nc);
|
||||
table.initializeLastRow(row + 1);
|
||||
nc = null;
|
||||
stage = 1;
|
||||
row = 0;
|
||||
|
||||
case 1:
|
||||
while (row < list.size()) {
|
||||
table.initializeRow(row + 1);
|
||||
if ((++row % 50) == 0 && longRunning()) {
|
||||
updateMeter();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
updateMeter();
|
||||
showTable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void showTable() {
|
||||
setMyTable(table);
|
||||
|
||||
if (PatchTable.this.onLoadCommand != null) {
|
||||
PatchTable.this.onLoadCommand.execute();
|
||||
PatchTable.this.onLoadCommand = null;
|
||||
}
|
||||
}
|
||||
|
||||
void initMeter() {
|
||||
if (meter == null) {
|
||||
meter = new ProgressBar(Util.M.loadingPatchSet(detail.getPatchSet().getId().get()));
|
||||
PatchTable.this.myBody.clear();
|
||||
PatchTable.this.myBody.add(meter);
|
||||
}
|
||||
updateMeter();
|
||||
}
|
||||
|
||||
void updateMeter() {
|
||||
if (meter != null) {
|
||||
final int n = list.size();
|
||||
meter.setValue(((100 * (stage * n + row)) / (2 * n)));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean longRunning() {
|
||||
return System.currentTimeMillis() - start > 200;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the next patch
|
||||
*
|
||||
* @param currentIndex
|
||||
* @param validators
|
||||
* @param loopAround loops back around to the front and traverses if this is
|
||||
* true
|
||||
* @return index of next valid patch, or -1 if no valid patches
|
||||
*/
|
||||
int getNextPatch(int currentIndex, boolean loopAround,
|
||||
PatchValidator... validators) {
|
||||
return getNextPatchHelper(currentIndex, loopAround, detail.getPatches()
|
||||
.size(), validators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for getNextPatch
|
||||
*
|
||||
* @param currentIndex
|
||||
* @param validators
|
||||
* @param loopAround
|
||||
* @param maxIndex will only traverse up to this index
|
||||
* @return index of next valid patch, or -1 if no valid patches
|
||||
*/
|
||||
private int getNextPatchHelper(int currentIndex, boolean loopAround,
|
||||
int maxIndex, PatchValidator... validators) {
|
||||
for (int i = currentIndex + 1; i < maxIndex; i++) {
|
||||
Patch patch = detail.getPatches().get(i);
|
||||
if (patch != null && patchIsValid(patch, validators)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (loopAround) {
|
||||
return getNextPatchHelper(-1, false, currentIndex, validators);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the index to the previous patch
|
||||
*/
|
||||
int getPreviousPatch(int currentIndex, PatchValidator... validators) {
|
||||
for (int i = currentIndex - 1; i >= 0; i--) {
|
||||
Patch patch = detail.getPatches().get(i);
|
||||
if (patch != null && patchIsValid(patch, validators)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns whether a patch is valid or not
|
||||
*
|
||||
* @param patch
|
||||
* @param validators
|
||||
* @return whether the patch is valid based on the validators
|
||||
*/
|
||||
private boolean patchIsValid(Patch patch, PatchValidator... validators) {
|
||||
for (PatchValidator v : validators) {
|
||||
if (!v.isValid(patch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -14,22 +14,9 @@
|
||||
|
||||
package com.google.gerrit.client.patches;
|
||||
|
||||
import com.google.gerrit.common.data.ChangeDetailService;
|
||||
import com.google.gerrit.common.data.PatchDetailService;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwtjsonrpc.client.JsonUtil;
|
||||
|
||||
public class PatchUtil {
|
||||
public static final PatchConstants C = GWT.create(PatchConstants.class);
|
||||
public static final PatchMessages M = GWT.create(PatchMessages.class);
|
||||
public static final ChangeDetailService CHANGE_SVC;
|
||||
public static final PatchDetailService PATCH_SVC;
|
||||
|
||||
static {
|
||||
CHANGE_SVC = GWT.create(ChangeDetailService.class);
|
||||
JsonUtil.bind(CHANGE_SVC, "rpc/ChangeDetailService");
|
||||
|
||||
PATCH_SVC = GWT.create(PatchDetailService.class);
|
||||
JsonUtil.bind(PATCH_SVC, "rpc/PatchDetailService");
|
||||
}
|
||||
}
|
||||
|
@@ -1,176 +0,0 @@
|
||||
// Copyright (C) 2012 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.VoidResult;
|
||||
import com.google.gerrit.client.changes.Util;
|
||||
import com.google.gerrit.client.patches.PatchTable.PatchValidator;
|
||||
import com.google.gerrit.client.rpc.RestApi;
|
||||
import com.google.gerrit.client.ui.ChangeLink;
|
||||
import com.google.gerrit.client.ui.InlineHyperlink;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeEvent;
|
||||
import com.google.gwt.event.logical.shared.ValueChangeHandler;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.Anchor;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
|
||||
class ReviewedPanels {
|
||||
final FlowPanel top;
|
||||
final FlowPanel bottom;
|
||||
|
||||
private Patch.Key patchKey;
|
||||
private PatchTable fileList;
|
||||
private InlineHyperlink reviewedLink;
|
||||
private CheckBox checkBoxTop;
|
||||
private CheckBox checkBoxBottom;
|
||||
|
||||
ReviewedPanels() {
|
||||
this.top = new FlowPanel();
|
||||
this.bottom = new FlowPanel();
|
||||
this.bottom.setStyleName(Gerrit.RESOURCES.css().reviewedPanelBottom());
|
||||
}
|
||||
|
||||
void populate(Patch.Key pk, PatchTable pt, int patchIndex) {
|
||||
patchKey = pk;
|
||||
fileList = pt;
|
||||
reviewedLink = createReviewedLink(patchIndex);
|
||||
|
||||
top.clear();
|
||||
checkBoxTop = createReviewedCheckbox();
|
||||
top.add(checkBoxTop);
|
||||
top.add(createReviewedAnchor());
|
||||
|
||||
bottom.clear();
|
||||
checkBoxBottom = createReviewedCheckbox();
|
||||
bottom.add(checkBoxBottom);
|
||||
bottom.add(createReviewedAnchor());
|
||||
}
|
||||
|
||||
private CheckBox createReviewedCheckbox() {
|
||||
final CheckBox checkBox = new CheckBox(PatchUtil.C.reviewedAnd() + " ");
|
||||
checkBox.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<Boolean> event) {
|
||||
final boolean value = event.getValue();
|
||||
setReviewedByCurrentUser(value);
|
||||
if (checkBoxTop.getValue() != value) {
|
||||
checkBoxTop.setValue(value);
|
||||
}
|
||||
if (checkBoxBottom.getValue() != value) {
|
||||
checkBoxBottom.setValue(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
boolean getValue() {
|
||||
return checkBoxTop.getValue();
|
||||
}
|
||||
|
||||
void setValue(final boolean value) {
|
||||
checkBoxTop.setValue(value);
|
||||
checkBoxBottom.setValue(value);
|
||||
}
|
||||
|
||||
void setReviewedByCurrentUser(boolean reviewed) {
|
||||
PatchSet.Id ps = patchKey.getParentKey();
|
||||
if (ps.get() != 0) {
|
||||
if (fileList != null) {
|
||||
fileList.updateReviewedStatus(patchKey, reviewed);
|
||||
}
|
||||
|
||||
RestApi api = new RestApi("/changes/").id(ps.getParentKey().get())
|
||||
.view("revisions").id(ps.get())
|
||||
.view("files").id(patchKey.getFileName())
|
||||
.view("reviewed");
|
||||
|
||||
AsyncCallback<VoidResult> cb = new AsyncCallback<VoidResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable arg0) {
|
||||
// nop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
// nop
|
||||
}
|
||||
};
|
||||
if (reviewed) {
|
||||
api.put(cb);
|
||||
} else {
|
||||
api.delete(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go() {
|
||||
if (reviewedLink != null) {
|
||||
setReviewedByCurrentUser(true);
|
||||
reviewedLink.go();
|
||||
}
|
||||
}
|
||||
|
||||
private InlineHyperlink createReviewedLink(final int patchIndex) {
|
||||
final PatchValidator unreviewedValidator = new PatchValidator() {
|
||||
@Override
|
||||
public boolean isValid(Patch patch) {
|
||||
return !patch.isReviewedByCurrentUser();
|
||||
}
|
||||
};
|
||||
|
||||
InlineHyperlink reviewedLink = new ChangeLink("", patchKey.getParentKey());
|
||||
if (fileList != null) {
|
||||
int nextUnreviewedPatchIndex =
|
||||
fileList.getNextPatch(patchIndex, true, unreviewedValidator,
|
||||
fileList.PREFERENCE_VALIDATOR);
|
||||
|
||||
if (nextUnreviewedPatchIndex > -1) {
|
||||
// Create invisible patch link to change page
|
||||
reviewedLink =
|
||||
fileList.createLink(nextUnreviewedPatchIndex, null, null);
|
||||
reviewedLink.setText("");
|
||||
}
|
||||
}
|
||||
return reviewedLink;
|
||||
}
|
||||
|
||||
private Anchor createReviewedAnchor() {
|
||||
SafeHtmlBuilder text = new SafeHtmlBuilder();
|
||||
text.append(PatchUtil.C.next());
|
||||
text.append(SafeHtml.asis(Util.C.nextPatchLinkIcon()));
|
||||
|
||||
Anchor reviewedAnchor = new Anchor("");
|
||||
SafeHtml.set(reviewedAnchor, text);
|
||||
|
||||
reviewedAnchor.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
setReviewedByCurrentUser(true);
|
||||
reviewedLink.go();
|
||||
}
|
||||
});
|
||||
|
||||
return reviewedAnchor;
|
||||
}
|
||||
}
|
@@ -1,643 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
import static com.google.gerrit.client.patches.PatchLine.Type.CONTEXT;
|
||||
import static com.google.gerrit.client.patches.PatchLine.Type.DELETE;
|
||||
import static com.google.gerrit.client.patches.PatchLine.Type.INSERT;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.common.data.CommentDetail;
|
||||
import com.google.gerrit.common.data.PatchScript;
|
||||
import com.google.gerrit.common.data.PatchScript.DisplayMethod;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.prettify.client.SparseHtmlFile;
|
||||
import com.google.gerrit.prettify.common.EditList;
|
||||
import com.google.gerrit.prettify.common.EditList.Hunk;
|
||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.dom.client.Element;
|
||||
import com.google.gwt.user.client.DOM;
|
||||
import com.google.gwt.user.client.Event;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwt.user.client.ui.UIObject;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class UnifiedDiffTable extends AbstractPatchContentTable {
|
||||
private static final int PC = 3;
|
||||
private static final Comparator<PatchLineComment> BY_DATE =
|
||||
new Comparator<PatchLineComment>() {
|
||||
@Override
|
||||
public int compare(final PatchLineComment o1, final PatchLineComment o2) {
|
||||
return o1.getWrittenOn().compareTo(o2.getWrittenOn());
|
||||
}
|
||||
};
|
||||
|
||||
protected boolean isFileCommentBorderRowExist;
|
||||
// Cursors.
|
||||
protected int rowOfTableHeaderB;
|
||||
protected int borderRowOfFileComment;
|
||||
|
||||
@Override
|
||||
protected void onCellDoubleClick(final int row, final int column) {
|
||||
if (column > C_ARROW && getRowItem(row) instanceof PatchLine) {
|
||||
final PatchLine pl = (PatchLine) getRowItem(row);
|
||||
switch (pl.getType()) {
|
||||
case DELETE:
|
||||
case CONTEXT:
|
||||
createCommentEditor(row + 1, PC, pl.getLineA(), (short) 0);
|
||||
break;
|
||||
case INSERT:
|
||||
createCommentEditor(row + 1, PC, pl.getLineB(), (short) 1);
|
||||
break;
|
||||
case REPLACE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCursor(final PatchLineComment newComment) {
|
||||
if (newComment.getLine() == R_HEAD) {
|
||||
final PatchSet.Id psId =
|
||||
newComment.getKey().getParentKey().getParentKey();
|
||||
switch (newComment.getSide()) {
|
||||
case FILE_SIDE_A:
|
||||
if (idSideA == null && idSideB.equals(psId)) {
|
||||
rowOfTableHeaderB++;
|
||||
borderRowOfFileComment++;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case FILE_SIDE_B:
|
||||
if (idSideA != null && idSideA.equals(psId)) {
|
||||
rowOfTableHeaderB++;
|
||||
borderRowOfFileComment++;
|
||||
} else if (idSideB.equals(psId)) {
|
||||
borderRowOfFileComment++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCellSingleClick(Event event, int row, int column) {
|
||||
super.onCellSingleClick(event, row, column);
|
||||
if (column == 1 || column == 2) {
|
||||
if (!"".equals(table.getText(row, column))) {
|
||||
onCellDoubleClick(row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void destroyCommentRow(final int row) {
|
||||
super.destroyCommentRow(row);
|
||||
if (this.rowOfTableHeaderB + 1 == row && row + 1 == borderRowOfFileComment) {
|
||||
table.removeRow(row);
|
||||
isFileCommentBorderRowExist = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(CommentEditorPanel panel) {
|
||||
super.remove(panel);
|
||||
if (panel.getComment().getLine() == AbstractPatchContentTable.R_HEAD) {
|
||||
final PatchSet.Id psId =
|
||||
panel.getComment().getKey().getParentKey().getParentKey();
|
||||
switch (panel.getComment().getSide()) {
|
||||
case FILE_SIDE_A:
|
||||
if (idSideA == null && idSideB.equals(psId)) {
|
||||
rowOfTableHeaderB--;
|
||||
borderRowOfFileComment--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case FILE_SIDE_B:
|
||||
if (idSideA != null && idSideA.equals(psId)) {
|
||||
rowOfTableHeaderB--;
|
||||
borderRowOfFileComment--;
|
||||
} else if (idSideB.equals(psId)) {
|
||||
borderRowOfFileComment--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInsertComment(final PatchLine pl) {
|
||||
final int row = getCurrentRow();
|
||||
switch (pl.getType()) {
|
||||
case DELETE:
|
||||
case CONTEXT:
|
||||
createCommentEditor(row + 1, PC, pl.getLineA(), (short) 0);
|
||||
break;
|
||||
case INSERT:
|
||||
createCommentEditor(row + 1, PC, pl.getLineB(), (short) 1);
|
||||
break;
|
||||
case REPLACE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void appendImgTag(SafeHtmlBuilder nc, String url) {
|
||||
nc.openElement("img");
|
||||
nc.setAttribute("src", url);
|
||||
nc.closeElement("img");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFileCommentEditorOnSideA() {
|
||||
createCommentEditor(R_HEAD + 1, PC, R_HEAD, FILE_SIDE_A);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createFileCommentEditorOnSideB() {
|
||||
createCommentEditor(rowOfTableHeaderB + 1, PC, R_HEAD, FILE_SIDE_B);
|
||||
createFileCommentBorderRow();
|
||||
}
|
||||
|
||||
private void populateTableHeader(final PatchScript script,
|
||||
final PatchSetDetail detail) {
|
||||
initHeaders(script, detail);
|
||||
table.setWidget(R_HEAD, PC, headerSideA);
|
||||
table.setWidget(rowOfTableHeaderB, PC, headerSideB);
|
||||
table.getFlexCellFormatter().addStyleName(R_HEAD, PC,
|
||||
Gerrit.RESOURCES.css().unifiedTableHeader());
|
||||
table.getFlexCellFormatter().addStyleName(rowOfTableHeaderB, PC,
|
||||
Gerrit.RESOURCES.css().unifiedTableHeader());
|
||||
|
||||
// Add icons to lineNumber column header
|
||||
if (headerSideA.isFileOrCommitMessage()) {
|
||||
table.setWidget(R_HEAD, 1, iconA);
|
||||
}
|
||||
if (headerSideB.isFileOrCommitMessage()) {
|
||||
table.setWidget(rowOfTableHeaderB, 2, iconB);
|
||||
}
|
||||
}
|
||||
|
||||
private void allocateTableHeader(SafeHtmlBuilder nc) {
|
||||
rowOfTableHeaderB = 1;
|
||||
borderRowOfFileComment = 2;
|
||||
for (int i = R_HEAD; i < borderRowOfFileComment; i++) {
|
||||
openTableHeaderLine(nc);
|
||||
padLineNumberOnTableHeaderForSideA(nc);
|
||||
padLineNumberOnTableHeaderForSideB(nc);
|
||||
nc.openTd();
|
||||
nc.setStyleName(Gerrit.RESOURCES.css().fileLine());
|
||||
nc.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
|
||||
nc.closeTd();
|
||||
closeLine(nc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void render(final PatchScript script, final PatchSetDetail detail) {
|
||||
final SafeHtmlBuilder nc = new SafeHtmlBuilder();
|
||||
allocateTableHeader(nc);
|
||||
|
||||
// Display the patch header
|
||||
for (final String line : script.getPatchHeader()) {
|
||||
appendFileHeader(nc, line);
|
||||
}
|
||||
final ArrayList<PatchLine> lines = new ArrayList<>();
|
||||
|
||||
if (hasDifferences(script)) {
|
||||
if (script.getDisplayMethodA() == DisplayMethod.IMG
|
||||
|| script.getDisplayMethodB() == DisplayMethod.IMG) {
|
||||
appendImageDifferences(script, nc);
|
||||
} else if (!isDisplayBinary) {
|
||||
appendTextDifferences(script, nc, lines);
|
||||
}
|
||||
} else {
|
||||
appendNoDifferences(nc);
|
||||
}
|
||||
|
||||
resetHtml(nc);
|
||||
populateTableHeader(script, detail);
|
||||
if (hasDifferences(script)) {
|
||||
initScript(script);
|
||||
if (!isDisplayBinary) {
|
||||
int row = script.getPatchHeader().size();
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
final Iterator<PatchLine> iLine = lines.iterator();
|
||||
while (iLine.hasNext()) {
|
||||
final PatchLine l = iLine.next();
|
||||
final String n;
|
||||
switch (l.getType()) {
|
||||
case CONTEXT:
|
||||
n = Gerrit.RESOURCES.css().diffTextCONTEXT();
|
||||
break;
|
||||
case DELETE:
|
||||
n = Gerrit.RESOURCES.css().diffTextDELETE();
|
||||
break;
|
||||
case INSERT:
|
||||
n = Gerrit.RESOURCES.css().diffTextINSERT();
|
||||
break;
|
||||
case REPLACE:
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
while (!fmt.getStyleName(row, PC).contains(n)) {
|
||||
row++;
|
||||
}
|
||||
setRowItem(row++, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendImageLine(final SafeHtmlBuilder nc, final String url,
|
||||
final boolean syntaxHighlighting, final boolean isInsert) {
|
||||
nc.openTr();
|
||||
nc.setAttribute("valign", "center");
|
||||
nc.setAttribute("align", "center");
|
||||
|
||||
nc.openTd();
|
||||
nc.setStyleName(Gerrit.RESOURCES.css().iconCell());
|
||||
nc.closeTd();
|
||||
|
||||
padLineNumberForSideA(nc);
|
||||
padLineNumberForSideB(nc);
|
||||
|
||||
nc.openTd();
|
||||
nc.setStyleName(Gerrit.RESOURCES.css().fileLine());
|
||||
if (isInsert) {
|
||||
setStyleInsert(nc, syntaxHighlighting);
|
||||
} else {
|
||||
setStyleDelete(nc, syntaxHighlighting);
|
||||
}
|
||||
appendImgTag(nc, url);
|
||||
nc.closeTd();
|
||||
|
||||
nc.closeTr();
|
||||
}
|
||||
|
||||
private void appendImageDifferences(final PatchScript script,
|
||||
final SafeHtmlBuilder nc) {
|
||||
final boolean syntaxHighlighting =
|
||||
script.getDiffPrefs().syntaxHighlighting;
|
||||
if (script.getDisplayMethodA() == DisplayMethod.IMG) {
|
||||
final String url = getUrlA();
|
||||
appendImageLine(nc, url, syntaxHighlighting, false);
|
||||
}
|
||||
if (script.getDisplayMethodB() == DisplayMethod.IMG) {
|
||||
final String url = getUrlB();
|
||||
appendImageLine(nc, url, syntaxHighlighting, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendTextDifferences(final PatchScript script,
|
||||
final SafeHtmlBuilder nc, final ArrayList<PatchLine> lines) {
|
||||
final SparseHtmlFile a = getSparseHtmlFileA(script);
|
||||
final SparseHtmlFile b = getSparseHtmlFileB(script);
|
||||
final boolean syntaxHighlighting =
|
||||
script.getDiffPrefs().syntaxHighlighting;
|
||||
for (final EditList.Hunk hunk : script.getHunks()) {
|
||||
appendHunkHeader(nc, hunk);
|
||||
while (hunk.next()) {
|
||||
if (hunk.isContextLine()) {
|
||||
openLine(nc);
|
||||
appendLineNumberForSideA(nc, hunk.getCurA());
|
||||
appendLineNumberForSideB(nc, hunk.getCurB());
|
||||
appendLineText(nc, false, CONTEXT, a, hunk.getCurA());
|
||||
closeLine(nc);
|
||||
hunk.incBoth();
|
||||
lines.add(new PatchLine(CONTEXT, hunk.getCurA(), hunk.getCurB()));
|
||||
|
||||
} else if (hunk.isDeletedA()) {
|
||||
openLine(nc);
|
||||
appendLineNumberForSideA(nc, hunk.getCurA());
|
||||
padLineNumberForSideB(nc);
|
||||
appendLineText(nc, syntaxHighlighting, DELETE, a, hunk.getCurA());
|
||||
closeLine(nc);
|
||||
hunk.incA();
|
||||
lines.add(new PatchLine(DELETE, hunk.getCurA(), -1));
|
||||
if (a.size() == hunk.getCurA()
|
||||
&& script.getA().isMissingNewlineAtEnd()) {
|
||||
appendNoLF(nc);
|
||||
}
|
||||
|
||||
} else if (hunk.isInsertedB()) {
|
||||
openLine(nc);
|
||||
padLineNumberForSideA(nc);
|
||||
appendLineNumberForSideB(nc, hunk.getCurB());
|
||||
appendLineText(nc, syntaxHighlighting, INSERT, b, hunk.getCurB());
|
||||
closeLine(nc);
|
||||
hunk.incB();
|
||||
lines.add(new PatchLine(INSERT, -1, hunk.getCurB()));
|
||||
if (b.size() == hunk.getCurB()
|
||||
&& script.getB().isMissingNewlineAtEnd()) {
|
||||
appendNoLF(nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(final CommentDetail cd, boolean expandComments) {
|
||||
if (cd == null || cd.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
setAccountInfoCache(cd.getAccounts());
|
||||
|
||||
final ArrayList<PatchLineComment> all = new ArrayList<>();
|
||||
for (int row = 0; row < table.getRowCount();) {
|
||||
final List<PatchLineComment> fora;
|
||||
final List<PatchLineComment> forb;
|
||||
if (row == R_HEAD) {
|
||||
fora = cd.getForA(R_HEAD);
|
||||
forb = cd.getForB(R_HEAD);
|
||||
row++;
|
||||
|
||||
if (!fora.isEmpty()) {
|
||||
row = insert(fora, row);
|
||||
}
|
||||
rowOfTableHeaderB = row;
|
||||
borderRowOfFileComment = row + 1;
|
||||
if (!forb.isEmpty()) {
|
||||
row++;// Skip the Header of sideB.
|
||||
row = insert(forb, row);
|
||||
borderRowOfFileComment = row;
|
||||
createFileCommentBorderRow();
|
||||
}
|
||||
} else if (getRowItem(row) instanceof PatchLine) {
|
||||
final PatchLine pLine = (PatchLine) getRowItem(row);
|
||||
fora = cd.getForA(pLine.getLineA());
|
||||
forb = cd.getForB(pLine.getLineB());
|
||||
row++;
|
||||
|
||||
if (!fora.isEmpty() && !forb.isEmpty()) {
|
||||
all.clear();
|
||||
all.addAll(fora);
|
||||
all.addAll(forb);
|
||||
Collections.sort(all, BY_DATE);
|
||||
row = insert(all, row);
|
||||
|
||||
} else if (!fora.isEmpty()) {
|
||||
row = insert(fora, row);
|
||||
|
||||
} else if (!forb.isEmpty()) {
|
||||
row = insert(forb, row);
|
||||
}
|
||||
} else {
|
||||
row++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void defaultStyle(final int row, final CellFormatter fmt) {
|
||||
fmt.addStyleName(row, PC - 2, Gerrit.RESOURCES.css().lineNumber());
|
||||
fmt.addStyleName(row, PC - 2, Gerrit.RESOURCES.css().rightBorder());
|
||||
fmt.addStyleName(row, PC - 1, Gerrit.RESOURCES.css().lineNumber());
|
||||
fmt.addStyleName(row, PC, Gerrit.RESOURCES.css().diffText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void insertRow(final int row) {
|
||||
super.insertRow(row);
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
defaultStyle(row, fmt);
|
||||
}
|
||||
|
||||
private int insert(final List<PatchLineComment> in, int row) {
|
||||
for (Iterator<PatchLineComment> ci = in.iterator(); ci.hasNext();) {
|
||||
final PatchLineComment c = ci.next();
|
||||
if (c.getLine() == R_HEAD) {
|
||||
insertFileCommentRow(row);
|
||||
} else {
|
||||
insertRow(row);
|
||||
}
|
||||
bindComment(row, PC, c, !ci.hasNext());
|
||||
row++;
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void insertFileCommentRow(final int row) {
|
||||
table.insertRow(row);
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
|
||||
fmt.addStyleName(row, C_ARROW, //
|
||||
Gerrit.RESOURCES.css().iconCellOfFileCommentRow());
|
||||
defaultStyle(row, fmt);
|
||||
|
||||
fmt.addStyleName(row, C_ARROW, //
|
||||
Gerrit.RESOURCES.css().cellsNextToFileComment());
|
||||
fmt.addStyleName(row, PC - 2, //
|
||||
Gerrit.RESOURCES.css().cellsNextToFileComment());
|
||||
fmt.addStyleName(row, PC - 1, //
|
||||
Gerrit.RESOURCES.css().cellsNextToFileComment());
|
||||
}
|
||||
|
||||
private void createFileCommentBorderRow() {
|
||||
if (!isFileCommentBorderRowExist) {
|
||||
isFileCommentBorderRowExist = true;
|
||||
table.insertRow(borderRowOfFileComment);
|
||||
final CellFormatter fmt = table.getCellFormatter();
|
||||
fmt.addStyleName(borderRowOfFileComment, C_ARROW, //
|
||||
Gerrit.RESOURCES.css().iconCellOfFileCommentRow());
|
||||
defaultStyle(borderRowOfFileComment, fmt);
|
||||
|
||||
final Element iconCell =
|
||||
fmt.getElement(borderRowOfFileComment, C_ARROW);
|
||||
UIObject.setStyleName(DOM.getParent(iconCell), //
|
||||
Gerrit.RESOURCES.css().fileCommentBorder(), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendFileHeader(final SafeHtmlBuilder m, final String line) {
|
||||
openLine(m);
|
||||
padLineNumberForSideA(m);
|
||||
padLineNumberForSideB(m);
|
||||
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().fileLine());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffText());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextFileHeader());
|
||||
m.append(line);
|
||||
m.closeTd();
|
||||
closeLine(m);
|
||||
}
|
||||
|
||||
private void appendHunkHeader(final SafeHtmlBuilder m, final Hunk hunk) {
|
||||
openLine(m);
|
||||
padLineNumberForSideA(m);
|
||||
padLineNumberForSideB(m);
|
||||
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().fileLine());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffText());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextHunkHeader());
|
||||
m.append("@@ -");
|
||||
appendRange(m, hunk.getCurA() + 1, hunk.getEndA() - hunk.getCurA());
|
||||
m.append(" +");
|
||||
appendRange(m, hunk.getCurB() + 1, hunk.getEndB() - hunk.getCurB());
|
||||
m.append(" @@");
|
||||
m.closeTd();
|
||||
|
||||
closeLine(m);
|
||||
}
|
||||
|
||||
private void appendRange(final SafeHtmlBuilder m, final int begin,
|
||||
final int cnt) {
|
||||
switch (cnt) {
|
||||
case 0:
|
||||
m.append(begin - 1);
|
||||
m.append(",0");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m.append(begin);
|
||||
break;
|
||||
|
||||
default:
|
||||
m.append(begin);
|
||||
m.append(',');
|
||||
m.append(cnt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setStyleDelete(final SafeHtmlBuilder m,
|
||||
boolean syntaxHighlighting) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextDELETE());
|
||||
if (syntaxHighlighting) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().fileLineDELETE());
|
||||
}
|
||||
}
|
||||
|
||||
private void setStyleInsert(final SafeHtmlBuilder m,
|
||||
boolean syntaxHighlighting) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextINSERT());
|
||||
if (syntaxHighlighting) {
|
||||
m.addStyleName(Gerrit.RESOURCES.css().fileLineINSERT());
|
||||
}
|
||||
}
|
||||
|
||||
private void appendLineText(final SafeHtmlBuilder m,
|
||||
boolean syntaxHighlighting, final PatchLine.Type type,
|
||||
final SparseHtmlFile src, final int i) {
|
||||
final SafeHtml text = src.getSafeHtmlLine(i);
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().fileLine());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffText());
|
||||
switch (type) {
|
||||
case CONTEXT:
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextCONTEXT());
|
||||
m.nbsp();
|
||||
m.append(text);
|
||||
break;
|
||||
case DELETE:
|
||||
setStyleDelete(m, syntaxHighlighting);
|
||||
m.append("-");
|
||||
m.append(text);
|
||||
break;
|
||||
case INSERT:
|
||||
setStyleInsert(m, syntaxHighlighting);
|
||||
m.append("+");
|
||||
m.append(text);
|
||||
break;
|
||||
case REPLACE:
|
||||
break;
|
||||
}
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void appendNoLF(final SafeHtmlBuilder m) {
|
||||
openLine(m);
|
||||
padLineNumberForSideA(m);
|
||||
padLineNumberForSideB(m);
|
||||
m.openTd();
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffText());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().diffTextNoLF());
|
||||
m.append("\\ No newline at end of file");
|
||||
m.closeTd();
|
||||
closeLine(m);
|
||||
}
|
||||
|
||||
private void openLine(final SafeHtmlBuilder m) {
|
||||
m.openTr();
|
||||
m.setAttribute("valign", "top");
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().iconCell());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void openTableHeaderLine(final SafeHtmlBuilder m) {
|
||||
m.openTr();
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().iconCell());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void closeLine(final SafeHtmlBuilder m) {
|
||||
m.closeTr();
|
||||
}
|
||||
|
||||
private void padLineNumberForSideB(final SafeHtmlBuilder m) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void padLineNumberForSideA(final SafeHtmlBuilder m) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void appendLineNumberForSideB(final SafeHtmlBuilder m, final int idx) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.append(SafeHtml.asis("<a href=\"javascript:void(0)\">"+ (idx + 1) + "</a>"));
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void appendLineNumberForSideA(final SafeHtmlBuilder m, final int idx) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
|
||||
m.append(SafeHtml.asis("<a href=\"javascript:void(0)\">"+ (idx + 1) + "</a>"));
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void padLineNumberOnTableHeaderForSideB(final SafeHtmlBuilder m) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
|
||||
m.closeTd();
|
||||
}
|
||||
|
||||
private void padLineNumberOnTableHeaderForSideA(final SafeHtmlBuilder m) {
|
||||
m.openTd();
|
||||
m.setStyleName(Gerrit.RESOURCES.css().lineNumber());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().fileColumnHeader());
|
||||
m.addStyleName(Gerrit.RESOURCES.css().rightBorder());
|
||||
m.closeTd();
|
||||
}
|
||||
}
|
@@ -1,564 +0,0 @@
|
||||
// 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Dispatcher;
|
||||
import com.google.gerrit.client.ErrorDialog;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.RpcStatus;
|
||||
import com.google.gerrit.client.diff.DiffApi;
|
||||
import com.google.gerrit.client.diff.DiffInfo;
|
||||
import com.google.gerrit.client.info.WebLinkInfo;
|
||||
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.ScreenLoadCallback;
|
||||
import com.google.gerrit.client.ui.CommentLinkProcessor;
|
||||
import com.google.gerrit.client.ui.InlineHyperlink;
|
||||
import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
|
||||
import com.google.gerrit.client.ui.Screen;
|
||||
import com.google.gerrit.common.data.PatchScript;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.prettify.client.ClientSideFormatter;
|
||||
import com.google.gerrit.prettify.client.PrettyFactory;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.Scheduler;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
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.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.ImageResourceRenderer;
|
||||
import com.google.gwtexpui.globalkey.client.GlobalKey;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommand;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class UnifiedPatchScreen extends Screen implements
|
||||
CommentEditorContainer {
|
||||
static final PrettyFactory PRETTY = ClientSideFormatter.FACTORY;
|
||||
static final short LARGE_FILE_CONTEXT = 100;
|
||||
|
||||
/**
|
||||
* What should be displayed in the top of the screen
|
||||
*/
|
||||
public static enum TopView {
|
||||
MAIN, COMMIT, PREFERENCES, PATCH_SETS, FILES
|
||||
}
|
||||
|
||||
protected final Patch.Key patchKey;
|
||||
protected PatchSetDetail patchSetDetail;
|
||||
protected PatchTable fileList;
|
||||
protected PatchSet.Id idSideA;
|
||||
protected PatchSet.Id idSideB;
|
||||
protected PatchScriptSettingsPanel settingsPanel;
|
||||
protected TopView topView;
|
||||
protected CommentLinkProcessor commentLinkProcessor;
|
||||
|
||||
private ReviewedPanels reviewedPanels;
|
||||
private HistoryTable historyTable;
|
||||
private FlowPanel topPanel;
|
||||
private FlowPanel contentPanel;
|
||||
private UnifiedDiffTable contentTable;
|
||||
private CommitMessageBlock commitMessageBlock;
|
||||
private NavLinks topNav;
|
||||
private NavLinks bottomNav;
|
||||
|
||||
private int rpcSequence;
|
||||
private PatchScript lastScript;
|
||||
|
||||
/** The index of the file we are currently looking at among the fileList */
|
||||
private int patchIndex;
|
||||
private ListenableAccountDiffPreference prefs;
|
||||
private HandlerRegistration prefsHandler;
|
||||
|
||||
/** Keys that cause an action on this screen */
|
||||
private KeyCommandSet keysNavigation;
|
||||
private KeyCommandSet keysAction;
|
||||
private HandlerRegistration regNavigation;
|
||||
private HandlerRegistration regAction;
|
||||
private boolean intralineFailure;
|
||||
private boolean intralineTimeout;
|
||||
|
||||
public UnifiedPatchScreen(Patch.Key id, TopView top, PatchSet.Id baseId) {
|
||||
patchKey = id;
|
||||
topView = top;
|
||||
|
||||
idSideA = baseId; // null here means we're diff'ing from the Base
|
||||
idSideB = id.getParentKey();
|
||||
|
||||
prefs = fileList != null
|
||||
? fileList.getPreferences()
|
||||
: new ListenableAccountDiffPreference();
|
||||
if (Gerrit.isSignedIn()) {
|
||||
prefs.reset();
|
||||
}
|
||||
reviewedPanels = new ReviewedPanels();
|
||||
settingsPanel = new PatchScriptSettingsPanel(prefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDraftDelta(int delta) {
|
||||
lastScript = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(CommentEditorPanel panel) {
|
||||
lastScript = null;
|
||||
}
|
||||
|
||||
private void update(DiffPreferencesInfo dp) {
|
||||
// Did the user just turn on auto-review?
|
||||
if (!reviewedPanels.getValue() && prefs.getOld().manualReview
|
||||
&& !dp.manualReview) {
|
||||
reviewedPanels.setValue(true);
|
||||
reviewedPanels.setReviewedByCurrentUser(true);
|
||||
}
|
||||
|
||||
if (lastScript != null && canReuse(dp, lastScript)) {
|
||||
lastScript.setDiffPrefs(dp);
|
||||
RpcStatus.INSTANCE.onRpcStart(null);
|
||||
settingsPanel.setEnabled(false);
|
||||
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
try {
|
||||
onResult(lastScript, false /* not the first time */);
|
||||
} finally {
|
||||
RpcStatus.INSTANCE.onRpcComplete(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
refresh(false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canReuse(DiffPreferencesInfo dp, PatchScript last) {
|
||||
if (last.getDiffPrefs().ignoreWhitespace != dp.ignoreWhitespace) {
|
||||
// Whitespace ignore setting requires server computation.
|
||||
return false;
|
||||
}
|
||||
|
||||
final int ctx = dp.context;
|
||||
if (ctx == DiffPreferencesInfo.WHOLE_FILE_CONTEXT
|
||||
&& !last.getA().isWholeFile()) {
|
||||
// We don't have the entire file here, so we can't render it.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (last.getDiffPrefs().context < ctx && !last.getA().isWholeFile()) {
|
||||
// We don't have sufficient context.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dp.syntaxHighlighting && !last.getA().isWholeFile()) {
|
||||
// We need the whole file to syntax highlight accurately.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInitUI() {
|
||||
super.onInitUI();
|
||||
|
||||
if (Gerrit.isSignedIn()) {
|
||||
setTitleFarEast(reviewedPanels.top);
|
||||
}
|
||||
|
||||
keysNavigation = new KeyCommandSet(Gerrit.C.sectionNavigation());
|
||||
keysNavigation.add(new UpToChangeCommand(patchKey.getParentKey(), 0, 'u'));
|
||||
keysNavigation.add(new FileListCmd(0, 'f', PatchUtil.C.fileList()));
|
||||
|
||||
if (Gerrit.isSignedIn()) {
|
||||
keysAction = new KeyCommandSet(Gerrit.C.sectionActions());
|
||||
keysAction
|
||||
.add(new ToggleReviewedCmd(0, 'm', PatchUtil.C.toggleReviewed()));
|
||||
keysAction.add(new MarkAsReviewedAndGoToNextCmd(0, 'M', PatchUtil.C
|
||||
.markAsReviewedAndGoToNext()));
|
||||
}
|
||||
|
||||
historyTable = new HistoryTable(this);
|
||||
|
||||
commitMessageBlock = new CommitMessageBlock();
|
||||
|
||||
topPanel = new FlowPanel();
|
||||
add(topPanel);
|
||||
|
||||
contentTable = new UnifiedDiffTable();
|
||||
contentTable.fileList = fileList;
|
||||
|
||||
topNav = new NavLinks(keysNavigation, patchKey.getParentKey());
|
||||
bottomNav = new NavLinks(null, patchKey.getParentKey());
|
||||
|
||||
add(topNav);
|
||||
contentPanel = new FlowPanel();
|
||||
contentPanel.setStyleName(Gerrit.RESOURCES.css().unifiedTable());
|
||||
|
||||
contentPanel.add(contentTable);
|
||||
add(contentPanel);
|
||||
add(bottomNav);
|
||||
if (Gerrit.isSignedIn()) {
|
||||
add(reviewedPanels.bottom);
|
||||
}
|
||||
|
||||
if (fileList != null) {
|
||||
displayNav();
|
||||
}
|
||||
}
|
||||
|
||||
private void displayNav() {
|
||||
DiffApi.diff(idSideB, patchKey.getFileName())
|
||||
.base(idSideA)
|
||||
.webLinksOnly()
|
||||
.get(new GerritCallback<DiffInfo>() {
|
||||
@Override
|
||||
public void onSuccess(DiffInfo diffInfo) {
|
||||
topNav.display(patchIndex, fileList,
|
||||
getLinks(), getWebLinks(diffInfo));
|
||||
bottomNav.display(patchIndex, fileList,
|
||||
getLinks(), getWebLinks(diffInfo));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<InlineHyperlink> getLinks() {
|
||||
InlineHyperlink toSideBySideDiffLink = new InlineHyperlink();
|
||||
toSideBySideDiffLink.setHTML(new ImageResourceRenderer().render(Gerrit.RESOURCES.sideBySideDiff()));
|
||||
toSideBySideDiffLink.setTargetHistoryToken(getSideBySideDiffUrl());
|
||||
toSideBySideDiffLink.setTitle(PatchUtil.C.sideBySideDiff());
|
||||
return Collections.singletonList(toSideBySideDiffLink);
|
||||
}
|
||||
|
||||
private List<WebLinkInfo> getWebLinks(DiffInfo diffInfo) {
|
||||
return diffInfo.unifiedWebLinks();
|
||||
}
|
||||
|
||||
private String getSideBySideDiffUrl() {
|
||||
return Dispatcher.toPatch("sidebyside", idSideA,
|
||||
new Patch.Key(idSideB, patchKey.getFileName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad() {
|
||||
super.onLoad();
|
||||
|
||||
if (patchSetDetail == null) {
|
||||
PatchUtil.CHANGE_SVC.patchSetDetail(idSideB,
|
||||
new GerritCallback<PatchSetDetail>() {
|
||||
@Override
|
||||
public void onSuccess(PatchSetDetail result) {
|
||||
patchSetDetail = result;
|
||||
if (fileList == null) {
|
||||
fileList = new PatchTable(prefs);
|
||||
fileList.display(idSideA, result);
|
||||
patchIndex = fileList.indexOf(patchKey);
|
||||
}
|
||||
refresh(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUnload() {
|
||||
if (prefsHandler != null) {
|
||||
prefsHandler.removeHandler();
|
||||
prefsHandler = null;
|
||||
}
|
||||
if (regNavigation != null) {
|
||||
regNavigation.removeHandler();
|
||||
regNavigation = null;
|
||||
}
|
||||
if (regAction != null) {
|
||||
regAction.removeHandler();
|
||||
regAction = null;
|
||||
}
|
||||
super.onUnload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerKeys() {
|
||||
super.registerKeys();
|
||||
contentTable.setRegisterKeys(contentTable.isVisible());
|
||||
if (regNavigation != null) {
|
||||
regNavigation.removeHandler();
|
||||
regNavigation = null;
|
||||
}
|
||||
regNavigation = GlobalKey.add(this, keysNavigation);
|
||||
if (regAction != null) {
|
||||
regAction.removeHandler();
|
||||
regAction = null;
|
||||
}
|
||||
if (keysAction != null) {
|
||||
regAction = GlobalKey.add(this, keysAction);
|
||||
}
|
||||
}
|
||||
|
||||
public PatchSet.Id getSideA() {
|
||||
return idSideA;
|
||||
}
|
||||
|
||||
public Patch.Key getPatchKey() {
|
||||
return patchKey;
|
||||
}
|
||||
|
||||
public int getPatchIndex() {
|
||||
return patchIndex;
|
||||
}
|
||||
|
||||
public PatchSetDetail getPatchSetDetail() {
|
||||
return patchSetDetail;
|
||||
}
|
||||
|
||||
public PatchTable getFileList() {
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public TopView getTopView() {
|
||||
return topView;
|
||||
}
|
||||
|
||||
protected void refresh(final boolean isFirst) {
|
||||
final int rpcseq = ++rpcSequence;
|
||||
lastScript = null;
|
||||
settingsPanel.setEnabled(false);
|
||||
reviewedPanels.populate(patchKey, fileList, patchIndex);
|
||||
if (isFirst && fileList != null && fileList.isLoaded()) {
|
||||
fileList.movePointerTo(patchKey);
|
||||
}
|
||||
|
||||
CallbackGroup cb = new CallbackGroup();
|
||||
ConfigInfoCache.get(patchSetDetail.getProject(),
|
||||
cb.add(new AsyncCallback<ConfigInfoCache.Entry>() {
|
||||
@Override
|
||||
public void onSuccess(ConfigInfoCache.Entry result) {
|
||||
commentLinkProcessor = result.getCommentLinkProcessor();
|
||||
contentTable.setCommentLinkProcessor(commentLinkProcessor);
|
||||
setTheme(result.getTheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
// Handled by ScreenLoadCallback.onFailure.
|
||||
}
|
||||
}));
|
||||
PatchUtil.PATCH_SVC.patchScript(patchKey, idSideA, idSideB,
|
||||
settingsPanel.getValue(), cb.addFinal(
|
||||
new ScreenLoadCallback<PatchScript>(this) {
|
||||
@Override
|
||||
protected void preDisplay(final PatchScript result) {
|
||||
if (rpcSequence == rpcseq) {
|
||||
onResult(result, isFirst);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable caught) {
|
||||
if (rpcSequence == rpcseq) {
|
||||
settingsPanel.setEnabled(true);
|
||||
super.onFailure(caught);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private void onResult(final PatchScript script, final boolean isFirst) {
|
||||
final String path = PatchTable.getDisplayFileName(patchKey);
|
||||
String fileName = path;
|
||||
final int last = fileName.lastIndexOf('/');
|
||||
if (last >= 0) {
|
||||
fileName = fileName.substring(last + 1);
|
||||
}
|
||||
|
||||
setWindowTitle(fileName);
|
||||
setPageTitle(path);
|
||||
|
||||
if (idSideB.equals(patchSetDetail.getPatchSet().getId())) {
|
||||
commitMessageBlock.setVisible(true);
|
||||
commitMessageBlock.display(patchSetDetail.getInfo().getMessage(),
|
||||
commentLinkProcessor);
|
||||
} else {
|
||||
commitMessageBlock.setVisible(false);
|
||||
PatchUtil.CHANGE_SVC.patchSetDetail(idSideB,
|
||||
new GerritCallback<PatchSetDetail>() {
|
||||
@Override
|
||||
public void onSuccess(PatchSetDetail result) {
|
||||
commitMessageBlock.setVisible(true);
|
||||
commitMessageBlock.display(result.getInfo().getMessage(),
|
||||
commentLinkProcessor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
historyTable.display(script.getHistory());
|
||||
|
||||
for (Patch p : patchSetDetail.getPatches()) {
|
||||
if (p.getKey().equals(patchKey)) {
|
||||
if (p.getPatchType().equals(Patch.PatchType.BINARY)) {
|
||||
contentTable.isDisplayBinary = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (script.isHugeFile()) {
|
||||
DiffPreferencesInfo dp = script.getDiffPrefs();
|
||||
int context = dp.context;
|
||||
if (context == DiffPreferencesInfo.WHOLE_FILE_CONTEXT) {
|
||||
context = Short.MAX_VALUE;
|
||||
} else if (context > Short.MAX_VALUE) {
|
||||
context = Short.MAX_VALUE;
|
||||
}
|
||||
dp.context = Math.min(context, LARGE_FILE_CONTEXT);
|
||||
dp.syntaxHighlighting = false;
|
||||
script.setDiffPrefs(dp);
|
||||
}
|
||||
|
||||
contentTable.display(patchKey, idSideA, idSideB, script, patchSetDetail);
|
||||
contentTable.display(script.getCommentDetail(), script.isExpandAllComments());
|
||||
contentTable.finishDisplay();
|
||||
contentTable.setRegisterKeys(isCurrentView());
|
||||
|
||||
settingsPanel.setEnableSmallFileFeatures(!script.isHugeFile());
|
||||
settingsPanel.setEnableIntralineDifference(script.hasIntralineDifference());
|
||||
settingsPanel.setEnabled(true);
|
||||
lastScript = script;
|
||||
|
||||
if (fileList != null) {
|
||||
displayNav();
|
||||
}
|
||||
|
||||
if (Gerrit.isSignedIn()) {
|
||||
boolean isReviewed = false;
|
||||
if (isFirst && !prefs.get().manualReview) {
|
||||
isReviewed = true;
|
||||
reviewedPanels.setReviewedByCurrentUser(isReviewed);
|
||||
} else {
|
||||
for (Patch p : patchSetDetail.getPatches()) {
|
||||
if (p.getKey().equals(patchKey)) {
|
||||
isReviewed = p.isReviewedByCurrentUser();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
reviewedPanels.setValue(isReviewed);
|
||||
}
|
||||
|
||||
intralineFailure = isFirst && script.hasIntralineFailure();
|
||||
intralineTimeout = isFirst && script.hasIntralineTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowView() {
|
||||
super.onShowView();
|
||||
if (prefsHandler == null) {
|
||||
prefsHandler = prefs.addValueChangeHandler(
|
||||
new ValueChangeHandler<DiffPreferencesInfo>() {
|
||||
@Override
|
||||
public void onValueChange(ValueChangeEvent<DiffPreferencesInfo> event) {
|
||||
update(event.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
if (intralineFailure) {
|
||||
intralineFailure = false;
|
||||
new ErrorDialog(PatchUtil.C.intralineFailure()).show();
|
||||
} else if (intralineTimeout) {
|
||||
intralineTimeout = false;
|
||||
new ErrorDialog(PatchUtil.C.intralineTimeout()).setText(
|
||||
Gerrit.C.warnTitle()).show();
|
||||
}
|
||||
if (topView != null && prefs.get().retainHeader) {
|
||||
setTopView(topView);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTopView(TopView tv) {
|
||||
topView = tv;
|
||||
topPanel.clear();
|
||||
switch(tv) {
|
||||
case COMMIT: topPanel.add(commitMessageBlock);
|
||||
break;
|
||||
case PREFERENCES: topPanel.add(settingsPanel);
|
||||
break;
|
||||
case PATCH_SETS: topPanel.add(historyTable);
|
||||
break;
|
||||
case FILES: topPanel.add(fileList);
|
||||
break;
|
||||
case MAIN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public class FileListCmd extends KeyCommand {
|
||||
public FileListCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
if (fileList == null || fileList.isAttached()) {
|
||||
final PatchSet.Id psid = patchKey.getParentKey();
|
||||
fileList = new PatchTable(prefs);
|
||||
fileList.setSavePointerId("PatchTable " + psid);
|
||||
PatchUtil.CHANGE_SVC.patchSetDetail(psid,
|
||||
new GerritCallback<PatchSetDetail>() {
|
||||
@Override
|
||||
public void onSuccess(final PatchSetDetail result) {
|
||||
fileList.display(idSideA, result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final PatchBrowserPopup p = new PatchBrowserPopup(patchKey, fileList);
|
||||
p.open();
|
||||
}
|
||||
}
|
||||
|
||||
public class ToggleReviewedCmd extends KeyCommand {
|
||||
public ToggleReviewedCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
final boolean isReviewed = !reviewedPanels.getValue();
|
||||
reviewedPanels.setValue(isReviewed);
|
||||
reviewedPanels.setReviewedByCurrentUser(isReviewed);
|
||||
}
|
||||
}
|
||||
|
||||
public class MarkAsReviewedAndGoToNextCmd extends KeyCommand {
|
||||
public MarkAsReviewedAndGoToNextCmd(int mask, int key, String help) {
|
||||
super(mask, key, help);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
reviewedPanels.go();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2010 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.patches;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.common.PageLinks;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||
import com.google.gwtexpui.globalkey.client.KeyCommand;
|
||||
|
||||
class UpToChangeCommand extends KeyCommand {
|
||||
private final PatchSet.Id patchSetId;
|
||||
|
||||
UpToChangeCommand(PatchSet.Id patchSetId, int mask, int key) {
|
||||
super(mask, key, PatchUtil.C.upToChange());
|
||||
this.patchSetId = patchSetId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyPress(final KeyPressEvent event) {
|
||||
Gerrit.display(PageLinks.toChange(patchSetId));
|
||||
}
|
||||
}
|
@@ -17,7 +17,6 @@ package com.google.gerrit.client.ui;
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.common.PageLinks;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
|
||||
public class ChangeLink extends InlineHyperlink {
|
||||
@@ -26,19 +25,11 @@ public class ChangeLink extends InlineHyperlink {
|
||||
}
|
||||
|
||||
protected Change.Id cid;
|
||||
protected PatchSet.Id psid;
|
||||
|
||||
public ChangeLink(final String text, final Change.Id c) {
|
||||
super(text, PageLinks.toChange(c));
|
||||
getElement().setPropertyString("href", permalink(c));
|
||||
cid = c;
|
||||
psid = null;
|
||||
}
|
||||
|
||||
public ChangeLink(final String text, final PatchSet.Id ps) {
|
||||
super(text, PageLinks.toChange(ps));
|
||||
cid = ps.getParentKey();
|
||||
psid = ps;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -184,7 +184,6 @@ public abstract class Screen extends View {
|
||||
if (windowTitle != null) {
|
||||
Gerrit.setWindowTitle(this, windowTitle);
|
||||
}
|
||||
Gerrit.updateMenus(this);
|
||||
Gerrit.EVENT_BUS.fireEvent(new ScreenLoadEvent(this));
|
||||
Gerrit.setQueryString(null);
|
||||
registerKeys();
|
||||
|
@@ -15,8 +15,6 @@
|
||||
package com.google.gerrit.httpd.rpc;
|
||||
|
||||
import com.google.gerrit.httpd.rpc.account.AccountModule;
|
||||
import com.google.gerrit.httpd.rpc.changedetail.ChangeModule;
|
||||
import com.google.gerrit.httpd.rpc.patch.PatchModule;
|
||||
import com.google.gerrit.httpd.rpc.project.ProjectModule;
|
||||
|
||||
/** Registers servlets to answer RPCs from client UI. */
|
||||
@@ -30,8 +28,6 @@ public class UiRpcModule extends RpcServletModule {
|
||||
rpc(SystemInfoServiceImpl.class);
|
||||
|
||||
install(new AccountModule());
|
||||
install(new ChangeModule());
|
||||
install(new PatchModule());
|
||||
install(new ProjectModule());
|
||||
}
|
||||
}
|
||||
|
@@ -1,44 +0,0 @@
|
||||
// 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.httpd.rpc.changedetail;
|
||||
|
||||
import com.google.gerrit.common.data.ChangeDetailService;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
class ChangeDetailServiceImpl implements ChangeDetailService {
|
||||
private final PatchSetDetailFactory.Factory patchSetDetail;
|
||||
|
||||
@Inject
|
||||
ChangeDetailServiceImpl(
|
||||
final PatchSetDetailFactory.Factory patchSetDetail) {
|
||||
this.patchSetDetail = patchSetDetail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void patchSetDetail(PatchSet.Id id,
|
||||
AsyncCallback<PatchSetDetail> callback) {
|
||||
patchSetDetail2(null, id, null, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void patchSetDetail2(PatchSet.Id baseId, PatchSet.Id id,
|
||||
DiffPreferencesInfo diffPrefs, AsyncCallback<PatchSetDetail> callback) {
|
||||
patchSetDetail.create(baseId, id, diffPrefs).to(callback);
|
||||
}
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
// Copyright (C) 2009 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.httpd.rpc.changedetail;
|
||||
|
||||
import com.google.gerrit.extensions.config.FactoryModule;
|
||||
import com.google.gerrit.httpd.rpc.RpcServletModule;
|
||||
import com.google.gerrit.httpd.rpc.UiRpcModule;
|
||||
|
||||
public class ChangeModule extends RpcServletModule {
|
||||
public ChangeModule() {
|
||||
super(UiRpcModule.PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
install(new FactoryModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
factory(PatchSetDetailFactory.Factory.class);
|
||||
}
|
||||
});
|
||||
rpc(ChangeDetailServiceImpl.class);
|
||||
}
|
||||
}
|
@@ -1,234 +0,0 @@
|
||||
// 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.httpd.rpc.changedetail;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.common.data.PatchSetDetail;
|
||||
import com.google.gerrit.common.errors.NoSuchEntityException;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.httpd.rpc.Handler;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.AccountPatchReview;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.PatchLineCommentsUtil;
|
||||
import com.google.gerrit.server.PatchSetUtil;
|
||||
import com.google.gerrit.server.edit.ChangeEdit;
|
||||
import com.google.gerrit.server.edit.ChangeEditUtil;
|
||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.patch.PatchList;
|
||||
import com.google.gerrit.server.patch.PatchListCache;
|
||||
import com.google.gerrit.server.patch.PatchListKey;
|
||||
import com.google.gerrit.server.patch.PatchListNotAvailableException;
|
||||
import com.google.gerrit.server.patch.PatchSetInfoFactory;
|
||||
import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Creates a {@link PatchSetDetail} from a {@link PatchSet}. */
|
||||
class PatchSetDetailFactory extends Handler<PatchSetDetail> {
|
||||
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(PatchSetDetailFactory.class);
|
||||
|
||||
interface Factory {
|
||||
PatchSetDetailFactory create(
|
||||
@Assisted("psIdBase") @Nullable PatchSet.Id psIdBase,
|
||||
@Assisted("psIdNew") PatchSet.Id psIdNew,
|
||||
@Nullable DiffPreferencesInfo diffPrefs);
|
||||
}
|
||||
|
||||
private final PatchSetInfoFactory infoFactory;
|
||||
private final ReviewDb db;
|
||||
private final PatchListCache patchListCache;
|
||||
private final Provider<CurrentUser> userProvider;
|
||||
private final ChangeControl.GenericFactory changeControlFactory;
|
||||
private final PatchLineCommentsUtil plcUtil;
|
||||
private final PatchSetUtil psUtil;
|
||||
private final ChangeEditUtil editUtil;
|
||||
|
||||
private Project.NameKey project;
|
||||
private final PatchSet.Id psIdBase;
|
||||
private final PatchSet.Id psIdNew;
|
||||
private final DiffPreferencesInfo diffPrefs;
|
||||
private ObjectId oldId;
|
||||
private ObjectId newId;
|
||||
|
||||
private PatchSetDetail detail;
|
||||
ChangeControl control;
|
||||
PatchSet patchSet;
|
||||
|
||||
@Inject
|
||||
PatchSetDetailFactory(final PatchSetInfoFactory psif, final ReviewDb db,
|
||||
final PatchListCache patchListCache,
|
||||
final Provider<CurrentUser> userProvider,
|
||||
final ChangeControl.GenericFactory changeControlFactory,
|
||||
final PatchLineCommentsUtil plcUtil,
|
||||
final PatchSetUtil psUtil,
|
||||
ChangeEditUtil editUtil,
|
||||
@Assisted("psIdBase") @Nullable final PatchSet.Id psIdBase,
|
||||
@Assisted("psIdNew") final PatchSet.Id psIdNew,
|
||||
@Assisted @Nullable final DiffPreferencesInfo diffPrefs) {
|
||||
this.infoFactory = psif;
|
||||
this.db = db;
|
||||
this.patchListCache = patchListCache;
|
||||
this.userProvider = userProvider;
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
this.plcUtil = plcUtil;
|
||||
this.psUtil = psUtil;
|
||||
this.editUtil = editUtil;
|
||||
|
||||
this.psIdBase = psIdBase;
|
||||
this.psIdNew = psIdNew;
|
||||
if (psIdBase != null && psIdNew != null) {
|
||||
checkArgument(psIdBase.getParentKey().equals(psIdNew.getParentKey()),
|
||||
"cannot compare PatchSets from different changes: %s and %s",
|
||||
psIdBase, psIdNew);
|
||||
}
|
||||
this.diffPrefs = diffPrefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PatchSetDetail call() throws OrmException, NoSuchEntityException,
|
||||
PatchSetInfoNotAvailableException, NoSuchChangeException, AuthException,
|
||||
IOException {
|
||||
Optional<ChangeEdit> edit = null;
|
||||
ChangeNotes notes;
|
||||
if (control == null || patchSet == null) {
|
||||
control = changeControlFactory.validateFor(db, psIdNew.getParentKey(),
|
||||
userProvider.get());
|
||||
notes = control.getNotes();
|
||||
if (psIdNew.get() == 0) {
|
||||
edit = editUtil.byChange(control.getChange());
|
||||
if (edit.isPresent()) {
|
||||
patchSet = edit.get().getBasePatchSet();
|
||||
}
|
||||
} else {
|
||||
patchSet = psUtil.get(db, notes, psIdNew);
|
||||
}
|
||||
if (patchSet == null) {
|
||||
throw new NoSuchEntityException();
|
||||
}
|
||||
} else {
|
||||
notes = control.getNotes();
|
||||
}
|
||||
project = control.getProject().getNameKey();
|
||||
final PatchList list;
|
||||
|
||||
try {
|
||||
if (psIdBase != null) {
|
||||
oldId = toObjectId(psUtil.get(db, notes, psIdBase));
|
||||
if (edit != null && edit.isPresent()) {
|
||||
newId = edit.get().getEditCommit().toObjectId();
|
||||
} else {
|
||||
newId = toObjectId(patchSet);
|
||||
}
|
||||
|
||||
list = listFor(keyFor(diffPrefs.ignoreWhitespace));
|
||||
} else { // OK, means use base to compare
|
||||
list = patchListCache.get(control.getChange(), patchSet);
|
||||
}
|
||||
} catch (PatchListNotAvailableException e) {
|
||||
throw new NoSuchEntityException();
|
||||
}
|
||||
|
||||
final List<Patch> patches = list.toPatchList(patchSet.getId());
|
||||
final Map<Patch.Key, Patch> byKey = new HashMap<>();
|
||||
for (final Patch p : patches) {
|
||||
byKey.put(p.getKey(), p);
|
||||
}
|
||||
|
||||
if (edit == null) {
|
||||
for (PatchLineComment c : plcUtil.publishedByPatchSet(db, notes, psIdNew)) {
|
||||
final Patch p = byKey.get(c.getKey().getParentKey());
|
||||
if (p != null) {
|
||||
p.setCommentCount(p.getCommentCount() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
detail = new PatchSetDetail();
|
||||
detail.setPatchSet(patchSet);
|
||||
detail.setProject(project);
|
||||
|
||||
detail.setInfo(infoFactory.get(db, notes, patchSet.getId()));
|
||||
detail.setPatches(patches);
|
||||
|
||||
final CurrentUser user = control.getUser();
|
||||
if (user.isIdentifiedUser() && edit == null) {
|
||||
// If we are signed in, compute the number of draft comments by the
|
||||
// current user on each of these patch files. This way they can more
|
||||
// quickly locate where they have pending drafts, and review them.
|
||||
//
|
||||
final Account.Id me = user.getAccountId();
|
||||
for (PatchLineComment c
|
||||
: plcUtil.draftByPatchSetAuthor(db, psIdNew, me, notes)) {
|
||||
final Patch p = byKey.get(c.getKey().getParentKey());
|
||||
if (p != null) {
|
||||
p.setDraftCount(p.getDraftCount() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (AccountPatchReview r : db.accountPatchReviews().byReviewer(me, psIdNew)) {
|
||||
final Patch p = byKey.get(r.getKey().getPatchKey());
|
||||
if (p != null) {
|
||||
p.setReviewedByCurrentUser(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
private ObjectId toObjectId(PatchSet ps) throws NoSuchEntityException {
|
||||
try {
|
||||
return ObjectId.fromString(ps.getRevision().get());
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Patch set " + ps.getId() + " has invalid revision");
|
||||
throw new NoSuchEntityException();
|
||||
}
|
||||
}
|
||||
|
||||
private PatchListKey keyFor(Whitespace whitespace) {
|
||||
return new PatchListKey(oldId, newId, whitespace);
|
||||
}
|
||||
|
||||
private PatchList listFor(PatchListKey key)
|
||||
throws PatchListNotAvailableException {
|
||||
return patchListCache.get(key, project);
|
||||
}
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
// 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.httpd.rpc.patch;
|
||||
|
||||
import com.google.gerrit.common.data.PatchDetailService;
|
||||
import com.google.gerrit.common.data.PatchScript;
|
||||
import com.google.gerrit.common.errors.NoSuchEntityException;
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
|
||||
import com.google.gerrit.httpd.rpc.Handler;
|
||||
import com.google.gerrit.reviewdb.client.Patch;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.patch.PatchScriptFactory;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gwtjsonrpc.common.AsyncCallback;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
class PatchDetailServiceImpl extends BaseServiceImplementation implements
|
||||
PatchDetailService {
|
||||
private final PatchScriptFactory.Factory patchScriptFactoryFactory;
|
||||
private final ChangeControl.GenericFactory changeControlFactory;
|
||||
|
||||
@Inject
|
||||
PatchDetailServiceImpl(final Provider<ReviewDb> schema,
|
||||
final Provider<CurrentUser> currentUser,
|
||||
final PatchScriptFactory.Factory patchScriptFactoryFactory,
|
||||
final ChangeControl.GenericFactory changeControlFactory) {
|
||||
super(schema, currentUser);
|
||||
|
||||
this.patchScriptFactoryFactory = patchScriptFactoryFactory;
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void patchScript(final Patch.Key patchKey, final PatchSet.Id psa,
|
||||
final PatchSet.Id psb, final DiffPreferencesInfo dp,
|
||||
final AsyncCallback<PatchScript> callback) {
|
||||
if (psb == null) {
|
||||
callback.onFailure(new NoSuchEntityException());
|
||||
return;
|
||||
}
|
||||
|
||||
new Handler<PatchScript>() {
|
||||
@Override
|
||||
public PatchScript call() throws Exception {
|
||||
ChangeControl control = changeControlFactory.validateFor(
|
||||
getDb(), patchKey.getParentKey().getParentKey(),
|
||||
getUser());
|
||||
return patchScriptFactoryFactory.create(
|
||||
control, patchKey.getFileName(), psa, psb, dp).call();
|
||||
}
|
||||
}.to(callback);
|
||||
}
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
// Copyright (C) 2009 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.httpd.rpc.patch;
|
||||
|
||||
import com.google.gerrit.httpd.rpc.RpcServletModule;
|
||||
import com.google.gerrit.httpd.rpc.UiRpcModule;
|
||||
|
||||
public class PatchModule extends RpcServletModule {
|
||||
public PatchModule() {
|
||||
super(UiRpcModule.PREFIX);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
rpc(PatchDetailServiceImpl.class);
|
||||
}
|
||||
}
|
@@ -3,15 +3,10 @@ SRC = 'src/main/java/com/google/gerrit/prettify/'
|
||||
gwt_module(
|
||||
name = 'client',
|
||||
srcs = glob([
|
||||
SRC + 'client/**/*.java',
|
||||
SRC + 'common/**/*.java',
|
||||
]),
|
||||
gwt_xml = SRC + 'PrettyFormatter.gwt.xml',
|
||||
resources = glob([
|
||||
'src/main/java/com/google/gerrit/prettify/client/*.properties',
|
||||
]),
|
||||
deps = [
|
||||
':google-code-prettify',
|
||||
'//gerrit-gwtexpui:SafeHtml',
|
||||
],
|
||||
exported_deps = [
|
||||
@@ -26,16 +21,6 @@ gwt_module(
|
||||
visibility = ['PUBLIC'],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = 'google-code-prettify',
|
||||
resources = glob([
|
||||
'src/main/resources/com/google/gerrit/prettify/client/**/*',
|
||||
]),
|
||||
deps = [
|
||||
'//lib:LICENSE-Apache2.0',
|
||||
],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = 'server',
|
||||
srcs = glob([SRC + 'common/**/*.java']),
|
||||
|
@@ -24,5 +24,4 @@
|
||||
<inherits name='com.google.gwt.resources.Resources'/>
|
||||
<inherits name='com.google.gwtexpui.safehtml.SafeHtml'/>
|
||||
<source path='common' />
|
||||
<source path='client' />
|
||||
</module>
|
||||
|
@@ -1,80 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.user.client.ui.RootPanel;
|
||||
|
||||
/** Evaluates prettify using the host browser's JavaScript engine. */
|
||||
public class ClientSideFormatter extends PrettyFormatter {
|
||||
public static final PrettyFactory FACTORY = new PrettyFactory() {
|
||||
@Override
|
||||
public PrettyFormatter get() {
|
||||
return new ClientSideFormatter();
|
||||
}
|
||||
};
|
||||
|
||||
private static final PrivateScopeImpl prettify;
|
||||
|
||||
static {
|
||||
Resources.I.prettify_css().ensureInjected();
|
||||
Resources.I.gerrit_css().ensureInjected();
|
||||
|
||||
prettify = GWT.create(PrivateScopeImpl.class);
|
||||
RootPanel.get().add(prettify);
|
||||
|
||||
prettify.compile(Resources.I.core());
|
||||
prettify.compile(Resources.I.lang_apollo());
|
||||
prettify.compile(Resources.I.lang_basic());
|
||||
prettify.compile(Resources.I.lang_clj());
|
||||
prettify.compile(Resources.I.lang_css());
|
||||
prettify.compile(Resources.I.lang_dart());
|
||||
prettify.compile(Resources.I.lang_erlang());
|
||||
prettify.compile(Resources.I.lang_go());
|
||||
prettify.compile(Resources.I.lang_hs());
|
||||
prettify.compile(Resources.I.lang_lisp());
|
||||
prettify.compile(Resources.I.lang_llvm());
|
||||
prettify.compile(Resources.I.lang_lua());
|
||||
prettify.compile(Resources.I.lang_matlab());
|
||||
prettify.compile(Resources.I.lang_ml());
|
||||
prettify.compile(Resources.I.lang_mumps());
|
||||
prettify.compile(Resources.I.lang_n());
|
||||
prettify.compile(Resources.I.lang_pascal());
|
||||
prettify.compile(Resources.I.lang_proto());
|
||||
prettify.compile(Resources.I.lang_r());
|
||||
prettify.compile(Resources.I.lang_rd());
|
||||
prettify.compile(Resources.I.lang_scala());
|
||||
prettify.compile(Resources.I.lang_sql());
|
||||
prettify.compile(Resources.I.lang_tcl());
|
||||
prettify.compile(Resources.I.lang_tex());
|
||||
prettify.compile(Resources.I.lang_vb());
|
||||
prettify.compile(Resources.I.lang_vhdl());
|
||||
prettify.compile(Resources.I.lang_wiki());
|
||||
prettify.compile(Resources.I.lang_xq());
|
||||
prettify.compile(Resources.I.lang_yaml());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prettify(String html, String type) {
|
||||
return go(prettify.getContext(), html, type);
|
||||
}
|
||||
|
||||
private static native String go(JavaScriptObject ctx, String srcText,
|
||||
String srcType)
|
||||
/*-{
|
||||
return ctx.prettyPrintOne(srcText, srcType);
|
||||
}-*/;
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.i18n.client.Constants;
|
||||
|
||||
public interface PrettifyConstants extends Constants {
|
||||
static final PrettifyConstants C = GWT.create(PrettifyConstants.class);
|
||||
|
||||
String wseTabAfterSpace();
|
||||
String wseTrailingSpace();
|
||||
String wseBareCR();
|
||||
String leCR();
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
wseTabAfterSpace=Whitespace error: Tab after space
|
||||
wseTrailingSpace=Whitespace error: Trailing space at end of line
|
||||
wseBareCR=CR without LF
|
||||
leCR=Carriage Return
|
@@ -1,20 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
/** Creates a new PrettyFormatter instance for one formatting run. */
|
||||
public interface PrettyFactory {
|
||||
PrettyFormatter get();
|
||||
}
|
@@ -1,561 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
|
||||
import com.google.gerrit.prettify.common.SparseFileContent;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
|
||||
|
||||
import org.eclipse.jgit.diff.Edit;
|
||||
import org.eclipse.jgit.diff.ReplaceEdit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class PrettyFormatter implements SparseHtmlFile {
|
||||
public abstract static class EditFilter {
|
||||
abstract String getStyleName();
|
||||
|
||||
abstract int getBegin(Edit edit);
|
||||
|
||||
abstract int getEnd(Edit edit);
|
||||
}
|
||||
|
||||
public static final EditFilter A = new EditFilter() {
|
||||
@Override
|
||||
String getStyleName() {
|
||||
return "wdd";
|
||||
}
|
||||
|
||||
@Override
|
||||
int getBegin(Edit edit) {
|
||||
return edit.getBeginA();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getEnd(Edit edit) {
|
||||
return edit.getEndA();
|
||||
}
|
||||
};
|
||||
|
||||
public static final EditFilter B = new EditFilter() {
|
||||
@Override
|
||||
String getStyleName() {
|
||||
return "wdi";
|
||||
}
|
||||
|
||||
@Override
|
||||
int getBegin(Edit edit) {
|
||||
return edit.getBeginB();
|
||||
}
|
||||
|
||||
@Override
|
||||
int getEnd(Edit edit) {
|
||||
return edit.getEndB();
|
||||
}
|
||||
};
|
||||
|
||||
protected SparseFileContent content;
|
||||
protected EditFilter side;
|
||||
protected List<Edit> edits;
|
||||
protected DiffPreferencesInfo diffPrefs;
|
||||
protected String fileName;
|
||||
protected Set<Integer> trailingEdits;
|
||||
|
||||
private int col;
|
||||
private int lineIdx;
|
||||
private Tag lastTag;
|
||||
private StringBuilder buf;
|
||||
|
||||
@Override
|
||||
public SafeHtml getSafeHtmlLine(int lineNo) {
|
||||
return SafeHtml.asis(content.get(lineNo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return content.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int idx) {
|
||||
return content.contains(idx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTrailingEdit(int idx) {
|
||||
return trailingEdits.contains(idx);
|
||||
}
|
||||
|
||||
public void setEditFilter(EditFilter f) {
|
||||
side = f;
|
||||
}
|
||||
|
||||
public void setEditList(List<Edit> all) {
|
||||
edits = all;
|
||||
}
|
||||
|
||||
public void setDiffPrefs(DiffPreferencesInfo how) {
|
||||
diffPrefs = how;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and format a complete source code file.
|
||||
*
|
||||
* @param src raw content of the file to format. The line strings will be HTML
|
||||
* escaped before processing, so it must be the raw text.
|
||||
*/
|
||||
public void format(SparseFileContent src) {
|
||||
content = new SparseFileContent();
|
||||
content.setSize(src.size());
|
||||
trailingEdits = new HashSet<>();
|
||||
|
||||
String html = toHTML(src);
|
||||
|
||||
html = expandTabs(html);
|
||||
if (diffPrefs.syntaxHighlighting && getFileType() != null
|
||||
&& src.isWholeFile()) {
|
||||
// The prettify parsers don't like ' as an entity for the
|
||||
// single quote character. Replace them all out so we don't
|
||||
// confuse the parser.
|
||||
//
|
||||
html = html.replaceAll("'", "'");
|
||||
|
||||
// If a line is modified at its end and the line ending is changed from
|
||||
// '\n' to '\r\n' then the '\r' of the new line is part of the modified
|
||||
// text. If intraline diffs are highlighted the modified text is
|
||||
// surrounded by a 'span' tag. As result '\r' and '\n' of the new line get
|
||||
// separated by '</span>'. For the prettify parser this now looks like two
|
||||
// separate line endings. This messes up the line counting below.
|
||||
// Drop any '\r' to avoid this problem.
|
||||
html = html.replaceAll("\r</span>(<span class=\"wdc\">)?\n", "</span>$1\n");
|
||||
|
||||
html = html.replaceAll("(\r)?\n", " $1\n");
|
||||
html = prettify(html, getFileType());
|
||||
html = html.replaceAll(" (\r)?\n", "$1\n");
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
int textChunkStart = 0;
|
||||
|
||||
lastTag = Tag.NULL;
|
||||
col = 0;
|
||||
lineIdx = 0;
|
||||
|
||||
buf = new StringBuilder();
|
||||
while (pos <= html.length()) {
|
||||
int tagStart = html.indexOf('<', pos);
|
||||
int lf = html.indexOf('\n', pos);
|
||||
|
||||
if (tagStart < 0 && lf < 0) {
|
||||
// No more tags remaining. What's left is plain text.
|
||||
//
|
||||
assert lastTag == Tag.NULL;
|
||||
pos = html.length();
|
||||
if (textChunkStart < pos) {
|
||||
htmlText(html.substring(textChunkStart, pos));
|
||||
}
|
||||
if (0 < buf.length()) {
|
||||
content.addLine(src.mapIndexToLine(lineIdx), buf.toString());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Line end occurs before the next HTML tag. Break the line.
|
||||
if (0 <= lf && (lf < tagStart || tagStart < 0)) {
|
||||
if (textChunkStart < lf) {
|
||||
lastTag.open(buf, html);
|
||||
htmlText(html.substring(textChunkStart, lf));
|
||||
}
|
||||
pos = lf + 1;
|
||||
textChunkStart = pos;
|
||||
|
||||
lastTag.close(buf, html);
|
||||
content.addLine(src.mapIndexToLine(lineIdx++), buf.toString());
|
||||
buf = new StringBuilder();
|
||||
col = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Assume no attribute contains '>' and that all tags
|
||||
// within the HTML will be well-formed.
|
||||
//
|
||||
int tagEnd = html.indexOf('>', tagStart);
|
||||
assert tagStart < tagEnd;
|
||||
pos = tagEnd + 1;
|
||||
|
||||
// Handle any text between the end of the last tag,
|
||||
// and the start of this tag.
|
||||
//
|
||||
if (textChunkStart < tagStart) {
|
||||
lastTag.open(buf, html);
|
||||
htmlText(html.substring(textChunkStart, tagStart));
|
||||
}
|
||||
textChunkStart = pos;
|
||||
|
||||
if (html.charAt(tagStart + 1) == '/') {
|
||||
lastTag = lastTag.pop(buf, html);
|
||||
|
||||
} else if (html.charAt(tagEnd - 1) != '/') {
|
||||
lastTag = new Tag(lastTag, tagStart, tagEnd);
|
||||
}
|
||||
}
|
||||
buf = null;
|
||||
}
|
||||
|
||||
private void htmlText(String txt) {
|
||||
int pos = 0;
|
||||
while (pos < txt.length()) {
|
||||
int start = txt.indexOf('&', pos);
|
||||
if (start < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
cleanText(txt, pos, start);
|
||||
pos = txt.indexOf(';', start + 1) + 1;
|
||||
|
||||
if (diffPrefs.lineLength <= col) {
|
||||
buf.append("<br />");
|
||||
col = 0;
|
||||
}
|
||||
|
||||
buf.append(txt.substring(start, pos));
|
||||
col++;
|
||||
}
|
||||
|
||||
cleanText(txt, pos, txt.length());
|
||||
}
|
||||
|
||||
private void cleanText(String txt, int pos, int end) {
|
||||
while (pos < end) {
|
||||
int free = diffPrefs.lineLength - col;
|
||||
if (free <= 0) {
|
||||
// The current line is full. Throw an explicit line break
|
||||
// onto the end, and we'll continue on the next line.
|
||||
//
|
||||
buf.append("<br />");
|
||||
col = 0;
|
||||
free = diffPrefs.lineLength;
|
||||
}
|
||||
|
||||
int n = Math.min(end - pos, free);
|
||||
buf.append(txt.substring(pos, pos + n));
|
||||
col += n;
|
||||
pos += n;
|
||||
}
|
||||
}
|
||||
|
||||
/** Run the prettify engine over the text and return the result. */
|
||||
protected abstract String prettify(String html, String type);
|
||||
|
||||
private static class Tag {
|
||||
static final Tag NULL = new Tag(null, 0, 0) {
|
||||
@Override
|
||||
void open(StringBuilder buf, String html) {
|
||||
}
|
||||
|
||||
@Override
|
||||
void close(StringBuilder buf, String html) {
|
||||
}
|
||||
|
||||
@Override
|
||||
Tag pop(StringBuilder buf, String html) {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
final Tag parent;
|
||||
final int start;
|
||||
final int end;
|
||||
boolean open;
|
||||
|
||||
Tag(Tag p, int s, int e) {
|
||||
parent = p;
|
||||
start = s;
|
||||
end = e;
|
||||
}
|
||||
|
||||
void open(StringBuilder buf, String html) {
|
||||
if (!open) {
|
||||
parent.open(buf, html);
|
||||
buf.append(html.substring(start, end + 1));
|
||||
open = true;
|
||||
}
|
||||
}
|
||||
|
||||
void close(StringBuilder buf, String html) {
|
||||
pop(buf, html);
|
||||
parent.close(buf, html);
|
||||
}
|
||||
|
||||
Tag pop(StringBuilder buf, String html) {
|
||||
if (open) {
|
||||
int sp = html.indexOf(' ', start + 1);
|
||||
if (sp < 0 || end < sp) {
|
||||
sp = end;
|
||||
}
|
||||
|
||||
buf.append("</");
|
||||
buf.append(html.substring(start + 1, sp));
|
||||
buf.append('>');
|
||||
open = false;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
private String toHTML(SparseFileContent src) {
|
||||
SafeHtml html;
|
||||
|
||||
if (diffPrefs.intralineDifference) {
|
||||
html = colorLineEdits(src);
|
||||
} else {
|
||||
SafeHtmlBuilder b = new SafeHtmlBuilder();
|
||||
for (int index = src.first(); index < src.size(); index = src.next(index)) {
|
||||
b.append(src.get(index));
|
||||
b.append('\n');
|
||||
}
|
||||
html = b;
|
||||
|
||||
final String r = "<span class=\"wse\"" //
|
||||
+ " title=\"" + PrettifyConstants.C.wseBareCR() + "\"" //
|
||||
+ "> </span>$1";
|
||||
html = html.replaceAll("\r([^\n])", r);
|
||||
}
|
||||
|
||||
if (diffPrefs.showWhitespaceErrors) {
|
||||
// We need to do whitespace errors before showing tabs, because
|
||||
// these patterns rely on \t as a literal, before it expands.
|
||||
//
|
||||
html = showTabAfterSpace(html);
|
||||
html = showTrailingWhitespace(html);
|
||||
}
|
||||
|
||||
if (diffPrefs.showLineEndings){
|
||||
html = showLineEndings(html);
|
||||
}
|
||||
|
||||
if (diffPrefs.showTabs) {
|
||||
String t = 1 < diffPrefs.tabSize ? "\t" : "";
|
||||
html = html.replaceAll("\t", "<span class=\"vt\">\u00BB</span>" + t);
|
||||
}
|
||||
|
||||
return html.asString();
|
||||
}
|
||||
|
||||
private SafeHtml colorLineEdits(SparseFileContent src) {
|
||||
// Make a copy of the edits with a sentinel that is after all lines
|
||||
// in the source. That simplifies our loop below because we'll never
|
||||
// run off the end of the edit list.
|
||||
//
|
||||
List<Edit> edits = new ArrayList<>(this.edits.size() + 1);
|
||||
edits.addAll(this.edits);
|
||||
edits.add(new Edit(src.size(), src.size()));
|
||||
|
||||
SafeHtmlBuilder buf = new SafeHtmlBuilder();
|
||||
|
||||
int curIdx = 0;
|
||||
Edit curEdit = edits.get(curIdx);
|
||||
|
||||
ReplaceEdit lastReplace = null;
|
||||
List<Edit> charEdits = null;
|
||||
int lastPos = 0;
|
||||
int lastIdx = 0;
|
||||
|
||||
for (int index = src.first(); index < src.size(); index = src.next(index)) {
|
||||
int cmp = compare(index, curEdit);
|
||||
while (0 < cmp) {
|
||||
// The index is after the edit. Skip to the next edit.
|
||||
//
|
||||
curEdit = edits.get(curIdx++);
|
||||
cmp = compare(index, curEdit);
|
||||
}
|
||||
|
||||
if (cmp < 0) {
|
||||
// index occurs before the edit. This is a line of context.
|
||||
//
|
||||
appendShowBareCR(buf, src.get(index), true);
|
||||
buf.append('\n');
|
||||
continue;
|
||||
}
|
||||
|
||||
// index occurs within the edit. The line is a modification.
|
||||
//
|
||||
if (curEdit instanceof ReplaceEdit) {
|
||||
if (lastReplace != curEdit) {
|
||||
lastReplace = (ReplaceEdit) curEdit;
|
||||
charEdits = lastReplace.getInternalEdits();
|
||||
lastPos = 0;
|
||||
lastIdx = 0;
|
||||
}
|
||||
|
||||
String line = src.get(index) + "\n";
|
||||
for (int c = 0; c < line.length();) {
|
||||
if (charEdits == null || (charEdits.size() <= lastIdx)) {
|
||||
appendShowBareCR(buf, line.substring(c), false);
|
||||
break;
|
||||
}
|
||||
|
||||
final Edit edit = charEdits.get(lastIdx);
|
||||
final int b = side.getBegin(edit) - lastPos;
|
||||
final int e = side.getEnd(edit) - lastPos;
|
||||
|
||||
if (c < b) {
|
||||
// There is text at the start of this line that is common
|
||||
// with the other side. Copy it with no style around it.
|
||||
//
|
||||
final int cmnLen = Math.min(b, line.length());
|
||||
buf.openSpan();
|
||||
buf.setStyleName("wdc");
|
||||
appendShowBareCR(buf, line.substring(c, cmnLen), //
|
||||
cmnLen == line.length() - 1);
|
||||
buf.closeSpan();
|
||||
c = cmnLen;
|
||||
}
|
||||
|
||||
final int modLen = Math.min(e, line.length());
|
||||
if (c < e && c < modLen) {
|
||||
buf.openSpan();
|
||||
buf.setStyleName(side.getStyleName());
|
||||
appendShowBareCR(buf, line.substring(c, modLen), //
|
||||
modLen == line.length() - 1);
|
||||
buf.closeSpan();
|
||||
if (modLen == line.length()) {
|
||||
trailingEdits.add(index);
|
||||
}
|
||||
c = modLen;
|
||||
}
|
||||
|
||||
if (e <= c) {
|
||||
lastIdx++;
|
||||
}
|
||||
}
|
||||
lastPos += line.length();
|
||||
|
||||
} else {
|
||||
appendShowBareCR(buf, src.get(index), true);
|
||||
buf.append('\n');
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void appendShowBareCR(SafeHtmlBuilder buf, String src, boolean end) {
|
||||
while (!src.isEmpty()) {
|
||||
int cr = src.indexOf('\r');
|
||||
if (cr < 0) {
|
||||
buf.append(src);
|
||||
return;
|
||||
|
||||
} else if (end) {
|
||||
if (cr == src.length() - 1) {
|
||||
buf.append(src.substring(0, cr + 1));
|
||||
return;
|
||||
}
|
||||
} else if (cr == src.length() - 2 && src.charAt(cr + 1) == '\n') {
|
||||
buf.append(src);
|
||||
return;
|
||||
}
|
||||
|
||||
buf.append(src.substring(0, cr));
|
||||
buf.openSpan();
|
||||
buf.setStyleName("wse");
|
||||
buf.setAttribute("title", PrettifyConstants.C.wseBareCR());
|
||||
buf.nbsp();
|
||||
buf.closeSpan();
|
||||
src = src.substring(cr + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private int compare(int index, Edit edit) {
|
||||
if (index < side.getBegin(edit)) {
|
||||
return -1; // index occurs before the edit.
|
||||
|
||||
} else if (index < side.getEnd(edit)) {
|
||||
return 0; // index occurs within the edit.
|
||||
|
||||
} else {
|
||||
return 1; // index occurs after the edit.
|
||||
}
|
||||
}
|
||||
|
||||
private SafeHtml showTabAfterSpace(SafeHtml src) {
|
||||
final String m = "( ( |<span[^>]*>|</span>)*\t)";
|
||||
final String r = "<span class=\"wse\"" //
|
||||
+ " title=\"" + PrettifyConstants.C.wseTabAfterSpace() + "\"" //
|
||||
+ ">$1</span>";
|
||||
src = src.replaceFirst("^" + m, r);
|
||||
src = src.replaceAll("\n" + m, "\n" + r);
|
||||
return src;
|
||||
}
|
||||
|
||||
private SafeHtml showTrailingWhitespace(SafeHtml src) {
|
||||
final String r = "<span class=\"wse\"" //
|
||||
+ " title=\"" + PrettifyConstants.C.wseTrailingSpace() + "\"" //
|
||||
+ ">$1</span>$2";
|
||||
src = src.replaceAll("([ \t][ \t]*)(\r?(</span>)?\n)", r);
|
||||
src = src.replaceFirst("([ \t][ \t]*)(\r?(</span>)?\n?)$", r);
|
||||
return src;
|
||||
}
|
||||
|
||||
private SafeHtml showLineEndings(SafeHtml src) {
|
||||
final String r = "<span class=\"lecr\""
|
||||
+ " title=\"" + PrettifyConstants.C.leCR() + "\"" //
|
||||
+ ">\\\\r</span>";
|
||||
src = src.replaceAll("\r", r);
|
||||
return src;
|
||||
}
|
||||
|
||||
private String expandTabs(String html) {
|
||||
StringBuilder tmp = new StringBuilder();
|
||||
int i = 0;
|
||||
if (diffPrefs.showTabs) {
|
||||
i = 1;
|
||||
}
|
||||
for (; i < diffPrefs.tabSize; i++) {
|
||||
tmp.append(" ");
|
||||
}
|
||||
return html.replaceAll("\t", tmp.toString());
|
||||
}
|
||||
|
||||
private String getFileType() {
|
||||
String srcType = fileName;
|
||||
if (srcType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int dot = srcType.lastIndexOf('.');
|
||||
if (dot < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (0 < dot) {
|
||||
srcType = srcType.substring(dot + 1);
|
||||
}
|
||||
|
||||
if ("txt".equalsIgnoreCase(srcType)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return srcType;
|
||||
}
|
||||
}
|
@@ -1,67 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
import com.google.gwt.resources.client.TextResource;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.NamedFrame;
|
||||
|
||||
/**
|
||||
* Creates a private JavaScript environment, typically inside an IFrame.
|
||||
* <p>
|
||||
* Instances must be created through {@code GWT.create(PrivateScopeImpl.class)}.
|
||||
* A scope must remain attached to the primary document for its entire life.
|
||||
* Behavior is undefined if a scope is detached and attached again later. It is
|
||||
* best to attach the scope with {@code RootPanel.get().add(scope)} as soon as
|
||||
* it has been created.
|
||||
*/
|
||||
public class PrivateScopeImpl extends Composite {
|
||||
private static int scopeId;
|
||||
|
||||
protected final String scopeName;
|
||||
|
||||
public PrivateScopeImpl() {
|
||||
scopeName = nextScopeName();
|
||||
|
||||
NamedFrame frame = new NamedFrame(scopeName);
|
||||
frame.setUrl("javascript:''");
|
||||
initWidget(frame);
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
public void compile(TextResource js) {
|
||||
eval(js.getText());
|
||||
}
|
||||
|
||||
public void eval(String js) {
|
||||
nativeEval(getContext(), js);
|
||||
}
|
||||
|
||||
public JavaScriptObject getContext() {
|
||||
return nativeGetContext(scopeName);
|
||||
}
|
||||
|
||||
private static String nextScopeName() {
|
||||
return "_PrivateScope" + (++scopeId);
|
||||
}
|
||||
|
||||
private static native void nativeEval(JavaScriptObject ctx, String js)
|
||||
/*-{ ctx.eval(js); }-*/;
|
||||
|
||||
private static native JavaScriptObject nativeGetContext(String scopeName)
|
||||
/*-{ return $wnd[scopeName]; }-*/;
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
/** MSIE requires us to initialize the document before we can use it. */
|
||||
public class PrivateScopeImplIE8 extends PrivateScopeImpl {
|
||||
private JavaScriptObject context;
|
||||
|
||||
@Override
|
||||
protected void onAttach() {
|
||||
super.onAttach();
|
||||
context = nativeInitContext(scopeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaScriptObject getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
private static native JavaScriptObject nativeInitContext(String scopeName)
|
||||
/*-{
|
||||
var fe = $wnd[scopeName];
|
||||
fe.document.write(
|
||||
'<script>'
|
||||
+ 'parent._PrivateScopeNewChild = this;'
|
||||
+ '</' + 'script>'
|
||||
);
|
||||
var ctx = $wnd._PrivateScopeNewChild;
|
||||
$wnd._PrivateScopeNewChild = undefined;
|
||||
return ctx;
|
||||
}-*/;
|
||||
}
|
@@ -1,63 +0,0 @@
|
||||
// Copyright (C) 2009 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.prettify.client;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.resources.client.ClientBundle;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
import com.google.gwt.resources.client.TextResource;
|
||||
|
||||
/** Loads the minimized form of prettify into the client. */
|
||||
interface Resources extends ClientBundle {
|
||||
static final Resources I = GWT.create(Resources.class);
|
||||
|
||||
@Source("prettify.css")
|
||||
CssResource prettify_css();
|
||||
|
||||
@Source("gerrit.css")
|
||||
CssResource gerrit_css();
|
||||
|
||||
@Source("prettify.js")
|
||||
TextResource core();
|
||||
|
||||
@Source("lang-apollo.js") TextResource lang_apollo();
|
||||
@Source("lang-basic.js") TextResource lang_basic();
|
||||
@Source("lang-clj.js") TextResource lang_clj();
|
||||
@Source("lang-css.js") TextResource lang_css();
|
||||
@Source("lang-dart.js") TextResource lang_dart();
|
||||
@Source("lang-erlang.js") TextResource lang_erlang();
|
||||
@Source("lang-go.js") TextResource lang_go();
|
||||
@Source("lang-hs.js") TextResource lang_hs();
|
||||
@Source("lang-lisp.js") TextResource lang_lisp();
|
||||
@Source("lang-llvm.js") TextResource lang_llvm();
|
||||
@Source("lang-lua.js") TextResource lang_lua();
|
||||
@Source("lang-matlab.js") TextResource lang_matlab();
|
||||
@Source("lang-ml.js") TextResource lang_ml();
|
||||
@Source("lang-mumps.js") TextResource lang_mumps();
|
||||
@Source("lang-n.js") TextResource lang_n();
|
||||
@Source("lang-pascal.js") TextResource lang_pascal();
|
||||
@Source("lang-proto.js") TextResource lang_proto();
|
||||
@Source("lang-r.js") TextResource lang_r();
|
||||
@Source("lang-rd.js") TextResource lang_rd();
|
||||
@Source("lang-scala.js") TextResource lang_scala();
|
||||
@Source("lang-sql.js") TextResource lang_sql();
|
||||
@Source("lang-tcl.js") TextResource lang_tcl();
|
||||
@Source("lang-tex.js") TextResource lang_tex();
|
||||
@Source("lang-vb.js") TextResource lang_vb();
|
||||
@Source("lang-vhdl.js") TextResource lang_vhdl();
|
||||
@Source("lang-wiki.js") TextResource lang_wiki();
|
||||
@Source("lang-xq.js") TextResource lang_xq();
|
||||
@Source("lang-yaml.js") TextResource lang_yaml();
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2010 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.prettify.client;
|
||||
|
||||
import com.google.gwtexpui.safehtml.client.SafeHtml;
|
||||
|
||||
public interface SparseHtmlFile {
|
||||
/** @return the line of formatted HTML. */
|
||||
SafeHtml getSafeHtmlLine(int lineNo);
|
||||
|
||||
/** @return the number of lines in this sparse list. */
|
||||
int size();
|
||||
|
||||
/** @return true if the line is valid in this sparse list. */
|
||||
boolean contains(int idx);
|
||||
|
||||
/** @return true if this line ends in the middle of a character edit span. */
|
||||
boolean hasTrailingEdit(int idx);
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
/* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
@external .wse;
|
||||
@external .lecr;
|
||||
@external .vt;
|
||||
@external .wdd;
|
||||
@external .wdi;
|
||||
|
||||
@external .str;
|
||||
@external .kwd;
|
||||
@external .com;
|
||||
@external .typ;
|
||||
@external .lit;
|
||||
@external .pun;
|
||||
@external .pln;
|
||||
@external .tag;
|
||||
@external .atn;
|
||||
@external .atv;
|
||||
@external .dec;
|
||||
|
||||
.wse {
|
||||
background: red;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.lecr {
|
||||
border-bottom: #aaaaaa 1px dashed;
|
||||
border-left: #aaaaaa 1px dashed;
|
||||
padding-bottom: 0px;
|
||||
margin: 0px 2px;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
border-top: #aaaaaa 1px dashed;
|
||||
border-right: #aaaaaa 1px dashed;
|
||||
padding-top: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.vt,
|
||||
.vt .str,
|
||||
.vt .kwd,
|
||||
.vt .com,
|
||||
.vt .typ,
|
||||
.vt .lit,
|
||||
.vt .pun,
|
||||
.vt .pln,
|
||||
.vt .tag,
|
||||
.vt .atn,
|
||||
.vt .atv,
|
||||
.vt .dec {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.wdd {
|
||||
background: #FAA;
|
||||
}
|
||||
.wdi {
|
||||
background: #9F9;
|
||||
}
|
||||
|
||||
/* Use special rules for special styles contained within a whitespace
|
||||
* error. For these we want the whitespace error to take precedence
|
||||
* so we have to override the contained style.
|
||||
*/
|
||||
.wse .vt, .wdd .vt,
|
||||
.wse .vt .pun, .wdd .vt .pun,
|
||||
.wse .vt .str, .wdd .vt .str,
|
||||
.wse .vt .kwd, .wdd .vt .kwd,
|
||||
.wse .vt .com, .wdd .vt .com,
|
||||
.wse .vt .typ, .wdd .vt .typ,
|
||||
.wse .vt .lit, .wdd .vt .lit,
|
||||
.wse .vt .pun, .wdd .vt .pun,
|
||||
.wse .vt .pln, .wdd .vt .pln,
|
||||
.wse .vt .tag, .wdd .vt .tag,
|
||||
.wse .vt .atn, .wdd .vt .atn,
|
||||
.wse .vt .atv, .wdd .vt .atv,
|
||||
.wse .vt .dec, .wdd .vt .dec {
|
||||
color: black;
|
||||
}
|
||||
.wse .wdd {
|
||||
background: red;
|
||||
}
|
||||
.wse .wdi {
|
||||
background: red;
|
||||
}
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
|
||||
null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]);
|
@@ -1,3 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["str",/^"(?:[^\n\r"\\]|\\.)*(?:"|$)/,a,'"'],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^REM[^\n\r]*/,a],["kwd",/^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/,a],["pln",/^[a-z][^\W_]?(?:\$|%)?/i,a],["lit",/^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/i,a,"0123456789"],["pun",
|
||||
/^.[^\s\w"$%.]*/,a]]),["basic","cbm"]);
|
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2011 Google Inc.
|
||||
|
||||
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.
|
||||
*/
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a],
|
||||
["typ",/^:[\dA-Za-z-]+/]]),["clj"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n\u000c"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]+)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],
|
||||
["com",/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}\b/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
|
@@ -1,3 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"]],[["com",/^#!.*/],["kwd",/^\b(?:import|library|part of|part|as|show|hide)\b/i],["com",/^\/\/.*/],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["kwd",/^\b(?:class|interface)\b/i],["kwd",/^\b(?:assert|break|case|catch|continue|default|do|else|finally|for|if|in|is|new|return|super|switch|this|throw|try|while)\b/i],["kwd",/^\b(?:abstract|const|extends|factory|final|get|implements|native|operator|set|static|typedef|var)\b/i],
|
||||
["typ",/^\b(?:bool|double|dynamic|int|num|object|string|void)\b/i],["kwd",/^\b(?:false|null|true)\b/i],["str",/^r?'''[\S\s]*?[^\\]'''/],["str",/^r?"""[\S\s]*?[^\\]"""/],["str",/^r?'('|[^\n\f\r]*?[^\\]')/],["str",/^r?"("|[^\n\f\r]*?[^\\]")/],["pln",/^[$_a-z]\w*/i],["pun",/^[!%&*+/:<-?^|~-]/],["lit",/^\b0x[\da-f]+/i],["lit",/^\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i],["lit",/^\b\.\d+(?:e[+-]?\d+)?/i],["pun",/^[(),.;[\]{}]/]]),
|
||||
["dart"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["lit",/^[a-z]\w*/],["lit",/^'(?:[^\n\f\r'\\]|\\[^&])+'?/,null,"'"],["lit",/^\?[^\t\n ({]+/,null,"?"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\n]*/],["kwd",/^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/],
|
||||
["kwd",/^-[_a-z]+/],["typ",/^[A-Z_]\w*/],["pun",/^[,.;]/]]),["erlang","erl"]);
|
@@ -1 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
|
||||
null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]);
|
@@ -1,3 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a],
|
||||
["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","lsp","scm","ss","rkt"]);
|
@@ -1 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^!?"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["com",/^;[^\n\r]*/,null,";"]],[["pln",/^[!%@](?:[$\-.A-Z_a-z][\w$\-.]*|\d+)/],["kwd",/^[^\W\d]\w*/,null],["lit",/^\d+\.\d+/],["lit",/^(?:\d+|0[Xx][\dA-Fa-f]+)/],["pun",/^[(-*,:<->[\]{}]|\.\.\.$/]]),["llvm","ll"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],
|
||||
["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]);
|
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
|
||||
["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"]|\\.)*"/,null,'"']],[["com",/^;[^\n\r]*/,null,";"],["dec",/^\$(?:d|device|ec|ecode|es|estack|et|etrap|h|horolog|i|io|j|job|k|key|p|principal|q|quit|st|stack|s|storage|sy|system|t|test|tl|tlevel|tr|trestart|x|y|z[a-z]*|a|ascii|c|char|d|data|e|extract|f|find|fn|fnumber|g|get|j|justify|l|length|na|name|o|order|p|piece|ql|qlength|qs|qsubscript|q|query|r|random|re|reverse|s|select|st|stack|t|text|tr|translate|nan)\b/i,
|
||||
null],["kwd",/^(?:[^$]b|break|c|close|d|do|e|else|f|for|g|goto|h|halt|h|hang|i|if|j|job|k|kill|l|lock|m|merge|n|new|o|open|q|quit|r|read|s|set|tc|tcommit|tre|trestart|tro|trollback|ts|tstart|u|use|v|view|w|write|x|xecute)\b/i,null],["lit",/^[+-]?(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?/i],["pln",/^[a-z][^\W_]*/i],["pun",/^[^\w\t\n\r"$%;^\xa0]|_/]]),["mumps"]);
|
@@ -1,4 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/,
|
||||
a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
|
||||
a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]);
|
@@ -1,3 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["str",/^'(?:[^\n\r'\\]|\\.)*(?:'|$)/,a,"'"],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^\(\*[\S\s]*?(?:\*\)|$)|^{[\S\s]*?(?:}|$)/,a],["kwd",/^(?:absolute|and|array|asm|assembler|begin|case|const|constructor|destructor|div|do|downto|else|end|external|for|forward|function|goto|if|implementation|in|inline|interface|interrupt|label|mod|not|object|of|or|packed|procedure|program|record|repeat|set|shl|shr|then|to|type|unit|until|uses|var|virtual|while|with|xor)\b/i,a],
|
||||
["lit",/^(?:true|false|self|nil)/i,a],["pln",/^[a-z][^\W_]*/i,a],["lit",/^(?:\$[\da-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)/i,a,"0123456789"],["pun",/^.[^\s\w$'./@]*/,a]]),["pascal"]);
|
@@ -1 +0,0 @@
|
||||
PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^'\\]|\\[\S\s])*(?:'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![\w.])/],["lit",/^0[Xx][\dA-Fa-f]+([Pp]\d+)?[Li]?/],["lit",/^[+-]?(\d+(\.\d+)?|\.\d+)([Ee][+-]?\d+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|\d+))(?![\w.])/],
|
||||
["pun",/^(?:<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|[!*+/^]|%.*?%|[$=@~]|:{1,3}|[(),;?[\]{}])/],["pln",/^(?:[A-Za-z]+[\w.]*|\.[^\W\d][\w.]*)(?![\w.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]);
|
@@ -1 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["lit",/^\\(?:cr|l?dots|R|tab)\b/],["kwd",/^\\[@-Za-z]+/],["kwd",/^#(?:ifn?def|endif)/],["pln",/^\\[{}]/],["pun",/^[()[\]{}]+/]]),["Rd","rd"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
|
||||
["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|apply|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|connect|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|following|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|matched|merge|natural|national|nocheck|nonclustered|nocycle|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|partition|percent|pivot|plan|preceding|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rows?|rule|save|schema|select|session_user|set|setuser|shutdown|some|start|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|unbounded|union|unique|unpivot|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|within|writetext|xml)(?=[^\w-]|$)/i,
|
||||
null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]);
|
@@ -1,3 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^{+/,a,"{"],["clo",/^}+/,a,"}"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:after|append|apply|array|break|case|catch|continue|error|eval|exec|exit|expr|for|foreach|if|incr|info|proc|return|set|switch|trace|uplevel|upvar|while)\b/,a],["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",
|
||||
/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["tcl"]);
|
@@ -1 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r \u00a0\u2028\u2029"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"\u201c\u201d'],["com",/^['\u2018\u2019](?:_(?:\r\n?|[^\r]?)|[^\n\r_\u2028\u2029])*/,null,"'\u2018\u2019"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i,
|
||||
null],["com",/^rem\b.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*(?:\[[!#%&@]+])?|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]);
|
@@ -1,3 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
|
||||
null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i],
|
||||
["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]);
|
@@ -1,2 +0,0 @@
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t \u00a0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]);
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]);
|
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
var a=null;
|
||||
PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]);
|
Reference in New Issue
Block a user