Java tutorial
/* * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * only, as published by the Free Software Foundation. * * This code 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 version 2 for more details (a copy is * included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 16 Network Circle, Menlo * Park, CA 94025 or visit www.sun.com if you need additional * information or have any questions. */ package com.sun.labs.aura.music.wsitm.client.ui.swidget; 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.sun.labs.aura.music.wsitm.client.ui.Popup; import com.sun.labs.aura.music.wsitm.client.ui.TagDisplayLib; import com.sun.labs.aura.music.wsitm.client.ui.MenuItem; import com.sun.labs.aura.music.wsitm.client.event.CommonTagsAsyncCallback; import com.sun.labs.aura.music.wsitm.client.ui.widget.StarRatingWidget; import com.sun.labs.aura.music.wsitm.client.*; import com.sun.labs.aura.music.wsitm.client.ui.widget.TagInputWidget; import com.sun.labs.aura.music.wsitm.client.ui.Updatable; import com.sun.labs.aura.music.wsitm.client.ui.widget.SteeringWheelWidget; import com.sun.labs.aura.music.wsitm.client.ui.widget.ArtistListWidget; import com.sun.labs.aura.music.wsitm.client.items.TagDetails; import com.sun.labs.aura.music.wsitm.client.items.ArtistPhoto; import com.sun.labs.aura.music.wsitm.client.items.AlbumDetails; import com.sun.labs.aura.music.wsitm.client.items.ItemInfo; import com.sun.labs.aura.music.wsitm.client.items.ArtistDetails; import com.sun.labs.aura.music.wsitm.client.items.ArtistEvent; import com.sun.labs.aura.music.wsitm.client.items.ArtistVideo; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DockPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.LoadListener; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sun.labs.aura.music.wsitm.client.event.DDEClickHandler; import com.sun.labs.aura.music.wsitm.client.event.DEAsyncCallback; import com.sun.labs.aura.music.wsitm.client.event.DEClickHandler; import com.sun.labs.aura.music.wsitm.client.event.HasListeners; import com.sun.labs.aura.music.wsitm.client.ui.widget.AbstractSearchWidget.searchTypes; import com.sun.labs.aura.music.wsitm.client.items.ArtistCompact; import com.sun.labs.aura.music.wsitm.client.items.ScoredC; import com.sun.labs.aura.music.wsitm.client.ui.PerformanceTimer; import com.sun.labs.aura.music.wsitm.client.ui.TagDisplayLib.TagColorType; import com.sun.labs.aura.music.wsitm.client.ui.bundles.ArtistRelatedBundle; import com.sun.labs.aura.music.wsitm.client.ui.widget.ContextMenuSteeringWheelWidget; import com.sun.labs.aura.music.wsitm.client.ui.widget.DualRoundedPanel; import com.sun.labs.aura.music.wsitm.client.ui.widget.PlayButton; import com.sun.labs.aura.music.wsitm.client.ui.widget.PopularitySelect; import java.util.ArrayList; import java.util.Map; import org.adamtacy.client.ui.NEffectPanel; import org.adamtacy.client.ui.effects.impl.Fade; /** * * @author plamere */ public class SimpleSearchSwidget extends Swidget implements HasListeners { public static ArtistRelatedBundle playImgBundle = (ArtistRelatedBundle) GWT.create(ArtistRelatedBundle.class); private Widget curResult; private String curResultToken = ""; private String curPageTitle = ""; private DockPanel mainPanel; private PopularitySelect popSelect; // Widgets that contain listeners that need to be removed to prevent leaks private ArtistListWidget leftRecList; private ArtistListWidget leftSimList; private ArtistListWidget leftRelList; private StarRatingWidget artistStar; private TagInputWidget tagInputWidget; private PlayButton playButton; public SimpleSearchSwidget(ClientDataManager cdm) { super("Simple Search", cdm); try { initWidget(getWidget(), true); showResults(History.getToken()); } catch (Exception e) { Popup.showErrorPopup(e, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "Server problem. Please try again later.", Popup.ERROR_LVL.CRITICAL, null); } } /** Creates a new instance of SimpleSearchWidget */ @Override public Widget getWidget() { //searchBoxContainerPanel = new FlowPanel(); //search = new SearchWidget(musicServer, cdm, searchBoxContainerPanel); //search.updateSuggestBox(Oracles.ARTIST); mainPanel = new DockPanel(); mainPanel.setWidth("100%"); mainPanel.setHorizontalAlignment(DockPanel.ALIGN_CENTER); mainPanel.add(new Label(), DockPanel.NORTH); return mainPanel; } private void setResults(String historyName, Widget result) { if (curResult == result || curResultToken.equals(historyName)) { return; } if (!History.getToken().equals(historyName)) { curResultToken = historyName; History.newItem(historyName, false); } if (curResult != null) { mainPanel.remove(curResult); curResult = null; } if (result != null) { cdm.setCurrSearchWidgetToken(historyName); mainPanel.add(result, DockPanel.CENTER); curResult = result; curResultToken = historyName; } // else { // search.setText(""); //} } private void clearResults() { setResults("artist:", new Label("")); } @Override public ArrayList<String> getTokenHeaders() { ArrayList<String> l = new ArrayList<String>(); l.add("artist:"); l.add("tag:"); l.add("artistSearch:"); l.add("artistSearchByTag:"); l.add("tagSearch:"); return l; } @Override protected void initMenuItem() { menuItem = new MenuItem("Exploration", new ClickHandler() { @Override public void onClick(ClickEvent event) { History.newItem(cdm.getCurrSearchWidgetToken()); } }, false, 0); } @Override public void doRemoveListeners() { if (leftRelList != null) { leftRelList.doRemoveListeners(); } if (leftSimList != null) { leftSimList.doRemoveListeners(); } if (leftRelList != null) { leftRelList.doRemoveListeners(); } if (artistStar != null) { artistStar.onDelete(); } if (tagInputWidget != null) { tagInputWidget.onDelete(); } if (playButton != null) { playButton.onDelete(); } } private void showResults(String resultName) { // Reset current artistID. Will be updated in invokeGetArtistInfo cdm.setCurrArtistInfo("", ""); // Clear all listeners doRemoveListeners(); // Reset the search cdm.getSearchAttentionManager().resetSearch(); if (resultName.startsWith("artist:")) { invokeGetArtistInfo(resultName, false, null); } else if (resultName.startsWith("tag:")) { invokeGetTagInfo(resultName, false); } else if (resultName.startsWith("artistSearch:")) { String query = resultName.replaceAll("artistSearch:", ""); invokeArtistSearchService(query, searchTypes.SEARCH_FOR_ARTIST_BY_ARTIST, 0); } else if (resultName.startsWith("artistSearchByTag:")) { String query = resultName.replaceAll("artistSearchByTag:", ""); invokeArtistSearchService(query, searchTypes.SEARCH_FOR_ARTIST_BY_TAG, 0); } else if (resultName.startsWith("tagSearch:")) { String query = resultName.replaceAll("tagSearch:", ""); invokeTagSearchService(query, 0); } else if (resultName.startsWith("searchHome:")) { cdm.setCurrSearchWidgetToken("searchHome:"); History.newItem("searchHome:"); } } @Override public void update(String historyToken) { // Only update results if the history token is different than the // currently loaded page if (!curResultToken.equals(historyToken)) { updateWindowTitleLocal(""); showResults(historyToken); } else { updateWindowTitleLocal(curPageTitle); } } private void updateWindowTitleLocal(String title) { curPageTitle = title; updateWindowTitle(title); } private void invokeTagSearchService(String searchText, int page) { AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { // do some UI stuff to show success SearchResults sr = (SearchResults) result; if (sr != null && sr.isOK()) { ItemInfo[] results = sr.getItemResults(cdm); if (results.length == 0) { showTopMessage("No Match for " + sr.getQuery()); clearResults(); } else if (results.length == 1) { WebLib.trackPageLoad("#tagSearch:" + sr.getQuery()); ItemInfo ar = results[0]; invokeGetTagInfo(ar.getId(), false); } else { showTopMessage("Found " + sr.getItemResults(cdm).length + " matches"); setResults(sr.toString(), getItemInfoList("Pick one: ", sr.getItemResults(cdm), null, false, true, cdm.getTagOracle())); } } else { if (sr == null) { showTopMessage("Error. Resultset is null. There were probably no tags found."); clearResults(); } else { showTopMessage("Whoops " + sr.getStatus()); clearResults(); } } } public void onFailure(Throwable caught) { Popup.showErrorPopup(caught, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "perform tag search.", Popup.ERROR_LVL.NORMAL, null); } }; updateWindowTitleLocal("Tag search"); showLoader(); try { musicServer.tagSearch(searchText, 100, callback); } catch (Exception ex) { Popup.showErrorPopup(ex, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "perform tag search.", Popup.ERROR_LVL.NORMAL, null); } } private void invokeArtistSearchService(final String searchText, searchTypes sT, int page) { AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { SearchResults sr = (SearchResults) result; if (sr != null && sr.isOK()) { ItemInfo[] results = sr.getItemResults(cdm); if (results.length == 0) { showTopMessage("No Match for " + sr.getQuery()); clearResults(); } else if (results.length == 1) { WebLib.trackPageLoad("#artistSearch:" + sr.getQuery()); cdm.getSearchAttentionManager().processUserClick(results[0].getId()); invokeGetArtistInfo(results[0].getId(), false, null); } else { // Did we get back an exact match of our query? If so // foward to user to that artist and offer him the choice // to see results String lowerSearch = searchText.toLowerCase(); for (ItemInfo iI : sr.getItemResults(null)) { if (lowerSearch.equals(iI.getItemName().toLowerCase())) { WebLib.trackPageLoad("#artistSearch:" + sr.getQuery()); cdm.getSearchAttentionManager().processUserClick(iI.getId()); invokeGetArtistInfo(iI.getId(), false, sr); return; } } searchResultsToArtistList(sr); } } else { if (sr == null) { showTopMessage("Error. Can't find artist specified."); clearResults(); } else { showTopMessage("Very Whooops " + sr.getStatus()); clearResults(); } } } public void onFailure(Throwable caught) { Popup.showErrorPopup(caught, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "perform artist search.", Popup.ERROR_LVL.NORMAL, null); } }; updateWindowTitleLocal("Artist search"); showLoader(); try { if (sT == searchTypes.SEARCH_FOR_ARTIST_BY_TAG) { musicServer.artistSearchByTag(searchText, 100, callback); } else if (sT == searchTypes.SEARCH_FOR_ARTIST_BY_ARTIST) { musicServer.artistSearch(searchText, 100, callback); } else { Popup.showInformationPopup("Error. Invalid search type."); } } catch (Exception ex) { Popup.showErrorPopup(ex, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "perform search.", Popup.ERROR_LVL.NORMAL, null); } } /** * Child method of invokeArtistSearchService * @param sr */ private void searchResultsToArtistList(SearchResults sr) { showTopMessage("Found " + sr.getItemResults(cdm).length + " matches"); Widget searchResults = getItemInfoList("Pick one: ", sr.getItemResults(cdm), null, true, true, cdm.getArtistOracle()); searchResults.setStyleName("searchResults"); searchResults.setWidth("300px"); setResults(sr.toString(), searchResults); } private void invokeGetArtistInfo(String artistID, boolean refresh, SearchResults listResults) { PerformanceTimer.start("invokeGetArtistInfo"); // // If we are currently fetching the similarity type, we can't fetch the // artist's info yet so let's try again in 250ms if (cdm.getCurrSimTypeName() == null || cdm.getCurrSimTypeName().equals("")) { Timer t = new TimerWithArtist(artistID, refresh); t.schedule(250); } else { if (artistID.startsWith("artist:")) { artistID = artistID.replaceAll("artist:", ""); } AsyncCallback callback = new DEAsyncCallback<SearchResults, ArtistDetails>(listResults) { public void onSuccess(ArtistDetails artistDetails) { PerformanceTimer.stop("getArtistDetails"); // do some UI stuff to show success if (artistDetails != null && artistDetails.isOK()) { PerformanceTimer.start("createArtistPanel"); cdm.setCurrArtistInfo(artistDetails.getId(), artistDetails.getName()); Widget artistPanel = createArtistPanel(artistDetails); //search.setText(artistDetails.getName(), searchTypes.SEARCH_FOR_ARTIST_BY_ARTIST); //search.updateSuggestBox(Oracles.ARTIST); setResults("artist:" + artistDetails.getId(), artistPanel); hideLoader(); showTopMessage(new Label("Artist bio is displayed below. Click any tag for details. " + "Similar artists are shown on the left. See where they overlap " + "with \"why?\". The big steering wheel on the right lets you " + "customize the recommended artists.")); // If we embeded a search result, a serch was made and although aura returned // multiple results, one of them matched exacly. Offer to display the full list if (data != null) { int length = data.getItemResults(null).length; Label l = new Label("Not the artist you were looking for? Show " + String.valueOf(length - 1) + " similar result" + (length > 2 ? "s" : "")); l.setStyleName("pointer topMsgIndicatorSmall"); l.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { searchResultsToArtistList(data); } }); showTopMessage(l); } PerformanceTimer.stop("createArtistPanel"); } else { if (artistDetails == null) { showTopMessage("Sorry. The details for the artist don't seem to be in our database."); clearResults(); } else { showTopMessage("Whooops " + artistDetails.getStatus()); clearResults(); } } PerformanceTimer.stop("invokeGetArtistInfo"); } public void onFailure(Throwable caught) { PerformanceTimer.stop("getArtistDetails"); Popup.showErrorPopup(caught, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve artist details.", Popup.ERROR_LVL.NORMAL, null); PerformanceTimer.stop("invokeGetArtistInfo"); } }; showLoader(); try { PerformanceTimer.start("getArtistDetails"); musicServer.getArtistDetails(artistID, refresh, cdm.getCurrSimTypeName(), cdm.getCurrPopularity(), callback); } catch (Exception ex) { Popup.showErrorPopup(ex, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve artist details.", Popup.ERROR_LVL.NORMAL, null); } } } private void invokeGetTagInfo(String tagID, boolean refresh) { AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { TagDetails tagDetails = (TagDetails) result; if (tagDetails != null && tagDetails.isOK()) { Widget tagPanel = createTagPanel(tagDetails); //search.setText(tagDetails.getName(), searchTypes.SEARCH_FOR_TAG_BY_TAG); //search.updateSuggestBox(Oracles.TAG); setResults("tag:" + tagDetails.getId(), tagPanel); hideLoader(); } else { if (tagDetails == null) { showTopMessage("Sorry. The details for the tag don't seem to be in our database."); clearResults(); } else { showTopMessage("Whooops " + tagDetails.getStatus()); clearResults(); } } } public void onFailure(Throwable caught) { Popup.showErrorPopup(caught, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve tag details.", Popup.ERROR_LVL.NORMAL, null); } }; showLoader(); try { musicServer.getTagDetails(tagID.substring(tagID.indexOf(":") + 1), refresh, cdm.getCurrSimTypeName(), callback); } catch (Exception ex) { Popup.showErrorPopup(ex, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve tag details.", Popup.ERROR_LVL.NORMAL, null); } } private final void addCompactArtistToOracle(ArrayList<ScoredC<ArtistCompact>> aCList) { for (ScoredC<ArtistCompact> aC : aCList) { cdm.getArtistOracle().add(aC.getItem().getName(), aC.getItem().getPopularity()); } } private final void addCompactArtistToOracle(ArtistCompact[] aCArray) { for (ArtistCompact aC : aCArray) { cdm.getArtistOracle().add(aC.getName(), aC.getPopularity()); } } private Widget createArtistPanel(ArtistDetails artistDetails) { ArtistCompact aC = artistDetails.toArtistCompact(); updateWindowTitleLocal(aC.getName()); VerticalPanel main = new VerticalPanel(); main.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER); main.add(getBioWidget(artistDetails)); if (artistDetails.getVideos().length > 0) { main.add(new DualRoundedPanel("Videos", new VideoScrollWidget(artistDetails.getVideos()))); } if (artistDetails.getPhotos().length > 0) { main.add(new DualRoundedPanel("Photos", new ImageScrollWidget(artistDetails.getPhotos()))); } if (artistDetails.getAlbums().length > 0) { main.add(new DualRoundedPanel("Albums", new AlbumScrollWidget(artistDetails.getAlbums()))); } main.setHorizontalAlignment(HorizontalPanel.ALIGN_LEFT); if (artistDetails.getEvents().length > 0) { main.add(getEventsWidget(artistDetails)); } main.setStyleName("center"); VerticalPanel left = new VerticalPanel(); left.setSpacing(4); left.setWidth("300px"); // Add similar artists ArtistCompact[] aCArray; aCArray = artistDetails.getSimilarArtistsAsArray(); addCompactArtistToOracle(aCArray); if (leftSimList != null) { leftSimList.doRemoveListeners(); } leftSimList = new ArtistCloudArtistListWidget(musicServer, cdm, artistDetails.getSimilarArtists(), aC); HorizontalPanel hP = new HorizontalPanel(); hP.add(new Label("Similar artists")); hP.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT); popSelect = new PopularitySelectAD(artistDetails); hP.add(popSelect); hP.setWidth("300px"); hP.setStyleName("h2"); left.add(new Updatable<ArtistDetails>(hP, leftSimList, cdm, artistDetails) { public void update(ArrayList<ScoredC<ArtistCompact>> aCList) { addCompactArtistToOracle(aCList); leftSimList.doRemoveListeners(); leftSimList = new ArtistCloudArtistListWidget(musicServer, cdm, aCList, data.toArtistCompact()); setNewContent(leftSimList); } }); // Add recommended artists if (artistDetails.getRecommendedArtists().length > 0) { aCArray = artistDetails.getRecommendedArtists(); addCompactArtistToOracle(aCArray); if (leftRecList != null) { leftRecList.doRemoveListeners(); } leftRecList = new ArtistCloudArtistListWidget(musicServer, cdm, aCArray, aC); left.add(WebLib.createSection("Recommendations", leftRecList)); } // Add related artists if (artistDetails.getCollaborations().length > 0) { aCArray = artistDetails.getCollaborations(); addCompactArtistToOracle(aCArray); if (leftRelList != null) { leftRelList.doRemoveListeners(); } leftRelList = new ArtistCloudArtistListWidget(musicServer, cdm, aCArray, aC); left.add(WebLib.createSection("Related", leftRelList)); } left.add(getMoreInfoWidget(artistDetails)); left.setStyleName("left"); DockPanel artistPanel = new DockPanel(); artistPanel.add(main, DockPanel.CENTER); artistPanel.add(left, DockPanel.WEST); artistPanel.setWidth("100%"); artistPanel.setStyleName("resultpanel"); return artistPanel; } private Widget createTagPanel(TagDetails tagDetails) { updateWindowTitleLocal(tagDetails.getName() + " tag"); VerticalPanel main = new VerticalPanel(); main.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER); main.add(getTagHeaderWidget(tagDetails)); main.add(new DualRoundedPanel("Videos", new VideoScrollWidget(tagDetails.getVideos()))); main.add(new DualRoundedPanel("Photos", new ImageScrollWidget(tagDetails.getPhotos()))); main.setStyleName("center"); VerticalPanel left = new VerticalPanel(); left.setSpacing(4); left.setWidth("300px"); // Add similar artists ArtistCompact[] aCArray; aCArray = tagDetails.getRepresentativeArtists(); addCompactArtistToOracle(aCArray); if (leftSimList != null) { leftSimList.doRemoveListeners(); } leftSimList = new TagCloudArtistListWidget(musicServer, cdm, aCArray); HorizontalPanel hP = new HorizontalPanel(); hP.add(new Label("Representative artists")); hP.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT); hP.setWidth("300px"); hP.setStyleName("h2"); left.add(hP); left.add(leftSimList); DockPanel artistPanel = new DockPanel(); artistPanel.add(main, DockPanel.CENTER); artistPanel.add(left, DockPanel.WEST); artistPanel.setWidth("100%"); artistPanel.setStyleName("resultpanel"); return artistPanel; } private Widget getTagHeaderWidget(final TagDetails tagDetails) { HTML html = new HTML(); html.setHTML(getBestTagImageAsHTML(tagDetails) + tagDetails.getDescription()); html.setStyleName("bio"); HorizontalPanel hP = new HorizontalPanel(); hP.setSpacing(3); hP.add(WebLib.getListenWidget(tagDetails)); SteeringWheelWidget sww = new SteeringWheelWidget(SteeringWheelWidget.wheelSize.BIG, new ClickHandler() { @Override public void onClick(ClickEvent event) { cdm.getSteerableTagCloudExternalController().clear(false); cdm.getSteerableTagCloudExternalController().addTag(tagDetails); History.newItem("steering:", true); } }); sww.setTitle("Steerable recommendations starting with the " + tagDetails.getName() + " tag"); hP.add(sww); return createMainSection(tagDetails.getName(), html, hP, tagDetails.getSimilarTags(), null, false); } private Widget getBioWidget(ArtistDetails artistDetails) { HTML html = new HTML(); html.setHTML(artistDetails.getBestArtistImageAsHTML() + artistDetails.getBiographySummary()); html.setStyleName("bio"); artistStar = new StarRatingWidget(musicServer, cdm, artistDetails.getId(), StarRatingWidget.InitialRating.FETCH, StarRatingWidget.Size.MEDIUM); cdm.getLoginListenerManager().addListener(artistStar); HorizontalPanel hP = new HorizontalPanel(); hP.setVerticalAlignment(VerticalPanel.ALIGN_MIDDLE); playButton = new PlayButton(cdm, artistDetails.toArtistCompact(), PlayButton.PLAY_ICON_SIZE.MEDIUM, musicServer); if (playButton != null) { cdm.getMusicProviderSwitchListenerManager().addListener(playButton); playButton.addStyleName("pointer"); hP.add(playButton); } ArtistCompact aC = artistDetails.toArtistCompact(); SteeringWheelWidget steerButton = new SteeringWheelWidget(SteeringWheelWidget.wheelSize.BIG, new DDEClickHandler<ClientDataManager, ArtistCompact>(cdm, aC) { @Override public void onClick(ClickEvent ce) { data.setSteerableReset(true); History.newItem("steering:" + sndData.getId()); } }); steerButton.setTitle("Steerable recommendations starting with " + aC.getName() + "'s tag cloud"); hP.add(new ContextMenuSteeringWheelWidget(cdm, steerButton, aC)); //return createMainSection(artistDetails.getName(), html, // hP, artistDetails.getDistinctiveTags(), artistStar, true); return createMainSection(artistDetails.getName(), html, hP, artistDetails.getDistinctiveTags(), null, true); } private Widget getMoreInfoWidget(ArtistDetails artistDetails) { Map<String, String> urls = artistDetails.getUrls(); if (urls != null && urls.size() > 0) { Grid grid = new Grid(urls.size(), 1); grid.setWidth("300px"); int index = 0; for (String key : urls.keySet()) { String url = urls.get(key); HTML html = new HTML(WebLib.createAnchor(key, url)); grid.setWidget(index++, 0, html); } return new DualRoundedPanel("More info", grid); } else { return new Label(""); } } /* Widget getTastAuraMeterPanel(ArtistDetails aD) { double currArtistScore = 1; //cdm.computeTastauraMeterScore(aD); double realMaxScore; // max between currArtist and user's fav artists' max score if (currArtistScore>cdm.getMaxScore()) { realMaxScore = currArtistScore; } else { realMaxScore = cdm.getMaxScore(); } VerticalPanel vPanel = new VerticalPanel(); for (String key : cdm.getFavArtist().keySet()) { vPanel.add(WebLib.getPopularityWidget(key, cdm.getFavArtist().get(key)/realMaxScore, false, null)); } vPanel.add(WebLib.getPopularityWidget(aD.getName(), currArtistScore/realMaxScore, false, "itemInfoHighlight")); return WebLib.createSection("Tast-aura-meter", vPanel); } */ private Widget getPopularityPanel(ArtistDetails artistDetails) { VerticalPanel vPanel = new VerticalPanel(); vPanel.add(WebLib.getPopularityWidget("The Beatles", 1, true, null)); vPanel.add( WebLib.getPopularityWidget(artistDetails.getName(), artistDetails.getNormPopularity(), true, null)); return WebLib.createSection("Popularity", vPanel); } private Widget getTastAuraMeterWidget(String name, double normPopularity, boolean log) { /** Widget popWidget = getPopularityWidget(name, normPopularity, log); Label why = new Label("why?"); why.setStyleName("tinyInfo"); why.addClickListener(new CommonTagsClickListener(highlightID, itemInfo[i].getId())); **/ return null; } private DualRoundedPanel getEventsWidget(ArtistDetails artistDetails) { ArtistEvent[] events = artistDetails.getEvents(); VerticalPanel widget = new VerticalPanel(); if (events.length == 0) { widget.setWidth("300px"); widget.add(new Label("No events found")); } else { String introMessage; if (artistDetails.isActive()) { introMessage = "Some upcoming events related to " + artistDetails.getName(); } else { introMessage = "Although we haven't heard from " + artistDetails.getName() + " since " + artistDetails.getEndYear() + ", you might find these related events to be of interest."; } widget.add(new HTML(introMessage + "<br/>")); Grid grid = new Grid(events.length, 3); for (int i = 0; i < events.length; i++) { ArtistEvent event = events[i]; grid.setWidget(i, 0, new Label(events[i].getDate())); grid.setWidget(i, 1, new HTML(WebLib.createAnchor(event.getName(), event.getEventURL()))); String venue = event.getVenue(); grid.setWidget(i, 2, new HTML(venue)); } widget.add(grid); } return new DualRoundedPanel("Upcoming Events", widget); } private Widget createMainSection(String title, Widget widget, Widget adornment, ItemInfo[] tagCloud, StarRatingWidget starWidget, boolean addTagInputWidget) { Panel panel = new VerticalPanel(); DockPanel h = new DockPanel(); h.add(new Label(title), DockPanel.WEST); if (adornment != null) { h.add(adornment, DockPanel.EAST); h.setCellHorizontalAlignment(adornment, HorizontalPanel.ALIGN_RIGHT); } if (starWidget != null) { h.add(starWidget, DockPanel.NORTH); } h.setWidth("100%"); h.setStyleName("h1"); panel.add(h); if (tagCloud != null) { if (tagInputWidget != null) { tagInputWidget.onDelete(); } if (addTagInputWidget) { tagInputWidget = new TagInputWidget(musicServer, cdm, "artist", cdm.getCurrArtistID()); cdm.getLoginListenerManager().addListener(tagInputWidget); //panel.add(tagInputWidget); } Panel p = TagDisplayLib.getTagsInPanel(tagCloud, TagDisplayLib.ORDER.SHUFFLE, cdm, TagColorType.TAG); // If there are not tags, this will be null if (p != null) { p.addStyleName("tagCloudMargin"); panel.add(p); } else { panel.add(new HTML("<br /<br />")); } } panel.add(widget); return panel; } private String getBestTagImageAsHTML(TagDetails td) { String imgHtml = ""; ArtistPhoto[] photos = td.getPhotos(); if (photos.length > 0) { imgHtml = photos[0].getHtmlWrapper(); } return imgHtml; } private String getEmbeddedVideo(ArtistVideo video, boolean autoplay) { String url = video.getUrl(); String autostring = autoplay ? "&autoplay=1" : ""; url = url.replaceAll("\\?v=", "/v/"); //String title = "<span style=\"text-align:center\">" + video.getTitle() + "</span><br/>"; String obj = "<center><object width=\"425\" height=\"350\"><param name=\"movie\" value=\"" + url + "\"></param><param name=\"wmode\" value=\"transparent\"></param>" + "<embed src=\"" + url + autostring + "\" type=\"application/x-shockwave-flash\"" + " wmode=\"transparent\" width=\"425\" height=\"350\"></embed></object></center>"; //return title + obj; return obj; } private VerticalPanel getItemInfoList(final String title, final ItemInfo[] itemInfo, String highlightID, boolean getArtistOnClick, boolean displayPopularity, PopSortedMultiWordSuggestOracle oracle) { Grid artistGrid; if (displayPopularity) { artistGrid = new Grid(itemInfo.length + 1, 2); artistGrid.setCellSpacing(5); artistGrid.setWidget(0, 0, new HTML("<b>Name</b>")); artistGrid.setWidget(0, 1, new HTML("<b>Popularity</b>")); } else { artistGrid = new Grid(itemInfo.length, 1); } // Find the maximum values for score and popularity double maxPopularity = 0; for (ItemInfo iI : itemInfo) { if (iI.getPopularity() > maxPopularity) { maxPopularity = iI.getPopularity(); } } for (int i = 0; i < itemInfo.length; i++) { if (oracle != null) { oracle.add(itemInfo[i].getItemName(), itemInfo[i].getPopularity()); } Label label = new Label(itemInfo[i].getItemName()); label.addClickHandler(new DEClickHandler<String>(itemInfo[i].getId()) { @Override public void onClick(ClickEvent event) { // Add search attention if necessary cdm.getSearchAttentionManager().processUserClick(data); } }); label.addClickHandler(new ItemInfoClickHandler(itemInfo[i], getArtistOnClick)); label.setTitle("Score: " + itemInfo[i].getScore() + " Popularity:" + itemInfo[i].getPopularity()); if (highlightID != null && highlightID.equals(itemInfo[i].getId())) { label.setStyleName("itemInfoHighlight"); } else { label.setStyleName("itemInfo"); } if (displayPopularity) { artistGrid.setWidget(i + 1, 0, label); artistGrid.setWidget(i + 1, 1, WebLib.getPopularityHisto(itemInfo[i].getPopularity() / maxPopularity, false, 10, 100)); } else { artistGrid.setWidget(i, 0, label); } } VerticalPanel w; if (!getArtistOnClick) { Grid titleWidget = new Grid(1, 2); titleWidget.setWidget(0, 0, new HTML("<h2>" + title + "</h2>")); Label l = new Label(" Cloud"); l.setStyleName("tinyInfo"); l.addClickHandler(new ClickHandler() { public void onClick(ClickEvent ce) { TagDisplayLib.showTagCloud(title, itemInfo, TagDisplayLib.ORDER.SHUFFLE, cdm); } }); titleWidget.setWidget(0, 1, l); w = WebLib.createSection(titleWidget, artistGrid); } else { w = WebLib.createSection(title, artistGrid); } w.setStyleName("infoList"); if (displayPopularity) { w.setWidth("325px"); } else { w.setWidth("200px"); } return w; } private class TimerWithArtist extends Timer { private String artistID; private boolean refresh; public TimerWithArtist(String artistID, boolean refresh) { super(); this.artistID = artistID; this.refresh = refresh; } @Override public void run() { History.newItem("artist:" + artistID); } } private class ItemInfoClickHandler implements ClickHandler { private ItemInfo info; private boolean getArtistOnClick; ItemInfoClickHandler(ItemInfo info, boolean getArtistOnClick) { this.info = info; this.getArtistOnClick = getArtistOnClick; } @Override public void onClick(ClickEvent ce) { if (getArtistOnClick) { History.newItem("artist:" + info.getId()); } else { History.newItem("tag:" + info.getId()); } } } private class ArtistCloudArtistListWidget extends ArtistListWidget { private ArtistCompact currArtist; public ArtistCloudArtistListWidget(MusicSearchInterfaceAsync musicServer, ClientDataManager cdm, ArrayList<ScoredC<ArtistCompact>> aC, ArtistCompact currArtist) { super(musicServer, cdm, aC, cdm.isLoggedIn(), true); this.currArtist = currArtist; } public ArtistCloudArtistListWidget(MusicSearchInterfaceAsync musicServer, ClientDataManager cdm, ArtistCompact[] aC, ArtistCompact currArtist) { super(musicServer, cdm, aC, cdm.isLoggedIn(), true); this.currArtist = currArtist; } @Override public void openWhyPopup(SwapableTxtButton why) { why.showLoad(); TagDisplayLib.invokeGetCommonTags(currArtist.getId(), why.getId(), musicServer, cdm, new CommonTagsAsyncCallback(why, "Common tags between " + currArtist.getName() + " and " + why.getName(), cdm) { }); } @Override public void openDiffPopup(DiffButton diff) { if (diff.getId().equals(currArtist.getId())) { diff.displayIdenticalArtistMsg(); } else { TagDisplayLib.showDifferenceCloud( "Difference cloud between " + currArtist.getName() + " and " + diff.getName(), currArtist.getDistinctiveTags(), diff.getDistinctiveTags(), cdm); } } } private class TagCloudArtistListWidget extends ArtistListWidget { private ArtistCompact[] aC; public TagCloudArtistListWidget(MusicSearchInterfaceAsync musicServer, ClientDataManager cdm, ArtistCompact[] aDArray) { super(musicServer, cdm, aDArray, cdm.isLoggedIn(), false); this.aC = aDArray; } @Override public void openWhyPopup(SwapableTxtButton why) { for (ArtistCompact t : aC) { if (t.getId().equals(why.getId())) { TagDisplayLib.showTagCloud(t.getName() + "'s tag cloud", t.getDistinctiveTags(), TagDisplayLib.ORDER.SHUFFLE, cdm); break; } } } @Override public void openDiffPopup(DiffButton diff) { Popup.showErrorPopup("", Popup.ERROR_MSG_PREFIX.NONE, "This feature is not yet implemented.", Popup.ERROR_LVL.SILENT, null); } } private abstract class ScrollWidget extends Composite { protected ScrollItem[] items; private final int NBR_ITEM_ON_PREVIEW = 12; private int NBR_ITEM_PER_LINE = 3; protected int maxImgHeight = 0; protected int maxImgWidth = 0; protected Grid mainPanel = new Grid(2, 1); protected Grid topPanel = new Grid(1, 3); protected Panel currPreview; protected Panel nextPreview; protected int currPageNbr = 0; protected int totalPageNbr = -1; private Label headerTitle; abstract protected void triggerAction(int index); abstract protected String getSectionName(); protected Widget init() { if (Window.getClientWidth() > 1024) { NBR_ITEM_PER_LINE = 4; } totalPageNbr = (int) Math.ceil(items.length / new Double(NBR_ITEM_ON_PREVIEW)); topPanel.addStyleName("center"); topPanel.setWidth("100%"); topPanel.setCellPadding(4); Image prev = playImgBundle.scrollWidgetPrev().createImage(); prev.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent ce) { setPreviewPanel(getElementsOnPage(currPageNbr - 1)); } }); Image next = playImgBundle.scrollWidgetNext().createImage(); next.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent ce) { setPreviewPanel(getElementsOnPage(currPageNbr + 1)); } }); if (items.length > NBR_ITEM_ON_PREVIEW) { topPanel.setWidget(0, 0, prev); topPanel.setWidget(0, 2, next); } headerTitle = new Label(); topPanel.setWidget(0, 1, headerTitle); for (int j = 0; j < 3; j++) { topPanel.getCellFormatter().setAlignment(0, j, HorizontalPanel.ALIGN_CENTER, VerticalPanel.ALIGN_MIDDLE); } if (items.length > 0) { setPreviewPanel(getElementsOnPage(currPageNbr)); mainPanel.setWidget(0, 0, topPanel); } else { mainPanel.setWidget(1, 0, new Label("No " + getSectionName())); } mainPanel.setWidth("100%"); return mainPanel; } private void updateHeaderTitle() { if (totalPageNbr > 1) { headerTitle.setText((currPageNbr + 1) + "/" + totalPageNbr); } } /** * Returns elements on the given page * @param page number * @return n scrollitems */ protected ArrayList<ScrollItem> getElementsOnPage(int newPageNbr) { // If we're going over or under, wrap us around if (newPageNbr < 0) { newPageNbr = totalPageNbr - 1; } else if (newPageNbr >= totalPageNbr) { newPageNbr = 0; } ArrayList<ScrollItem> sI = new ArrayList<ScrollItem>(); for (int i = 0; i < NBR_ITEM_ON_PREVIEW; i++) { int idx = i + (newPageNbr * NBR_ITEM_ON_PREVIEW); if (idx >= items.length) { break; } sI.add(new ScrollItem(items[idx].title, items[idx].thumb, idx)); } currPageNbr = newPageNbr; return sI; } private void setPreviewPanel(ArrayList<ScrollItem> sI) { nextPreview = new VerticalPanel(); ArrayList<HorizontalPanel> topPreviewArray = new ArrayList<HorizontalPanel>(); HorizontalPanel topPreview = null; int index = 0; for (ScrollItem i : sI) { if (topPreview == null || ++index >= NBR_ITEM_PER_LINE) { if (topPreview != null) { topPreviewArray.add(topPreview); topPreview = null; } index = 0; topPreview = new HorizontalPanel(); topPreview.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER); topPreview.setVerticalAlignment(VerticalPanel.ALIGN_MIDDLE); topPreview.setWidth("100%"); topPreview.setSpacing(8); } Grid g = new Grid(1, 1); g.setSize(maxImgWidth + "px", maxImgHeight + "px"); g.getCellFormatter().getElement(0, 0).setAttribute("valign", "middle"); g.getCellFormatter().getElement(0, 0).setAttribute("align", "center"); g.setTitle(i.title); NEffectPanel theEffectPanel = new NEffectPanel(); Fade f = new Fade(); f.getProperties().setStartOpacity(0); f.getProperties().setEndOpacity(100); theEffectPanel.addEffect(f); Image img = new Image(i.thumb); //img.setTitle(i.title); theEffectPanel.add(img); img.setVisible(false); img.addLoadListener(new LoadListenerPanelContainer(theEffectPanel)); img.addClickHandler(new IndexClickHandler(i.index)); // Crop if necessary if (maxImgHeight > 0 && maxImgWidth > 0) { img.setVisibleRect(0, 0, maxImgWidth, maxImgHeight); } g.setWidget(0, 0, theEffectPanel); topPreview.add(g); } if (topPreview != null) { while (index < NBR_ITEM_PER_LINE) { topPreview.add(new Label("")); index++; } topPreviewArray.add(topPreview); topPreview = null; } nextPreview = new VerticalPanel(); for (HorizontalPanel p : topPreviewArray) { nextPreview.add(p); } mainPanel.setWidget(1, 0, nextPreview); updateHeaderTitle(); } protected class IndexClickHandler implements ClickHandler { protected int index; public IndexClickHandler(int index) { super(); this.index = index; } @Override public void onClick(ClickEvent ce) { triggerAction(index); } } private class LoadListenerPanelContainer implements LoadListener { private NEffectPanel theEffectPanel; /** * @param w widget we want the effect applied to */ public LoadListenerPanelContainer(NEffectPanel theEffectPanel) { super(); this.theEffectPanel = theEffectPanel; } @Override public void onError(Widget arg0) { } @Override public void onLoad(Widget arg0) { theEffectPanel.playEffects(); } } protected class ScrollItem { public String title; public String thumb; public int index; public ScrollItem(String title, String thumb, int index) { this.title = title; this.thumb = thumb; this.index = index; } } } private class ImageScrollWidget extends ScrollWidget { private ArtistPhoto[] aP; public ImageScrollWidget(ArtistPhoto[] aPArray) { this.aP = aPArray; ArrayList<ScrollItem> sIList = new ArrayList<ScrollItem>(); int i = 0; for (ArtistPhoto a : aPArray) { if (a != null) { sIList.add(new ScrollItem(a.getTitle(), a.getSmallImageUrl(), i++)); } } items = sIList.toArray(new ScrollItem[0]); maxImgHeight = 130; maxImgWidth = 130; initWidget(init()); } @Override protected String getSectionName() { return "photos"; } @Override protected void triggerAction(int index) { HTML html = new HTML(aP[index].getRichHtmlWrapper()); //Popup.showPopup(html,"WebMusicExplaura :: Flickr Photo"); //Popup.showRoundedPopup(html, "WebMusicExplaura :: Flickr Photo"); Popup.showRoundedPopup(html, aP[index].getTitle(), 600); } } private class VideoScrollWidget extends ScrollWidget { private ArtistVideo[] aV; public VideoScrollWidget(ArtistVideo[] aVArray) { this.aV = aVArray; ArrayList<ScrollItem> sIList = new ArrayList<ScrollItem>(); int i = 0; for (ArtistVideo a : aVArray) { if (a != null) { sIList.add(new ScrollItem(a.getTitle(), a.getThumbnail(), i++)); } } items = sIList.toArray(new ScrollItem[0]); maxImgHeight = 97; maxImgWidth = 130; initWidget(init()); } @Override protected String getSectionName() { return "videos"; } @Override protected void triggerAction(int index) { HTML html = new HTML(getEmbeddedVideo(aV[index], true)); //Popup.showPopup(html,"WebMusicExplaura :: YouTube Video"); //Popup.showRoundedPopup(html, "WebMusicExplaura :: YouTube Video"); Popup.showRoundedPopup(html, aV[index].getTitle(), 600); } } private class AlbumScrollWidget extends ScrollWidget { private AlbumDetails[] aD; public AlbumScrollWidget(AlbumDetails[] aDArray) { this.aD = aDArray; ArrayList<ScrollItem> sIList = new ArrayList<ScrollItem>(); int i = 0; for (AlbumDetails a : aDArray) { if (a != null) { sIList.add(new ScrollItem(a.getTitle(), a.getAlbumArt(), i++)); } } items = sIList.toArray(new ScrollItem[0]); maxImgHeight = 130; maxImgWidth = 130; initWidget(init()); } @Override protected void triggerAction(int index) { Window.open(aD[index].getAmazonLink(), "Window1", ""); } @Override protected String getSectionName() { return "albums"; } } private class PopularitySelectAD extends PopularitySelect { private ArtistDetails aD; public PopularitySelectAD(ArtistDetails aD) { super(cdm.getCurrPopularity()); this.aD = aD; } @Override public void onSelectionChange(String newPopularity) { cdm.setCurrPopularity(newPopularity); cdm.displayWaitIconUpdatableWidgets(); invokeGetArtistInfo(aD.getId()); } /** * Fetch new similar artists. Used when similarity type is updated * @param artistID * @param refresh */ private void invokeGetArtistInfo(String artistID) { if (artistID.startsWith("artist:")) { artistID = artistID.replaceAll("artist:", ""); } final String fArtistID = artistID; AsyncCallback<ArrayList<ScoredC<ArtistCompact>>> callback = new AsyncCallback<ArrayList<ScoredC<ArtistCompact>>>() { public void onSuccess(ArrayList<ScoredC<ArtistCompact>> aC) { // do some UI stuff to show success if (aC != null) { cdm.updateUpdatableWidgets(aC); } else { Popup.showErrorPopup("Returned list was null.", Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve the new recommendations.", Popup.ERROR_LVL.NORMAL, new DECommand<String>(fArtistID) { @Override public void execute() { invokeGetArtistInfo(data); } }); } } public void onFailure(Throwable caught) { Popup.showErrorPopup(caught, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve the new recommendations.", Popup.ERROR_LVL.NORMAL, new DECommand<String>(fArtistID) { @Override public void execute() { invokeGetArtistInfo(data); } }); } }; try { musicServer.getSimilarArtists(artistID, cdm.getCurrSimTypeName(), cdm.getCurrPopularity(), callback); } catch (Exception ex) { Popup.showErrorPopup(ex, Popup.ERROR_MSG_PREFIX.ERROR_OCC_WHILE, "retrieve the new recommendations.", Popup.ERROR_LVL.NORMAL, new DECommand<String>(fArtistID) { @Override public void execute() { invokeGetArtistInfo(data); } }); } } }; }