X-Git-Url: http://git.nikiroo.be/?p=jvcard.git;a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Fjvcard%2Ftui%2FMainWindow.java;h=13c6b3e238a4e021873d2a4694a667b023137eb8;hp=459d1b1a4dabfea6a13dd6049c2afce3c1d95b5c;hb=296a0b75515b3a7424b98292c87cbbf2272b73f9;hpb=bcb54330afff6a443ab43ee3d38cc7f863c701b7 diff --git a/src/be/nikiroo/jvcard/tui/MainWindow.java b/src/be/nikiroo/jvcard/tui/MainWindow.java index 459d1b1..13c6b3e 100644 --- a/src/be/nikiroo/jvcard/tui/MainWindow.java +++ b/src/be/nikiroo/jvcard/tui/MainWindow.java @@ -9,10 +9,11 @@ import java.util.List; import be.nikiroo.jvcard.Card; import be.nikiroo.jvcard.Contact; import be.nikiroo.jvcard.Data; +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.ContactDetailsRaw; import be.nikiroo.jvcard.tui.panes.ContactList; import be.nikiroo.jvcard.tui.panes.MainContent; @@ -25,7 +26,6 @@ import com.googlecode.lanterna.gui2.Label; import com.googlecode.lanterna.gui2.LinearLayout; import com.googlecode.lanterna.gui2.Panel; import com.googlecode.lanterna.gui2.TextBox; -import com.googlecode.lanterna.gui2.TextGUIGraphics; import com.googlecode.lanterna.gui2.Window; import com.googlecode.lanterna.input.KeyStroke; import com.googlecode.lanterna.input.KeyType; @@ -42,8 +42,7 @@ public class MainWindow extends BasicWindow { private List actions = new LinkedList(); private List contentStack = new LinkedList(); private boolean waitForOneKeyAnswer; - private KeyStroke questionKey; // key that "asked" a question, and to replay - // later with an answer + private KeyAction questionAction; private String titleCache; private Panel titlePanel; private Panel mainPanel; @@ -51,7 +50,6 @@ public class MainWindow extends BasicWindow { private Panel actionPanel; private Panel messagePanel; private TextBox text; - private int width; /** * Create a new, empty window. @@ -69,8 +67,6 @@ public class MainWindow extends BasicWindow { public MainWindow(MainContent content) { super(content == null ? "" : content.getTitle()); - width = -1; - setHints(Arrays.asList(Window.Hint.FULL_SCREEN, Window.Hint.NO_DECORATIONS, Window.Hint.FIT_TERMINAL_WINDOW)); @@ -201,13 +197,15 @@ public class MainWindow extends BasicWindow { * {@link MainWindow#handleQuestion}. The user will be asked to enter some * answer and confirm with ENTER. * + * @param action + * the related action * @param question * the question to ask * @param initial * the initial answer if any (to be edited by the user) */ - public void setQuestion(KeyStroke key, String question, String initial) { - setQuestion(key, question, initial, false); + public void setQuestion(KeyAction action, String question, String initial) { + setQuestion(action, question, initial, false); } /** @@ -215,41 +213,21 @@ public class MainWindow extends BasicWindow { * {@link MainWindow#handleQuestion}. The user will be asked to hit one key * as an answer. * + * @param action + * the related action * @param question * the question to ask */ - public void setQuestion(KeyStroke key, String question) { - setQuestion(key, question, null, true); - } - - @Override - public void draw(TextGUIGraphics graphics) { - int width = graphics.getSize().getColumns(); - - if (width != this.width) { - this.width = width; - - setTitle(); - - if (actions != null) - setActions(new ArrayList(actions), false); - } - - super.draw(graphics); - } - - @Override - public void invalidate() { - super.invalidate(); - for (MainContent content : contentStack) { - content.invalidate(); - } + public void setQuestion(KeyAction action, String question) { + setQuestion(action, question, null, true); } /** * Show a question to the user and switch to "ask for answer" mode see * {@link MainWindow#handleQuestion}. * + * @param action + * the related action * @param question * the question to ask * @param initial @@ -258,9 +236,9 @@ public class MainWindow extends BasicWindow { * TRUE for a one-key answer, FALSE for a text answer validated * by ENTER */ - private void setQuestion(KeyStroke key, String question, String initial, + private void setQuestion(KeyAction action, String question, String initial, boolean oneKey) { - questionKey = key; + questionAction = action; waitForOneKeyAnswer = oneKey; messagePanel.removeAllComponents(); @@ -272,8 +250,8 @@ public class MainWindow extends BasicWindow { Label lbl = UiColors.Element.LINE_MESSAGE_QUESTION.createLabel(" " + question + " "); - text = new TextBox(new TerminalSize(width - lbl.getSize().getColumns(), - 1)); + text = new TextBox(new TerminalSize(getSize().getColumns() + - lbl.getSize().getColumns(), 1)); if (initial != null) text.setText(initial); @@ -289,9 +267,61 @@ public class MainWindow extends BasicWindow { text.takeFocus(); } + /** + * Refresh the window and the empty-space handling. You should call this + * method when the window size changed. + * + * @param size + * the new size of the window + */ + public void refresh(TerminalSize size) { + if (size == null) + return; + + if (getSize() == null || !getSize().equals(size)) + setSize(size); + + setTitle(); + + if (actions != null) + setActions(new ArrayList(actions), false); + + invalidate(); + } + + @Override + public void invalidate() { + super.invalidate(); + for (MainContent content : contentStack) { + content.invalidate(); + } + } + + @Override + public boolean handleInput(KeyStroke key) { + boolean handled = false; + + if (questionAction != null) { + String answer = handleQuestion(key); + if (answer != null) { + handled = true; + + handleAction(questionAction, answer); + questionAction = null; + } + } else { + handled = handleKey(key); + } + + if (!handled) + handled = super.handleInput(key); + + return handled; + } + /** * Actually set the title inside the window. Will also call - * {@link BasicWindow#setTitle} with the compuited parameters. + * {@link BasicWindow#setTitle} with the computed parameters. */ private void setTitle() { String prefix = " " + Main.APPLICATION_TITLE + " (version " @@ -311,6 +341,8 @@ public class MainWindow extends BasicWindow { if (title.length() > 0) { prefix = prefix + ": "; + title = StringUtils.sanitize(title, UiColors.getInstance() + .isUnicode()); } String countStr = ""; @@ -318,6 +350,11 @@ public class MainWindow extends BasicWindow { countStr = "[" + count + "]"; } + int width = -1; + if (getSize() != null) { + width = getSize().getColumns(); + } + if (width > 0) { int padding = width - prefix.length() - title.length() - countStr.length(); @@ -398,29 +435,7 @@ public class MainWindow extends BasicWindow { if (" ".equals(trans)) continue; - String keyTrans = ""; - switch (action.getKey().getKeyType()) { - case Enter: - keyTrans = " ⤶ "; - break; - case Tab: - keyTrans = " ↹ "; - break; - case Character: - keyTrans = " " + action.getKey().getCharacter() + " "; - break; - default: - keyTrans = "" + action.getKey().getKeyType(); - int width = 3; - if (keyTrans.length() > width) { - keyTrans = keyTrans.substring(0, width); - } else if (keyTrans.length() < width) { - keyTrans = keyTrans - + new String(new char[width - keyTrans.length()]) - .replace('\0', ' '); - } - break; - } + String keyTrans = Trans.getInstance().trans(action.getKey()); Panel kPane = new Panel(); LinearLayout layout = new LinearLayout(Direction.HORIZONTAL); @@ -435,10 +450,14 @@ public class MainWindow extends BasicWindow { } // fill with "desc" colour + int width = -1; + if (getSize() != null) { + width = getSize().getColumns(); + } + if (width > 0) { actionPanel.addComponent(UiColors.Element.ACTION_DESC .createLabel(StringUtils.padString("", width))); - } } @@ -487,178 +506,166 @@ public class MainWindow extends BasicWindow { * * @return if the window handled the input */ - private boolean handleInput(KeyStroke key, String answer) { + private boolean handleKey(KeyStroke key) { boolean handled = false; - // reset the message pane if no answers are pending - if (answer == null) { - if (setMessage(null, false)) - return true; - } + if (setMessage(null, false)) + return true; for (KeyAction action : actions) { if (!action.match(key)) continue; - MainContent content = getContent(); handled = true; if (action.onAction()) { - Card card = action.getCard(); - Contact contact = action.getContact(); - Data data = action.getData(); - - switch (action.getMode()) { - case MOVE: - int x = 0; - int y = 0; - - if (action.getKey().getKeyType() == KeyType.ArrowUp) - x = -1; - if (action.getKey().getKeyType() == KeyType.ArrowDown) - x = 1; - if (action.getKey().getKeyType() == KeyType.ArrowLeft) - y = -1; - if (action.getKey().getKeyType() == KeyType.ArrowRight) - y = 1; - - if (content != null) { - String err = content.move(x, y); - if (err != null) - setMessage(err, true); - } + handleAction(action, null); + } - break; - // mode with windows: - case CONTACT_LIST: - if (card != null) { - pushContent(new ContactList(card)); - } - break; - case CONTACT_DETAILS: - if (contact != null) { - pushContent(new ContactDetails(contact)); - } - break; - // mode interpreted by MainWindow: - case HELP: - // TODO - // setMessage("Help! I need somebody! Help!", false); - if (answer == null) { - setQuestion(key, "Test question?", "[initial]"); - } else { - setMessage("You answered: " + answer, false); - } + break; + } - break; - case BACK: - String warning = content.getExitWarning(); - if (warning != null) { - if (answer == null) { - setQuestion(key, warning); - } else { - setMessage(null, false); - if (answer.equalsIgnoreCase("y")) { - popContent(); - } - } - } else { + return handled; + } + + /** + * Handle the input in case of "normal" (not "ask for answer") mode. + * + * @param key + * the key that was pressed + * @param answer + * the answer given for this key + * + * @return if the window handled the input + */ + private void handleAction(KeyAction action, String answer) { + MainContent content = getContent(); + + Card card = action.getCard(); + Contact contact = action.getContact(); + Data data = action.getData(); + + switch (action.getMode()) { + case MOVE: + int x = 0; + int y = 0; + + if (action.getKey().getKeyType() == KeyType.ArrowUp) + x = -1; + if (action.getKey().getKeyType() == KeyType.ArrowDown) + x = 1; + if (action.getKey().getKeyType() == KeyType.ArrowLeft) + y = -1; + if (action.getKey().getKeyType() == KeyType.ArrowRight) + y = 1; + + if (content != null) { + String err = content.move(x, y); + if (err != null) + setMessage(err, true); + } + + break; + // mode with windows: + case CONTACT_LIST: + if (card != null) { + pushContent(new ContactList(card)); + } + break; + case CONTACT_DETAILS: + if (contact != null) { + pushContent(new ContactDetailsRaw(contact)); + } + break; + // mode interpreted by MainWindow: + case HELP: + // TODO + // setMessage("Help! I need somebody! Help!", false); + if (answer == null) { + setQuestion(action, "Test question?", "[initial]"); + } else { + setMessage("You answered: " + answer, false); + } + + break; + case BACK: + String warning = content.getExitWarning(); + if (warning != null) { + if (answer == null) { + setQuestion(action, warning); + } else { + setMessage(null, false); + if (answer.equalsIgnoreCase("y")) { popContent(); } + } + } else { + popContent(); + } - if (contentStack.size() == 0) { - close(); - } + if (contentStack.size() == 0) { + close(); + } - break; - // action modes: - case EDIT_DETAIL: - if (answer == null) { - if (data != null) { - String name = data.getName(); - String value = data.getValue(); - setQuestion(key, name, value); - } + break; + // action modes: + case EDIT_DETAIL: + if (answer == null) { + if (data != null) { + String name = data.getName(); + String value = data.getValue(); + setQuestion(action, name, value); + } + } else { + setMessage(null, false); + data.setValue(answer); + } + break; + case DELETE_CONTACT: + if (answer == null) { + if (contact != null) { + setQuestion(action, "Delete contact? [Y/N]"); + } + } else { + setMessage(null, false); + if (answer.equalsIgnoreCase("y")) { + if (contact.delete()) { + content.refreshData(); + invalidate(); + setTitle(); } else { - setMessage(null, false); - data.setValue(answer); + setMessage("Cannot delete this contact", true); } - break; - case DELETE_CONTACT: - if (answer == null) { - if (contact != null) { - setQuestion(key, "Delete contact? [Y/N]"); - } - } else { - setMessage(null, false); - if (answer.equalsIgnoreCase("y")) { - if (contact.delete()) { - content.refreshData(); - invalidate(); - setTitle(); - } else { - setMessage("Cannot delete this contact", true); - } + } + } + break; + case SAVE_CARD: + if (answer == null) { + if (card != null) { + setQuestion(action, "Save changes? [Y/N]"); + } + } else { + setMessage(null, false); + if (answer.equalsIgnoreCase("y")) { + boolean ok = false; + try { + if (card.save()) { + ok = true; + invalidate(); } + } catch (IOException ioe) { + ioe.printStackTrace(); } - break; - case SAVE_CARD: - if (answer == null) { - if (card != null) { - setQuestion(key, "Save changes? [Y/N]"); - } - } else { - setMessage(null, false); - if (answer.equalsIgnoreCase("y")) { - boolean ok = false; - try { - if (card.save()) { - ok = true; - invalidate(); - } - } catch (IOException ioe) { - ioe.printStackTrace(); - } - - if (!ok) { - setMessage("Cannot save to file", true); - } - } + + if (!ok) { + setMessage("Cannot save to file", true); } - break; - default: - case NONE: - break; } } - + break; + default: + case NONE: break; } - - return handled; - } - - @Override - public boolean handleInput(KeyStroke key) { - boolean handled = false; - - if (questionKey != null) { - String answer = handleQuestion(key); - if (answer != null) { - handled = true; - - key = questionKey; - questionKey = null; - - handleInput(key, answer); - } - } else { - handled = handleInput(key, null); - } - - if (!handled) - handled = super.handleInput(key); - - return handled; } }