diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java index 1784daef8c..873ab4d7f2 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/AvatarImage.java @@ -14,28 +14,49 @@ package com.google.gerrit.client; +import com.google.gerrit.client.account.AccountInfo; import com.google.gerrit.client.rpc.RestApi; import com.google.gwt.event.dom.client.ErrorEvent; import com.google.gwt.event.dom.client.ErrorHandler; +import com.google.gwt.event.dom.client.MouseOutEvent; +import com.google.gwt.event.dom.client.MouseOutHandler; +import com.google.gwt.event.dom.client.MouseOverEvent; +import com.google.gwt.event.dom.client.MouseOverHandler; +import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.UIObject; public class AvatarImage extends Image { /** A default sized avatar image. */ - public AvatarImage(String email) { - this(email, 0); + public AvatarImage(AccountInfo account) { + this(account, 0); } /** * An avatar image for the given account using the requested size. * - * @param email The email address of the account in which we are interested + * @param account The account in which we are interested * @param size A requested size. Note that the size can be ignored depending * on the avatar provider. A size <= 0 indicates to let the provider * decide a default size. */ - public AvatarImage(String email, int size) { - super(url(email, size)); + public AvatarImage(AccountInfo account, int size) { + this(account, size, true); + } + + /** + * An avatar image for the given account using the requested size. + * + * @param account The account in which we are interested + * @param size A requested size. Note that the size can be ignored depending + * on the avatar provider. A size <= 0 indicates to let the provider + * decide a default size. + * @param addPopup show avatar popup with user info on hovering over the + * avatar image + */ + public AvatarImage(AccountInfo account, int size, boolean addPopup) { + super(url(account.email(), size)); if (size > 0) { // If the provider does not resize the image, force it in the browser. @@ -50,6 +71,13 @@ public class AvatarImage extends Image { setVisible(false); } }); + + if (addPopup) { + UserPopupPanel userPopup = new UserPopupPanel(account, false, false); + PopupHandler popupHandler = new PopupHandler(userPopup, this); + addMouseOverHandler(popupHandler); + addMouseOutHandler(popupHandler); + } } private static String url(String email, int size) { @@ -68,4 +96,79 @@ public class AvatarImage extends Image { } return api.url(); } + + private class PopupHandler implements MouseOverHandler, MouseOutHandler { + private final UserPopupPanel popup; + private final UIObject target; + + private Timer showTimer; + private Timer hideTimer; + + public PopupHandler(UserPopupPanel popup, UIObject target) { + this.popup = popup; + this.target = target; + + popup.addDomHandler(new MouseOverHandler() { + @Override + public void onMouseOver(MouseOverEvent event) { + scheduleShow(); + } + }, MouseOverEvent.getType()); + popup.addDomHandler(new MouseOutHandler() { + @Override + public void onMouseOut(MouseOutEvent event) { + scheduleHide(); + } + }, MouseOutEvent.getType()); + } + + @Override + public void onMouseOver(MouseOverEvent event) { + scheduleShow(); + } + + @Override + public void onMouseOut(MouseOutEvent event) { + scheduleHide(); + } + + private void scheduleShow() { + if (hideTimer != null) { + hideTimer.cancel(); + hideTimer = null; + } + if ((popup.isShowing() && popup.isVisible()) || showTimer != null) { + return; + } + showTimer = new Timer() { + @Override + public void run() { + if (!popup.isShowing() || !popup.isVisible()) { + popup.showRelativeTo(target); + } + + } + }; + showTimer.schedule(600); + } + + private void scheduleHide() { + if (showTimer != null) { + showTimer.cancel(); + showTimer = null; + } + if (!popup.isShowing() || !popup.isVisible() || hideTimer != null) { + return; + } + hideTimer = new Timer() { + @Override + public void run() { + popup.hide(); + } + }; + hideTimer.schedule(50); + } + } + + } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java index 37c33581cb..2e94db78ce 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java @@ -178,7 +178,7 @@ public class FormatUtil { return nameEmail(ai); } - private static AccountInfo asInfo(Account acct) { + public static AccountInfo asInfo(Account acct) { if (acct == null) { return AccountInfo.create(0, null, null); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java index e018978d52..2a9cb71b12 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java @@ -19,6 +19,7 @@ import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP; import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT; import com.google.gerrit.client.account.AccountCapabilities; +import com.google.gerrit.client.account.AccountInfo; import com.google.gerrit.client.admin.ProjectScreen; import com.google.gerrit.client.changes.ChangeConstants; import com.google.gerrit.client.changes.ChangeListScreen; @@ -249,6 +250,11 @@ public class Gerrit implements EntryPoint { return myAccount; } + /** @return the currently signed in user's account data; empty account data if no account */ + public static AccountInfo getUserAccountInfo() { + return FormatUtil.asInfo(myAccount); + } + /** @return access token to prove user identity during REST API calls. */ public static String getXGerritAuth() { return xGerritAuth; @@ -762,9 +768,9 @@ public class Gerrit implements EntryPoint { } private static void whoAmI(boolean canLogOut) { - Account account = getUserAccount(); - final CurrentUserPopupPanel userPopup = - new CurrentUserPopupPanel(account, canLogOut); + AccountInfo account = getUserAccountInfo(); + final UserPopupPanel userPopup = + new UserPopupPanel(account, canLogOut, true); final FlowPanel userSummaryPanel = new FlowPanel(); class PopupHandler implements KeyDownHandler, ClickHandler { private void showHidePopup() { @@ -791,7 +797,7 @@ public class Gerrit implements EntryPoint { final PopupHandler popupHandler = new PopupHandler(); final InlineLabel l = new InlineLabel(FormatUtil.name(account)); l.setStyleName(RESOURCES.css().menuBarUserName()); - final AvatarImage avatar = new AvatarImage(account.getPreferredEmail(), 26); + final AvatarImage avatar = new AvatarImage(account, 26, false); avatar.setStyleName(RESOURCES.css().menuBarUserNameAvatar()); userSummaryPanel.setStyleName(RESOURCES.css().menuBarUserNamePanel()); userSummaryPanel.add(l); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java similarity index 74% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java index f6636cd079..01811a6013 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.java @@ -14,8 +14,8 @@ package com.google.gerrit.client; +import com.google.gerrit.client.account.AccountInfo; import com.google.gerrit.common.PageLinks; -import com.google.gerrit.reviewdb.client.Account; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -24,8 +24,8 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; import com.google.gwtexpui.user.client.PluginSafePopupPanel; -public class CurrentUserPopupPanel extends PluginSafePopupPanel { - interface Binder extends UiBinder { +public class UserPopupPanel extends PluginSafePopupPanel { + interface Binder extends UiBinder { } private static final Binder binder = GWT.create(Binder.class); @@ -41,9 +41,10 @@ public class CurrentUserPopupPanel extends PluginSafePopupPanel { @UiField Anchor settings; - public CurrentUserPopupPanel(Account account, boolean canLogOut) { + public UserPopupPanel(AccountInfo account, boolean canLogOut, + boolean showSettingsLink) { super(/* auto hide */true, /* modal */false); - avatar = new AvatarImage(account.getPreferredEmail(), 100); + avatar = new AvatarImage(account, 100, false); setWidget(binder.createAndBindUi(this)); // We must show and then hide this popup so that it is part of the DOM. // Otherwise the image does not get any events. Calling hide() would @@ -51,17 +52,21 @@ public class CurrentUserPopupPanel extends PluginSafePopupPanel { show(); setVisible(false); setStyleName(Gerrit.RESOURCES.css().userInfoPopup()); - if (account.getFullName() != null) { - userName.setText(account.getFullName()); + if (account.name() != null) { + userName.setText(account.name()); } - if (account.getPreferredEmail() != null) { - userEmail.setText(account.getPreferredEmail()); + if (account.email() != null) { + userEmail.setText(account.email()); } if (canLogOut) { logout.setHref(Gerrit.selfRedirect("/logout")); } else { logout.setVisible(false); } - settings.setHref(Gerrit.selfRedirect(PageLinks.SETTINGS)); + if (showSettingsLink) { + settings.setHref(Gerrit.selfRedirect(PageLinks.SETTINGS)); + } else { + settings.setVisible(false); + } } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.ui.xml similarity index 100% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/CurrentUserPopupPanel.ui.xml rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/UserPopupPanel.ui.xml diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java index cae3c71563..4fa76dd236 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java @@ -360,10 +360,10 @@ public class PublishCommentScreen extends AccountScreen implements final CommentEditorPanel editor = new CommentEditorPanel(c, commentLinkProcessor); if (c.getLine() == AbstractPatchContentTable.R_HEAD) { - editor.setAuthorNameText(Gerrit.getUserAccount().getPreferredEmail(), + editor.setAuthorNameText(Gerrit.getUserAccountInfo(), Util.C.fileCommentHeader()); } else { - editor.setAuthorNameText(Gerrit.getUserAccount().getPreferredEmail(), + editor.setAuthorNameText(Gerrit.getUserAccountInfo(), Util.M.lineHeader(c.getLine())); } editor.setOpen(true); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java index 289138a735..9ed3f1802e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java @@ -65,8 +65,7 @@ public class CommentEditorPanel extends CommentPanel implements ClickHandler, comment = plc; addStyleName(Gerrit.RESOURCES.css().commentEditorPanel()); - setAuthorNameText(Gerrit.getUserAccount().getPreferredEmail(), - PatchUtil.C.draft()); + setAuthorNameText(Gerrit.getUserAccountInfo(), PatchUtil.C.draft()); setMessageText(plc.getMessage()); addDoubleClickHandler(this); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java index d87cdeaefb..05c6b5a09d 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/CommentPanel.java @@ -63,7 +63,7 @@ public class CommentPanel extends Composite implements HasDoubleClickHandlers, this(commentLinkProcessor); setMessageText(message); - setAuthorNameText(author.email(), FormatUtil.name(author)); + setAuthorNameText(author, FormatUtil.name(author)); setDateText(FormatUtil.shortFormatDayTime(when)); final CellFormatter fmt = header.getCellFormatter(); @@ -126,8 +126,8 @@ public class CommentPanel extends Composite implements HasDoubleClickHandlers, SafeHtml.set(messageText, buf); } - public void setAuthorNameText(final String authorEmail, final String nameText) { - header.setWidget(0, 0, new AvatarImage(authorEmail, 26)); + public void setAuthorNameText(final AccountInfo author, final String nameText) { + header.setWidget(0, 0, new AvatarImage(author, 26)); header.setText(0, 1, nameText); }