/*
* RHQ Management Platform
* Copyright (C) 2005-2010 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.coregui.client.inventory.groups.detail;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLFlow;
import com.smartgwt.client.widgets.Img;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite.GroupAvailabilityType;
import org.rhq.core.domain.tagging.Tag;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.ResourceTypeUtility;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.ImageManager;
import org.rhq.coregui.client.UserSessionManager;
import org.rhq.coregui.client.components.tagging.TagEditorView;
import org.rhq.coregui.client.components.tagging.TagsChangedCallback;
import org.rhq.coregui.client.gwt.GWTServiceLookup;
import org.rhq.coregui.client.util.enhanced.EnhancedHLayout;
import org.rhq.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.coregui.client.util.message.Message;
/**
* @author Greg Hinkle
* @author Ian Springer
*/
public class ResourceGroupTitleBar extends EnhancedVLayout {
private static final String FAV_ICON = "Favorite_24_Selected.png";
private static final String NOT_FAV_ICON = "Favorite_24.png";
private static final String COLLAPSED_TOOLTIP = MSG.view_titleBar_group_summary_collapsedTooltip();
private static final String EXPANDED_TOOLTIP = MSG.view_titleBar_group_summary_expandedTooltip();
private ResourceGroup group;
boolean isAutoCluster;
boolean isAutoGroup;
private Img expandCollapseArrow;
private Img badge;
private Img favoriteButton;
private HTMLFlow title;
private Img explicitAvailabilityImage;
private Img implicitAvailabilityImage;
private boolean favorite;
private boolean supportsFavorite;
private GeneralProperties generalProperties;
public ResourceGroupTitleBar(boolean isAutoGroup, boolean isAutoCluster) {
super();
this.isAutoGroup = isAutoGroup;
this.isAutoCluster = isAutoCluster;
this.supportsFavorite = (!(this.isAutoGroup || this.isAutoCluster));
setWidth100();
setHeight(30);
setPadding(5);
setMembersMargin(5);
}
public void update() {
for (Canvas child : getChildren()) {
child.destroy();
}
final EnhancedHLayout hlayout = new EnhancedHLayout();
hlayout.setStyleName("resourceSummary");
addMember(hlayout);
this.title = new HTMLFlow();
this.title.setWidth("*");
this.explicitAvailabilityImage = new Img(ImageManager.getAvailabilityLargeIcon(null), 24, 24);
this.explicitAvailabilityImage.setTooltip(MSG.view_group_detail_explicitAvail());
this.implicitAvailabilityImage = new Img(ImageManager.getAvailabilityLargeIcon(null), 24, 24);
this.implicitAvailabilityImage.setTooltip(MSG.view_group_detail_implicitAvail());
if (this.supportsFavorite) {
this.favoriteButton = new Img(NOT_FAV_ICON, 24, 24);
this.favoriteButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
Set<Integer> favorites = toggleFavoriteLocally();
UserSessionManager.getUserPreferences().setFavoriteResourceGroups(favorites,
new UpdateFavoritesCallback());
}
});
}
expandCollapseArrow = new Img("[SKIN]/ListGrid/row_collapsed.png", 16, 16);
expandCollapseArrow.setTooltip(COLLAPSED_TOOLTIP);
expandCollapseArrow.setLayoutAlign(VerticalAlignment.CENTER);
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
criteria.addFilterId(this.group.getId());
// for autoclusters and autogroups we need to add more criteria
if (isAutoCluster) {
criteria.addFilterVisible(false);
} else if (isAutoGroup) {
criteria.addFilterVisible(false);
criteria.addFilterPrivate(true);
}
GWTServiceLookup.getResourceGroupService().findResourceGroupCompositesByCriteria(criteria,
new AsyncCallback<PageList<ResourceGroupComposite>>() {
@Override
public void onSuccess(PageList<ResourceGroupComposite> result) {
if (result == null || result.size() != 1) {
CoreGUI.getErrorHandler().handleError(
MSG.view_titleBar_group_failInfo(group.getName(),
String.valueOf(ResourceGroupTitleBar.this.group.getId())));
return;
}
ResourceGroupComposite resultComposite = result.get(0);
setGroupIcons(resultComposite);
// Localize the default group name for an AutoCluster with disparate members (see setGroup()).
if (isAutoCluster) {
resultComposite.getResourceGroup().setName(group.getName());
}
generalProperties = new GeneralProperties(resultComposite, ResourceGroupTitleBar.this,
(!(isAutoGroup || isAutoCluster)));
generalProperties.setVisible(false);
ResourceGroupTitleBar.this.addMember(generalProperties);
expandCollapseArrow.addClickHandler(new ClickHandler() {
private boolean collapsed = true;
@Override
public void onClick(ClickEvent event) {
collapsed = !collapsed;
if (collapsed) {
expandCollapseArrow.setSrc("[SKIN]/ListGrid/row_collapsed.png");
expandCollapseArrow.setTooltip(COLLAPSED_TOOLTIP);
generalProperties.hide();
} else {
expandCollapseArrow.setSrc("[SKIN]/ListGrid/row_expanded.png");
expandCollapseArrow.setTooltip(EXPANDED_TOOLTIP);
generalProperties.show();
}
ResourceGroupTitleBar.this.markForRedraw();
}
});
}
@Override
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
MSG.view_titleBar_group_failInfo(group.getName(),
String.valueOf(ResourceGroupTitleBar.this.group.getId())), caught);
}
});
badge = new Img(ImageManager.getGroupLargeIcon(GroupCategory.MIXED), 24, 24);
badge.setLayoutAlign(VerticalAlignment.CENTER);
TagEditorView tagEditorView = new TagEditorView(group.getTags(), false, new TagsChangedCallback() {
public void tagsChanged(final HashSet<Tag> tags) {
GWTServiceLookup.getTagService().updateResourceGroupTags(group.getId(), tags,
new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
MSG.view_titleBar_common_updateTagsFailure(group.getName()), caught);
}
public void onSuccess(Void result) {
CoreGUI.getMessageCenter().notify(
new Message(MSG.view_titleBar_common_updateTagsSuccessful(group.getName()),
Message.Severity.Info));
// update what is essentially our local cache
group.setTags(tags);
}
});
}
});
loadTags(tagEditorView);
hlayout.addMember(expandCollapseArrow);
hlayout.addMember(badge);
hlayout.addMember(title);
hlayout.addMember(explicitAvailabilityImage);
hlayout.addMember(implicitAvailabilityImage);
if (this.supportsFavorite) {
hlayout.addMember(favoriteButton);
}
//conditionally add tags. Defaults to true, not available in JON builds.
if (CoreGUI.isTagsEnabledForUI()) {
addMember(tagEditorView);
}
}
private void loadTags(final TagEditorView tagEditorView) {
ResourceGroupCriteria criteria = new ResourceGroupCriteria();
criteria.addFilterId(group.getId());
// for autoclusters and autogroups we need to add more criteria
if (isAutoCluster) {
criteria.addFilterVisible(false);
} else if (isAutoGroup) {
criteria.addFilterVisible(false);
criteria.addFilterPrivate(true);
}
criteria.fetchTags(true);
GWTServiceLookup.getResourceGroupService().findResourceGroupsByCriteria(criteria,
new AsyncCallback<PageList<ResourceGroup>>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_titleBar_common_loadTagsFailure(group.getName()),
caught);
}
public void onSuccess(PageList<ResourceGroup> result) {
LinkedHashSet<Tag> tags = new LinkedHashSet<Tag>();
tags.addAll(result.get(0).getTags());
tagEditorView.setTags(tags);
}
});
}
public void setGroup(ResourceGroupComposite groupComposite, boolean isRefresh) {
this.group = groupComposite.getResourceGroup();
// Localize the default group name for an AutoCluster with disparate members. This is safe for AutoCluster
// backing groups because they can't be edited, can't be set as a favorite, and the name is not used
// for subsequent querying. If an autoCluster contains disparate resource names the server names the group
// "Group of <ResourceTypeName>" because it can't name the group after a common resource name. This typically
// happens if the cluster group (i.e. root group) members are themselves disparate. In general this is not the
// case, because recursive compat groups are typically used specifically for groups of logically equivalent
// resources, like cloned AS instances. The problem is that it is not localized. Change it on the fly.
if (isAutoCluster) {
String typeName = ResourceTypeUtility.displayName(group.getResourceType());
String cannedName = "Group of " + typeName;
if (cannedName.equals(group.getName())) {
group.setName(MSG.group_tree_groupOfResourceType(typeName));
}
}
update();
displayGroupName(group.getName());
Set<Integer> favorites = UserSessionManager.getUserPreferences().getFavoriteResourceGroups();
this.favorite = favorites.contains(group.getId());
updateFavoriteButton();
setGroupIcons(groupComposite);
markForRedraw();
}
void displayGroupName(String groupName) {
if (!group.getName().equals(groupName)) {
group.setName(groupName); // the name must have been changed by the user via the editable field
}
String catName = null;
switch (group.getGroupCategory()) {
case COMPATIBLE: {
catName = MSG.view_group_summary_compatible();
break;
}
case MIXED: {
catName = MSG.view_group_summary_mixed();
break;
}
}
this.title.setContents("<span class=\"SectionHeader\">" + group.getName()
+ "</span> <span class=\"subtitle\">" + catName + "</span>");
this.title.markForRedraw();
}
private void setGroupIcons(ResourceGroupComposite composite) {
GroupAvailabilityType explicitGroupAvailType = composite.getExplicitAvailabilityType();
this.badge.setSrc(ImageManager.getGroupLargeIcon(this.group.getGroupCategory(), explicitGroupAvailType));
this.explicitAvailabilityImage.setSrc(ImageManager.getAvailabilityGroupLargeIcon(explicitGroupAvailType));
if (composite.getResourceGroup().isRecursive()) {
GroupAvailabilityType implicitGroupAvailType = composite.getImplicitAvailabilityType();
this.implicitAvailabilityImage.setSrc(ImageManager.getAvailabilityGroupLargeIcon(implicitGroupAvailType));
} else {
this.implicitAvailabilityImage.setVisible(false);
}
}
private void updateFavoriteButton() {
if (!this.supportsFavorite) {
return;
}
this.favoriteButton.setSrc(favorite ? FAV_ICON : NOT_FAV_ICON);
if (favorite) {
this.favoriteButton.setTooltip(MSG.view_titleBar_common_clickToRemoveFav());
} else {
this.favoriteButton.setTooltip(MSG.view_titleBar_common_clickToAddFav());
}
}
private Set<Integer> toggleFavoriteLocally() {
this.favorite = !this.favorite;
Set<Integer> favorites = UserSessionManager.getUserPreferences().getFavoriteResourceGroups();
if (this.favorite) {
favorites.add(group.getId());
} else {
favorites.remove(group.getId());
}
return favorites;
}
public class UpdateFavoritesCallback implements AsyncCallback<Subject> {
public void onSuccess(Subject subject) {
String m;
if (favorite) {
m = MSG.view_titleBar_common_addedFav(ResourceGroupTitleBar.this.group.getName());
} else {
m = MSG.view_titleBar_common_removedFav(ResourceGroupTitleBar.this.group.getName());
}
CoreGUI.getMessageCenter().notify(new Message(m, Message.Severity.Info));
updateFavoriteButton();
}
public void onFailure(Throwable throwable) {
String m;
if (favorite) {
m = MSG.view_titleBar_common_addedFavFailure(ResourceGroupTitleBar.this.group.getName());
} else {
m = MSG.view_titleBar_common_removedFavFailure(ResourceGroupTitleBar.this.group.getName());
}
CoreGUI.getErrorHandler().handleError(m, throwable);
// Revert back to our original favorite status, since the server update failed.
toggleFavoriteLocally();
}
}
}