com.google.appinventor.client.explorer.youngandroid.GalleryList.java Source code

Java tutorial

Introduction

Here is the source code for com.google.appinventor.client.explorer.youngandroid.GalleryList.java

Source

// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0

package com.google.appinventor.client.explorer.youngandroid;

import static com.google.appinventor.client.Ode.MESSAGES;

import java.util.ArrayList;
import java.util.List;

import com.google.appinventor.client.GalleryClient;
import com.google.appinventor.client.GalleryGuiFactory;
import com.google.appinventor.client.GalleryRequestListener;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.output.OdeLog;
import com.google.appinventor.shared.rpc.project.GalleryApp;
import com.google.appinventor.shared.rpc.project.GalleryAppListResult;
import com.google.appinventor.shared.rpc.project.GalleryComment;
import com.google.appinventor.shared.rpc.project.UserProject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * The gallery list shows apps from the gallery in a table.
 *
 * <p> The project name and date created will be shown in the table.
 *
 * @author wolberd@google.com (Dave Wolber)
 */
public class GalleryList extends Composite implements GalleryRequestListener {

    final Ode ode = Ode.getInstance();
    private List<GalleryApp> apps;
    private final List<GalleryApp> selectedApps;
    GalleryClient gallery = null;
    GalleryGuiFactory galleryGF = null;

    // UI elements
    private final FlowPanel galleryGUI;
    private final TabPanel appTabs;
    private final FlowPanel appRecent;
    private final FlowPanel appFeatured;
    private final FlowPanel appPopular;
    private final FlowPanel appSearch;
    private final FlowPanel appTutorial;
    private final FlowPanel appRecentContent;
    private final FlowPanel appFeaturedContent;
    private final FlowPanel appPopularContent;
    private final FlowPanel appSearchContent;
    private final FlowPanel appTutorialContent;
    private final TextBox searchText;

    private GalleryAppTab appRecentTab;
    private GalleryAppTab appFeaturedTab;
    private GalleryAppTab appPopularTab;
    private GalleryAppTab appSearchTab;
    private GalleryAppTab appTutorialTab;

    public static final int REQUEST_FEATURED = 1;
    public static final int REQUEST_RECENT = 2;
    public static final int REQUEST_SEARCH = 3;
    public static final int REQUEST_MOSTLIKED = 4;
    public static final int REQUEST_MOSTDOWNLOADED = 5;
    public static final int REQUEST_MOSTVIEWED = 6;
    public static final int REQUEST_BYDEVELOPER = 7;
    public static final int REQUEST_BYTAG = 8;
    public static final int REQUEST_ALL = 9;
    public static final int REQUEST_REMIXED_TO = 10;
    public static final int REQUEST_TUTORIAL = 11;

    private int appRecentCounter = 0;
    private int appFeaturedCounter = 0;
    private int appPopularCounter = 0;
    private int appSearchCounter = 0;
    private int appTutorialCounter = 0;

    private boolean appRecentExhausted = false;
    private boolean appFeaturedExhausted = false;
    private boolean appPopularExhausted = false;
    private boolean appSearchExhausted = false;
    private boolean appTutorialExhausted = false;
    public static final int NUMAPPSTOSHOW = 10;

    /**
     * Creates a new GalleryList
     */
    public GalleryList() {

        gallery = GalleryClient.getInstance();
        gallery.addListener(this);
        galleryGF = new GalleryGuiFactory();

        selectedApps = new ArrayList<GalleryApp>();

        // Initialize UI
        galleryGUI = new FlowPanel();
        galleryGUI.addStyleName("gallery");
        appTabs = new TabPanel();
        appRecent = new FlowPanel();
        appFeatured = new FlowPanel();
        appPopular = new FlowPanel();
        appSearch = new FlowPanel();
        appTutorial = new FlowPanel();
        appRecentContent = new FlowPanel();
        appFeaturedContent = new FlowPanel();
        appPopularContent = new FlowPanel();
        appSearchContent = new FlowPanel();
        appTutorialContent = new FlowPanel();
        searchText = new TextBox();

        // HTML segment for gallery typeface
        HTML headerExtra = new HTML("<link href='http://fonts.googleapis.com/css?"
                + "family=Roboto:400,300,100' rel='stylesheet' type='text/css'>");
        galleryGUI.add(headerExtra);

        // Add content to panels
        appFeaturedTab = new GalleryAppTab(appFeatured, appFeaturedContent, REQUEST_FEATURED);
        appRecentTab = new GalleryAppTab(appRecent, appRecentContent, REQUEST_RECENT);
        appSearchTab = new GalleryAppTab(appSearch, appSearchContent, REQUEST_SEARCH);
        appPopularTab = new GalleryAppTab(appPopular, appPopularContent, REQUEST_MOSTLIKED);
        appTutorialTab = new GalleryAppTab(appTutorial, appTutorialContent, REQUEST_TUTORIAL);
        // don't think we need because in regular addgallerytab below

        // Add panels to main tabPanel
        appTabs.add(appRecent, "Recent");
        appTabs.add(appTutorial, "Tutorials");
        appTabs.add(appFeatured, "Featured");
        appTabs.add(appPopular, "Popular");
        appTabs.add(appSearch, "Search");
        appTabs.selectTab(0);
        appTabs.addStyleName("gallery-app-tabs");
        galleryGUI.add(appTabs);

        // Initialize top-level GUI
        VerticalPanel panel = new VerticalPanel();
        panel.setWidth("100%");
        panel.add(galleryGUI);

        initWidget(panel);
    }

    /**
     * A wrapper class of tab, which provides help method to get/set UI components
     */
    private class GalleryAppTab {
        Label buttonNext;
        Label noResultsFound;
        Label keywordTotalResultsLabel;
        Label generalTotalResultsLabel;

        /**
         * @param container: the FlowPanel that this app tab will reside.
         * @param content: the sub-panel that contains the actual app content.
         * @param request: type of app request, for pagination.
         */
        GalleryAppTab(FlowPanel container, FlowPanel content, final int request) {
            addGalleryAppTab(container, content, request);
        }

        /**
         * @return Label buttonNext
         */
        public Label getButtonNext() {
            return buttonNext;
        }

        /**
         * @return Label noResultsFound
         */
        public Label getNoResultsFound() {
            return noResultsFound;
        }

        /**
         * @return Label keywordTotalResultsLabel
         */
        public Label getKeywordTotalResultsLabel() {
            return keywordTotalResultsLabel;
        }

        /**
         * Set keywordTotalResultsLabel's text to new text
         * @param keyword the search keyword
         * @param num number of results
         */
        public void setKeywordTotalResultsLabel(String keyword, int num) {
            keywordTotalResultsLabel.setText(MESSAGES.gallerySearchResultsPrefix() + keyword
                    + MESSAGES.gallerySearchResultsInfix() + num + MESSAGES.gallerySearchResultsSuffix());
        }

        /**
         * @return Label generalTotalResultsLabel
         */
        public Label getGeneralTotalResultsLabel() {
            return generalTotalResultsLabel;
        }

        /**
         * set generalTotalResultsLabel to new text
         * @param num number of results
         */
        public void setGeneralTotalResultsLabel(int num) {
            generalTotalResultsLabel.setText(num + MESSAGES.gallerySearchResultsSuffix());
        }

        /**
         * Creates the GUI components for a regular app tab.
         * This method resides here because it needs access to global variables.
         * @param container: the FlowPanel that this app tab will reside.
         * @param content: the sub-panel that contains the actual app content.
         * @param request: type of app request, for pagination.
         */
        private void addGalleryAppTab(FlowPanel container, FlowPanel content, final int request) {
            // Search specific
            if (request == REQUEST_SEARCH) {
                FlowPanel searchPanel = new FlowPanel();
                searchText.addStyleName("gallery-search-textarea");
                Button sb = new Button("Search for apps");
                searchPanel.add(searchText);
                searchPanel.add(sb);
                searchPanel.addStyleName("gallery-search-panel");
                //        container.add(searchPanel);
                appSearchContent.addStyleName("gallery-search-results");
                container.add(appSearchContent);
                keywordTotalResultsLabel = new Label();
                container.add(keywordTotalResultsLabel);
                noResultsFound = new Label(MESSAGES.noResultsFound());
                noResultsFound.setVisible(false);
                container.add(noResultsFound);
                container.addStyleName("gallery-search");
                sb.addClickHandler(new ClickHandler() {
                    //  @Override
                    public void onClick(ClickEvent event) {
                        gallery.FindApps(searchText.getText(), 0, NUMAPPSTOSHOW, 0, true);
                        searchText.setFocus(true);
                    }
                });
                searchText.addKeyDownHandler(new KeyDownHandler() {
                    //  @Override
                    public void onKeyDown(KeyDownEvent e) {
                        if (e.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                            gallery.FindApps(searchText.getText(), 0, NUMAPPSTOSHOW, 0, true);
                            searchText.setFocus(true);
                        }
                    }
                });
            } else if (request == REQUEST_TUTORIAL) {
                generalTotalResultsLabel = new Label();
                container.add(generalTotalResultsLabel);
                gallery.GetTutorial(appTutorialCounter, NUMAPPSTOSHOW, 0, false);
            } else if (request == REQUEST_RECENT) {
                generalTotalResultsLabel = new Label();
                container.add(generalTotalResultsLabel);
                gallery.GetMostRecent(appRecentCounter, NUMAPPSTOSHOW, false);
            } else if (request == REQUEST_MOSTLIKED) {
                generalTotalResultsLabel = new Label();
                container.add(generalTotalResultsLabel);
                gallery.GetMostLiked(appPopularCounter, NUMAPPSTOSHOW, false);
            } else if (request == REQUEST_FEATURED) {
                generalTotalResultsLabel = new Label();
                container.add(generalTotalResultsLabel);
                gallery.GetFeatured(appFeaturedCounter, NUMAPPSTOSHOW, 0, false);
            }
            container.add(content);

            buttonNext = new Label();
            buttonNext.setText(MESSAGES.galleryMoreApps());
            buttonNext.addStyleName("active");
            if (request == REQUEST_SEARCH) {
                buttonNext.setVisible(false);
            }

            FlowPanel next = new FlowPanel();
            next.add(buttonNext);
            next.addStyleName("gallery-nav-next");
            container.add(next);

            buttonNext.addClickHandler(new ClickHandler() {
                //  @Override
                public void onClick(ClickEvent event) {
                    switch (request) {
                    case REQUEST_FEATURED:
                        if (!appFeaturedExhausted) {
                            // If the next page still has apps to retrieve, do it
                            appFeaturedCounter += NUMAPPSTOSHOW;
                            gallery.GetFeatured(appFeaturedCounter, NUMAPPSTOSHOW, 0, false);
                        }
                        break;
                    case REQUEST_TUTORIAL:
                        if (!appTutorialExhausted) {
                            // If the next page still has apps to retrieve, do it
                            appTutorialCounter += NUMAPPSTOSHOW;
                            gallery.GetTutorial(appTutorialCounter, NUMAPPSTOSHOW, 0, false);
                        }
                        break;
                    case REQUEST_RECENT:
                        if (!appRecentExhausted) {
                            // If the next page still has apps to retrieve, do it
                            appRecentCounter += NUMAPPSTOSHOW;
                            gallery.GetMostRecent(appRecentCounter, NUMAPPSTOSHOW, false);
                        }
                        break;
                    case REQUEST_SEARCH:
                        if (!appSearchExhausted) {
                            // If the next page still has apps to retrieve, do it
                            appSearchCounter += NUMAPPSTOSHOW;
                            gallery.FindApps(searchText.getText(), appSearchCounter, NUMAPPSTOSHOW, 0, false);
                        }
                        break;
                    case REQUEST_MOSTLIKED:
                        if (!appPopularExhausted) {
                            // If the next page still has apps to retrieve, do it
                            appPopularCounter += NUMAPPSTOSHOW;
                            gallery.GetMostLiked(appPopularCounter, NUMAPPSTOSHOW, false);
                        }
                        break;
                    }
                }
            });
        }
    }

    /**
     * @return TextBox searchText
     */
    public TextBox getSearchText() {
        return searchText;
    }

    /**
     * Creates the GUI components for search tab.
     *
     * @param searchApp: the FlowPanel that search tab will reside.
     */
    private void addGallerySearchTab(FlowPanel searchApp) {
        // Add search GUI
        FlowPanel searchPanel = new FlowPanel();
        final TextBox searchText = new TextBox();
        searchText.addStyleName("gallery-search-textarea");
        Button sb = new Button(MESSAGES.gallerySearchForAppsButton());
        searchPanel.add(searchText);
        searchPanel.add(sb);
        searchPanel.addStyleName("gallery-search-panel");
        searchApp.add(searchPanel);
        appSearchContent.addStyleName("gallery-search-results");
        searchApp.add(appSearchContent);
        searchApp.addStyleName("gallery-search");

        sb.addClickHandler(new ClickHandler() {
            //  @Override
            public void onClick(ClickEvent event) {
                gallery.FindApps(searchText.getText(), 0, NUMAPPSTOSHOW, 0, true);
            }
        });
    }

    /**
     * Loads the proper tab GUI with gallery's app data.
     * @param appsResult: list of returned gallery apps from callback.
     * @param requestId: determines the specific type of app data.
     */
    private void refreshApps(GalleryAppListResult appsResult, int requestId, boolean refreshable) {
        switch (requestId) {
        case REQUEST_FEATURED:
            appFeaturedTab.setGeneralTotalResultsLabel(appsResult.getTotalCount());
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW) {
                // That means there's not enough apps to show (reaches the end)
                appFeaturedExhausted = true;
            } else {
                appFeaturedExhausted = false;
            }
            galleryGF.generateHorizontalAppList(appsResult.getApps(), appFeaturedContent, refreshable);
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW
                    || appFeaturedCounter + NUMAPPSTOSHOW >= appsResult.getTotalCount()) {
                appFeaturedTab.getButtonNext().setVisible(false);
            } else {
                appFeaturedTab.getButtonNext().setVisible(true);
            }
            break;
        case REQUEST_TUTORIAL:
            appTutorialTab.setGeneralTotalResultsLabel(appsResult.getTotalCount());
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW) {
                // That means there's not enough apps to show (reaches the end)
                appTutorialExhausted = true;
            } else {
                appTutorialExhausted = false;
            }
            galleryGF.generateHorizontalAppList(appsResult.getApps(), appTutorialContent, refreshable);
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW
                    || appTutorialCounter + NUMAPPSTOSHOW >= appsResult.getTotalCount()) {
                appTutorialTab.getButtonNext().setVisible(false);
            } else {
                appTutorialTab.getButtonNext().setVisible(true);
            }
            break;
        case REQUEST_RECENT:
            appRecentTab.setGeneralTotalResultsLabel(appsResult.getTotalCount());
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW
                    || appRecentCounter + NUMAPPSTOSHOW >= appsResult.getTotalCount()) {
                appRecentTab.getButtonNext().setVisible(false);
            } else {
                appRecentTab.getButtonNext().setVisible(true);
            }

            if (appsResult.getApps().size() < NUMAPPSTOSHOW) {
                // That means there's not enough apps to show (reaches the end)
                appRecentExhausted = true;
            } else {
                appRecentExhausted = false;
            }
            galleryGF.generateHorizontalAppList(appsResult.getApps(), appRecentContent, refreshable);
            break;
        case REQUEST_SEARCH:
            appSearchTab.setKeywordTotalResultsLabel(appsResult.getKeyword(), appsResult.getTotalCount());
            if (appsResult.getTotalCount() == 0) {
                appSearchTab.getNoResultsFound().setVisible(true);
            } else {
                appSearchTab.getNoResultsFound().setVisible(false);
            }
            if (refreshable) {
                appSearchCounter = 0;
            }

            if (appSearchCounter + NUMAPPSTOSHOW >= appsResult.getTotalCount()) {
                appSearchTab.getButtonNext().setVisible(false);
            } else {
                appSearchTab.getButtonNext().setVisible(true);
            }
            if (appsResult.getApps().size() < NUMAPPSTOSHOW) {
                // That means there's not enough apps to show (reaches the end)
                appSearchExhausted = true;
            } else {
                appSearchExhausted = false;
            }
            galleryGF.generateHorizontalAppList(appsResult.getApps(), appSearchContent, refreshable);
            break;
        case REQUEST_MOSTLIKED:
            appPopularTab.setGeneralTotalResultsLabel(appsResult.getTotalCount());
            if (appsResult.getTotalCount() < NUMAPPSTOSHOW
                    || appPopularCounter + NUMAPPSTOSHOW >= appsResult.getTotalCount()) {
                appPopularTab.getButtonNext().setVisible(false);
            } else {
                appPopularTab.getButtonNext().setVisible(true);
            }
            if (appsResult.getApps().size() < NUMAPPSTOSHOW) {
                // That means there's not enough apps to show (reaches the end)
                appPopularExhausted = true;
            } else {
                appPopularExhausted = false;
            }
            galleryGF.generateHorizontalAppList(appsResult.getApps(), appPopularContent, refreshable);
            break;
        }
    }

    /**
     * Gets the number of projects
     *
     * @return the number of projects
     */
    public int getNumProjects() {
        return apps.size();
    }

    /**
     * Gets the number of selected projects
     *
     * @return the number of selected projects
     */
    public int getNumSelectedApps() {
        return selectedApps.size();
    }

    /**
     * Returns the list of selected projects
     *
     * @return the selected projects
     */
    public List<GalleryApp> getSelectedApps() {
        return selectedApps;
    }

    /**
     * select specific tab index based on given index
     * @param index
     */
    public void setSelectTabIndex(int index) {
        appTabs.selectTab(index);
    }

    /**
     * Process the results after retrieving GalleryAppListResult
     * @param appsResult GalleryAppList Result
     * @param requestId request id
     * @param refreshable whether or not clear container
     * @see GalleryRequestListener
     */
    public void onAppListRequestCompleted(GalleryAppListResult appsResult, int requestId, boolean refreshable) {
        List<GalleryApp> apps = appsResult.getApps();
        if (apps != null)
            refreshApps(appsResult, requestId, refreshable);
        else
            OdeLog.log("apps was null");
    }

    /**
     * Process the results after retrieving list of GalleryComment
     * @see GalleryRequestListener
     */
    public void onCommentsRequestCompleted(List<GalleryComment> comments) {

    }

    /**
     * Process the results after retrieving list of UserProject
     * @see GalleryRequestListener
     */
    public void onSourceLoadCompleted(UserProject projectInfo) {

    }

}