/* * 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, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * 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 and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser General Public License along with this program; * if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.rhq.coregui.client.report.tag; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.widgets.events.ClickEvent; import com.smartgwt.client.widgets.events.ClickHandler; import org.rhq.core.domain.criteria.TagCriteria; import org.rhq.core.domain.tagging.Tag; import org.rhq.core.domain.tagging.compsite.TagReportComposite; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.LinkManager; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.coregui.client.util.enhanced.EnhancedIButton.ButtonColor; import org.rhq.coregui.client.util.message.Message; import org.rhq.coregui.client.util.message.Message.Severity; /** * Shows the tags in a large HTML block, where the most used tags are shown in bigger fonts. * * @author Greg Hinkle * @author John Mazzitelli */ public class TagCloudView extends EnhancedVLayout { private static final String REMOVE_ICON = "[skin]/images/actions/remove.png"; private static final int MIN_FONTSIZE = 8; private static final int MAX_FONTSIZE = 22; private PageList<TagReportComposite> tags; private String selectedTag; private IButton deleteButton; public TagCloudView() { super(); } @Override protected void onDraw() { super.onDraw(); refresh(); } private void refresh() { removeMembers(getMembers()); TagCriteria tagCriteria = new TagCriteria(); tagCriteria.setPageControl(PageControl.getUnlimitedInstance()); GWTServiceLookup.getTagService().findTagReportCompositesByCriteria(tagCriteria, new AsyncCallback<PageList<TagReportComposite>>() { public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_tagCloud_error_fetchFailure(), caught); } public void onSuccess(PageList<TagReportComposite> result) { drawTags(result); } }); } private void drawTags(PageList<TagReportComposite> tags) { if (tags == null) { return; // tags are still loading } this.tags = tags; // determine the maximum number of times any single tag is used long max = 0; for (TagReportComposite tag : tags) { if (tag.getTotal() > max) { max = tag.getTotal(); } } // sort the tags so they appear alphabetically Collections.sort(tags, new Comparator<TagReportComposite>() { public int compare(TagReportComposite o1, TagReportComposite o2) { return o1.getTag().toString().compareTo(o2.getTag().toString()); } }); // build the HTML block that contains all the tags with variable font sizes // where the font size represents the relative number of times the tag is used StringBuilder buf = new StringBuilder(); for (TagReportComposite tag : tags) { int font = (int) ((((double) tag.getTotal()) / (double) max) * (MAX_FONTSIZE - MIN_FONTSIZE)) + MIN_FONTSIZE; buf.append("<a href=\"").append(LinkManager.getTagLink(tag.getTag().toString())).append( "\" style=\"font-size: ").append(font).append("pt; margin: 8px;\""); buf.append(" title=\"").append(MSG.view_tagCloud_error_tagUsedCount(String.valueOf(tag.getTotal()))) .append("\""); if (tag.getTag().toString().equals(selectedTag)) { buf.append(" class=\"selectedTag\""); } buf.append(">").append(tag.getTag()).append("</a> "); } HTMLFlow flow = new HTMLFlow(buf.toString()); addMember(flow); } public String getSelectedTag() { return this.selectedTag; } /** * Determines which, if any, tag is currently selected. * * @param selectedTag the full tag name, or <code>null</code> if nothing is selected */ public void setSelectedTag(String selectedTag) { this.selectedTag = selectedTag; TagReportComposite selected = getSelectedTagReportComposite(); getDeleteButton().setDisabled(selected == null || selected.getTotal() > 0); // don't be able to delete non-existent tag or tag that is used removeMembers(getMembers()); drawTags(this.tags); } /** * This view can provide a delete button that, when clicked, will delete the currently * selected tag. This view doesn't put this delete button anywhere, the caller can place * this button where ever it deems appropriate. * * @return a delete button component that can be placed as a member of a canvas */ public IButton getDeleteButton() { if (this.deleteButton == null) { final IButton button = new DeleteButton(); button.setIcon(REMOVE_ICON); button.setIconWidth(16); button.setIconHeight(16); button.setAutoFit(true); button.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { final TagReportComposite selected = getSelectedTagReportComposite(); if (selected != null) { HashSet<Tag> doomedTag = new HashSet<Tag>(1); doomedTag.add(selected.getTag()); GWTServiceLookup.getTagService().removeTags(doomedTag, new AsyncCallback<Void>() { @Override public void onSuccess(Void result) { tags.remove(selected); CoreGUI.goToView(LinkManager.getTagLink(null)); CoreGUI.getMessageCenter().notify( new Message(MSG.view_tagCloud_deleteTagSuccess(selected.getTag().toString()), Severity.Info)); } @Override public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError( MSG.view_tagCloud_deleteTagFailure(selected.getTag().toString()), caught); } }); } } }); this.deleteButton = button; } return this.deleteButton; } private TagReportComposite getSelectedTagReportComposite() { if (selectedTag != null && tags != null) { for (TagReportComposite tag : tags) { if (tag.getTag().toString().equals(selectedTag)) { return tag; } } } return null; } class DeleteButton extends EnhancedIButton { public DeleteButton() { super(MSG.view_tagCloud_deleteTag(), ButtonColor.RED); } @Override protected void onDestroy() { super.onDestroy(); deleteButton = null; } } }