Java tutorial
/* * Copyright 2014 Roque Pinel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cc.pinel.mangue.ui; import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; import java.util.NoSuchElementException; import org.apache.commons.io.IOUtils; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.kwt.ui.KWTSelectableLabel; import cc.pinel.mangue.Main; import cc.pinel.mangue.handler.ConnectivityHandler; import cc.pinel.mangue.handler.StorageHandler; import cc.pinel.mangue.model.Chapter; import cc.pinel.mangue.model.Manga; import cc.pinel.mangue.storage.GeneralStorage; import cc.pinel.mangue.storage.StateStorage; import cc.pinel.mangue.util.StringUtils; import com.amazon.kindle.kindlet.event.KindleKeyCodes; import com.amazon.kindle.kindlet.ui.KBoxLayout; import com.amazon.kindle.kindlet.ui.KLabel; import com.amazon.kindle.kindlet.ui.KPages; import com.amazon.kindle.kindlet.ui.KPanel; import com.amazon.kindle.kindlet.ui.pages.LocationIterator; import com.amazon.kindle.kindlet.ui.pages.PageProviders; /** * The panel to displays a manga chapters. * * @author Roque Pinel * */ public class ChaptersPanel extends KPanel { private static final long serialVersionUID = 7836204925749827794L; private final Main main; private final KPages chaptersPages; private final ChapterLabelActionListener chapterListener; private Manga manga = null; /** * @param main the main controller * @param manga the manga */ public ChaptersPanel(Main main, Manga manga) { super(new GridBagLayout()); this.main = main; chaptersPages = new KPages(PageProviders.createKBoxLayoutProvider(KBoxLayout.Y_AXIS)); chaptersPages.setFocusable(true); chaptersPages.setEnabled(true); chaptersPages.setPageKeyPolicy(KPages.PAGE_KEYS_LOCAL); chapterListener = new ChapterLabelActionListener(); GridBagConstraints gc = new GridBagConstraints(); gc.gridx = 0; gc.gridy = 0; gc.insets = new Insets(20, 20, 20, 20); gc.anchor = GridBagConstraints.NORTH; gc.weightx = 1.0; gc.weighty = 1.0; gc.fill = GridBagConstraints.BOTH; add(chaptersPages, gc); chaptersPages.first(); loadChapters(manga); } /** * {@inheritDoc} */ public void requestFocus() { try { ((Component) chaptersPages.getPageModel().getElementAt(0)).requestFocus(); } catch (NoSuchElementException e) { chaptersPages.requestFocus(); } } /** * Loads all chapters from the given manga. * * @param manga the manga */ public void loadChapters(final Manga manga) { if (this.manga != null && this.manga.getId().equals(manga.getId())) return; this.manga = manga; rememberManga(); new StorageHandler(main.getContext(), "Loading mangas...") { /** * {@inheritDoc} */ public void handleRun() throws Exception { final String lastChapterNumber = new StateStorage(main.getContext()).getChapter(manga.getId()); final ConnectivityHandler handler = new ConnectivityHandler(main.getContext(), "Loading chapters...") { /** * {@inheritDoc} */ public void handleConnected() throws Exception { JSONParser parser = new JSONParser(); JSONArray chapters = (JSONArray) parser .parse(IOUtils.toString(new URL(manga.getAllChaptersLink()).openStream())); chaptersPages.removeAllItems(); for (int i = chapters.size() - 1; i >= 0; i--) { JSONObject chapter = (JSONObject) chapters.get(i); String chapterNumber = chapter.get("chapter").toString(); String chapterName = StringUtils.unescapeHtml(chapter.get("chapter_name").toString()); String chapterTitle = chapterNumber + (chapterName != null && chapterName.length() != 0 ? ": " + chapterName : ""); final KWTSelectableLabel chapterLabel = new KWTSelectableLabel(chapterTitle); chapterLabel.setName(chapterNumber); chapterLabel.setFocusable(true); chapterLabel.setEnabled(true); chapterLabel.addActionListener(chapterListener); // last read chapter if (lastChapterNumber != null && chapterNumber.equals(lastChapterNumber)) highlightLabel(chapterLabel); chaptersPages.addItem(chapterLabel); } EventQueue.invokeAndWait(new Runnable() { public void run() { chaptersPages.first(); requestFocus(); repaint(); } }); } }; main.getContext().getConnectivity().submitSingleAttemptConnectivityRequest(handler, true); } }.start(); } /** * Updates the last chapter highlight when * the user selects a new chapter to read. * * @param lastChapterNumber the last chapter number */ private void updateLastChapter(String lastChapterNumber) { for (LocationIterator iter = chaptersPages.getPageModel().locationIterator(-1, true); iter.hasNext();) { final KWTSelectableLabel chapterLabel = (KWTSelectableLabel) iter.next(); if (lastChapterNumber != null && chapterLabel.getName().equals(lastChapterNumber)) highlightLabel(chapterLabel); else unhighlightLabel(chapterLabel); } } /** * Handles the panel actions. * * Basically, when a chapter is selected. * * @author Roque Pinel * */ private class ChapterLabelActionListener implements ActionListener { /** * {@inheritDoc} */ public void actionPerformed(ActionEvent event) { if (Integer.parseInt(event.getActionCommand()) == KindleKeyCodes.VK_FIVE_WAY_SELECT) { String chapterNumber = ((KWTSelectableLabel) event.getSource()).getName(); updateLastChapter(chapterNumber); rememberChapter(chapterNumber); Chapter chapter = new Chapter(chapterNumber, manga.getChapterLink(chapterNumber)); ViewPanel viewPanel = main.getViewPanel(); if (viewPanel == null) main.setViewPanel(new ViewPanel(main, chapter)); else viewPanel.loadImage(chapter); main.paintViewPanel(); } } /** * Remembers the chapter to be able to * restore it in the future. * * @param chapterNumber the chapter number */ private void rememberChapter(final String chapterNumber) { new StorageHandler(main.getContext(), "Loading mangas...") { /** * {@inheritDoc} */ public void handleRun() throws Exception { new StateStorage(main.getContext()).setChapter(manga.getId(), chapterNumber); } }.start(); } } /** * Remembers the current manga to be able to * restore it in the future. */ private void rememberManga() { new GeneralStorage(main.getContext()).setCurrentMangaId(manga.getId()); } /** * Highlights the label. * * @param label the chapter label */ private void highlightLabel(KLabel label) { Font font = label.getFont(); label.setFont(new Font(font.getFamily(), Font.BOLD, font.getSize())); label.setForeground(new Color(255, 84, 84)); } /** * Unhighlights the label. * * @param label the chapter label */ private void unhighlightLabel(KLabel label) { Font font = label.getFont(); label.setFont(new Font(font.getFamily(), Font.PLAIN, font.getSize())); label.setForeground(Color.BLACK); } }