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
.WindowEvent
;
11 import java
.io
.IOException
;
12 import java
.util
.ArrayList
;
13 import java
.util
.List
;
15 import javax
.swing
.JFileChooser
;
16 import javax
.swing
.JFrame
;
17 import javax
.swing
.JMenu
;
18 import javax
.swing
.JMenuBar
;
19 import javax
.swing
.JMenuItem
;
20 import javax
.swing
.JOptionPane
;
21 import javax
.swing
.JPanel
;
22 import javax
.swing
.JScrollPane
;
23 import javax
.swing
.SwingUtilities
;
25 import be
.nikiroo
.fanfix
.Instance
;
26 import be
.nikiroo
.fanfix
.bundles
.UiConfig
;
27 import be
.nikiroo
.fanfix
.data
.MetaData
;
28 import be
.nikiroo
.fanfix
.reader
.LocalReaderBook
.BookActionListener
;
29 import be
.nikiroo
.utils
.Progress
;
30 import be
.nikiroo
.utils
.ui
.ProgressBar
;
31 import be
.nikiroo
.utils
.ui
.WrapLayout
;
33 class LocalReaderFrame
extends JFrame
{
34 private static final long serialVersionUID
= 1L;
35 private LocalReader reader
;
36 private List
<MetaData
> stories
;
37 private List
<LocalReaderBook
> books
;
38 private JPanel bookPane
;
41 private ProgressBar pgBar
;
43 private LocalReaderBook selectedBook
;
45 public LocalReaderFrame(LocalReader reader
, String type
) {
46 super("Fanfix Library");
50 setDefaultCloseOperation(JFrame
.EXIT_ON_CLOSE
);
52 setLayout(new BorderLayout());
54 books
= new ArrayList
<LocalReaderBook
>();
55 bookPane
= new JPanel(new WrapLayout(WrapLayout
.LEADING
, 5, 5));
57 color
= Instance
.getUiConfig().getColor(UiConfig
.BACKGROUND_COLOR
);
61 bookPane
.setBackground(color
);
64 JScrollPane scroll
= new JScrollPane(bookPane
);
65 scroll
.getVerticalScrollBar().setUnitIncrement(16);
66 add(scroll
, BorderLayout
.CENTER
);
68 pgBar
= new ProgressBar();
69 add(pgBar
, BorderLayout
.SOUTH
);
72 setJMenuBar(createMenu());
77 private void refreshBooks(String type
) {
79 stories
= Instance
.getLibrary().getList(type
);
82 for (MetaData meta
: stories
) {
83 LocalReaderBook book
= new LocalReaderBook(meta
,
84 reader
.isCached(meta
.getLuid()));
86 book
.setBackground(color
);
90 final String luid
= meta
.getLuid();
91 book
.addActionListener(new BookActionListener() {
92 public void select(LocalReaderBook book
) {
94 for (LocalReaderBook abook
: books
) {
95 abook
.setSelected(abook
== book
);
99 public void action(final LocalReaderBook book
) {
100 final Progress pg
= new Progress();
101 outOfUi(pg
, new Runnable() {
104 File target
= LocalReaderFrame
.this.reader
105 .getTarget(luid
, pg
);
106 book
.setCached(true);
107 // TODO: allow custom programs, with
108 // Desktop/xdg-open fallback
110 Desktop
.getDesktop().browse(target
.toURI());
111 } catch (UnsupportedOperationException e
) {
112 String browsers
[] = new String
[] {
113 "xdg-open", "epiphany",
114 "konqueror", "firefox", "chrome",
115 "google-chrome", "mozilla" };
117 Runtime runtime
= Runtime
.getRuntime();
118 for (String browser
: browsers
) {
120 runtime
.exec(new String
[] {
122 target
.getAbsolutePath() });
125 } catch (IOException ioe
) {
126 // continue, try next browser
130 if (runtime
!= null) {
131 throw new IOException(
132 "Cannot find a working GUI browser...");
135 } catch (IOException e
) {
150 private JMenuBar
createMenu() {
151 bar
= new JMenuBar();
153 JMenu file
= new JMenu("File");
154 file
.setMnemonic(KeyEvent
.VK_F
);
156 JMenuItem imprt
= new JMenuItem("Import URL", KeyEvent
.VK_U
);
157 imprt
.addActionListener(new ActionListener() {
158 public void actionPerformed(ActionEvent e
) {
162 JMenuItem imprtF
= new JMenuItem("Import File", KeyEvent
.VK_F
);
163 imprtF
.addActionListener(new ActionListener() {
164 public void actionPerformed(ActionEvent e
) {
168 JMenuItem exit
= new JMenuItem("Exit", KeyEvent
.VK_X
);
169 exit
.addActionListener(new ActionListener() {
170 public void actionPerformed(ActionEvent e
) {
171 LocalReaderFrame
.this.dispatchEvent(new WindowEvent(
172 LocalReaderFrame
.this, WindowEvent
.WINDOW_CLOSING
));
183 JMenu edit
= new JMenu("Edit");
184 edit
.setMnemonic(KeyEvent
.VK_E
);
186 final String notYet
= "[TODO] Show not ready yet, but you can do it on command line, see: fanfix --help";
188 JMenuItem export
= new JMenuItem("Export", KeyEvent
.VK_E
);
189 export
.addActionListener(new ActionListener() {
190 public void actionPerformed(ActionEvent e
) {
191 JOptionPane
.showMessageDialog(LocalReaderFrame
.this, notYet
);
195 JMenuItem refresh
= new JMenuItem("Refresh", KeyEvent
.VK_R
);
196 refresh
.addActionListener(new ActionListener() {
197 public void actionPerformed(ActionEvent e
) {
198 if (selectedBook
!= null) {
199 outOfUi(null, new Runnable() {
201 reader
.refresh(selectedBook
.getLuid());
202 selectedBook
.setCached(false);
203 SwingUtilities
.invokeLater(new Runnable() {
205 selectedBook
.repaint();
214 JMenuItem delete
= new JMenuItem("Delete", KeyEvent
.VK_D
);
215 delete
.addActionListener(new ActionListener() {
216 public void actionPerformed(ActionEvent e
) {
217 if (selectedBook
!= null) {
218 outOfUi(null, new Runnable() {
220 reader
.delete(selectedBook
.getLuid());
222 SwingUtilities
.invokeLater(new Runnable() {
239 JMenu view
= new JMenu("View");
240 view
.setMnemonic(KeyEvent
.VK_V
);
242 List
<String
> tt
= Instance
.getLibrary().getTypes();
244 for (final String type
: tt
) {
246 JMenuItem item
= new JMenuItem(type
== null ?
"All books" : type
);
247 item
.addActionListener(new ActionListener() {
248 public void actionPerformed(ActionEvent e
) {
264 private void outOfUi(final Progress pg
, final Runnable run
) {
265 pgBar
.setProgress(pg
);
267 SwingUtilities
.invokeLater(new Runnable() {
269 setAllEnabled(false);
270 pgBar
.addActioListener(new ActionListener() {
271 public void actionPerformed(ActionEvent e
) {
272 pgBar
.setProgress(null);
279 new Thread(new Runnable() {
283 SwingUtilities
.invokeLater(new Runnable() {
288 } else if (!pg
.isDone()) {
289 pg
.setProgress(pg
.getMax());
295 private void imprt(boolean askUrl
) {
296 JFileChooser fc
= new JFileChooser();
300 url
= JOptionPane
.showInputDialog(LocalReaderFrame
.this,
301 "url of the story to import?", "Importing from URL",
302 JOptionPane
.QUESTION_MESSAGE
);
303 } else if (fc
.showOpenDialog(this) != JFileChooser
.CANCEL_OPTION
) {
304 url
= fc
.getSelectedFile().getAbsolutePath();
309 if (url
!= null && !url
.isEmpty()) {
310 final Progress pg
= new Progress("Importing " + url
);
311 outOfUi(pg
, new Runnable() {
315 Instance
.getLibrary()
316 .imprt(BasicReader
.getUrl(url
), pg
);
317 } catch (IOException e
) {
321 final Exception e
= ex
;
323 final boolean ok
= (e
== null);
324 SwingUtilities
.invokeLater(new Runnable() {
327 JOptionPane
.showMessageDialog(
328 LocalReaderFrame
.this,
329 "Cannot import: " + url
,
331 JOptionPane
.ERROR_MESSAGE
);
344 public void setAllEnabled(boolean enabled
) {
345 for (LocalReaderBook book
: books
) {
346 book
.setEnabled(enabled
);
351 bar
.setEnabled(enabled
);
352 bookPane
.setEnabled(enabled
);