From fae07ea7af01c64ca1a858db75a615555318d5e2 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Wed, 24 Feb 2016 14:38:05 +0100 Subject: [PATCH] Move MainContent and its derivative to a new package, rework ContactList to use it for other purposes, too --- src/be/nikiroo/jvcard/test/TestCli.java | 18 ++- src/be/nikiroo/jvcard/tui/KeyAction.java | 30 +++- src/be/nikiroo/jvcard/tui/MainWindow.java | 7 +- .../jvcard/tui/panes/ContactDetails.java | 60 ++++++++ .../nikiroo/jvcard/tui/panes/ContactList.java | 129 ++++++++++++++++ src/be/nikiroo/jvcard/tui/panes/FileList.java | 69 +++++++++ .../nikiroo/jvcard/tui/panes/MainContent.java | 81 ++++++++++ .../jvcard/tui/panes/MainContentList.java | 144 ++++++++++++++++++ 8 files changed, 527 insertions(+), 11 deletions(-) create mode 100644 src/be/nikiroo/jvcard/tui/panes/ContactDetails.java create mode 100644 src/be/nikiroo/jvcard/tui/panes/ContactList.java create mode 100644 src/be/nikiroo/jvcard/tui/panes/FileList.java create mode 100644 src/be/nikiroo/jvcard/tui/panes/MainContent.java create mode 100644 src/be/nikiroo/jvcard/tui/panes/MainContentList.java diff --git a/src/be/nikiroo/jvcard/test/TestCli.java b/src/be/nikiroo/jvcard/test/TestCli.java index 37a3ac9..6cda3e6 100644 --- a/src/be/nikiroo/jvcard/test/TestCli.java +++ b/src/be/nikiroo/jvcard/test/TestCli.java @@ -2,18 +2,19 @@ package be.nikiroo.jvcard.test; import java.io.File; import java.io.IOException; +import java.util.LinkedList; import java.util.List; import be.nikiroo.jvcard.Card; import be.nikiroo.jvcard.parsers.Format; -import be.nikiroo.jvcard.tui.ContactList; import be.nikiroo.jvcard.tui.MainWindow; import be.nikiroo.jvcard.tui.TuiLauncher; +import be.nikiroo.jvcard.tui.panes.ContactList; +import be.nikiroo.jvcard.tui.panes.FileList; import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.TextColor; import com.googlecode.lanterna.gui2.BasicWindow; -import com.googlecode.lanterna.gui2.BorderLayout; import com.googlecode.lanterna.gui2.Button; import com.googlecode.lanterna.gui2.DefaultWindowManager; import com.googlecode.lanterna.gui2.EmptySpace; @@ -37,11 +38,18 @@ public class TestCli { if (args.length > 0 && args[0].equals("--gui")) textMode = false; - //TODO: do not hardcode that: + Window win = null; + + // TODO: do not hardcode that: Card card = new Card(new File("/home/niki/.addressbook"), Format.Abook); - Window win = new MainWindow(new ContactList(card)); + win = new MainWindow(new ContactList(card)); // - + List files = new LinkedList(); + files.add(new File("/home/niki/vcf/coworkers.vcf")); + files.add(new File("/home/niki/vcf/oce.vcf")); + win = new MainWindow(new FileList(files)); + // + TuiLauncher.start(textMode, win); /* diff --git a/src/be/nikiroo/jvcard/tui/KeyAction.java b/src/be/nikiroo/jvcard/tui/KeyAction.java index e6aad03..ac1b093 100644 --- a/src/be/nikiroo/jvcard/tui/KeyAction.java +++ b/src/be/nikiroo/jvcard/tui/KeyAction.java @@ -1,5 +1,7 @@ package be.nikiroo.jvcard.tui; +import java.io.File; + import be.nikiroo.jvcard.Card; import be.nikiroo.jvcard.Contact; import be.nikiroo.jvcard.Data; @@ -24,12 +26,32 @@ public class KeyAction { * @author niki * */ - enum Mode { - NONE, MOVE, BACK, HELP, CONTACT_LIST, CONTACT_DETAILS, SWICTH_FORMAT, + public enum Mode { + NONE, MOVE, BACK, HELP, FILE_LIST, CONTACT_LIST, CONTACT_DETAILS, SWICTH_FORMAT, } - enum DataType { - CONTACT, CARD, DATA, NONE + public enum DataType { + /** + * A list of Card {@link File}s. + */ + CARD_FILES, + /** + * Contains a list of contacts. + */ + CARD, + /** + * All the known informations about a specific contact person or + * company. + */ + CONTACT, + /** + * An information about a contact. + */ + DATA, + /** + * Empty. + */ + NONE } private StringId id; diff --git a/src/be/nikiroo/jvcard/tui/MainWindow.java b/src/be/nikiroo/jvcard/tui/MainWindow.java index a17e549..7f438d9 100644 --- a/src/be/nikiroo/jvcard/tui/MainWindow.java +++ b/src/be/nikiroo/jvcard/tui/MainWindow.java @@ -10,6 +10,9 @@ import be.nikiroo.jvcard.i18n.Trans; import be.nikiroo.jvcard.i18n.Trans.StringId; import be.nikiroo.jvcard.tui.KeyAction.Mode; import be.nikiroo.jvcard.tui.UiColors.Element; +import be.nikiroo.jvcard.tui.panes.ContactDetails; +import be.nikiroo.jvcard.tui.panes.ContactList; +import be.nikiroo.jvcard.tui.panes.MainContent; import com.googlecode.lanterna.TerminalSize; import com.googlecode.lanterna.gui2.BasicWindow; @@ -272,7 +275,7 @@ public class MainWindow extends BasicWindow { messagePanel.addComponent(hpanel, LinearLayout .createLayoutData(LinearLayout.Alignment.Beginning)); - this.setFocusedInteractable(text); + text.takeFocus(); } } @@ -296,7 +299,7 @@ public class MainWindow extends BasicWindow { // focus = content.get(0).getDefaultFocusElement(); focus = content.get(0).nextFocus(null); - this.setFocusedInteractable(focus); + focus.takeFocus(); } return answer; diff --git a/src/be/nikiroo/jvcard/tui/panes/ContactDetails.java b/src/be/nikiroo/jvcard/tui/panes/ContactDetails.java new file mode 100644 index 0000000..2cd1403 --- /dev/null +++ b/src/be/nikiroo/jvcard/tui/panes/ContactDetails.java @@ -0,0 +1,60 @@ +package be.nikiroo.jvcard.tui.panes; + +import java.util.List; + +import be.nikiroo.jvcard.Contact; +import be.nikiroo.jvcard.Data; +import be.nikiroo.jvcard.tui.KeyAction; +import be.nikiroo.jvcard.tui.KeyAction.DataType; +import be.nikiroo.jvcard.tui.KeyAction.Mode; + +import com.googlecode.lanterna.gui2.Direction; +import com.googlecode.lanterna.gui2.Label; + +public class ContactDetails extends MainContent { + private Contact contact; + + public ContactDetails(Contact contact) { + super(Direction.VERTICAL); + + this.contact = contact; + + for (Data data : contact.getContent()) { + addComponent(new Label(data.getName() + ": " + data.getValue())); + } + } + + @Override + public DataType getDataType() { + return DataType.CONTACT; + } + + @Override + public String getExitWarning() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getKeyBindings() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Mode getMode() { + return Mode.CONTACT_DETAILS; + } + + @Override + public String getTitle() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String move(int x, int y) { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/be/nikiroo/jvcard/tui/panes/ContactList.java b/src/be/nikiroo/jvcard/tui/panes/ContactList.java new file mode 100644 index 0000000..3a943f9 --- /dev/null +++ b/src/be/nikiroo/jvcard/tui/panes/ContactList.java @@ -0,0 +1,129 @@ +package be.nikiroo.jvcard.tui.panes; + +import java.util.LinkedList; +import java.util.List; + +import be.nikiroo.jvcard.Card; +import be.nikiroo.jvcard.i18n.Trans; +import be.nikiroo.jvcard.tui.KeyAction; +import be.nikiroo.jvcard.tui.UiColors; +import be.nikiroo.jvcard.tui.KeyAction.DataType; +import be.nikiroo.jvcard.tui.KeyAction.Mode; + +import com.googlecode.lanterna.input.KeyType; + +public class ContactList extends MainContentList { + private Card card; + + private List formats = new LinkedList(); + private int selectedFormat = -1; + private String format = ""; + + public ContactList(Card card) { + super(UiColors.Element.CONTACT_LINE, + UiColors.Element.CONTACT_LINE_SELECTED); + + // TODO: should get that in an INI file + formats.add("NICKNAME@3|FN@+|EMAIL@30"); + formats.add("FN@+|EMAIL@40"); + switchFormat(); + + setCard(card); + } + + /** + * Change the currently displayed contacts card. + * + * @param card + * the new {@link Card} + */ + public void setCard(Card card) { + clearItems(); + this.card = card; + + if (card != null) { + for (int i = 0; i < card.getContacts().size(); i++) { + addItem("[contact line]"); + } + } + + setSelectedIndex(0); + } + + @Override + public String getExitWarning() { + if (card != null && card.isDirty()) { + return "Some of your contact information is not saved"; + } + return null; + } + + @Override + public List getKeyBindings() { + List actions = new LinkedList(); + + // TODO del, save... + actions.add(new KeyAction(Mode.CONTACT_DETAILS, 'e', + Trans.StringId.KEY_ACTION_EDIT_CONTACT) { + @Override + public Object getObject() { + int index = getSelectedIndex(); + return card.getContacts().get(index); + } + }); + actions.add(new KeyAction(Mode.CONTACT_DETAILS, KeyType.Enter, + Trans.StringId.KEY_ACTION_VIEW_CONTACT) { + @Override + public Object getObject() { + int index = getSelectedIndex(); + return card.getContacts().get(index); + } + }); + actions.add(new KeyAction(Mode.SWICTH_FORMAT, KeyType.Tab, + Trans.StringId.KEY_ACTION_SWITCH_FORMAT) { + @Override + public boolean onAction() { + switchFormat(); + return false; + } + }); + + return actions; + } + + @Override + public DataType getDataType() { + return DataType.CARD; + } + + @Override + public Mode getMode() { + return Mode.CONTACT_LIST; + } + + @Override + public String getTitle() { + // TODO Auto-generated method stub + return null; + } + + @Override + protected String getLabel(int index, int width) { + // we could use: " ", "┃", "│"... + return card.getContacts().get(index).toString(format, " ┃ ", width); + } + + private void switchFormat() { + if (formats.size() == 0) + return; + + selectedFormat++; + if (selectedFormat >= formats.size()) { + selectedFormat = 0; + } + + format = formats.get(selectedFormat); + + invalidate(); + } +} diff --git a/src/be/nikiroo/jvcard/tui/panes/FileList.java b/src/be/nikiroo/jvcard/tui/panes/FileList.java new file mode 100644 index 0000000..9930070 --- /dev/null +++ b/src/be/nikiroo/jvcard/tui/panes/FileList.java @@ -0,0 +1,69 @@ +package be.nikiroo.jvcard.tui.panes; + +import java.io.File; +import java.util.List; + +import be.nikiroo.jvcard.tui.KeyAction; +import be.nikiroo.jvcard.tui.UiColors; +import be.nikiroo.jvcard.tui.KeyAction.DataType; +import be.nikiroo.jvcard.tui.KeyAction.Mode; + +import com.googlecode.lanterna.gui2.Label; + +public class FileList extends MainContentList { + private List files; + + public FileList(List files) { + super(UiColors.Element.CONTACT_LINE, + UiColors.Element.CONTACT_LINE_SELECTED); + + setFiles(files); + } + + /** + * Change the list of currently selected files. + * + * @param files + * the new files + */ + public void setFiles(List files) { + clearItems(); + this.files = files; + + // TODO + for (File file : files) { + addItem(file.getName()); + } + + setSelectedIndex(0); + } + + @Override + public DataType getDataType() { + return DataType.CARD_FILES; + } + + @Override + public String getExitWarning() { + // TODO Auto-generated method stub + return null; + } + + @Override + public List getKeyBindings() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Mode getMode() { + return Mode.FILE_LIST; + } + + @Override + public String getTitle() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/src/be/nikiroo/jvcard/tui/panes/MainContent.java b/src/be/nikiroo/jvcard/tui/panes/MainContent.java new file mode 100644 index 0000000..df87313 --- /dev/null +++ b/src/be/nikiroo/jvcard/tui/panes/MainContent.java @@ -0,0 +1,81 @@ +package be.nikiroo.jvcard.tui.panes; + +import java.util.List; + +import be.nikiroo.jvcard.tui.KeyAction; + +import com.googlecode.lanterna.gui2.Direction; +import com.googlecode.lanterna.gui2.LinearLayout; +import com.googlecode.lanterna.gui2.Panel; + +/** + * This class represents the main content that you can see in this application + * (i.e., everything but the title and the actions keys is a {@link Panel} + * extended from this class). + * + * @author niki + * + */ +abstract public class MainContent extends Panel { + + public MainContent() { + super(); + } + + public MainContent(Direction dir) { + super(); + LinearLayout layout = new LinearLayout(dir); + layout.setSpacing(0); + setLayoutManager(layout); + } + + /** + * The title to display instead of the application name, or NULL for the + * default application name. + * + * @return the title or NULL + */ + abstract public String getTitle(); + + /** + * Returns an error message ready to be displayed if we should ask something + * to the user before exiting. + * + * @return an error message or NULL + */ + abstract public String getExitWarning(); + + /** + * The {@link KeyAction#Mode} that links to this {@link MainContent}. + * + * @return the linked mode + */ + abstract public KeyAction.Mode getMode(); + + /** + * The kind of data displayed by this {@link MainContent}. + * + * @return the kind of data displayed + */ + abstract public KeyAction.DataType getDataType(); + + /** + * Returns the list of actions and the keys that are bound to it. + * + * @return the list of actions + */ + abstract public List getKeyBindings(); + + /** + * Move the active cursor (not the text cursor, but the currently active + * item). + * + * @param x + * the horizontal move (< 0 for left, > 0 for right) + * @param y + * the vertical move (< 0 for up, > 0 for down) + * + * @return the error message to display if any + */ + abstract public String move(int x, int y); +} diff --git a/src/be/nikiroo/jvcard/tui/panes/MainContentList.java b/src/be/nikiroo/jvcard/tui/panes/MainContentList.java new file mode 100644 index 0000000..137a68d --- /dev/null +++ b/src/be/nikiroo/jvcard/tui/panes/MainContentList.java @@ -0,0 +1,144 @@ +package be.nikiroo.jvcard.tui.panes; + +import be.nikiroo.jvcard.tui.UiColors; + +import com.googlecode.lanterna.gui2.ActionListBox; +import com.googlecode.lanterna.gui2.Direction; +import com.googlecode.lanterna.gui2.LinearLayout; +import com.googlecode.lanterna.gui2.TextGUIGraphics; +import com.googlecode.lanterna.gui2.AbstractListBox.ListItemRenderer; + +abstract public class MainContentList extends MainContent implements Runnable { + private ActionListBox lines; + + public MainContentList(final UiColors.Element normalStyle, + final UiColors.Element selectedStyle) { + super(Direction.VERTICAL); + + lines = new ActionListBox(); + + lines + .setListItemRenderer(new ListItemRenderer() { + /** + * This is the main drawing method for a single list box + * item, it applies the current theme to setup the colors + * and then calls {@code getLabel(..)} and draws the result + * using the supplied {@code TextGUIGraphics}. The graphics + * object is created just for this item and is restricted so + * that it can only draw on the area this item is occupying. + * The top-left corner (0x0) should be the starting point + * when drawing the item. + * + * @param graphics + * Graphics object to draw with + * @param listBox + * List box we are drawing an item from + * @param index + * Index of the item we are drawing + * @param item + * The item we are drawing + * @param selected + * Will be set to {@code true} if the item is + * currently selected, otherwise {@code false}, + * but please notice what context 'selected' + * refers to here (see {@code setSelectedIndex}) + * @param focused + * Will be set to {@code true} if the list box + * currently has input focus, otherwise {@code + * false} + */ + public void drawItem(TextGUIGraphics graphics, + ActionListBox listBox, int index, Runnable item, + boolean selected, boolean focused) { + + if (selected && focused) { + graphics.setForegroundColor(selectedStyle + .getForegroundColor()); + graphics.setBackgroundColor(selectedStyle + .getBackgroundColor()); + } else { + graphics.setForegroundColor(normalStyle + .getForegroundColor()); + graphics.setBackgroundColor(normalStyle + .getBackgroundColor()); + } + + // original impl: + // String label = getLabel(listBox, index, item); + // label = TerminalTextUtils.fitString(label, + // graphics.getSize().getColumns()); + + // TODO: why +5 ?? padding problem? + String label = MainContentList.this.getLabel(index, + lines.getSize().getColumns() + 5); + graphics.putString(0, 0, label); + } + }); + + addComponent(lines, LinearLayout + .createLayoutData(LinearLayout.Alignment.Fill)); + } + + /** + * Add an item to this {@link MainContentList}. + * + * @param line + * the item to add + */ + public void addItem(String line) { + lines.addItem(line, this); + } + + /** + * Clear all the items in this {@link MainContentList} + */ + public void clearItems() { + lines.clearItems(); + } + + /** + * Get the index of the currently selected line. + * + * @return the index + */ + public int getSelectedIndex() { + return lines.getSelectedIndex(); + } + + /** + * Change the index of the currently selected line. + * + * @param index + * the new index + */ + public void setSelectedIndex(int index) { + lines.setSelectedIndex(index); + } + + @Override + public void run() { + // item selected. + // ignore. + } + + @Override + public String move(int x, int y) { + setSelectedIndex(getSelectedIndex() + x); + // TODO: y? + return null; + } + + /** + * Return the text representation of the selected line. + * + * @param index + * the line index + * @param width + * the max width of the line + * + * @return the text representation + */ + protected String getLabel(int index, int width) { + return "" + lines.getItems().get(index); + } +} -- 2.27.0