import java.awt.BorderLayout;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Queue;
import java.util.concurrent.ExecutionException;
import javax.swing.DefaultListModel;
import javax.swing.JPopupMenu;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix_swing.gui.book.BookInfo;
import be.nikiroo.fanfix_swing.gui.book.BookLine;
import be.nikiroo.fanfix_swing.gui.book.BookPopup;
+import be.nikiroo.fanfix_swing.gui.utils.DelayWorker;
import be.nikiroo.fanfix_swing.gui.utils.ListenerPanel;
import be.nikiroo.fanfix_swing.gui.utils.UiHelper;
private JList<BookInfo> list;
private int hoveredIndex = -1;
private ListModel data = new ListModel();
+ private DelayWorker bookCoverUpdater;
private SearchBar searchBar;
- private Queue<BookBlock> updateBookQueue = new LinkedList<BookBlock>();
- private Object updateBookQueueLock = new Object();
-
public BooksPanel(boolean listMode) {
setLayout(new BorderLayout());
}
});
+ bookCoverUpdater = new DelayWorker(20);
+ bookCoverUpdater.start();
add(UiHelper.scroll(initList(listMode)), BorderLayout.CENTER);
-
- Thread bookBlocksUpdater = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- BasicLibrary lib = Instance.getInstance().getLibrary();
- while (true) {
- final BookBlock book;
- synchronized (updateBookQueueLock) {
- if (!updateBookQueue.isEmpty()) {
- book = updateBookQueue.remove();
- } else {
- book = null;
- break;
- }
- }
-
- try {
- final Image coverImage = BookBlock.generateCoverImage(lib, book.getInfo());
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- try {
- book.setCoverImage(coverImage);
- data.fireElementChanged(book.getInfo());
- } catch (Exception e) {
- }
- }
- });
- } catch (Exception e) {
- }
- }
-
- try {
- Thread.sleep(10);
- } catch (InterruptedException e) {
- }
- }
- }
- });
- bookBlocksUpdater.setName("BookBlocks visual updater");
- bookBlocksUpdater.setDaemon(true);
- bookBlocksUpdater.start();
}
// null or empty -> all sources
// sources hierarchy supported ("source/" will includes all "source" and
// "source/*")
- public void load(final List<String> sources, final List<String> authors, final List<String> tags) {
+ public void load(final List<String> sources, final List<String> authors,
+ final List<String> tags) {
new SwingWorker<List<BookInfo>, Void>() {
@Override
protected List<BookInfo> doInBackground() throws Exception {
List<BookInfo> bookInfos = new ArrayList<BookInfo>();
BasicLibrary lib = Instance.getInstance().getLibrary();
- for (MetaData meta : lib.getList().filter(sources, authors, tags)) {
+ for (MetaData meta : lib.getList().filter(sources, authors,
+ tags)) {
bookInfos.add(BookInfo.fromMeta(lib, meta));
}
public void load(List<BookInfo> bookInfos) {
this.bookInfos.clear();
this.bookInfos.addAll(bookInfos);
- synchronized (updateBookQueueLock) {
- updateBookQueue.clear();
- }
+ bookCoverUpdater.clear();
filter(searchBar.getText());
}
data.clear();
for (BookInfo bookInfo : bookInfos) {
if (bookInfo.getMainInfo() == null || filter.isEmpty()
- || bookInfo.getMainInfo().toLowerCase().contains(filter.toLowerCase())) {
+ || bookInfo.getMainInfo().toLowerCase()
+ .contains(filter.toLowerCase())) {
data.addElement(bookInfo);
}
}
/**
* The secondary value content: word count or author.
*
- * @param seeWordCount TRUE to see word counts, FALSE to see authors
+ * @param seeWordCount
+ * TRUE to see word counts, FALSE to see authors
*/
public void setSeeWordCount(boolean seeWordCount) {
if (this.seeWordCount != seeWordCount) {
private JList<BookInfo> initList(boolean listMode) {
final JList<BookInfo> list = new JList<BookInfo>(data);
- final JPopupMenu popup = new BookPopup(Instance.getInstance().getLibrary(), new BookPopup.Informer() {
- @Override
- public void setCached(BookInfo book, boolean cached) {
- book.setCached(cached);
- fireElementChanged(book);
- }
+ final JPopupMenu popup = new BookPopup(
+ Instance.getInstance().getLibrary(), new BookPopup.Informer() {
+ @Override
+ public void setCached(BookInfo book, boolean cached) {
+ book.setCached(cached);
+ fireElementChanged(book);
+ }
- public void fireElementChanged(BookInfo book) {
- data.fireElementChanged(book);
- }
+ public void fireElementChanged(BookInfo book) {
+ data.fireElementChanged(book);
+ }
- @Override
- public List<BookInfo> getSelected() {
- List<BookInfo> selected = new ArrayList<BookInfo>();
- for (int index : list.getSelectedIndices()) {
- selected.add(data.get(index));
- }
+ @Override
+ public List<BookInfo> getSelected() {
+ List<BookInfo> selected = new ArrayList<BookInfo>();
+ for (int index : list.getSelectedIndices()) {
+ selected.add(data.get(index));
+ }
- return selected;
- }
+ return selected;
+ }
- @Override
- public BookInfo getUniqueSelected() {
- List<BookInfo> selected = getSelected();
- if (selected.size() == 1) {
- return selected.get(0);
- }
- return null;
- }
+ @Override
+ public BookInfo getUniqueSelected() {
+ List<BookInfo> selected = getSelected();
+ if (selected.size() == 1) {
+ return selected.get(0);
+ }
+ return null;
+ }
- @Override
- public void invalidateCache() {
- // TODO: also reset the popup menu for sources/author
- fireActionPerformed(INVALIDATE_CACHE);
- }
- });
+ @Override
+ public void invalidateCache() {
+ // TODO: also reset the popup menu for sources/author
+ fireActionPerformed(INVALIDATE_CACHE);
+ }
+ });
list.addMouseMotionListener(new MouseAdapter() {
@Override
final BookInfo book = data.get(index);
BasicLibrary lib = Instance.getInstance().getLibrary();
- Actions.openExternal(lib, book.getMeta(), BooksPanel.this, new Runnable() {
- @Override
- public void run() {
- book.setCached(true);
- data.fireElementChanged(book);
- }
- });
+ Actions.openExternal(lib, book.getMeta(), BooksPanel.this,
+ new Runnable() {
+ @Override
+ public void run() {
+ book.setCached(true);
+ data.fireElementChanged(book);
+ }
+ });
}
}
private void check(MouseEvent e) {
if (e.isPopupTrigger()) {
if (list.getSelectedIndices().length <= 1) {
- list.setSelectedIndex(list.locationToIndex(e.getPoint()));
+ list.setSelectedIndex(
+ list.locationToIndex(e.getPoint()));
}
popup.show(list, e.getX(), e.getY());
private ListCellRenderer<BookInfo> generateRenderer() {
return new ListCellRenderer<BookInfo>() {
@Override
- public Component getListCellRendererComponent(JList<? extends BookInfo> list, BookInfo value, int index,
+ public Component getListCellRendererComponent(
+ JList<? extends BookInfo> list, BookInfo value, int index,
boolean isSelected, boolean cellHasFocus) {
BookLine book = books.get(value);
if (book == null) {
book = new BookLine(value, seeWordCount);
} else {
book = new BookBlock(value, seeWordCount);
- synchronized (updateBookQueueLock) {
- updateBookQueue.add((BookBlock) book);
- }
+ startUpdateBookCover((BookBlock) book);
}
books.put(value, book);
}
};
}
+ private void startUpdateBookCover(final BookBlock book) {
+ bookCoverUpdater.delay(book.getInfo().getId(),
+ new SwingWorker<Image, Void>() {
+ @Override
+ protected Image doInBackground() throws Exception {
+ BasicLibrary lib = Instance.getInstance().getLibrary();
+ return BookBlock.generateCoverImage(lib,
+ book.getInfo());
+ }
+
+ protected void done() {
+ try {
+ book.setCoverImage(get());
+ data.fireElementChanged(book.getInfo());
+ } catch (Exception e) {
+ // TODO ? probably just log
+ }
+ }
+ });
+ }
+
public boolean isListMode() {
return listMode;
}
public void setListMode(boolean listMode) {
this.listMode = listMode;
books.clear();
- list.setLayoutOrientation(listMode ? JList.VERTICAL : JList.HORIZONTAL_WRAP);
+ list.setLayoutOrientation(
+ listMode ? JList.VERTICAL : JList.HORIZONTAL_WRAP);
+ StringBuilder longString = new StringBuilder();
+ for (int i = 0; i < 20; i++) {
+ longString.append(
+ "Some long string, which is 50 chars long itself...");
+ }
if (listMode) {
- synchronized (updateBookQueueLock) {
- updateBookQueue.clear();
- }
+ bookCoverUpdater.clear();
+ Dimension sz = new BookLine(
+ BookInfo.fromSource(null, longString.toString()), true)
+ .getPreferredSize();
+ list.setFixedCellHeight((int) sz.getHeight());
+ list.setFixedCellWidth(list.getWidth());
+ } else {
+ Dimension sz = new BookBlock(
+ BookInfo.fromSource(null, longString.toString()), true)
+ .getPreferredSize();
+ list.setFixedCellHeight((int) sz.getHeight());
+ list.setFixedCellWidth((int) sz.getWidth());
}
}
}