/** * Copyright (c) 2012-2013 Nokia Corporation. All rights reserved. * Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation. * Oracle and Java are trademarks or registered trademarks of Oracle and/or its * affiliates. Other product and company names mentioned herein may be trademarks * or trade names of their respective owners. * See LICENSE.TXT for license information. */ package com.nokia.example.rlinks.view; import com.nokia.example.rlinks.Main; import com.nokia.example.rlinks.VisualStyles; import com.nokia.example.rlinks.model.LinkThing; import com.nokia.example.rlinks.network.HttpClient; import com.nokia.example.rlinks.network.HttpOperation; import com.nokia.example.rlinks.network.operation.LinksLoadOperation; import com.nokia.example.rlinks.network.operation.LinksLoadOperation.LoadLinksListener; import com.nokia.example.rlinks.view.item.LinkItem; import com.nokia.example.rlinks.view.item.LinkItem.LinkSelectionListener; import com.nokia.example.rlinks.view.item.LoaderItem; import com.nokia.example.rlinks.view.item.TextItem; import java.util.Hashtable; import java.util.Vector; import javax.microedition.lcdui.Command; import javax.microedition.lcdui.Displayable; import javax.microedition.lcdui.Item; import javax.microedition.lcdui.Spacer; /** * The LinksView is the default view of the application. It lists all links * under a certain reddit (category). */ public class LinksView extends BaseFormView implements LoadLinksListener { private final Command exitCommand = new Command("Exit", Command.EXIT, 0); private final Command categoryCommand = new Command("Category", Command.SCREEN, 0); private final String category; private final CategorySelectionListener categoryListener; private final LinkSelectionListener linkListener; private final Hashtable imageCache = new Hashtable(); private HttpOperation operation; private int loadingItemIndex = -1; private Vector linkListItems; private static boolean firstShow = true; /** * Create a LinksView. * * @param category Category to show links for * @param categoryListener Listener to signal of category change * @param linkListener Listener to signal of link being selected */ public LinksView(String category, CategorySelectionListener categoryListener, LinkSelectionListener linkListener) { super("RLinks", new Item[] {}); this.category = category; this.categoryListener = categoryListener; this.linkListener = linkListener; if (firstShow) { append(new Spacer(1, 1)); } setupCommands(); } protected final void setupCommands() { // Only include 'Exit' on the front page, otherwise use 'Back' addCommand(category == null ? exitCommand : backCommand); addCommand(categoryCommand); addCommand(refreshCommand); addCommand(aboutCommand); setupLoginCommands(); } /** * Show the view. */ public void show() { if (firstShow) { if (!requireNetworkAccess()) { return; } deleteAll(); firstShow = false; } setupCommands(); setTitle(category == null ? "RLinks - Popular": "/r/" + category); addLoginStatusItem(); loadLinks(); } /** * Refresh the view. */ private void refresh() { if (operation != null && !operation.isFinished()) { return; } operation = null; deleteAll(); show(); } /** * Load links to be shown in the view. */ private void loadLinks() { // Do not reload if already loaded, or if in process if (HttpOperation.reloadNeeded(operation)) { // Add 'Loading' item loadingItemIndex = append(new LoaderItem()); operation = new LinksLoadOperation(category, this); operation.start(); } } /** * Handle displaying incoming links. * * @param links Vector of LinkThing items received */ public synchronized void linksReceived(final Vector links) { if (links == null) { Main.executeInUIThread(new Runnable() { public void run() { delete(loadingItemIndex); showNetworkError(); } }); return; } linkListItems = createLinkItems(links); Main.executeInUIThread(new Runnable() { public void run() { for (int i = 0, len = links.size(); i < len; i++) { append((LinkItem) linkListItems.elementAt(i)); } delete(loadingItemIndex); } }); } /** * Create link items from a Vector of links. * * @param links LinkThing items populated from server data * @return Vector of LinkItem objects */ private Vector createLinkItems(final Vector links) { final boolean showSubreddit = category == null; LinkThing link; LinkItem linkItem; Vector items = new Vector(); for (int i = 0, len = links.size(); i < len; i++) { link = (LinkThing) links.elementAt(i); linkItem = new LinkItem(link, getWidth(), showSubreddit, linkListener, imageCache, this); items.addElement(linkItem); } return items; } public void commandAction(Command command, Displayable displayable) { if (command == backCommand) { // Going back equals going back to the first view (popular page) abortPendingOperations(); categoryListener.categorySelected(null); } else if (command == exitCommand) { Main.getInstance().onExitCommanded(); } else if (command == categoryCommand) { showCategoryView(); } else if (command == refreshCommand) { refresh(); } else if (command == aboutCommand) { showAboutView(); } else if (command == loginCommand) { showLoginView(); } else if (command == logoutCommand) { session.setLoggedOut(); setupCommands(); } } /** * Abort any pending loading operation. */ private void abortPendingOperations() { if (operation != null && !operation.isFinished()) { operation.abort(); delete(loadingItemIndex); } } /** * Show the category selection view. */ private void showCategoryView() { final CategorySelectView csv = new CategorySelectView(category, categoryListener, defaultBackListener); setDisplay(csv); csv.show(); } private boolean requireNetworkAccess() { if (HttpClient.isAllowed()) { return true; } setTitle("Network required"); append( new TextItem("Please restart and allow network access.", getWidth(), VisualStyles.LARGE_BOLD_FONT, this) ); removeCommand(categoryCommand); addCommand(exitCommand); return false; } }