InlineEdit: Allow to rename files in the UI

This change allows to rename files that are not contained in the
change. Renaming of files that already exist in the change (i.e.
from the file table) will be added later.

Change-Id: Iee396e73dc246bd232cca005af7e8f4f9041340c
This commit is contained in:
David Ostrovsky 2015-01-21 00:18:34 +01:00 committed by David Pursehouse
parent 847e503033
commit 7e0e2aee68
6 changed files with 256 additions and 0 deletions

View File

@ -191,6 +191,7 @@ public class ChangeScreen extends Screen {
@UiField Button reviewMode; @UiField Button reviewMode;
@UiField Button addFile; @UiField Button addFile;
@UiField Button deleteFile; @UiField Button deleteFile;
@UiField Button renameFile;
@UiField Button expandAll; @UiField Button expandAll;
@UiField Button collapseAll; @UiField Button collapseAll;
@UiField QuickApprove quickApprove; @UiField QuickApprove quickApprove;
@ -201,6 +202,7 @@ public class ChangeScreen extends Screen {
private DownloadAction downloadAction; private DownloadAction downloadAction;
private AddFileAction addFileAction; private AddFileAction addFileAction;
private DeleteFileAction deleteFileAction; private DeleteFileAction deleteFileAction;
private RenameFileAction renameFileAction;
public ChangeScreen(Change.Id changeId, String base, String revision, public ChangeScreen(Change.Id changeId, String base, String revision,
boolean openReplyBox, FileTable.Mode mode) { boolean openReplyBox, FileTable.Mode mode) {
@ -486,6 +488,7 @@ public class ChangeScreen extends Screen {
editMode.setVisible(fileTableMode == FileTable.Mode.REVIEW); editMode.setVisible(fileTableMode == FileTable.Mode.REVIEW);
addFile.setVisible(!editMode.isVisible()); addFile.setVisible(!editMode.isVisible());
deleteFile.setVisible(!editMode.isVisible()); deleteFile.setVisible(!editMode.isVisible());
renameFile.setVisible(!editMode.isVisible());
reviewMode.setVisible(!editMode.isVisible()); reviewMode.setVisible(!editMode.isVisible());
addFileAction = new AddFileAction( addFileAction = new AddFileAction(
changeId, info.revision(revision), changeId, info.revision(revision),
@ -493,6 +496,9 @@ public class ChangeScreen extends Screen {
deleteFileAction = new DeleteFileAction( deleteFileAction = new DeleteFileAction(
changeId, info.revision(revision), changeId, info.revision(revision),
style, addFile); style, addFile);
renameFileAction = new RenameFileAction(
changeId, info.revision(revision),
style, addFile);
} else { } else {
editMode.setVisible(false); editMode.setVisible(false);
addFile.setVisible(false); addFile.setVisible(false);
@ -670,6 +676,7 @@ public class ChangeScreen extends Screen {
editMode.setVisible(false); editMode.setVisible(false);
addFile.setVisible(true); addFile.setVisible(true);
deleteFile.setVisible(true); deleteFile.setVisible(true);
renameFile.setVisible(true);
reviewMode.setVisible(true); reviewMode.setVisible(true);
} }
@ -680,6 +687,7 @@ public class ChangeScreen extends Screen {
editMode.setVisible(true); editMode.setVisible(true);
addFile.setVisible(false); addFile.setVisible(false);
deleteFile.setVisible(false); deleteFile.setVisible(false);
renameFile.setVisible(false);
reviewMode.setVisible(false); reviewMode.setVisible(false);
} }
@ -693,6 +701,11 @@ public class ChangeScreen extends Screen {
deleteFileAction.onDelete(); deleteFileAction.onDelete();
} }
@UiHandler("renameFile")
void onRenameFile(@SuppressWarnings("unused") ClickEvent e) {
renameFileAction.onRename();
}
private void refreshFileTable() { private void refreshFileTable() {
int idx = diffBase.getSelectedIndex(); int idx = diffBase.getSelectedIndex();
if (0 <= idx) { if (0 <= idx) {

View File

@ -496,6 +496,13 @@ limitations under the License.
<ui:attribute name='title'/> <ui:attribute name='title'/>
<div><ui:msg>Delete&#8230;</ui:msg></div> <div><ui:msg>Delete&#8230;</ui:msg></div>
</g:Button> </g:Button>
<g:Button ui:field='renameFile'
title='Rename file in the repository'
styleName=''
visible='false'>
<ui:attribute name='title'/>
<div><ui:msg>Rename&#8230;</ui:msg></div>
</g:Button>
<div class='{style.headerButtons}'> <div class='{style.headerButtons}'>
<g:Button ui:field='openAll' <g:Button ui:field='openAll'
styleName='' styleName=''

View File

@ -0,0 +1,71 @@
//Copyright (C) 2015 The Android Open Source Project
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package com.google.gerrit.client.change;
import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.user.client.PluginSafePopupPanel;
class RenameFileAction {
private final Change.Id changeId;
private final RevisionInfo revision;
private final ChangeScreen.Style style;
private final Widget renameButton;
private RenameFileBox renameBox;
private PopupPanel popup;
RenameFileAction(Change.Id changeId, RevisionInfo revision,
ChangeScreen.Style style, Widget renameButton) {
this.changeId = changeId;
this.revision = revision;
this.style = style;
this.renameButton = renameButton;
}
void onRename() {
if (popup != null) {
popup.hide();
return;
}
if (renameBox == null) {
renameBox = new RenameFileBox(changeId, revision);
}
renameBox.clearPath();
final PluginSafePopupPanel p = new PluginSafePopupPanel(true);
p.setStyleName(style.replyBox());
p.addAutoHidePartner(renameButton.getElement());
p.addCloseHandler(new CloseHandler<PopupPanel>() {
@Override
public void onClose(CloseEvent<PopupPanel> event) {
if (popup == p) {
popup = null;
}
}
});
p.add(renameBox);
p.showRelativeTo(renameButton);
GlobalKey.dialog(p);
renameBox.setFocus(true);
popup = p;
}
}

View File

@ -0,0 +1,107 @@
//Copyright (C) 2015 The Android Open Source Project
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package com.google.gerrit.client.change;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.changes.ChangeEditApi;
import com.google.gerrit.client.changes.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.ui.RemoteSuggestBox;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextBox;
class RenameFileBox extends Composite {
interface Binder extends UiBinder<HTMLPanel, RenameFileBox> {}
private static final Binder uiBinder = GWT.create(Binder.class);
private final Change.Id changeId;
@UiField Button rename;
@UiField Button cancel;
@UiField(provided = true)
RemoteSuggestBox path;
@UiField NpTextBox newPath;
RenameFileBox(Change.Id changeId, RevisionInfo revision) {
this.changeId = changeId;
path = new RemoteSuggestBox(new PathSuggestOracle(changeId, revision));
path.addCloseHandler(new CloseHandler<RemoteSuggestBox>() {
@Override
public void onClose(CloseEvent<RemoteSuggestBox> event) {
hide();
}
});
initWidget(uiBinder.createAndBindUi(this));
}
void setFocus(boolean focus) {
path.setFocus(focus);
}
void clearPath() {
path.setText("");
}
@UiHandler("rename")
void onRename(@SuppressWarnings("unused") ClickEvent e) {
rename(path.getText(), newPath.getText());
}
private void rename(String path, String newPath) {
hide();
ChangeEditApi.rename(changeId.get(), path, newPath,
new AsyncCallback<VoidResult>() {
@Override
public void onSuccess(VoidResult result) {
Gerrit.display(PageLinks.toChangeInEditMode(changeId));
}
@Override
public void onFailure(Throwable caught) {
}
});
}
@UiHandler("cancel")
void onCancel(@SuppressWarnings("unused") ClickEvent e) {
hide();
}
private void hide() {
for (Widget w = getParent(); w != null; w = w.getParent()) {
if (w instanceof PopupPanel) {
((PopupPanel) w).hide();
break;
}
}
}
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2013 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:c='urn:import:com.google.gwtexpui.globalkey.client'
xmlns:u='urn:import:com.google.gerrit.client.ui'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field='res' type='com.google.gerrit.client.change.Resources'/>
<ui:style>
.cancel { float: right; }
</ui:style>
<g:HTMLPanel>
<div class='{res.style.section}'>
<ui:msg>Old: <u:RemoteSuggestBox ui:field='path' visibleLength='86'/></ui:msg>
</div>
<div class='{res.style.section}'>
<ui:msg>New: <c:NpTextBox ui:field='newPath' visibleLength='86'/></ui:msg>
</div>
<div class='{res.style.section}'>
<g:Button ui:field='rename'
title='Rename file in the repository'
styleName='{res.style.button}'>
<ui:attribute name='title'/>
<div><ui:msg>Rename</ui:msg></div>
</g:Button>
<g:Button ui:field='cancel'
styleName='{res.style.button}'
addStyleNames='{style.cancel}'>
<div>Cancel</div>
</g:Button>
</div>
</g:HTMLPanel>
</ui:UiBinder>

View File

@ -72,6 +72,15 @@ public class ChangeEditApi {
editFile(id, path).delete(cb); editFile(id, path).delete(cb);
} }
/** Rename a file in the pending edit. */
public static void rename(int id, String path, String newPath,
AsyncCallback<VoidResult> cb) {
Input in = Input.create();
in.old_path(path);
in.new_path(newPath);
ChangeApi.edit(id).post(in, cb);
}
/** Restore (undo delete/modify) a file in the pending edit. */ /** Restore (undo delete/modify) a file in the pending edit. */
public static void restore(int id, String path, AsyncCallback<VoidResult> cb) { public static void restore(int id, String path, AsyncCallback<VoidResult> cb) {
Input in = Input.create(); Input in = Input.create();
@ -93,6 +102,8 @@ public class ChangeEditApi {
} }
final native void restore_path(String p) /*-{ this.restore_path=p }-*/; final native void restore_path(String p) /*-{ this.restore_path=p }-*/;
final native void old_path(String p) /*-{ this.old_path=p }-*/;
final native void new_path(String p) /*-{ this.new_path=p }-*/;
protected Input() { protected Input() {
} }