Some changes to support Files
authorNiki Roo <roo.niki@gmail.com>
Wed, 24 Feb 2016 15:50:28 +0000 (16:50 +0100)
committerNiki Roo <roo.niki@gmail.com>
Wed, 24 Feb 2016 15:50:28 +0000 (16:50 +0100)
src/be/nikiroo/jvcard/Contact.java
src/be/nikiroo/jvcard/i18n/Trans.java
src/be/nikiroo/jvcard/tui/MainWindow.java
src/be/nikiroo/jvcard/tui/UiColors.java
src/be/nikiroo/jvcard/tui/panes/ContactList.java
src/be/nikiroo/jvcard/tui/panes/FileList.java
src/be/nikiroo/jvcard/tui/panes/MainContentList.java

index 08d5eee0fdcfe25588d37f466293225af6c17217..f2a8b01b5ac4be470383f2b29934fde412bbeca8 100644 (file)
@@ -159,34 +159,71 @@ public class Contact {
         * @return the {@link String} representation
         */
        public String toString(String format, String separator, int width) {
-               String str = null;
+               StringBuilder builder = new StringBuilder();
 
                String[] formatFields = format.split("\\|");
-               String[] values = new String[formatFields.length];
-               Boolean[] expandedFields = new Boolean[formatFields.length];
-               Boolean[] fixedsizeFields = new Boolean[formatFields.length];
-               int numOfFieldsToExpand = 0;
-               int totalSize = 0;
-
-               if (width == 0) {
-                       return "";
-               }
-
                if (width > -1 && separator != null && separator.length() > 0
                                && formatFields.length > 1) {
                        int swidth = (formatFields.length - 1) * separator.length();
                        if (swidth >= width) {
-                               str = separator;
-                               while (str.length() < width) {
-                                       str += separator;
+                               int num = width / separator.length();
+                               int remainder = width % separator.length();
+
+                               if (remainder > 0)
+                                       num++;
+
+                               while (builder.length() < width) {
+                                       if (builder.length() + separator.length() <= width)
+                                               builder.append(separator);
+                                       else
+                                               builder.append(separator
+                                                               .substring(0, (builder.length() + separator
+                                                                               .length())
+                                                                               - width));
                                }
 
-                               return str.substring(0, width);
+                               return builder.toString();
                        }
 
                        width -= swidth;
                }
 
+               for (String str : toStringArray(format, width)) {
+                       builder.append(str);
+               }
+
+               return builder.toString();
+       }
+
+       /**
+        * Return a {@link String} representation of this contact formated
+        * accordingly to the given format, part by part.
+        * 
+        * The format is basically a list of field names separated by a pipe and
+        * optionally parametrised. See {@link Contact#toString} for more
+        * information about the format.
+        * 
+        * @param format
+        *            the format to use
+        * @param width
+        *            a fixed width or -1 for "as long as needed"
+        * 
+        * @return the {@link String} representation
+        */
+       public String[] toStringArray(String format, int width) {
+               List<String> str = new LinkedList<String>();
+
+               String[] formatFields = format.split("\\|");
+               String[] values = new String[formatFields.length];
+               Boolean[] expandedFields = new Boolean[formatFields.length];
+               Boolean[] fixedsizeFields = new Boolean[formatFields.length];
+               int numOfFieldsToExpand = 0;
+               int totalSize = 0;
+
+               if (width == 0) {
+                       return str.toArray(new String[] {});
+               }
+
                for (int i = 0; i < formatFields.length; i++) {
                        String field = formatFields[i];
 
@@ -236,7 +273,7 @@ public class Contact {
                                totalSize += value.length();
                        }
                }
-               
+
                if (width > -1 && totalSize > width) {
                        int toDo = totalSize - width;
                        for (int i = fixedsizeFields.length - 1; toDo > 0 && i >= 0; i--) {
@@ -257,7 +294,7 @@ public class Contact {
 
                        totalSize = width + toDo;
                }
-               
+
                if (width > -1 && numOfFieldsToExpand > 0) {
                        int availablePadding = width - totalSize;
 
@@ -284,23 +321,13 @@ public class Contact {
                                totalSize = width;
                        }
                }
-               
-               for (String field : values) {
-                       if (str == null) {
-                               str = field;
-                       } else {
-                               str += separator + field;
-                       }
-               }
-
-               if (str == null)
-                       str = "";
 
-               if (width > -1) {
-                       str = fixedString(str, width);
+               int currentSize = 0;
+               for (int i = 0; i < values.length; i++) {
+                       currentSize += addToList(str, values[i], currentSize, width);
                }
 
-               return str;
+               return str.toArray(new String[] {});
        }
 
        /**
@@ -326,6 +353,41 @@ public class Contact {
                return string;
        }
 
+       /**
+        * Add a {@link String} to the given {@link List}, but make sure it does not
+        * exceed the maximum size, and truncate it if needed to fit.
+        * 
+        * @param list
+        * @param add
+        * @param currentSize
+        * @param maxSize
+        * @return
+        */
+       static private int addToList(List<String> list, String add,
+                       int currentSize, int maxSize) {
+               if (add == null || add.length() == 0) {
+                       if (add != null)
+                               list.add(add);
+                       return 0;
+               }
+
+               if (maxSize > -1) {
+                       if (currentSize < maxSize) {
+                               if (currentSize + add.length() >= maxSize) {
+                                       add = add.substring(0, maxSize - currentSize);
+                               }
+                       } else {
+                               add = "";
+                       }
+               }
+
+               if (add.length() > 0) {
+                       list.add(add);
+               }
+
+               return add.length();
+       }
+
        /**
         * Return a {@link String} representation of this contact, in vCard 2.1,
         * without BKeys.
index 3ea95625ca177182d75a0ddce0be5fcd68cd1a63..8c744d38f2123ccf08eeb309d6837d69319133d7 100644 (file)
@@ -23,7 +23,7 @@ public class Trans {
         * 
         */
        public enum StringId {
-               KEY_ACTION_BACK, KEY_ACTION_HELP, KEY_ACTION_VIEW_CONTACT, KEY_ACTION_EDIT_CONTACT, KEY_ACTION_SWITCH_FORMAT, TITLE, NULL;
+               KEY_ACTION_BACK, KEY_ACTION_HELP, KEY_ACTION_VIEW_CONTACT, KEY_ACTION_VIEW_CARD, KEY_ACTION_EDIT_CONTACT, KEY_ACTION_SWITCH_FORMAT, TITLE, NULL;
 
                public String trans() {
                        return Trans.getInstance().trans(this);
index 7f438d918a717792f2686d6a86379c8949d74dd2..aa996353c9b2b8d292dfa92761f763c94bd98a09 100644 (file)
@@ -1,5 +1,6 @@
 package be.nikiroo.jvcard.tui;
 
+import java.io.File;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -122,13 +123,30 @@ public class MainWindow extends BasicWindow {
                        actions = content.getKeyBindings();
                        contentPanel.addComponent(content, BorderLayout.Location.CENTER);
                        this.content.add(content);
+
+                       Interactable focus = content.nextFocus(null);
+                       if (focus != null)
+                               focus.takeFocus();
                }
 
                setTitle(title);
                setActions(actions, true, true);
+
                invalidate();
        }
 
+       public MainContent popContent() {
+               MainContent removed = null;
+               MainContent prev = null;
+               if (content.size() > 0)
+                       removed = content.remove(content.size() - 1);
+               if (content.size() > 0)
+                       prev = content.remove(content.size() - 1);
+               pushContent(prev);
+
+               return removed;
+       }
+
        /**
         * Set the application title.
         * 
@@ -152,6 +170,52 @@ public class MainWindow extends BasicWindow {
                                .createLayoutData(LinearLayout.Alignment.Center));
        }
 
+       /**
+        * Show the given message on screen. It will disappear at the next action.
+        * 
+        * @param mess
+        *            the message to display
+        * @param error
+        *            TRUE for an error message, FALSE for an information message
+        */
+       public void setMessage(String mess, boolean error) {
+               messagePanel.removeAllComponents();
+               if (mess != null) {
+                       Element element = (error ? UiColors.Element.LINE_MESSAGE_ERR
+                                       : UiColors.Element.LINE_MESSAGE);
+                       Label lbl = element.createLabel(" " + mess + " ");
+                       messagePanel.addComponent(lbl, LinearLayout
+                                       .createLayoutData(LinearLayout.Alignment.Center));
+               }
+       }
+
+       public void setQuestion(String mess, boolean oneKey) {
+               messagePanel.removeAllComponents();
+               if (mess != null) {
+                       waitForOneKeyAnswer = oneKey;
+
+                       Panel hpanel = new Panel();
+                       LinearLayout llayout = new LinearLayout(Direction.HORIZONTAL);
+                       llayout.setSpacing(0);
+                       hpanel.setLayoutManager(llayout);
+
+                       Label lbl = UiColors.Element.LINE_MESSAGE_QUESTION.createLabel(" "
+                                       + mess + " ");
+                       text = new TextBox(new TerminalSize(getSize().getColumns()
+                                       - lbl.getSize().getColumns(), 1));
+
+                       hpanel.addComponent(lbl, LinearLayout
+                                       .createLayoutData(LinearLayout.Alignment.Beginning));
+                       hpanel.addComponent(text, LinearLayout
+                                       .createLayoutData(LinearLayout.Alignment.Fill));
+
+                       messagePanel.addComponent(hpanel, LinearLayout
+                                       .createLayoutData(LinearLayout.Alignment.Beginning));
+
+                       text.takeFocus();
+               }
+       }
+
        @Override
        public void draw(TextGUIGraphics graphics) {
                setTitle(title);
@@ -165,24 +229,12 @@ public class MainWindow extends BasicWindow {
                super.draw(graphics);
        }
 
-       public MainContent popContent() {
-               MainContent removed = null;
-               MainContent prev = null;
-               if (content.size() > 0)
-                       removed = content.remove(content.size() - 1);
-               if (content.size() > 0)
-                       prev = content.remove(content.size() - 1);
-               pushContent(prev);
-
-               return removed;
-       }
-
        private void setActions(List<KeyAction> actions, boolean allowKeys,
                        boolean enableDefaultactions) {
 
                this.actions.clear();
                actionsPadded = false;
-               
+
                if (enableDefaultactions)
                        this.actions.addAll(defaultActions);
 
@@ -233,52 +285,6 @@ public class MainWindow extends BasicWindow {
                }
        }
 
-       /**
-        * Show the given message on screen. It will disappear at the next action.
-        * 
-        * @param mess
-        *            the message to display
-        * @param error
-        *            TRUE for an error message, FALSE for an information message
-        */
-       public void setMessage(String mess, boolean error) {
-               messagePanel.removeAllComponents();
-               if (mess != null) {
-                       Element element = (error ? UiColors.Element.LINE_MESSAGE_ERR
-                                       : UiColors.Element.LINE_MESSAGE);
-                       Label lbl = element.createLabel(" " + mess + " ");
-                       messagePanel.addComponent(lbl, LinearLayout
-                                       .createLayoutData(LinearLayout.Alignment.Center));
-               }
-       }
-
-       public void setQuestion(String mess, boolean oneKey) {
-               messagePanel.removeAllComponents();
-               if (mess != null) {
-                       waitForOneKeyAnswer = oneKey;
-
-                       Panel hpanel = new Panel();
-                       LinearLayout llayout = new LinearLayout(Direction.HORIZONTAL);
-                       llayout.setSpacing(0);
-                       hpanel.setLayoutManager(llayout);
-
-                       Label lbl = UiColors.Element.LINE_MESSAGE_QUESTION.createLabel(" "
-                                       + mess + " ");
-                       text = new TextBox(new TerminalSize(getSize().getColumns()
-                                       - lbl.getSize().getColumns(), 1));
-
-                       hpanel.addComponent(lbl, LinearLayout
-                                       .createLayoutData(LinearLayout.Alignment.Beginning));
-                       hpanel.addComponent(text, LinearLayout
-                                       .createLayoutData(LinearLayout.Alignment.Fill));
-
-                       messagePanel.addComponent(hpanel, LinearLayout
-                                       .createLayoutData(LinearLayout.Alignment.Beginning));
-
-                       text.takeFocus();
-               }
-       }
-
        private String handleQuestion(KeyStroke key) {
                String answer = null;
 
index 75c074a3609aed4ca602b45d646672f9a8ff5622..0525a53297f1789403bf3e471b2de6abc708082b 100644 (file)
@@ -34,7 +34,7 @@ public class UiColors {
        }
 
        public enum Element {
-               ACTION_KEY, ACTION_DESC, LINE_MESSAGE, LINE_MESSAGE_ERR, LINE_MESSAGE_QUESTION, LINE_MESSAGE_ANS, CONTACT_LINE, CONTACT_LINE_SELECTED;
+               DEFAULT, ACTION_KEY, ACTION_DESC, LINE_MESSAGE, LINE_MESSAGE_ERR, LINE_MESSAGE_QUESTION, LINE_MESSAGE_ANS, CONTACT_LINE, CONTACT_LINE_SEPARATOR, CONTACT_LINE_SELECTED, CONTACT_LINE_SEPARATOR_SELECTED;
 
                /**
                 * Get the foreground colour of this element.
@@ -79,7 +79,7 @@ public class UiColors {
                        return mapForegroundColor.get(el);
                }
 
-               return TextColor.ANSI.BLUE;
+               return TextColor.ANSI.BLACK;
        }
 
        private TextColor getBackgroundColor(Element el) {
@@ -87,7 +87,7 @@ public class UiColors {
                        return mapBackgroundColor.get(el);
                }
 
-               return TextColor.ANSI.BLUE;
+               return TextColor.ANSI.WHITE;
        }
 
        private UiColors() {
@@ -101,6 +101,9 @@ public class UiColors {
                addEl(Element.CONTACT_LINE, TextColor.ANSI.WHITE, TextColor.ANSI.BLACK);
                addEl(Element.CONTACT_LINE_SELECTED, TextColor.ANSI.WHITE,
                                TextColor.ANSI.BLUE);
+               addEl(Element.CONTACT_LINE_SEPARATOR, TextColor.ANSI.RED, TextColor.ANSI.BLACK);
+               addEl(Element.CONTACT_LINE_SEPARATOR_SELECTED, TextColor.ANSI.RED,
+                               TextColor.ANSI.BLUE);
                addEl(Element.LINE_MESSAGE, TextColor.ANSI.BLUE, TextColor.ANSI.WHITE);
                addEl(Element.LINE_MESSAGE_ERR, TextColor.ANSI.RED,
                                TextColor.ANSI.WHITE);
index 3a943f900610a75a56cec552be84eff1d7f4d5d0..7bb15dc6a048bd5277216f88b14d752f00c78de2 100644 (file)
@@ -9,6 +9,8 @@ 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 be.nikiroo.jvcard.tui.UiColors.Element;
+import be.nikiroo.jvcard.tui.panes.MainContentList.TextPart;
 
 import com.googlecode.lanterna.input.KeyType;
 
@@ -108,9 +110,31 @@ public class ContactList extends MainContentList {
        }
 
        @Override
-       protected String getLabel(int index, int width) {
+       protected List<TextPart> getLabel(int index, int width, boolean selected,
+                       boolean focused) {
+               List<TextPart> parts = new LinkedList<TextPart>();
+
+               Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
+                               : Element.CONTACT_LINE;
+               Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
+                               : Element.CONTACT_LINE_SEPARATOR;
+
+               // TODO: width/separator to check
+               String separator = " ┃ ";
+               width -= (format.split("\\|").length + 1) * separator.length();
+               String[] array = card.getContacts().get(index).toStringArray(format,
+                               width);
+
                // we could use: " ", "┃", "│"...
-               return card.getContacts().get(index).toString(format, " ┃ ", width);
+               for (String str : array) {
+                       parts.add(new TextPart(str, el));
+                       parts.add(new TextPart(separator, elSep));
+               }
+
+               if (parts.size() > 0)
+                       parts.remove(parts.get(parts.size() - 1));
+
+               return parts;
        }
 
        private void switchFormat() {
index 993007066ff75da71552bbc403c0a3280910e069..79f530e0604f38318d6b3283ce1dc75ce9530f88 100644 (file)
@@ -1,14 +1,19 @@
 package be.nikiroo.jvcard.tui.panes;
 
 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.i18n.Trans;
+import be.nikiroo.jvcard.parsers.Format;
 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;
+import com.googlecode.lanterna.input.KeyType;
 
 public class FileList extends MainContentList {
        private List<File> files;
@@ -51,8 +56,33 @@ public class FileList extends MainContentList {
 
        @Override
        public List<KeyAction> getKeyBindings() {
-               // TODO Auto-generated method stub
-               return null;
+               List<KeyAction> actions = new LinkedList<KeyAction>();
+
+               // TODO del, save...
+               actions.add(new KeyAction(Mode.CONTACT_LIST, KeyType.Enter,
+                               Trans.StringId.KEY_ACTION_VIEW_CARD) {
+                       @Override
+                       public Object getObject() {
+                               File file = files.get(getSelectedIndex());
+                               Format format = Format.Abook;
+                               String ext = file.getName();
+                               if (ext.contains(".")) {
+                                       String tab[] = ext.split("\\.");
+                                       if (tab.length > 1
+                                                       && tab[tab.length - 1].equalsIgnoreCase("vcf")) {
+                                               format = Format.VCard21;
+                                       }
+                               }
+                               try {
+                                       return new Card(file, format);
+                               } catch (IOException ioe) {
+                                       ioe.printStackTrace();
+                                       return null;
+                               }
+                       }
+               });
+
+               return actions;
        }
 
        @Override
index 137a68dd210833e6a8613c125d87fa289609e200..79cfb2baa6cec9f9aa482ad504040b9499fc2cb0 100644 (file)
@@ -1,7 +1,12 @@
 package be.nikiroo.jvcard.tui.panes;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import be.nikiroo.jvcard.tui.UiColors;
+import be.nikiroo.jvcard.tui.UiColors.Element;
 
+import com.googlecode.lanterna.TextColor;
 import com.googlecode.lanterna.gui2.ActionListBox;
 import com.googlecode.lanterna.gui2.Direction;
 import com.googlecode.lanterna.gui2.LinearLayout;
@@ -11,6 +16,43 @@ import com.googlecode.lanterna.gui2.AbstractListBox.ListItemRenderer;
 abstract public class MainContentList extends MainContent implements Runnable {
        private ActionListBox lines;
 
+       /**
+        * This class represent a part of a text line to draw in this
+        * {@link MainContentList}.
+        * 
+        * @author niki
+        * 
+        */
+       protected class TextPart {
+               private String text;
+               private Element element;
+
+               public TextPart(String text, Element element) {
+                       this.text = text;
+                       this.element = element;
+               }
+
+               public String getText() {
+                       return text;
+               }
+
+               public Element getElement() {
+                       return element;
+               }
+
+               public TextColor getForegroundColor() {
+                       if (element != null)
+                               return element.getForegroundColor();
+                       return Element.DEFAULT.getForegroundColor();
+               }
+
+               public TextColor getBackgroundColor() {
+                       if (element != null)
+                               return element.getBackgroundColor();
+                       return Element.DEFAULT.getBackgroundColor();
+               }
+       }
+
        public MainContentList(final UiColors.Element normalStyle,
                        final UiColors.Element selectedStyle) {
                super(Direction.VERTICAL);
@@ -51,27 +93,21 @@ abstract public class MainContentList extends MainContent implements Runnable {
                                                        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
+                                               // TODO: why +5 ?? padding problem?
+                                               List<TextPart> parts = MainContentList.this.getLabel(
+                                                               index, lines.getSize().getColumns() + 5,
+                                                               selected, focused);
+
+                                               int position = 0;
+                                               for (TextPart part : parts) {
+                                                       graphics.setForegroundColor(part
                                                                        .getForegroundColor());
-                                                       graphics.setBackgroundColor(normalStyle
+                                                       graphics.setBackgroundColor(part
                                                                        .getBackgroundColor());
+                                                       String label = part.getText();
+                                                       graphics.putString(position, 0, label);
+                                                       position += label.length();
                                                }
-
-                                               // 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);
                                        }
                                });
 
@@ -88,7 +124,7 @@ abstract public class MainContentList extends MainContent implements Runnable {
        public void addItem(String line) {
                lines.addItem(line, this);
        }
-       
+
        /**
         * Clear all the items in this {@link MainContentList}
         */
@@ -129,16 +165,31 @@ abstract public class MainContentList extends MainContent implements Runnable {
        }
 
        /**
-        * Return the text representation of the selected line.
+        * Return the representation of the selected line, in {@link TextPart}s.
         * 
         * @param index
         *            the line index
         * @param width
         *            the max width of the line
+        * @param selected
+        *            TRUE if the item is selected
+        * @param focused
+        *            TRUE if the item is focused
         * 
         * @return the text representation
         */
-       protected String getLabel(int index, int width) {
-               return "" + lines.getItems().get(index);
+       protected List<TextPart> getLabel(int index, int width, boolean selected,
+                       boolean focused) {
+               List<TextPart> parts = new LinkedList<TextPart>();
+
+               if (selected && focused) {
+                       parts.add(new TextPart("" + lines.getItems().get(index),
+                                       Element.CONTACT_LINE_SELECTED));
+               } else {
+                       parts.add(new TextPart("" + lines.getItems().get(index),
+                                       Element.CONTACT_LINE));
+               }
+
+               return parts;
        }
 }