/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2010-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) 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, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.features.poller.remote.gwt.client; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.GwtEvent; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.resources.client.CssResource; 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.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Hyperlink; import com.google.gwt.user.client.ui.InlineHTML; import com.google.gwt.user.client.ui.Widget; /** * <p>TagPanel class.</p> * * @author ranger * @version $Id: $ * @since 1.8.1 */ public class TagPanel extends Composite implements Collection<String> { private final List<String> m_delegate = new ArrayList<String>(); interface Binder extends UiBinder<Widget, TagPanel> { } private static final Binder BINDER = GWT.create(Binder.class); interface TagStyles extends CssResource { public final static double COUNT = 10.0; String selectedTag(); String tag0(); String tag1(); String tag2(); String tag3(); String tag4(); String tag5(); String tag6(); String tag7(); String tag8(); String tag9(); } private transient HandlerManager m_eventBus; @UiField FlowPanel tagPanel; @UiField TagStyles tagStyles; @UiField Hyperlink clearTags; public interface TagSelectedEventHandler extends EventHandler { public void onTagSelected(String tagName); } public interface TagClearedEventHandler extends EventHandler { public void onTagCleared(); } public interface TagResizeEventHandler extends EventHandler{ public void onTagPanelResize(); } public static class TagSelectedEvent extends GwtEvent<TagSelectedEventHandler> { public static Type<TagSelectedEventHandler> TYPE = new Type<TagSelectedEventHandler>(); private final String m_tagName; public TagSelectedEvent(String tagName) { m_tagName = tagName; } protected void dispatch(TagSelectedEventHandler handler) { handler.onTagSelected(m_tagName); } public GwtEvent.Type<TagSelectedEventHandler> getAssociatedType() { return TYPE; } } public static class TagClearedEvent extends GwtEvent<TagClearedEventHandler> { public static Type<TagClearedEventHandler> TYPE = new Type<TagClearedEventHandler>(); public TagClearedEvent() {} protected void dispatch(TagClearedEventHandler handler) { handler.onTagCleared(); } public GwtEvent.Type<TagClearedEventHandler> getAssociatedType() { return TYPE; } } public static class TagResizeEvent extends GwtEvent<TagResizeEventHandler>{ public static Type<TagResizeEventHandler> TYPE = new Type<TagResizeEventHandler>(); @Override protected void dispatch(TagResizeEventHandler handler) { handler.onTagPanelResize(); } @Override public com.google.gwt.event.shared.GwtEvent.Type<TagResizeEventHandler> getAssociatedType() { return TYPE; } } /** * <p>Constructor for TagPanel.</p> */ public TagPanel() { super(); initWidget(BINDER.createAndBindUi(this)); } /** * <p>setEventBus</p> * * @param eventBus a {@link com.google.gwt.event.shared.HandlerManager} object. */ public void setEventBus(final HandlerManager eventBus) { m_eventBus = eventBus; } /** * <p>onClearTagsClick</p> * * @param event a {@link com.google.gwt.event.dom.client.ClickEvent} object. */ @UiHandler("clearTags") public void onClearTagsClick(ClickEvent event) { // Remove the "selected" style from all tags for (int i = 0; i < tagPanel.getWidgetCount(); i++) { tagPanel.getWidget(i).removeStyleName(tagStyles.selectedTag()); } m_eventBus.fireEvent(new TagClearedEvent()); } /** * <p>add</p> * * @param e a {@link java.lang.String} object. * @return a boolean. */ public boolean add(String e) { boolean retval = m_delegate.add(e); updatePanel(); return retval; } /** {@inheritDoc} */ public boolean addAll(Collection<? extends String> c) { boolean retval = m_delegate.addAll(c); updatePanel(); m_eventBus.fireEvent(new TagResizeEvent()); return retval; } /** * <p>clear</p> */ public void clear() { m_delegate.clear(); updatePanel(); } /** {@inheritDoc} */ public boolean contains(Object o) { return m_delegate.contains(o); } /** {@inheritDoc} */ public boolean containsAll(Collection<?> c) { return m_delegate.containsAll(c); } /** * <p>isEmpty</p> * * @return a boolean. */ public boolean isEmpty() { return m_delegate.isEmpty(); } /** * <p>iterator</p> * * @return a {@link java.util.Iterator} object. */ public Iterator<String> iterator() { return m_delegate.iterator(); } /** {@inheritDoc} */ public boolean remove(Object o) { boolean retval = m_delegate.remove(o); updatePanel(); return retval; } /** {@inheritDoc} */ public boolean removeAll(Collection<?> c) { boolean retval = m_delegate.removeAll(c); updatePanel(); return retval; } /** {@inheritDoc} */ public boolean retainAll(Collection<?> c) { boolean retval = m_delegate.retainAll(c); updatePanel(); return retval; } /** * <p>size</p> * * @return a int. */ public int size() { return m_delegate.size(); } /** * <p>toArray</p> * * @return an array of {@link java.lang.Object} objects. */ public Object[] toArray() { return m_delegate.toArray(); } /** * <p>toArray</p> * * @param a an array of T objects. * @param <T> a T object. * @return an array of T objects. */ public <T> T[] toArray(T[] a) { return m_delegate.toArray(a); } /** * <p>selectTag</p> * * @param tag a {@link java.lang.String} object. */ public void selectTag(String tag) { for (Widget widget : tagPanel) { if (widget instanceof Anchor) { Anchor anchor = (Anchor)widget; if (tag != null && tag.replaceAll(" ", " ").equals(anchor.getHTML())) { anchor.addStyleName(tagStyles.selectedTag()); } else { anchor.removeStyleName(tagStyles.selectedTag()); } } } } private void updatePanel() { int minCount = Integer.MAX_VALUE, maxCount = Integer.MIN_VALUE; Map<String,Integer> tagCounts = new TreeMap<String,Integer>(); for (String tag : m_delegate) { if (tagCounts.containsKey(tag)) { tagCounts.put(tag, tagCounts.get(tag).intValue() + 1); } else { tagCounts.put(tag, 1); } } for (int entry : tagCounts.values()) { if (entry < minCount) minCount = entry; if (entry > maxCount) maxCount = entry; } tagPanel.clear(); for (final Map.Entry<String, Integer> entry : tagCounts.entrySet()) { final String tagText = entry.getKey(); final Anchor tagLabel = new Anchor(); double rawValue = (double)(entry.getValue() - minCount) * TagStyles.COUNT / (double)(maxCount - minCount); tagLabel.setHTML(tagText.replace(" ", " ")); tagLabel.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { selectTag(tagText); m_eventBus.fireEvent(new TagSelectedEvent(tagText)); } }); switch ((int)Math.round(rawValue)) { case(0): tagLabel.addStyleName(tagStyles.tag0()); break; case(1): tagLabel.addStyleName(tagStyles.tag1()); break; case(2): tagLabel.addStyleName(tagStyles.tag2()); break; case(3): tagLabel.addStyleName(tagStyles.tag3()); break; case(4): tagLabel.addStyleName(tagStyles.tag4()); break; case(5): tagLabel.addStyleName(tagStyles.tag5()); break; case(6): tagLabel.addStyleName(tagStyles.tag6()); break; case(7): tagLabel.addStyleName(tagStyles.tag7()); break; case(8): tagLabel.addStyleName(tagStyles.tag8()); break; case(9): tagLabel.addStyleName(tagStyles.tag9()); break; default: tagLabel.addStyleName(tagStyles.tag9()); } tagPanel.add(tagLabel); // without this, the tag cloud doesn't wrap properly tagPanel.add(new InlineHTML(" ")); } } }