1c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka/*
2c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Copyright (C) 2014 The Android Open Source Project
3c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka *
4c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
5c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * you may not use this file except in compliance with the License.
6c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * You may obtain a copy of the License at
7c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka *
8c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka *
10c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
11c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
12c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * See the License for the specific language governing permissions and
14c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * limitations under the License.
15c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */
16c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
17c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokapackage com.android.inputmethod.keyboard.layout.expected;
18c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
19c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport com.android.inputmethod.keyboard.Key;
20c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
21c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.MoreKeySpec;
22f62b5d633d17b94a7ea46c968e073fdaa3fcbe15Tadashi G. Takaokaimport com.android.inputmethod.latin.common.StringUtils;
23c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
24c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaokaimport java.util.Locale;
25c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
26c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka/**
27c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * This class represents an expected visual outlook of a key.
28c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka *
29c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka * There are two types of expected visual, an integer icon id and a string label.
30c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka */
3151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaokapublic abstract class ExpectedKeyVisual {
3251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    public static ExpectedKeyVisual newInstance(final String label) {
33c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        return new Label(label);
34c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    }
35c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
3651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    public static ExpectedKeyVisual newInstance(final int iconId) {
37c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        return new Icon(iconId);
38c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    }
39c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
4051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    public abstract int getIconId();
4151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    public abstract String getLabel();
42c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    abstract ExpectedKeyVisual toUpperCase(final Locale locale);
43c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka    abstract ExpectedKeyVisual preserveCase();
4451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    abstract boolean hasSameKeyVisual(final String text);
4551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    abstract boolean hasSameKeyVisual(final Key key);
4651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    abstract boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec);
4751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    abstract boolean hasSameKeyVisual(final ExpectedKeyOutput output);
4851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka    abstract boolean hasSameKeyVisual(final ExpectedKeyVisual visual);
49c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
50c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    /**
51c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka     * This class represents an integer icon id.
52c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka     */
53c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    private static class Icon extends ExpectedKeyVisual {
54c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        private final int mIconId;
55c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
56c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        Icon(final int iconId) {
57c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            mIconId = iconId;
58c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
59c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
60c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
6151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        public int getIconId() {
6251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mIconId;
6351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        }
6451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka
6551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        @Override
6651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        public String getLabel() {
6751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return null;
6851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        }
6951333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka
7051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        @Override
71c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        ExpectedKeyVisual toUpperCase(final Locale locale) {
72c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return this;
73c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
74c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
75c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
76c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        ExpectedKeyVisual preserveCase() {
77c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            return this;
78c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        }
79c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka
80c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        @Override
8151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final String text) {
82c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return false;
83c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
84c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
85c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
8651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final Key key) {
8751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // If the actual key has an icon as its visual, a label has to be null.
8851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
8951333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mIconId == key.getIconId() && key.getLabel() == null;
90c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
91c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
92c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
9351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
9451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // If the actual more key has an icon as its visual, a label has to be null.
9551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // See {@link KeySpecParser#getIconId(String)} and
9651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // {@link KeySpecParser#getLabel(String)}.
9751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mIconId == moreKeySpec.mIconId && moreKeySpec.mLabel == null;
98c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
99c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
100c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
10151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
102c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return false;
103c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
104c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
105c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
10651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
107c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return (visual instanceof Icon) && mIconId == ((Icon)visual).mIconId;
108c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
109c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
110c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
111c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        public String toString() {
112c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return KeyboardIconsSet.getIconName(mIconId);
113c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
114c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    }
115c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
116c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    /**
117c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka     * This class represents a string label.
118c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka     */
119c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    private static class Label extends ExpectedKeyVisual {
120c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        private final String mLabel;
121c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
12251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        Label(final String label) {
12351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            mLabel = label;
12451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        }
12551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka
12651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        @Override
12751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        public int getIconId() {
12851333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return KeyboardIconsSet.ICON_UNDEFINED;
12951333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        }
13051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka
13151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        @Override
13251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        public String getLabel() {
13351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mLabel;
13451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        }
135c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
136c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
137c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        ExpectedKeyVisual toUpperCase(final Locale locale) {
1386c47403e27fd703ece844f4b1b24632721da1772Tadashi G. Takaoka            return new Label(StringUtils.toTitleCaseOfKeyLabel(mLabel, locale));
139c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
140c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
141c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
142c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        ExpectedKeyVisual preserveCase() {
143c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            return new CasePreservedLabel(mLabel);
144c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        }
145c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka
146c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        @Override
14751333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final String text) {
148c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return mLabel.equals(text);
149c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
150c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
151c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
15251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final Key key) {
15351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // If the actual key has a label as its visual, an icon has to be undefined.
15451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // See {@link KeyboardView#onDrawKeyTopVisuals(Key,Canvas,Paint,KeyDrawParams).
15551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mLabel.equals(key.getLabel())
15651333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka                    && key.getIconId() == KeyboardIconsSet.ICON_UNDEFINED;
157c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
158c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
159c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
16051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final MoreKeySpec moreKeySpec) {
16151333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // If the actual more key has a label as its visual, an icon has to be undefined.
16251333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // See {@link KeySpecParser#getIconId(String)} and
16351333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            // {@link KeySpecParser#getLabel(String)}.
16451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return mLabel.equals(moreKeySpec.mLabel)
16551333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka                    && moreKeySpec.mIconId == KeyboardIconsSet.ICON_UNDEFINED;
166c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
167c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
168c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
16951333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final ExpectedKeyOutput output) {
17051333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka            return output.hasSameKeyOutput(mLabel);
171c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
172c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
173c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
17451333ba4c36726a2f7acff859cd8ffb782e8f2b3Tadashi G. Takaoka        boolean hasSameKeyVisual(final ExpectedKeyVisual visual) {
175c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return (visual instanceof Label) && mLabel.equals(((Label)visual).mLabel);
176c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
177c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka
178c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        @Override
179c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        public String toString() {
180c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka            return mLabel;
181c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka        }
182c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka
183c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        private static class CasePreservedLabel extends Label {
184c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            CasePreservedLabel(final String label) { super(label); }
185c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka
186c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            @Override
187c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            ExpectedKeyVisual toUpperCase(final Locale locale) { return this; }
188c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka
189c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            @Override
190c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka            ExpectedKeyVisual preserveCase() { return this; }
191c9aa1beb6de6bbea71af8eba94354bff3001e0acTadashi G. Takaoka        }
192c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka    }
193c39c912a331c9993438783c6eb03910aa314813dTadashi G. Takaoka}
194