CSS change, some fallbacks programs for Desktop
[fanfix.git] / src / be / nikiroo / fanfix / reader / LocalReaderFrame.java
CommitLineData
a6395bef
NR
1package be.nikiroo.fanfix.reader;
2
d3c84ac3 3import java.awt.BorderLayout;
b4dc6ab5 4import java.awt.Color;
a6395bef 5import java.awt.Desktop;
a6395bef
NR
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
333f0e7b
NR
8import java.awt.event.KeyEvent;
9import java.awt.event.WindowEvent;
10import java.io.File;
a6395bef 11import java.io.IOException;
333f0e7b 12import java.util.ArrayList;
a6395bef
NR
13import java.util.List;
14
a6395bef 15import javax.swing.JFrame;
333f0e7b
NR
16import javax.swing.JMenu;
17import javax.swing.JMenuBar;
18import javax.swing.JMenuItem;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
d3c84ac3 21import javax.swing.JScrollPane;
3b2b638f 22import javax.swing.SwingUtilities;
a6395bef
NR
23
24import be.nikiroo.fanfix.Instance;
b4dc6ab5 25import be.nikiroo.fanfix.bundles.UiConfig;
a6395bef 26import be.nikiroo.fanfix.data.MetaData;
92fb0719 27import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListener;
3b2b638f
NR
28import be.nikiroo.utils.Progress;
29import be.nikiroo.utils.ui.ProgressBar;
33ab6d12 30import be.nikiroo.utils.ui.WrapLayout;
a6395bef
NR
31
32class LocalReaderFrame extends JFrame {
33 private static final long serialVersionUID = 1L;
34 private LocalReader reader;
333f0e7b
NR
35 private List<MetaData> stories;
36 private List<LocalReaderBook> books;
37 private JPanel bookPane;
38 private String type;
b4dc6ab5 39 private Color color;
3b2b638f
NR
40 private ProgressBar pgBar;
41 private JMenuBar bar;
a6395bef 42
333f0e7b 43 public LocalReaderFrame(LocalReader reader, String type) {
b4dc6ab5 44 super("Fanfix Library");
a6395bef
NR
45
46 this.reader = reader;
47
48 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
49 setSize(800, 600);
d3c84ac3 50 setLayout(new BorderLayout());
a6395bef 51
333f0e7b 52 books = new ArrayList<LocalReaderBook>();
b4dc6ab5
NR
53 bookPane = new JPanel(new WrapLayout(WrapLayout.LEADING, 5, 5));
54
3b2b638f 55 color = Instance.getUiConfig().getColor(UiConfig.BACKGROUND_COLOR);
b4dc6ab5
NR
56
57 if (color != null) {
58 setBackground(color);
59 bookPane.setBackground(color);
60 }
d3c84ac3 61
b4dc6ab5
NR
62 JScrollPane scroll = new JScrollPane(bookPane);
63 scroll.getVerticalScrollBar().setUnitIncrement(16);
64 add(scroll, BorderLayout.CENTER);
a6395bef 65
3b2b638f
NR
66 pgBar = new ProgressBar();
67 add(pgBar, BorderLayout.SOUTH);
68
333f0e7b
NR
69 refreshBooks(type);
70 setJMenuBar(createMenu());
71
72 setVisible(true);
73 }
74
75 private void refreshBooks(String type) {
76 this.type = type;
77 stories = Instance.getLibrary().getList(type);
78 books.clear();
79 bookPane.removeAll();
80 for (MetaData meta : stories) {
81 LocalReaderBook book = new LocalReaderBook(meta);
b4dc6ab5
NR
82 if (color != null) {
83 book.setBackground(color);
84 }
85
333f0e7b
NR
86 books.add(book);
87 final String luid = meta.getLuid();
92fb0719 88 book.addActionListener(new BookActionListener() {
333f0e7b
NR
89 public void select(LocalReaderBook book) {
90 for (LocalReaderBook abook : books) {
91 abook.setSelected(abook == book);
92 }
93 }
94
95 public void action(LocalReaderBook book) {
3b2b638f
NR
96 final Progress pg = new Progress();
97 outOfUi(pg, new Runnable() {
98 public void run() {
99 try {
100 File target = LocalReaderFrame.this.reader
101 .getTarget(luid, pg);
63985d92
NR
102 // TODO: allow custom programs, with
103 // Desktop/xdg-open fallback
104 try {
105 Desktop.getDesktop().browse(target.toURI());
106 } catch (UnsupportedOperationException e) {
107 String browsers[] = new String[] {
108 "xdg-open", "epiphany",
109 "konqueror", "firefox", "chrome",
110 "google-chrome", "mozilla" };
111
112 Runtime runtime = Runtime.getRuntime();
113 for (String browser : browsers) {
114 try {
115 runtime.exec(new String[] {
116 browser,
117 target.getAbsolutePath() });
118 runtime = null;
119 break;
120 } catch (IOException ioe) {
121 // continue, try next browser
122 }
123 }
124
125 if (runtime != null) {
126 throw new IOException(
127 "Cannot find a working GUI browser...");
128 }
129 }
3b2b638f
NR
130 } catch (IOException e) {
131 Instance.syserr(e);
132 }
133 }
134 });
a6395bef
NR
135 }
136 });
137
333f0e7b 138 bookPane.add(book);
a6395bef
NR
139 }
140
333f0e7b
NR
141 bookPane.validate();
142 bookPane.repaint();
143 }
144
145 private JMenuBar createMenu() {
3b2b638f 146 bar = new JMenuBar();
333f0e7b
NR
147
148 JMenu file = new JMenu("File");
149
150 JMenuItem imprt = new JMenuItem("Import", KeyEvent.VK_I);
151 imprt.addActionListener(new ActionListener() {
152 public void actionPerformed(ActionEvent e) {
3b2b638f
NR
153 final String url = JOptionPane.showInputDialog(
154 LocalReaderFrame.this, "url of the story to import?",
b4dc6ab5
NR
155 "Importing from URL", JOptionPane.QUESTION_MESSAGE);
156 if (url != null && !url.isEmpty()) {
3b2b638f
NR
157 final Progress pg = new Progress("Importing " + url);
158 outOfUi(pg, new Runnable() {
159 public void run() {
160 Exception ex = null;
161 try {
162 Instance.getLibrary().imprt(
163 BasicReader.getUrl(url), pg);
164 } catch (IOException e) {
165 ex = e;
166 }
167
168 final Exception e = ex;
169
170 final boolean ok = (e == null);
171 SwingUtilities.invokeLater(new Runnable() {
172 public void run() {
173 if (!ok) {
174 JOptionPane.showMessageDialog(
175 LocalReaderFrame.this,
176 "Cannot import: " + url,
177 e.getMessage(),
178 JOptionPane.ERROR_MESSAGE);
179
180 setAllEnabled(true);
181 } else {
182 refreshBooks(type);
183 }
184 }
185 });
186 }
187 });
333f0e7b
NR
188 }
189 }
190 });
191 JMenu types = new JMenu("Type");
192 List<String> tt = Instance.getLibrary().getTypes();
193 tt.add(0, null);
194 for (final String type : tt) {
195 JMenuItem item = new JMenuItem(type == null ? "[all]" : type);
196 item.addActionListener(new ActionListener() {
197 public void actionPerformed(ActionEvent e) {
198 refreshBooks(type);
199 }
200 });
201 types.add(item);
202 }
203 JMenuItem exit = new JMenuItem("Exit", KeyEvent.VK_X);
204 exit.addActionListener(new ActionListener() {
205 public void actionPerformed(ActionEvent e) {
206 LocalReaderFrame.this.dispatchEvent(new WindowEvent(
207 LocalReaderFrame.this, WindowEvent.WINDOW_CLOSING));
208 }
209 });
210
211 file.add(imprt);
212 file.add(types);
213 file.addSeparator();
214 file.add(exit);
215
216 bar.add(file);
217
218 return bar;
a6395bef 219 }
3b2b638f
NR
220
221 private void outOfUi(final Progress pg, final Runnable run) {
222 pgBar.setProgress(pg);
223
224 SwingUtilities.invokeLater(new Runnable() {
225 public void run() {
226 setAllEnabled(false);
227 pgBar.addActioListener(new ActionListener() {
228 public void actionPerformed(ActionEvent e) {
229 pgBar.setProgress(null);
230 setAllEnabled(true);
231 }
232 });
233 }
234 });
235
236 new Thread(new Runnable() {
237 public void run() {
238 run.run();
239 if (!pg.isDone()) {
240 pg.setProgress(pg.getMax());
241 }
242 }
243 }).start();
244 }
245
246 public void setAllEnabled(boolean enabled) {
247 for (LocalReaderBook book : books) {
248 book.setEnabled(enabled);
249 book.validate();
250 book.repaint();
251 }
252 bar.setEnabled(enabled);
253 bookPane.setEnabled(enabled);
254 bookPane.validate();
255 bookPane.repaint();
256 setEnabled(enabled);
257 validate();
258 repaint();
259 }
a6395bef 260}