* @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];
totalSize += value.length();
}
}
-
+
if (width > -1 && totalSize > width) {
int toDo = totalSize - width;
for (int i = fixedsizeFields.length - 1; toDo > 0 && i >= 0; i--) {
totalSize = width + toDo;
}
-
+
if (width > -1 && numOfFieldsToExpand > 0) {
int availablePadding = width - totalSize;
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[] {});
}
/**
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.
*
*/
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);
package be.nikiroo.jvcard.tui;
+import java.io.File;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
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.
*
.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);
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);
}
}
- /**
- * 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;
}
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.
return mapForegroundColor.get(el);
}
- return TextColor.ANSI.BLUE;
+ return TextColor.ANSI.BLACK;
}
private TextColor getBackgroundColor(Element el) {
return mapBackgroundColor.get(el);
}
- return TextColor.ANSI.BLUE;
+ return TextColor.ANSI.WHITE;
}
private 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);
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;
}
@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() {
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;
@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
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;
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);
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);
}
});
public void addItem(String line) {
lines.addItem(line, this);
}
-
+
/**
* Clear all the items in this {@link MainContentList}
*/
}
/**
- * 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;
}
}