1 package be
.nikiroo
.fanfix
.reader
;
3 import java
.awt
.BorderLayout
;
5 import java
.awt
.Desktop
;
6 import java
.awt
.event
.ActionEvent
;
7 import java
.awt
.event
.ActionListener
;
8 import java
.awt
.event
.KeyEvent
;
9 import java
.awt
.event
.MouseEvent
;
10 import java
.awt
.event
.MouseListener
;
11 import java
.awt
.event
.WindowEvent
;
13 import java
.io
.IOException
;
14 import java
.util
.ArrayList
;
15 import java
.util
.List
;
17 import javax
.swing
.JFileChooser
;
18 import javax
.swing
.JFrame
;
19 import javax
.swing
.JMenu
;
20 import javax
.swing
.JMenuBar
;
21 import javax
.swing
.JMenuItem
;
22 import javax
.swing
.JOptionPane
;
23 import javax
.swing
.JPanel
;
24 import javax
.swing
.JPopupMenu
;
25 import javax
.swing
.JScrollPane
;
26 import javax
.swing
.SwingUtilities
;
28 import be
.nikiroo
.fanfix
.Instance
;
29 import be
.nikiroo
.fanfix
.bundles
.UiConfig
;
30 import be
.nikiroo
.fanfix
.data
.MetaData
;
31 import be
.nikiroo
.fanfix
.reader
.LocalReaderBook
.BookActionListener
;
32 import be
.nikiroo
.utils
.Progress
;
33 import be
.nikiroo
.utils
.ui
.ProgressBar
;
34 import be
.nikiroo
.utils
.ui
.WrapLayout
;
36 class LocalReaderFrame
extends JFrame
{
37 private static final long serialVersionUID
= 1L;
38 private LocalReader reader
;
39 private List
<MetaData
> stories
;
40 private List
<LocalReaderBook
> books
;
41 private JPanel bookPane
;
44 private ProgressBar pgBar
;
46 private LocalReaderBook selectedBook
;
48 public LocalReaderFrame(LocalReader reader
, String type
) {
49 super("Fanfix Library");
53 setDefaultCloseOperation(JFrame
.EXIT_ON_CLOSE
);
55 setLayout(new BorderLayout());
57 books
= new ArrayList
<LocalReaderBook
>();
58 bookPane
= new JPanel(new WrapLayout(WrapLayout
.LEADING
, 5, 5));
60 color
= Instance
.getUiConfig().getColor(UiConfig
.BACKGROUND_COLOR
);
64 bookPane
.setBackground(color
);
67 JScrollPane scroll
= new JScrollPane(bookPane
);
68 scroll
.getVerticalScrollBar().setUnitIncrement(16);
69 add(scroll
, BorderLayout
.CENTER
);
71 pgBar
= new ProgressBar();
72 add(pgBar
, BorderLayout
.SOUTH
);
75 setJMenuBar(createMenu());
80 private void refreshBooks(String type
) {
82 stories
= Instance
.getLibrary().getList(type
);
85 for (MetaData meta
: stories
) {
86 LocalReaderBook book
= new LocalReaderBook(meta
,
87 reader
.isCached(meta
.getLuid()));
89 book
.setBackground(color
);
92 book
.addMouseListener(new MouseListener() {
93 public void mouseReleased(MouseEvent e
) {
94 if (e
.isPopupTrigger())
98 public void mousePressed(MouseEvent e
) {
99 if (e
.isPopupTrigger())
103 public void mouseExited(MouseEvent e
) {
106 public void mouseEntered(MouseEvent e
) {
109 public void mouseClicked(MouseEvent e
) {
112 private void pop(MouseEvent e
) {
113 JPopupMenu popup
= new JPopupMenu();
114 popup
.add(createMenuItemExport());
115 popup
.add(createMenuItemRefresh());
116 popup
.addSeparator();
117 popup
.add(createMenuItemDelete());
118 // popup.show(e.getComponent(), e.getX(), e.getY());
123 book
.addActionListener(new BookActionListener() {
124 public void select(LocalReaderBook book
) {
126 for (LocalReaderBook abook
: books
) {
127 abook
.setSelected(abook
== book
);
131 public void popupRequested(LocalReaderBook book
, MouseEvent e
) {
132 JPopupMenu popup
= new JPopupMenu();
133 popup
.add(createMenuItemOpenBook());
134 popup
.addSeparator();
135 popup
.add(createMenuItemExport());
136 popup
.add(createMenuItemRefresh());
137 popup
.addSeparator();
138 popup
.add(createMenuItemDelete());
139 popup
.show(e
.getComponent(), e
.getX(), e
.getY());
142 public void action(final LocalReaderBook book
) {
154 private JMenuBar
createMenu() {
155 bar
= new JMenuBar();
157 JMenu file
= new JMenu("File");
158 file
.setMnemonic(KeyEvent
.VK_F
);
160 JMenuItem imprt
= new JMenuItem("Import URL", KeyEvent
.VK_U
);
161 imprt
.addActionListener(new ActionListener() {
162 public void actionPerformed(ActionEvent e
) {
166 JMenuItem imprtF
= new JMenuItem("Import File", KeyEvent
.VK_F
);
167 imprtF
.addActionListener(new ActionListener() {
168 public void actionPerformed(ActionEvent e
) {
172 JMenuItem exit
= new JMenuItem("Exit", KeyEvent
.VK_X
);
173 exit
.addActionListener(new ActionListener() {
174 public void actionPerformed(ActionEvent e
) {
175 LocalReaderFrame
.this.dispatchEvent(new WindowEvent(
176 LocalReaderFrame
.this, WindowEvent
.WINDOW_CLOSING
));
180 file
.add(createMenuItemOpenBook());
181 file
.add(createMenuItemExport());
190 JMenu edit
= new JMenu("Edit");
191 edit
.setMnemonic(KeyEvent
.VK_E
);
193 edit
.add(createMenuItemRefresh());
195 edit
.add(createMenuItemDelete());
199 JMenu view
= new JMenu("View");
200 view
.setMnemonic(KeyEvent
.VK_V
);
202 List
<String
> tt
= Instance
.getLibrary().getTypes();
204 for (final String type
: tt
) {
206 JMenuItem item
= new JMenuItem(type
== null ?
"All books" : type
);
207 item
.addActionListener(new ActionListener() {
208 public void actionPerformed(ActionEvent e
) {
224 private JMenuItem
createMenuItemExport() {
226 final String notYet
= "[TODO] not ready yet, but you can do it on command line, see: fanfix --help";
228 JMenuItem export
= new JMenuItem("Save as...", KeyEvent
.VK_E
);
229 export
.addActionListener(new ActionListener() {
230 public void actionPerformed(ActionEvent e
) {
231 JOptionPane
.showMessageDialog(LocalReaderFrame
.this, notYet
);
238 private JMenuItem
createMenuItemRefresh() {
239 JMenuItem refresh
= new JMenuItem("Refresh", KeyEvent
.VK_R
);
240 refresh
.addActionListener(new ActionListener() {
241 public void actionPerformed(ActionEvent e
) {
242 if (selectedBook
!= null) {
243 outOfUi(null, new Runnable() {
245 reader
.refresh(selectedBook
.getLuid());
246 selectedBook
.setCached(false);
247 SwingUtilities
.invokeLater(new Runnable() {
249 selectedBook
.repaint();
261 private JMenuItem
createMenuItemDelete() {
262 JMenuItem delete
= new JMenuItem("Delete", KeyEvent
.VK_D
);
263 delete
.addActionListener(new ActionListener() {
264 public void actionPerformed(ActionEvent e
) {
265 if (selectedBook
!= null) {
266 outOfUi(null, new Runnable() {
268 reader
.delete(selectedBook
.getLuid());
270 SwingUtilities
.invokeLater(new Runnable() {
284 private JMenuItem
createMenuItemOpenBook() {
285 JMenuItem open
= new JMenuItem("Open", KeyEvent
.VK_O
);
286 open
.addActionListener(new ActionListener() {
287 public void actionPerformed(ActionEvent e
) {
288 if (selectedBook
!= null) {
289 openBook(selectedBook
);
297 private void openBook(final LocalReaderBook book
) {
298 final Progress pg
= new Progress();
299 outOfUi(pg
, new Runnable() {
302 File target
= LocalReaderFrame
.this.reader
.getTarget(
304 book
.setCached(true);
305 // TODO: allow custom programs, with
306 // Desktop/xdg-open fallback
308 Desktop
.getDesktop().browse(target
.toURI());
309 } catch (UnsupportedOperationException e
) {
310 String browsers
[] = new String
[] { "xdg-open",
311 "epiphany", "konqueror", "firefox", "chrome",
312 "google-chrome", "mozilla" };
314 Runtime runtime
= Runtime
.getRuntime();
315 for (String browser
: browsers
) {
317 runtime
.exec(new String
[] { browser
,
318 target
.getAbsolutePath() });
321 } catch (IOException ioe
) {
322 // continue, try next browser
326 if (runtime
!= null) {
327 throw new IOException(
328 "Cannot find a working GUI browser...");
331 } catch (IOException e
) {
338 private void outOfUi(final Progress pg
, final Runnable run
) {
339 pgBar
.setProgress(pg
);
341 SwingUtilities
.invokeLater(new Runnable() {
343 setAllEnabled(false);
344 pgBar
.addActioListener(new ActionListener() {
345 public void actionPerformed(ActionEvent e
) {
346 pgBar
.setProgress(null);
353 new Thread(new Runnable() {
357 SwingUtilities
.invokeLater(new Runnable() {
362 } else if (!pg
.isDone()) {
363 pg
.setProgress(pg
.getMax());
369 private void imprt(boolean askUrl
) {
370 JFileChooser fc
= new JFileChooser();
374 url
= JOptionPane
.showInputDialog(LocalReaderFrame
.this,
375 "url of the story to import?", "Importing from URL",
376 JOptionPane
.QUESTION_MESSAGE
);
377 } else if (fc
.showOpenDialog(this) != JFileChooser
.CANCEL_OPTION
) {
378 url
= fc
.getSelectedFile().getAbsolutePath();
383 if (url
!= null && !url
.isEmpty()) {
384 final Progress pg
= new Progress("Importing " + url
);
385 outOfUi(pg
, new Runnable() {
389 Instance
.getLibrary()
390 .imprt(BasicReader
.getUrl(url
), pg
);
391 } catch (IOException e
) {
395 final Exception e
= ex
;
397 final boolean ok
= (e
== null);
398 SwingUtilities
.invokeLater(new Runnable() {
401 JOptionPane
.showMessageDialog(
402 LocalReaderFrame
.this,
403 "Cannot import: " + url
,
405 JOptionPane
.ERROR_MESSAGE
);
418 public void setAllEnabled(boolean enabled
) {
419 for (LocalReaderBook book
: books
) {
420 book
.setEnabled(enabled
);
425 bar
.setEnabled(enabled
);
426 bookPane
.setEnabled(enabled
);