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;
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<File> files = new LinkedList<File>();
+ 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);
/*
package be.nikiroo.jvcard.tui;
+import java.io.File;
+
import be.nikiroo.jvcard.Card;
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
* @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;
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;
messagePanel.addComponent(hpanel, LinearLayout
.createLayoutData(LinearLayout.Alignment.Beginning));
- this.setFocusedInteractable(text);
+ text.takeFocus();
}
}
// focus = content.get(0).getDefaultFocusElement();
focus = content.get(0).nextFocus(null);
- this.setFocusedInteractable(focus);
+ focus.takeFocus();
}
return answer;
--- /dev/null
+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<KeyAction> 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;
+ }
+}
--- /dev/null
+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<String> formats = new LinkedList<String>();
+ 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<KeyAction> getKeyBindings() {
+ List<KeyAction> actions = new LinkedList<KeyAction>();
+
+ // 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();
+ }
+}
--- /dev/null
+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<File> files;
+
+ public FileList(List<File> 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<File> 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<KeyAction> 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;
+ }
+
+}
--- /dev/null
+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<KeyAction> 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);
+}
--- /dev/null
+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<Runnable, ActionListBox>() {
+ /**
+ * 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);
+ }
+}