import javax.swing.JFrame;
-import be.nikiroo.fanfix.DataLoader;
import be.nikiroo.fanfix.Instance;
-import be.nikiroo.fanfix.bundles.Config;
-import be.nikiroo.fanfix.library.BasicLibrary;
-import be.nikiroo.fanfix.library.LocalLibrary;
import be.nikiroo.fanfix_swing.gui.MainFrame;
import be.nikiroo.utils.ui.UIUtils;
+/**
+ * The main class of the application, the launcher.
+ *
+ * @author niki
+ */
public class Main {
+ /**
+ * The main entry point of the application.
+ * <p>
+ * If arguments are passed, everything will be passed to Fanfix CLI; if no
+ * argument are present, Fanfix-Swing proper will be launched.
+ *
+ * @param args
+ * the arguments (none, or will be passed to Fanfix)
+ */
public static void main(String[] args) {
// Defer to main application if parameters (we are only a UI)
// (though we could handle some of the parameters in the future,
import be.nikiroo.fanfix_swing.gui.book.BookLine;
import be.nikiroo.fanfix_swing.gui.book.BookPopup;
import be.nikiroo.fanfix_swing.gui.book.BookPopup.Informer;
+import be.nikiroo.fanfix_swing.gui.importer.ImporterFrame;
import be.nikiroo.utils.compat.JList6;
import be.nikiroo.utils.compat.ListCellRenderer6;
import be.nikiroo.utils.ui.DelayWorker;
import be.nikiroo.utils.ui.UIUtils;
public class BooksPanel extends ListenerPanel {
+ /**
+ * The {@link ActionEvent} you receive from
+ * {@link BooksPanel#addActionListener(ActionListener)} (see
+ * {@link ActionEvent#getActionCommand()}) when the cache should be
+ * invalidated.
+ */
static public final String INVALIDATE_CACHE = "invalidate_cache";
private enum ReloadMode {
}.execute();
}
- // TODO
+ // TODO loadData by Book.Type + value
private void loadData(final Type type, final String value) {
synchronized (lastLoad) {
lastLoad = new ReloadData(type, value);
}
- // TODO todo todo
+ // TODO loadData todo todo
}
- // TODO
+ // TODO loadData by Book.Type + value
private void loadData(List<BookInfo> bookInfos) {
// synchronized (lastLoad) {
// lastLoad[0] = "bookInfos";
package be.nikiroo.fanfix_swing.gui;
import java.awt.BorderLayout;
-import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
-import javax.swing.SwingWorker;
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix_swing.gui.importer.ImporterFrame;
import be.nikiroo.fanfix_swing.gui.search.SearchFrame;
import be.nikiroo.fanfix_swing.gui.utils.UiHelper;
-import be.nikiroo.fanfix_swing.images.IconGenerator;
-import be.nikiroo.fanfix_swing.images.IconGenerator.Icon;
-import be.nikiroo.fanfix_swing.images.IconGenerator.Size;
import be.nikiroo.utils.Version;
+import be.nikiroo.utils.ui.BreadCrumbsBar;
import be.nikiroo.utils.ui.ConfigEditor;
-import be.nikiroo.utils.ui.UIUtils;
+/**
+ * The main frame of this application, where everything should start.
+ *
+ * @author niki
+ */
public class MainFrame extends JFrame {
+ static private final long serialVersionUID = 1L;
+
static private ImporterFrame importer;
private BooksPanel books;
private boolean detailsPanel;
private Runnable onCrumbsbreadChange;
+ /**
+ * Create a new main frame.
+ * <p>
+ * You should probably only use one for the life of the application.
+ */
public MainFrame() {
super("Fanfix " + Version.getCurrentVersion());
importer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- if (e != null && ImporterFrame.IMPORTED
+ if (e != null && ImporterFrame.IMPORTED_SUCCESS
.equals(e.getActionCommand())) {
browser.reloadData();
books.reloadData();
UiHelper.setFrameIcon(this);
}
- static public ImporterFrame getImporter() {
- return importer;
- }
-
+ /**
+ * Change the side panel mode.
+ * <p>
+ * The side panel contains an author/source/tag/... browser.
+ * <p>
+ * If we have no side panel, a {@link BreadCrumbsBar} will be used instead.
+ *
+ * @param sidePanel
+ * TRUE to have a side panel (if FALSE, only a
+ * {@link BreadCrumbsBar} will be used)
+ */
public void setSidePanel(boolean sidePanel) {
setMode(sidePanel, detailsPanel);
}
+ /**
+ * Change the details panel mode.
+ * <p>
+ * The details panel is a side panel with some details about the current
+ * item selected by the browser side panel or the {@link BreadCrumbsBar}.
+ *
+ * @param detailsPanel
+ * TRUE for a details panel, FALSE for no details panel
+ *
+ */
public void setDetailsPanel(boolean detailsPanel) {
setMode(sidePanel, detailsPanel);
}
+ /**
+ * Split the two component via a {@link JSplitPane}.
+ *
+ * @param leftTop
+ * the first component, that will go on top or on the left
+ * @param rightBottom
+ * the second component, that will go on the bottom or on the
+ * right
+ * @param horizontal
+ * TRUE for horisontal layout (left/right), FALSE for vertical
+ * (top/bottom)
+ * @param dividerLocation
+ * the location o the divider, usually in pixels (0 means
+ * "default to preferred sizes")
+ * @param weight
+ * the way to divide newly created space on this panel between
+ * the two component (1 = everything goes to the left/top
+ * component, 0 means everything to the other component, 0.5
+ * means equally shared)
+ *
+ * @return the newly created {@link JSplitPane}
+ */
private JSplitPane split(JComponent leftTop, JComponent rightBottom,
boolean horizontal, int dividerLocation, double weight) {
JSplitPane split = new JSplitPane(
return split;
}
+ /**
+ * Create the menu bar for the main frame.
+ *
+ * @return the new menu bar
+ */
private JMenuBar createMenuBar() {
JMenuBar bar = new JMenuBar();
return bar;
}
+ /**
+ * Save the given option into the config file (as in, save back to disk,
+ * now).
+ *
+ * @param option
+ * the option to change
+ * @param value
+ * the new value
+ */
private void saveConfig(UiConfig option, boolean value) {
Instance.getInstance().getUiConfig().setBoolean(option, value);
try {
}
}
+ /**
+ * Change the side panels mode.
+ *
+ * @param sidePanel
+ * a side panel with an author/source/tag/... browser (if not,
+ * only a {@link BreadCrumbsBar} will be used)
+ * @param detailsPanel
+ * a side panel with some details about the current item selected
+ * by the browser side panel or the {@link BreadCrumbsBar}
+ */
private void setMode(boolean sidePanel, boolean detailsPanel) {
if (this.sidePanel == sidePanel && this.detailsPanel == detailsPanel) {
return;
});
}
+ /**
+ * The (unique) {@link ImporterFrame} used by Fanfix-Swing.
+ *
+ * @return the importer
+ */
+ static public ImporterFrame getImporter() {
+ return importer;
+ }
+
+ /**
+ * Translate the given id into user text.
+ *
+ * @param id
+ * the ID to translate
+ * @param values
+ * the values to insert instead of the place holders in the
+ * translation
+ *
+ * @return the translated text with the given value where required or NULL
+ * if not found (not present in the resource file)
+ */
static public String trans(StringIdGui id, Object... values) {
return Instance.getInstance().getTransGui().getString(id, values);
}
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.bundles.StringIdGui;
import be.nikiroo.fanfix.library.LocalLibrary;
-import be.nikiroo.fanfix.reader.BasicReader;
import be.nikiroo.fanfix.supported.BasicSupport;
import be.nikiroo.fanfix_swing.Actions;
import be.nikiroo.fanfix_swing.gui.SearchBar;
import be.nikiroo.utils.ui.ListenerPanel;
import be.nikiroo.utils.ui.UIUtils;
+/**
+ * A window showing the items currently being processed (downloaded,
+ * converted...).
+ * <p>
+ * You can keep it in memory and let the user close it, it will unhide itself on
+ * import.
+ *
+ * @author niki
+ */
public class ImporterFrame extends JFrame implements ListenerItem {
- static public final String IMPORTED = "imported";
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The {@link ActionEvent} you receive from
+ * {@link ImporterFrame#addActionListener(ActionListener)} (see
+ * {@link ActionEvent#getActionCommand()}) when an item is imported
+ * successfully.
+ */
+ static public final String IMPORTED_SUCCESS = "imported_success";
+
+ /**
+ * The {@link ActionEvent} you receive from
+ * {@link ImporterFrame#addActionListener(ActionListener)} (see
+ * {@link ActionEvent#getActionCommand()}) when an item failed to be
+ * imported.
+ */
+ static public final String IMPORTED_FAIL = "imported_fail";
private ListenerPanel root;
private ListModel<ImporterItem> data;
private String filter = "";
+ /**
+ * Create a new {@link ImporterFrame}.
+ * <p>
+ * You can keep it in memory and let the user close it, it will unhode
+ * itself on import.
+ */
public ImporterFrame() {
root = new ListenerPanel();
setLayout(new BorderLayout());
* <p>
* Should be called inside the UI thread.
* <p>
- * Will fire {@link ImporterFrame#IMPORTED} if/when successful.
+ * Will fire {@link ImporterFrame#IMPORTED_SUCCESS} or
+ * {@link ImporterFrame#IMPORTED_SUCCESS} when done.
*
* @param parent
* a container we can use to display the {@link URL} chooser and
* <p>
* Should be called inside the UI thread.
* <p>
- * Will fire {@link ImporterFrame#IMPORTED} if/when successful.
+ * Will fire {@link ImporterFrame#IMPORTED_SUCCESS} or
+ * {@link ImporterFrame#IMPORTED_SUCCESS} when done.
*
* @param parent
* a container we can use to display the {@link File} chooser and
@Override
public void run() {
item.setDone(true);
- fireActionPerformed(IMPORTED);
+ fireActionPerformed(IMPORTED_SUCCESS);
}
}, new Runnable() {
@Override
public void run() {
item.setFailed(true);
item.setDone(true);
- fireActionPerformed(IMPORTED);
+ fireActionPerformed(IMPORTED_FAIL);
}
});
* <p>
* Should be called inside the UI thread.
* <p>
- * Will fire {@link ImporterFrame#IMPORTED} if/when successful.
+ * Will fire {@link ImporterFrame#IMPORTED_SUCCESS} or
+ * {@link ImporterFrame#IMPORTED_SUCCESS} when done.
*
* @param parent
* a container we can use to display the {@link URL} chooser and
@Override
public void run() {
item.setDone(true);
- fireActionPerformed(IMPORTED);
+ fireActionPerformed(IMPORTED_SUCCESS);
}
}, new Runnable() {
@Override
public void run() {
item.setFailed(true);
item.setDone(true);
- fireActionPerformed(IMPORTED);
+ fireActionPerformed(IMPORTED_FAIL);
}
});
}
}
+ /**
+ * Add a new {@link ImporterItem} linked to the given {@link Progress}.
+ *
+ * @param pg
+ * the {@link Progress} to link, must not be NULL
+ * @param basename
+ * the base name given to the {@link ImporterItem} (should be the
+ * name of the web site you download/convert from)
+ * @param storyName
+ * the name of the story, if already known
+ *
+ * @return the new item, already linked (you still need to flag it Done or
+ * Failed as needed)
+ */
private ImporterItem add(Progress pg, final String basename,
String storyName) {
final ImporterItem item = new ImporterItem(pg, basename, storyName);
return item;
}
+ /**
+ * Filter the {@link ImporterItem} and keep only those that conform to
+ * {@link ImporterFrame#filter}.
+ */
private void filter() {
data.filter(new Predicate<ImporterItem>() {
@Override
/**
* The {@link ActionEvent} you receive from
- * {@link ImporterItem#addActionListener(ActionListener)} can return this as
- * a command (see {@link ActionEvent#getActionCommand()}) for change event
- * on this {@link ImporterItem}.
+ * {@link ImporterItem#addActionListener(ActionListener)} (see
+ * {@link ActionEvent#getActionCommand()}) when an item changed.
*/
static public final String CHANGE = "change";
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.getVerticalScrollBar().setUnitIncrement(16);
- // TODO:
// JButton up = new BasicArrowButton(BasicArrowButton.NORTH);
// JButton down = new BasicArrowButton(BasicArrowButton.SOUTH);