Package com.ponysdk.ui.terminal.ui.widget.mask

Source Code of com.ponysdk.ui.terminal.ui.widget.mask.TextBoxMaskedDecorator$Flag

package com.ponysdk.ui.terminal.ui.widget.mask;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.ui.TextBox;

public class TextBoxMaskedDecorator implements KeyPressHandler, FocusHandler, KeyDownHandler {

    public static abstract class Flag {

        protected boolean set = false;
        protected char c;

        protected char freeSymbol;
        protected boolean showMask;

        public Flag() {}

        public Flag(final char c, final boolean showMask) {
            this.c = c;
            this.set = true;
            this.showMask = showMask;
        }

        public abstract boolean match(final char c);

        public boolean isDigit() {
            return false;
        }

        public boolean isChar() {
            return false;
        }

        public boolean isConst() {
            return false;
        }

        public boolean isSet() {
            return set;
        }

        public void unset() {
            this.set = false;
        }

        public void set(final char c) {
            this.c = c;
            this.set = true;
        }

        @Override
        public String toString() {
            if (isSet()) return Character.toString(c);
            return " ";
        }

        public char getValue(final boolean filling) {
            if (set) return c;
            return freeSymbol;
        }

    }

    public static class Digit extends Flag {

        public Digit(final char freeSymbol) {
            super();
            this.freeSymbol = freeSymbol;
        }

        @Override
        public boolean isDigit() {
            return true;
        }

        @Override
        public boolean match(final char c) {
            if (Character.isDigit(c)) return true;
            return false;
        }

        @Override
        public String toString() {
            if (isSet()) return Character.toString(c);
            return "0";
        }
    }

    public static class Char extends Flag {

        public Char(final char freeSymbol) {
            super();
            this.freeSymbol = freeSymbol;
        }

        @Override
        public boolean isChar() {
            return true;
        }

        @Override
        public boolean match(final char c) {
            if (Character.isLetter(c)) return true;
            return false;
        }

        @Override
        public String toString() {
            if (isSet()) return Character.toString(c);
            return "@";
        }
    }

    public static class Const extends Flag {

        public Const(final char c, final boolean showMask, final char freeSymbol) {
            super(c, showMask);
            this.freeSymbol = freeSymbol;
        }

        @Override
        public boolean isConst() {
            return true;
        }

        @Override
        public boolean match(final char c) {
            return c == this.c;
        }

        @Override
        public char getValue(final boolean filling) {
            if (!filling) {
                if (showMask) return c;
                return freeSymbol;
            }

            if (set) return c;
            return freeSymbol;
        }
    }

    public static class InputValue {

        private int insertPosition = 0;
        private List<Flag> flags;

        public void init(final List<Flag> flags) {
            this.flags = flags;
        }

        public void reset() {
            for (final Flag f : flags) {
                if (!f.isConst()) f.unset();
            }
        }

        public String getText() {
            boolean updateInsert = true;
            insertPosition = 0;
            int pos = 0;
            final StringBuilder sb = new StringBuilder();
            for (final Flag f : flags) {
                sb.append(f.getValue(updateInsert));
                if (!f.isSet()) {
                    updateInsert = false;
                }
                pos++;
                if (updateInsert) insertPosition = pos;
            }
            return sb.toString();
        }

        public int getInsertPosition() {
            return insertPosition;
        }

        public int insert(final int pos, final char charCode) {

            // if full, return
            if (pos >= flags.size()) return -1;

            int nextPositon = -1;
            Flag next = null;
            for (nextPositon = pos; nextPositon < flags.size(); nextPositon++) {
                next = flags.get(nextPositon);
                if (next.isConst()) {
                    if (next.match(charCode)) {
                        // consume key and exit
                        return -1;
                    }
                } else {
                    break;
                }
            }

            // if not assignable, return
            if (!next.match(charCode)) return -1;

            // we can set the new value, shift if required
            if (!next.isSet()) {
                next.set(charCode);
            } else {
                insert(pos + 1, next.c);
                next.set(charCode);
            }

            return nextPositon + 1;
        }

        public boolean remove(final int from, final int to) {
            if (from < 0) return false;

            for (int f = from; f < to; f++) {
                final Flag flag = flags.get(f);
                if (!flag.isConst()) flag.unset();
            }
            shift(from);

            return true;
        }

        private void shift(final int pos) {

            if (pos >= flags.size()) return;

            // go to next "settable"
            int next;
            Flag flag = null;
            for (next = pos; next < flags.size(); next++) {
                flag = flags.get(next);
                if (!flag.isConst() && !flag.isSet()) break;
            }

            if (flag == null) return;

            next++;

            // find next "value"
            for (int i = next; i < flags.size(); i++) {
                final Flag n = flags.get(i);
                if (n.isConst()) continue;
                if (!n.isSet()) continue;

                if (flag.match(n.c)) {
                    flag.set(n.c);
                    n.unset();
                }
                break;
            }

            shift(next);
        }

    }

    private static final RegExp regExp = RegExp.compile("{{([A0]+)}}", "g");

    private final InputValue value = new InputValue();
    private final TextBox textBox;

    public TextBoxMaskedDecorator(final TextBox textBox) {
        this.textBox = textBox;
        this.textBox.addKeyDownHandler(this);
        this.textBox.addKeyPressHandler(this);
        this.textBox.addFocusHandler(this);
    }

    public void setMask(final String mask, final boolean showMask, final char freeSymbol) {

        final List<Flag> flags = new ArrayList<Flag>();

        int current = 0;
        MatchResult matchResult = regExp.exec(mask);
        while (matchResult != null) {
            final String group = matchResult.getGroup(1);

            // Fill forced
            for (int i = current; i < matchResult.getIndex(); i++) {
                final char c = mask.charAt(current);
                flags.add(new Const(c, showMask, freeSymbol));
                current++;
            }

            // start of group '{{'
            current += 2;

            for (int i = 0; i < group.length(); i++) {
                if (Character.isDigit(group.charAt(i))) flags.add(new Digit(freeSymbol));
                else flags.add(new Char(freeSymbol));
                current++;
            }

            // end of group '}}'
            current += 2;

            matchResult = regExp.exec(mask);
        }

        // Fill forced
        for (int i = current; i < mask.length(); i++) {
            final char c = mask.charAt(current);
            flags.add(new Const(c, showMask, freeSymbol));
            current++;
        }

        value.init(flags);

        final String currentText = getText();
        for (int c = 0; c < currentText.length(); c++) {
            final int insert = value.insert(c, currentText.charAt(c));
            if (insert == -1) break;
        }

        final String text = value.getText();
        setText(text);
        setMaxLength(text.length());
    }

    @Override
    public void onFocus(final FocusEvent event) {
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {

            @Override
            public void execute() {
                setInitialPosition();
            }
        });
    }

    protected void setInitialPosition() {
        setText(value.getText());
        setCursorPos(value.getInsertPosition());
    }

    private void refresh(final int newPosition) {
        setText(value.getText());
        setCursorPos(newPosition);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {

        final int pos = getCursorPos();
        if (getSelectionLength() > 0) clearSelection();

        final int nextPos = value.insert(pos, event.getCharCode());
        if (nextPos != -1) {
            refresh(nextPos);
        }

        cancelKey();
    }

    @Override
    public void onKeyDown(final KeyDownEvent event) {
        final int pos = getCursorPos();
        if (event.getNativeKeyCode() == KeyCodes.KEY_BACKSPACE) {

            if (getSelectionLength() > 0) {
                clearSelection();
                cancelKey();
                return;
            }

            final int from = pos - 1;
            final int to = from + 1;

            int np = pos - 1;
            if (np < 0) np = 0;

            if (value.remove(from, to)) {
                refresh(np);
            } else {
                setCursorPos(np);
            }

            cancelKey();
        } else if (event.getNativeKeyCode() == KeyCodes.KEY_DELETE) {

            if (getSelectionLength() > 0) {
                clearSelection();
                cancelKey();
                return;
            }

            final int from = pos;
            final int to = from + 1;

            if (value.remove(from, to)) {
                refresh(pos);
            } else {
                setCursorPos(pos);
            }

            cancelKey();
        }
    }

    private void clearSelection() {
        final int from = getCursorPos();
        final int to = from + getSelectionLength();
        if (value.remove(from, to)) {
            refresh(from);
        } else {
            setCursorPos(from);
        }
    }

    // Delegates
    public void cancelKey() {
        textBox.cancelKey();
    }

    public int getCursorPos() {
        return textBox.getCursorPos();
    }

    public String getText() {
        return textBox.getText();
    }

    public int getSelectionLength() {
        return textBox.getSelectionLength();
    }

    public void setCursorPos(final int pos) {
        textBox.setCursorPos(pos);
    }

    public void setText(final String text) {
        textBox.setText(text);
    }

    public void setMaxLength(final int length) {
        textBox.setMaxLength(length);
    }

}
TOP

Related Classes of com.ponysdk.ui.terminal.ui.widget.mask.TextBoxMaskedDecorator$Flag

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.