From 9c59820764e52d69c4248a2c38a8f4a42059d647 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Thu, 18 Apr 2019 22:20:18 +0200 Subject: [PATCH] GUI search: regorg done --- .../nikiroo/fanfix/reader/ui/GuiReader.java | 21 +- .../reader/ui/GuiReaderSearchByNamePanel.java | 428 ++---------------- .../reader/ui/GuiReaderSearchFrame.java | 116 ++--- 3 files changed, 97 insertions(+), 468 deletions(-) diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java index 1d78212..b720af4 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReader.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReader.java @@ -234,16 +234,7 @@ class GuiReader extends BasicReader { @Override public void search(SupportType searchOn, String keywords, int page, int item, boolean sync) { - final GuiReaderSearchFrame search = new GuiReaderSearchFrame( - GuiReader.this); - while (!search.isEnabled()) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - Instance.getTraceHandler().error(e); - } - } - + GuiReaderSearchFrame search = new GuiReaderSearchFrame(this); search.search(searchOn, keywords, page, item); if (sync) { sync(search); @@ -256,15 +247,7 @@ class GuiReader extends BasicReader { public void searchTag(final SupportType searchOn, final int page, final int item, final boolean sync, final Integer... tags) { - final GuiReaderSearchFrame search = new GuiReaderSearchFrame( - GuiReader.this); - while (!search.isEnabled()) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - Instance.getTraceHandler().error(e); - } - } + final GuiReaderSearchFrame search = new GuiReaderSearchFrame(this); final BasicSearchable searchable = BasicSearchable .getSearchable(searchOn); diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchByNamePanel.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchByNamePanel.java index cfd6920..94579fd 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchByNamePanel.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchByNamePanel.java @@ -1,8 +1,6 @@ package be.nikiroo.fanfix.reader.ui; import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; @@ -11,19 +9,12 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import javax.swing.BoxLayout; import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JList; import javax.swing.JPanel; -import javax.swing.JTabbedPane; import javax.swing.JTextField; -import javax.swing.ListCellRenderer; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.searchable.BasicSearchable; -import be.nikiroo.fanfix.searchable.SearchableTag; -import be.nikiroo.fanfix.supported.SupportType; /** * This panel represents a search panel that works for keywords and tags based @@ -31,73 +22,33 @@ import be.nikiroo.fanfix.supported.SupportType; * * @author niki */ -// JCombobox not 1.6 compatible -@SuppressWarnings({ "unchecked", "rawtypes" }) public class GuiReaderSearchByNamePanel extends JPanel { private static final long serialVersionUID = 1L; - private int actionEventId = ActionEvent.ACTION_FIRST; - private BasicSearchable searchable; - private boolean searchByTags; - private int page; - private int maxPage; - - private JTabbedPane searchTabs; private JTextField keywordsField; private JButton submitKeywords; - private SearchableTag currentTag; - private JPanel tagBars; - private List combos; - - private List actions = new ArrayList(); + private int page; + private int maxPage; private List stories = new ArrayList(); private int storyItem; - // will throw illegalArgEx if bad support type, NULL allowed - public GuiReaderSearchByNamePanel(final SupportType supportType, - final Runnable inUi) { - setLayout(new BorderLayout()); - - page = 1; - maxPage = -1; - currentTag = null; - searchByTags = false; - - searchTabs = new JTabbedPane(); - searchTabs.addTab("By name", createByNameSearchPanel()); - searchTabs.addTab("By tags", createByTagSearchPanel()); - - add(searchTabs, BorderLayout.CENTER); - updateSearchBy(searchByTags); - - // TODO: check if null really is OK for supportType (must be) - new Thread(new Runnable() { - @Override - public void run() { - setSupportType(supportType, inUi); - } - }).start(); - } - - private JPanel createByNameSearchPanel() { - JPanel byName = new JPanel(new BorderLayout()); + public GuiReaderSearchByNamePanel(final Runnable fireEvent) { + super(new BorderLayout()); keywordsField = new JTextField(); - byName.add(keywordsField, BorderLayout.CENTER); + add(keywordsField, BorderLayout.CENTER); submitKeywords = new JButton("Search"); - byName.add(submitKeywords, BorderLayout.EAST); - - // TODO: ENTER -> search + add(submitKeywords, BorderLayout.EAST); keywordsField.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { - search(keywordsField.getText(), 1, 0, null); + search(keywordsField.getText(), 1, 0); } else { super.keyReleased(e); } @@ -107,35 +58,34 @@ public class GuiReaderSearchByNamePanel extends JPanel { submitKeywords.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - search(keywordsField.getText(), 1, 0, null); + new Thread(new Runnable() { + @Override + public void run() { + search(keywordsField.getText(), 1, 0); + fireEvent.run(); + } + }).start(); } }); - return byName; - } - - private JPanel createByTagSearchPanel() { - combos = new ArrayList(); - - JPanel byTag = new JPanel(); - tagBars = new JPanel(); - tagBars.setLayout(new BoxLayout(tagBars, BoxLayout.Y_AXIS)); - byTag.add(tagBars, BorderLayout.NORTH); - - return byTag; + setSearchable(null); } - // slow - public void setSupportType(SupportType supportType, Runnable inUi) { - BasicSearchable searchable = BasicSearchable.getSearchable(supportType); - if (searchable == null && supportType != null) { - throw new java.lang.IllegalArgumentException( - "Unupported support type: " + supportType); - } - + /** + * The {@link BasicSearchable} object use for the searches themselves. + *

+ * Can be NULL, but no searches will work. + * + * @param searchable + * the new searchable + */ + public void setSearchable(BasicSearchable searchable) { this.searchable = searchable; - - searchTag(null, 1, 0, inUi); + page = 1; + maxPage = -1; + storyItem = 0; + stories = new ArrayList(); + updateKeywords(""); } public int getPage() { @@ -146,22 +96,8 @@ public class GuiReaderSearchByNamePanel extends JPanel { return maxPage; } - // throw outOfBounds if needed - public void setPage(int page, Runnable inUi) { - if (searchByTags) { - searchTag(currentTag, page, 0, inUi); - } else { - search(keywordsField.getText(), page, 0, inUi); - } - } - - // actions will be fired in UIthread - public void addActionListener(ActionListener action) { - actions.add(action); - } - - public boolean removeActionListener(ActionListener action) { - return actions.remove(action); + public String getCurrentKeywords() { + return keywordsField.getText(); } public List getStories() { @@ -173,47 +109,6 @@ public class GuiReaderSearchByNamePanel extends JPanel { return storyItem; } - private void fireAction(final Runnable inUi) { - GuiReaderSearchFrame.inUi(new Runnable() { - @Override - public void run() { - ActionEvent ae = new ActionEvent( - GuiReaderSearchByNamePanel.this, actionEventId, - "stories found"); - - actionEventId++; - if (actionEventId > ActionEvent.ACTION_LAST) { - actionEventId = ActionEvent.ACTION_FIRST; - } - - for (ActionListener action : actions) { - try { - action.actionPerformed(ae); - } catch (Exception e) { - GuiReaderSearchFrame.error(e); - } - } - - if (inUi != null) { - inUi.run(); - } - } - }); - } - - private void updateSearchBy(final boolean byTag) { - GuiReaderSearchFrame.inUi(new Runnable() { - @Override - public void run() { - if (!byTag) { - searchTabs.setSelectedIndex(0); - } else { - searchTabs.setSelectedIndex(1); - } - } - }); - } - // cannot be NULL private void updateKeywords(final String keywords) { if (!keywords.equals(keywordsField.getText())) { @@ -226,183 +121,12 @@ public class GuiReaderSearchByNamePanel extends JPanel { } } - // update and reset the tagsbar - // can be NULL, for base tags - private void updateTags(final SearchableTag tag) { - final List parents = new ArrayList(); - SearchableTag parent = (tag == null) ? null : tag; - while (parent != null) { - parents.add(parent); - parent = parent.getParent(); - } - - List rootTags = null; - SearchableTag selectedRootTag = null; - selectedRootTag = parents.isEmpty() ? null : parents - .get(parents.size() - 1); - - try { - rootTags = searchable.getTags(); - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - } - - final List rootTagsF = rootTags; - final SearchableTag selectedRootTagF = selectedRootTag; - - GuiReaderSearchFrame.inUi(new Runnable() { - @Override - public void run() { - tagBars.invalidate(); - tagBars.removeAll(); - - addTagBar(rootTagsF, selectedRootTagF); - - for (int i = parents.size() - 1; i >= 0; i--) { - SearchableTag selectedChild = null; - if (i > 0) { - selectedChild = parents.get(i - 1); - } - - SearchableTag parent = parents.get(i); - addTagBar(parent.getChildren(), selectedChild); - } - - tagBars.validate(); - } - }); - } - - // must be quick and no thread change - private void addTagBar(List tags, - final SearchableTag selected) { - tags.add(0, null); - - final int comboIndex = combos.size(); - - final JComboBox combo = new JComboBox( - tags.toArray(new SearchableTag[] {})); - combo.setSelectedItem(selected); - - final ListCellRenderer basic = combo.getRenderer(); - - combo.setRenderer(new ListCellRenderer() { - @Override - public Component getListCellRendererComponent(JList list, - Object value, int index, boolean isSelected, - boolean cellHasFocus) { - - Object displayValue = value; - if (value instanceof SearchableTag) { - displayValue = ((SearchableTag) value).getName(); - } else { - displayValue = "Select a tag..."; - cellHasFocus = false; - isSelected = false; - } - - Component rep = basic.getListCellRendererComponent(list, - displayValue, index, isSelected, cellHasFocus); - - if (value == null) { - rep.setForeground(Color.GRAY); - } - - return rep; - } - }); - - combo.addActionListener(createComboTagAction(comboIndex)); - - combos.add(combo); - tagBars.add(combo); - } - - private ActionListener createComboTagAction(final int comboIndex) { - return new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - List combos = GuiReaderSearchByNamePanel.this.combos; - if (combos == null || comboIndex < 0 - || comboIndex >= combos.size()) { - return; - } - - // Tag can be NULL - final SearchableTag tag = (SearchableTag) combos - .get(comboIndex).getSelectedItem(); - - while (comboIndex + 1 < combos.size()) { - JComboBox combo = combos.remove(comboIndex + 1); - tagBars.remove(combo); - } - - new Thread(new Runnable() { - @Override - public void run() { - final List children = getChildrenForTag(tag); - if (children != null) { - GuiReaderSearchFrame.inUi(new Runnable() { - @Override - public void run() { - addTagBar(children, tag); - } - }); - } - - if (tag != null && tag.isLeaf()) { - try { - GuiReaderSearchByNamePanel.this.page = 1; - stories = searchable.search(tag, 1); - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - GuiReaderSearchByNamePanel.this.page = 0; - stories = new ArrayList(); - } - - fireAction(null); - } - } - }).start(); - } - }; - } - - // sync, add children of tag, NULL = base tags - // return children of the tag or base tags or NULL - private List getChildrenForTag(final SearchableTag tag) { - List children = new ArrayList(); - if (tag == null) { - try { - List baseTags = searchable.getTags(); - children = baseTags; - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - } - } else { - try { - searchable.fillTag(tag); - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - } - - if (!tag.isLeaf()) { - children = tag.getChildren(); - } else { - children = null; - } - } - - return children; - } - // item 0 = no selection, else = default selection // throw if page > max - public void search(String keywords, int page, int item, Runnable inUi) { + public void search(String keywords, int page, int item) { List stories = new ArrayList(); int storyItem = 0; - updateSearchBy(false); updateKeywords(keywords); int maxPage = -1; @@ -435,79 +159,9 @@ public class GuiReaderSearchByNamePanel extends JPanel { } this.page = page; - this.stories = stories; - this.storyItem = storyItem; this.maxPage = maxPage; - - fireAction(inUi); - } - - // slow - // tag: null = base tags - // throw if page > max, but only if stories - public void searchTag(SearchableTag tag, int page, int item, Runnable inUi) { - List stories = new ArrayList(); - int storyItem = 0; - - currentTag = tag; - updateSearchBy(true); - updateTags(tag); - - int maxPage = 1; - if (tag != null) { - try { - searchable.fillTag(tag); - - if (!tag.isLeaf()) { - List subtags = tag.getChildren(); - if (item > 0 && item <= subtags.size()) { - SearchableTag subtag = subtags.get(item - 1); - try { - tag = subtag; - searchable.fillTag(tag); - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - } - } else if (item > 0) { - GuiReaderSearchFrame.error(String.format( - "Tag item does not exist: Tag [%s], item %d", - tag.getFqName(), item)); - } - } - - maxPage = searchable.searchPages(tag); - if (page > 0 && tag.isLeaf()) { - if (maxPage >= 0 && (page <= 0 || page > maxPage)) { - throw new IndexOutOfBoundsException("Page " + page - + " out of " + maxPage); - } - - try { - stories = searchable.search(tag, page); - if (item > 0 && item <= stories.size()) { - storyItem = item; - } else if (item > 0) { - GuiReaderSearchFrame - .error(String - .format("Story item does not exist: Tag [%s], item %d", - tag.getFqName(), item)); - } - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - } - } - } catch (IOException e) { - GuiReaderSearchFrame.error(e); - maxPage = 0; - } - } - this.stories = stories; this.storyItem = storyItem; - this.page = page; - this.maxPage = maxPage; - - fireAction(inUi); } /** @@ -522,19 +176,9 @@ public class GuiReaderSearchByNamePanel extends JPanel { * this component is disabled */ @Override - public void setEnabled(final boolean enabled) { - GuiReaderSearchFrame.inUi(new Runnable() { - @Override - public void run() { - GuiReaderSearchByNamePanel.super.setEnabled(enabled); - searchTabs.setEnabled(enabled); - keywordsField.setEnabled(enabled); - submitKeywords.setEnabled(enabled); - tagBars.setEnabled(enabled); - for (JComboBox combo : combos) { - combo.setEnabled(enabled); - } - } - }); + public void setEnabled(boolean b) { + super.setEnabled(b); + keywordsField.setEnabled(b); + submitKeywords.setEnabled(b); } } diff --git a/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchFrame.java b/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchFrame.java index 1c8802a..c67c735 100644 --- a/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchFrame.java +++ b/src/be/nikiroo/fanfix/reader/ui/GuiReaderSearchFrame.java @@ -39,7 +39,7 @@ public class GuiReaderSearchFrame extends JFrame { private int maxPage; private JComboBox comboSupportTypes; - private GuiReaderSearchByNamePanel searchPanel; + private GuiReaderSearchByPanel searchPanel; private boolean seeWordcount; private GuiReaderGroup books; @@ -65,13 +65,13 @@ public class GuiReaderSearchFrame extends JFrame { comboSupportTypes.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - setWaitingScreen(true); + setWaiting(true); updateSupportType( (SupportType) comboSupportTypes.getSelectedItem(), new Runnable() { @Override public void run() { - setWaitingScreen(false); + setWaiting(false); } }); } @@ -80,18 +80,18 @@ public class GuiReaderSearchFrame extends JFrame { searchSites.add(comboSupportTypes, BorderLayout.CENTER); searchSites.add(new JLabel(" " + "Website : "), BorderLayout.WEST); - searchPanel = new GuiReaderSearchByNamePanel(supportType, - new Runnable() { + searchPanel = new GuiReaderSearchByPanel(supportType, + new GuiReaderSearchByPanel.Waitable() { @Override - public void run() { - setWaitingScreen(false); + public void setWaiting(boolean waiting) { + GuiReaderSearchFrame.this.setWaiting(waiting); } }); searchPanel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - updateMaxPage(searchPanel.getMaxPage()); + updatePages(searchPanel.getPage(), searchPanel.getMaxPage()); List infos = new ArrayList(); for (MetaData meta : searchPanel.getStories()) { infos.add(GuiReaderBookInfo.fromMeta(meta)); @@ -133,50 +133,44 @@ public class GuiReaderSearchFrame extends JFrame { JScrollPane scroll = new JScrollPane(books); scroll.getVerticalScrollBar().setUnitIncrement(16); add(scroll, BorderLayout.CENTER); - - setWaitingScreen(true); } - private void updateSupportType(SupportType supportType, Runnable inUi) { - if (supportType != this.supportType) { - this.supportType = supportType; - comboSupportTypes.setSelectedItem(supportType); - books.clear(); - searchPanel.setSupportType(supportType, inUi); - } - } + private void updateSupportType(final SupportType supportType, + final Runnable inUi) { + this.supportType = supportType; + comboSupportTypes.setSelectedItem(supportType); + books.clear(); - private void updatePage(final int page) { - inUi(new Runnable() { + new Thread(new Runnable() { @Override public void run() { - GuiReaderSearchFrame.this.page = page; - - // TODO: gui - System.out.println("page: " + page); + searchPanel.setSupportType(supportType); + inUi(inUi); } - }); + }).start(); } - private void updateMaxPage(final int maxPage) { + private void updatePages(final int page, final int maxPage) { inUi(new Runnable() { @Override public void run() { + GuiReaderSearchFrame.this.page = page; GuiReaderSearchFrame.this.maxPage = maxPage; // TODO: gui + System.out.println("page: " + page); System.out.println("max page: " + maxPage); } }); } private void updateBooks(final List infos) { - setWaitingScreen(true); + setWaiting(true); inUi(new Runnable() { @Override public void run() { books.refreshBooks(infos, seeWordcount); - setWaitingScreen(false); + setWaiting(false); } }); } @@ -184,47 +178,39 @@ public class GuiReaderSearchFrame extends JFrame { // item 0 = no selection, else = default selection public void search(final SupportType searchOn, final String keywords, final int page, final int item) { - - setWaitingScreen(true); - - searchPanel.setSupportType(searchOn, new Runnable() { + setWaiting(true); + new Thread(new Runnable() { @Override public void run() { - if (keywords != null) { - setWaitingScreen(true); - searchPanel.search(keywords, page, item, new Runnable() { - @Override - public void run() { - updateMaxPage(searchPanel.getMaxPage()); - updatePage(page); - setWaitingScreen(false); - } - }); - } + searchPanel.setSupportType(searchOn); + searchPanel.search(keywords, page, item); + inUi(new Runnable() { + @Override + public void run() { + setWaiting(false); + } + }); } - }); + }).start(); } // tag: null = base tags public void searchTag(final SupportType searchOn, final int page, final int item, final SearchableTag tag) { - - setWaitingScreen(true); - - searchPanel.setSupportType(searchOn, new Runnable() { + setWaiting(true); + new Thread(new Runnable() { @Override public void run() { - setWaitingScreen(true); - searchPanel.searchTag(tag, page, item, new Runnable() { + searchPanel.setSupportType(searchOn); + searchPanel.searchTag(tag, page, item); + inUi(new Runnable() { @Override public void run() { - updateMaxPage(searchPanel.getMaxPage()); - updatePage(page); - setWaitingScreen(false); + setWaiting(false); } }); } - }); + }).start(); } /** @@ -260,13 +246,29 @@ public class GuiReaderSearchFrame extends JFrame { Instance.getTraceHandler().error(e); } - private void setWaitingScreen(final boolean waiting) { + /** + * Enables or disables this component, depending on the value of the + * parameter b. An enabled component can respond to user input + * and generate events. Components are enabled initially by default. + *

+ * Disabling this component will also affect its children. + * + * @param b + * If true, this component is enabled; otherwise + * this component is disabled + */ + @Override + public void setEnabled(boolean b) { + super.setEnabled(b); + books.setEnabled(b); + searchPanel.setEnabled(b); + } + + private void setWaiting(final boolean waiting) { inUi(new Runnable() { @Override public void run() { GuiReaderSearchFrame.this.setEnabled(!waiting); - books.setEnabled(!waiting); - searchPanel.setEnabled(!waiting); } }); } -- 2.27.0