Java tutorial
// Copyright (C) 2011 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.gerrit.client.changes; import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.patches.CommentEditorContainer; import com.google.gerrit.client.patches.CommentEditorPanel; import com.google.gerrit.client.patches.PatchUtil; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.AccountScreen; import com.google.gerrit.client.ui.PatchLink; import com.google.gerrit.client.ui.SmallHeading; import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.data.AccountInfo; import com.google.gerrit.common.data.AccountInfoCache; import com.google.gerrit.common.data.ApprovalType; import com.google.gerrit.common.data.ApprovalTypes; import com.google.gerrit.common.data.ChangeDetail; import com.google.gerrit.common.data.ChangeSetDetail; import com.google.gerrit.common.data.ChangeSetPublishDetail; import com.google.gerrit.common.data.PatchSetPublishDetail; import com.google.gerrit.common.data.Permission; import com.google.gerrit.common.data.PermissionRange; import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.ApprovalCategory; import com.google.gerrit.reviewdb.ApprovalCategoryValue; import com.google.gerrit.reviewdb.Change; import com.google.gerrit.reviewdb.ChangeSet; import com.google.gerrit.reviewdb.ChangeSetInfo; import com.google.gerrit.reviewdb.Patch; import com.google.gerrit.reviewdb.PatchLineComment; import com.google.gerrit.reviewdb.PatchSet; import com.google.gerrit.reviewdb.PatchSetApproval; import com.google.gerrit.reviewdb.Topic; import com.google.gerrit.reviewdb.UserIdentity; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; import com.google.gwt.user.client.ui.FormPanel.SubmitEvent; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.globalkey.client.NpTextArea; import com.google.gwtjsonrpc.client.VoidResult; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; public class PublishTopicCommentScreen extends AccountScreen implements ClickHandler, CommentEditorContainer { private static SavedState lastState; private final ChangeSet.Id changeSetId; private Collection<ValueRadioButton> approvalButtons; private TopicDescriptionBlock descBlock; private Panel approvalPanel; private NpTextArea message; private FlowPanel draftsPanel; private Button send; private Button submit; private Button cancel; private boolean saveStateOnUnload = true; private List<CommentEditorPanel> commentEditors; public PublishTopicCommentScreen(final ChangeSet.Id csi) { changeSetId = csi; } @Override protected void onInitUI() { super.onInitUI(); addStyleName(Gerrit.RESOURCES.css().publishCommentsScreen()); approvalButtons = new ArrayList<ValueRadioButton>(); descBlock = new TopicDescriptionBlock(); add(descBlock); final FormPanel form = new FormPanel(); final FlowPanel body = new FlowPanel(); form.setWidget(body); form.addSubmitHandler(new FormPanel.SubmitHandler() { @Override public void onSubmit(final SubmitEvent event) { event.cancel(); } }); add(form); approvalPanel = new FlowPanel(); body.add(approvalPanel); initMessage(body); draftsPanel = new FlowPanel(); body.add(draftsPanel); final FlowPanel buttonRow = new FlowPanel(); buttonRow.setStyleName(Gerrit.RESOURCES.css().patchSetActions()); body.add(buttonRow); send = new Button(Util.C.buttonPublishCommentsSend()); send.addClickHandler(this); buttonRow.add(send); submit = new Button(Util.C.buttonPublishSubmitSend()); submit.addClickHandler(this); buttonRow.add(submit); cancel = new Button(Util.C.buttonPublishCommentsCancel()); cancel.addClickHandler(this); buttonRow.add(cancel); } private void enableForm(final boolean enabled) { for (final ValueRadioButton approvalButton : approvalButtons) { approvalButton.setEnabled(enabled); } message.setEnabled(enabled); for (final CommentEditorPanel commentEditor : commentEditors) { commentEditor.enableButtons(enabled); } send.setEnabled(enabled); submit.setEnabled(enabled); cancel.setEnabled(enabled); } @Override protected void onLoad() { super.onLoad(); // TODO // Util.DETAIL_SVC.patchSetPublishDetail(patchSetId, // new ScreenLoadCallback<PatchSetPublishDetail>(this) { // @Override // protected void preDisplay(final PatchSetPublishDetail result) { // send.setEnabled(true); // display(result); // } // // @Override // protected void postDisplay() { // message.setFocus(true); // } // }); // TODO delete the following lines, as it is a replacement for the server side // BEGIN send.setEnabled(true); ChangeSetPublishDetail r = new ChangeSetPublishDetail(); Account me = Gerrit.getUserAccount(); Account.Id aId = me.getId(); AccountInfo ai = new AccountInfo(aId); ai.setPreferredEmail("my@email.com"); List<AccountInfo> aiList = new ArrayList<AccountInfo>(); aiList.add(ai); AccountInfoCache aic = new AccountInfoCache(aiList); List<ChangeSet> lcs = new ArrayList<ChangeSet>(); ChangeSetDetail csDetail = new ChangeSetDetail(); ChangeSet.Id csId = null; lcs.clear(); UserIdentity uid = new UserIdentity(); uid.setAccount(aId); uid.setEmail("my@email.com"); uid.setName("FakeName"); uid.setTimeZone(0); Change.Id currentTopicId = new Change.Id(1100011); ChangeSetInfo csi = null; csId = new ChangeSet.Id(currentTopicId, 1); ChangeSet cs = new ChangeSet(csId); cs.setTopicId(currentTopicId); csDetail.setChangeSet(cs); csId = new ChangeSet.Id(currentTopicId, 1); csi = new ChangeSetInfo(csId); csi.setSubject( "This is the subject from the last change set - Problem - which one of the commits we should take??"); csi.setAuthor(uid); csi.setMessage("ChangeSetInfo message"); csDetail.setInfo(csi); lcs.add(cs); Topic.Key tKey = new Topic.Key("1100010101101 harcoded"); Topic topic = new Topic(tKey, currentTopicId, aId, null); topic.setCurrentChangeSet(csi); topic.setStatus(Change.Status.NEW); topic.setTopic("This is the topic string"); List<PermissionRange> labels = new ArrayList<PermissionRange>(); PermissionRange pr = new PermissionRange("Permission", -2, 2); labels.add(pr); r.setAccounts(aic); r.setCanSubmit(true); r.setChangeSetInfo(csi); r.setTopic(topic); r.setLabels(labels); display(r); this.display(); message.setFocus(true); // END } @Override protected void onUnload() { super.onUnload(); lastState = saveStateOnUnload ? new SavedState(this) : null; } @Override public void onClick(final ClickEvent event) { final Widget sender = (Widget) event.getSource(); if (send == sender) { onSend(false); } else if (submit == sender) { onSend(true); } else if (cancel == sender) { saveStateOnUnload = false; goChangeSet(); } } @Override public void notifyDraftDelta(int delta) { } @Override public void remove(CommentEditorPanel editor) { commentEditors.remove(editor); // The editor should be embedded into a panel holding all // editors for the same file. // FlowPanel parent = (FlowPanel) editor.getParent(); parent.remove(editor); // If the panel now holds no editors, remove it. // int editorCount = 0; for (Widget w : parent) { if (w instanceof CommentEditorPanel) { editorCount++; } } if (editorCount == 0) { parent.removeFromParent(); } // If that was the last file with a draft, remove the heading. // if (draftsPanel.getWidgetCount() == 1) { draftsPanel.clear(); } } private void initMessage(final Panel body) { body.add(new SmallHeading(Util.C.headingCoverMessage())); final VerticalPanel mwrap = new VerticalPanel(); mwrap.setStyleName(Gerrit.RESOURCES.css().coverMessage()); body.add(mwrap); message = new NpTextArea(); message.setCharacterWidth(60); message.setVisibleLines(10); message.setSpellCheck(true); mwrap.add(message); } private void initApprovals(final ChangeSetPublishDetail r, final Panel body) { ApprovalTypes types = Gerrit.getConfig().getApprovalTypes(); for (ApprovalType type : types.getApprovalTypes()) { String permission = Permission.forLabel(type.getCategory().getLabelName()); PermissionRange range = r.getRange(permission); if (range != null && !range.isEmpty()) { initApprovalType(r, body, type, range); } } for (PermissionRange range : r.getLabels()) { // TODO // if (!range.isEmpty() && types.byLabel(range.getLabel()) == null) { // // TODO: this is a non-standard label. Offer it without the type. // } } } private void initApprovalType(final ChangeSetPublishDetail r, final Panel body, final ApprovalType ct, final PermissionRange range) { body.add(new SmallHeading(ct.getCategory().getName() + ":")); final VerticalPanel vp = new VerticalPanel(); vp.setStyleName(Gerrit.RESOURCES.css().approvalCategoryList()); final List<ApprovalCategoryValue> lst = new ArrayList<ApprovalCategoryValue>(ct.getValues()); Collections.reverse(lst); final ApprovalCategory.Id catId = ct.getCategory().getId(); final PatchSetApproval prior = r.getChangeApproval(catId); for (final ApprovalCategoryValue buttonValue : lst) { if (!range.contains(buttonValue.getValue())) { continue; } final ValueRadioButton b = new ValueRadioButton(buttonValue, ct.getCategory().getName()); b.setText(buttonValue.format()); if (lastState != null && changeSetId.equals(lastState.changeSetId) && lastState.approvals.containsKey(buttonValue.getCategoryId())) { b.setValue(lastState.approvals.get(buttonValue.getCategoryId()).equals(buttonValue)); } else { b.setValue( prior != null ? buttonValue.getValue() == prior.getValue() : buttonValue.getValue() == 0); } approvalButtons.add(b); vp.add(b); } body.add(vp); } private void display(final ChangeSetPublishDetail r) { // TODO change this setPageTitle(Util.M.publishCommentsOnSet(r.getTopic().getKey().abbreviate(), r.getTopic().getTopic())); descBlock.display(r.getTopic(), r.getAccounts()); if (r.getTopic().getStatus().isOpen()) { initApprovals(r, approvalPanel); } if (lastState != null && changeSetId.equals(lastState.changeSetId)) { message.setText(lastState.message); } draftsPanel.clear(); commentEditors = new ArrayList<CommentEditorPanel>(); // if (!r.getDrafts().isEmpty()) { // draftsPanel.add(new SmallHeading(Util.C.headingPatchComments())); // // Panel panel = null; // String priorFile = ""; // for (final PatchLineComment c : r.getDrafts()) { // final Patch.Key patchKey = c.getKey().getParentKey(); // final String fn = patchKey.get(); // if (!fn.equals(priorFile)) { // panel = new FlowPanel(); // panel.addStyleName(Gerrit.RESOURCES.css().patchComments()); // draftsPanel.add(panel); // // Parent table can be null here since we are not showing any // // next/previous links // panel.add(new PatchLink.SideBySide(PatchTable // .getDisplayFileName(patchKey), patchKey, 0, null, null)); // priorFile = fn; // } // // final CommentEditorPanel editor = new CommentEditorPanel(c); // editor.setAuthorNameText(Util.M.lineHeader(c.getLine())); // editor.setOpen(true); // commentEditors.add(editor); // panel.add(editor); // } // } submit.setVisible(r.canSubmit()); } private void onSend(final boolean submit) { if (commentEditors.isEmpty()) { onSend2(submit); } else { final GerritCallback<VoidResult> afterSaveDraft = new GerritCallback<VoidResult>() { private int done; @Override public void onSuccess(final VoidResult result) { if (++done == commentEditors.size()) { onSend2(submit); } } }; for (final CommentEditorPanel p : commentEditors) { p.saveDraft(afterSaveDraft); } } } private void onSend2(final boolean submit) { final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> values = new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>(); for (final ValueRadioButton b : approvalButtons) { if (b.getValue()) { values.put(b.value.getCategoryId(), b.value.getId()); } } enableForm(false); // TODO // PatchUtil.DETAIL_SVC.publishComments(patchSetId, message.getText().trim(), // new HashSet<ApprovalCategoryValue.Id>(values.values()), // new GerritCallback<VoidResult>() { // public void onSuccess(final VoidResult result) { // if(submit) { // submit(); // } else { // saveStateOnUnload = false; // goChangeSet(); // } // } // // @Override // public void onFailure(Throwable caught) { // super.onFailure(caught); // enableForm(true); // } // }); } private void submit() { // TODO // Util.MANAGE_SVC.submit(patchSetId, // new GerritCallback<ChangeDetail>() { // public void onSuccess(ChangeDetail result) { // saveStateOnUnload = false; // goChangeSet(); // } // // @Override // public void onFailure(Throwable caught) { // goChangeSet(); // super.onFailure(caught); // } // }); } private void goChangeSet() { final Change.Id ck = changeSetId.getParentKey(); // TODO // We need a new entity to return to, instead of a query Gerrit.display(PageLinks.toTopic(ck), new TopicScreen(ck)); } private static class ValueRadioButton extends RadioButton { final ApprovalCategoryValue value; ValueRadioButton(final ApprovalCategoryValue v, final String label) { super(label); value = v; } } private static class SavedState { final ChangeSet.Id changeSetId; final String message; final Map<ApprovalCategory.Id, ApprovalCategoryValue> approvals; SavedState(final PublishTopicCommentScreen p) { changeSetId = p.changeSetId; message = p.message.getText(); approvals = new HashMap<ApprovalCategory.Id, ApprovalCategoryValue>(); for (final ValueRadioButton b : p.approvalButtons) { if (b.getValue()) { approvals.put(b.value.getCategoryId(), b.value); } } } } }