================================================
FILE: .idea/vcs.xml
================================================
================================================
FILE: .scrutinizer.yml
================================================
checks:
java: true
================================================
FILE: .travis.yml
================================================
language: android
sudo: required
dist: trusty
group: deprecated-2017Q4
android:
components:
- tools
- build-tools-26.0.0
- android-26
- extra-android-support
- extra-android-m2repository
licenses:
- 'android-sdk-license-.+'
- '.*intel.+'
addons:
apt:
packages:
- oracle-java8-installer
before_install:
- chmod +x gradlew
- git submodule update --init --recursive
script:
- ./gradlew build check
branches:
only:
- master
- dev
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
[]()
[]()
[]()
[]()
[]()
[]()
# BeHe Keyboard
A lightweight hacking & programming keyboard with material design.
BeHe Keyboard aims to provide a smooth and simple keyboard experience, while also providing special keys and interfaces, all with material design.
Also, BeHe Keyboard does not spy on you and is easy to use. Check it out!
## License
Copyright 2017 - 2019 Vlad Todosin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: app/.gitignore
================================================
/build
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
lintOptions {
abortOnError false
}
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.vlath.keyboard"
minSdkVersion 18
targetSdkVersion 26
versionCode 112
versionName "1.1.2"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Vlad\Desktop\SDK/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: app/src/androidTest/java/com/vlath/keyboard/ExampleInstrumentedTest.java
================================================
package com.vlath.keyboard;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumentation test, which will execute on an Android device.
*
* @see Testing documentation
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.vlath.keyboard", appContext.getPackageName());
}
}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
================================================
FILE: app/src/main/java/com/vlath/keyboard/CandidateView.java
================================================
package com.vlath.keyboard;
/**
* Created by todo on 02.08.2017.
*/
/*
* Copyright (C) 2008-2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.view.MotionEvent;
import android.view.View;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class CandidateView extends View {
private static final int OUT_OF_BOUNDS = -1;
private PCKeyboard mService;
private List mSuggestions;
private int mSelectedIndex;
private int mTouchX = OUT_OF_BOUNDS;
private Drawable mSelectionHighlight;
private boolean mTypedWordValid;
private Rect mBgPadding;
private static final int MAX_SUGGESTIONS = 32;
private static final int SCROLL_PIXELS = 20;
private int[] mWordWidth = new int[MAX_SUGGESTIONS];
private int[] mWordX = new int[MAX_SUGGESTIONS];
private static final int X_GAP = 60;
private static final List EMPTY_LIST = new ArrayList();
private int mColorNormal;
private int mColorRecommended;
private int mColorOther;
private int mVerticalPadding;
private Paint mPaint;
private boolean mScrolled;
private int mTargetScrollX;
private int mTotalWidth;
private GestureDetector mGestureDetector;
public CandidateView(Context context) {
super(context);
mSelectionHighlight = context.getResources().getDrawable(
android.R.drawable.list_selector_background);
mSelectionHighlight.setState(new int[] {
android.R.attr.state_enabled,
android.R.attr.state_focused,
android.R.attr.state_window_focused,
android.R.attr.state_pressed
});
Resources r = context.getResources();
setBackgroundColor(r.getColor(R.color.gray));
mColorNormal = r.getColor(R.color.candidate_normal);
mColorRecommended = r.getColor(R.color.candidate_recommended);
mColorOther = r.getColor(R.color.candidate_other);
mVerticalPadding = r.getDimensionPixelSize(R.dimen.candidate_vertical_padding);
mPaint = new Paint();
mPaint.setColor(mColorNormal);
mPaint.setAntiAlias(true);
mPaint.setTextSize(r.getDimensionPixelSize(R.dimen.candidate_font_height));
mPaint.setStrokeWidth(5);
mGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
mScrolled = true;
int sx = getScrollX();
sx += distanceX;
if (sx < 0) {
sx = 0;
}
if (sx + getWidth() > mTotalWidth) {
sx -= distanceX;
}
mTargetScrollX = sx;
scrollTo(sx, getScrollY());
invalidate();
return true;
}
});
setHorizontalFadingEdgeEnabled(true);
setWillNotDraw(false);
setHorizontalScrollBarEnabled(false);
setVerticalScrollBarEnabled(false);
}
/**
* A connection back to the service to communicate with the text field
* @param listener
*/
public void setService(PCKeyboard listener) {
mService = listener;
}
@Override
public int computeHorizontalScrollRange() {
return mTotalWidth;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = resolveSize(50, widthMeasureSpec);
// Get the desired height of the icon menu view (last row of items does
// not have a divider below)
Rect padding = new Rect();
mSelectionHighlight.getPadding(padding);
final int desiredHeight = ((int)mPaint.getTextSize()) + mVerticalPadding
+ padding.top + padding.bottom;
// Maximum possible width and desired height
setMeasuredDimension(measuredWidth,
resolveSize(desiredHeight, heightMeasureSpec));
}
/**
* If the canvas is null, then only touch calculations are performed to pick the target
* candidate.
*/
@Override
protected void onDraw(Canvas canvas) {
if (canvas != null) {
super.onDraw(canvas);
}
mTotalWidth = 0;
if (mSuggestions == null) return;
if (mBgPadding == null) {
mBgPadding = new Rect(0, 0, 0, 0);
if (getBackground() != null) {
getBackground().getPadding(mBgPadding);
}
}
int x = 0;
final int count = mSuggestions.size();
final int height = getHeight();
final Rect bgPadding = mBgPadding;
final Paint paint = mPaint;
final int touchX = mTouchX;
final int scrollX = getScrollX();
final boolean scrolled = mScrolled;
final boolean typedWordValid = mTypedWordValid;
final int y = (int) (((height - mPaint.getTextSize()) / 2) - mPaint.ascent());
for (int i = 0; i < count; i++) {
String suggestion = mSuggestions.get(i);
float textWidth = paint.measureText(suggestion);
final int wordWidth = (int) textWidth + X_GAP * 2;
mWordX[i] = x;
mWordWidth[i] = wordWidth;
paint.setColor(mColorNormal);
if (touchX + scrollX >= x && touchX + scrollX < x + wordWidth && !scrolled) {
if (canvas != null) {
canvas.translate(x, 0);
mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height);
mSelectionHighlight.draw(canvas);
canvas.translate(-x, 0);
}
mSelectedIndex = i;
}
if (canvas != null) {
if ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid)) {
paint.setFakeBoldText(true);
paint.setColor(mColorRecommended);
} else if (i != 0) {
paint.setColor(mColorOther);
}
canvas.drawText(suggestion, x + X_GAP, y, paint);
paint.setColor(mColorOther);
canvas.drawLine(x + wordWidth + 0.5f, bgPadding.top,
x + wordWidth + 0.5f, height + 1, paint);
paint.setFakeBoldText(false);
}
x += wordWidth;
}
mTotalWidth = x;
if (mTargetScrollX != getScrollX()) {
scrollToTarget();
}
}
private void scrollToTarget() {
int sx = getScrollX();
if (mTargetScrollX > sx) {
sx += SCROLL_PIXELS;
if (sx >= mTargetScrollX) {
sx = mTargetScrollX;
requestLayout();
}
} else {
sx -= SCROLL_PIXELS;
if (sx <= mTargetScrollX) {
sx = mTargetScrollX;
requestLayout();
}
}
scrollTo(sx, getScrollY());
invalidate();
}
public void setSuggestions(List suggestions, boolean completions,
boolean typedWordValid) {
clear();
if (suggestions != null) {
mSuggestions = new ArrayList(suggestions);
}
mTypedWordValid = typedWordValid;
scrollTo(0, 0);
mTargetScrollX = 0;
// Compute the total width
draw(new Canvas());
invalidate();
requestLayout();
}
public void clear() {
mSuggestions = EMPTY_LIST;
mTouchX = OUT_OF_BOUNDS;
mSelectedIndex = -1;
invalidate();
}
@Override
public boolean onTouchEvent(MotionEvent me) {
if (mGestureDetector.onTouchEvent(me)) {
return true;
}
int action = me.getAction();
int x = (int) me.getX();
int y = (int) me.getY();
mTouchX = x;
switch (action) {
case MotionEvent.ACTION_DOWN:
mScrolled = false;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if (y <= 0) {
// Fling up!?
if (mSelectedIndex >= 0) {
mService.pickSuggestionManually(mSelectedIndex);
mSelectedIndex = -1;
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
if (!mScrolled) {
if (mSelectedIndex >= 0) {
mService.pickSuggestionManually(mSelectedIndex);
}
}
mSelectedIndex = -1;
removeHighlight();
requestLayout();
break;
}
return true;
}
/**
* For flick through from keyboard, call this method with the x coordinate of the flick
* gesture.
* @param x
*/
public void takeSuggestionAt(float x) {
mTouchX = (int) x;
// To detect candidate
draw(null);
if (mSelectedIndex >= 0) {
mService.pickSuggestionManually(mSelectedIndex);
}
invalidate();
}
private void removeHighlight() {
mTouchX = OUT_OF_BOUNDS;
invalidate();
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/CustomKeyboard.java
================================================
package com.vlath.keyboard;
/**
* Created by Vlad on 6/14/2017.
*/
import android.graphics.Bitmap;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.inputmethodservice.KeyboardView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.Keyboard.Key;
import android.inputmethodservice.KeyboardView;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.PopupWindow;
import java.lang.reflect.Field;
import java.util.List;
public class CustomKeyboard extends KeyboardView {
Drawable mTransparent = new ColorDrawable(Color.TRANSPARENT);
NinePatchDrawable mSpaceBackground = (NinePatchDrawable) getContext().getResources().getDrawable(R.drawable.space);
NinePatchDrawable mPressedBackground = (NinePatchDrawable) getContext().getResources().getDrawable(R.drawable.press);
Paint mPaint = new Paint();
public CustomKeyboard(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomKeyboard(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public LatinKeyboard getLatinKeyboard(){
return (LatinKeyboard)getKeyboard();
}
@Override
protected boolean onLongPress(Key key) {
if (key.codes[0] == Keyboard.KEYCODE_CANCEL) {
getOnKeyboardActionListener().onKey(LatinKeyboard.KEYCODE_OPTIONS, null);
return true;
}
return super.onLongPress(key);
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setTextSize(28);
mPaint.setColor(Color.parseColor("#a5a7aa"));
List keys = getKeyboard().getKeys();
for(Key key: keys) {
if(key.label != null) {
if (key.codes[0] == 32) {
mSpaceBackground.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
mSpaceBackground.draw(canvas);
}
if (Variables.isAnyOn()) {
if (Variables.isCtrl()) {
if (key.codes[0] == -113) {
mPressedBackground.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
mPressedBackground.draw(canvas);
}
}
if (Variables.isAlt()){
if (key.codes[0] == -114) {
mPressedBackground.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
mPressedBackground.draw(canvas);
}
}
}
else{
if(key.codes[0] == -113) {
mTransparent.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
mTransparent.draw(canvas);
}
if(key.codes[0] == -114) {
mTransparent.setBounds(key.x, key.y, key.x + key.width, key.y + key.height);
mTransparent.draw(canvas);
}
}
}
}
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/LatinKeyboard.java
================================================
package com.vlath.keyboard;
/**
* Created by Vlad on 6/14/2017.
*/
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.Keyboard;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
public class LatinKeyboard extends Keyboard {
static final int KEYCODE_OPTIONS = -100;
static final int KEYCODE_LAYUOUT_SWITCH = -101;
static final int KEYCODE_DPAD_R = -111;
static final int KEYCODE_DPAD_L = -108;
static final int KEYCODE_DPAD_U = -107;
static final int KEYCODE_DPAD_DO = -109;
static final int KEYCODE_ESCAPE = -112;
static final int KEYCODE_CTRL = -113;
static final int KEYCODE_ALT = -114;
static final int KEYCODE_STANDARD_SWITCH = -117;
static final int KEYCODE_DELL_PROCESS = -121;
static final int KEYCODE_I_DONT_KNOW_WHY_I_PUT_THAT_HERE = -122;
private Key mEnterKey;
private Key mSpaceKey;
private static short rowNumber = 4;
/**
* Stores the current state of the mode change key. Its width will be dynamically updated to
* match the region of {@link #mModeChangeKey} when {@link #mModeChangeKey} becomes invisible.
*/
private Key mModeChangeKey;
/**
* Stores the current state of the language switch key (a.k.a. globe key). This should be
* returns true. When this key becomes invisible, its width will be shrunk to zero.
*/
private Key mLanguageSwitchKey;
/**
* Stores the size and other information of {@link #mModeChangeKey} when
* {@link #mLanguageSwitchKey} is visible. This should be immutable and will be used only as a
* reference size when the visibility of {@link #mLanguageSwitchKey} is changed.
*/
private Key mSavedModeChangeKey;
/**
* Stores the size and other information of {@link #mLanguageSwitchKey} when it is visible.
* This should be immutable and will be used only as a reference size when the visibility of
* {@link #mLanguageSwitchKey} is changed.
*/
private Key mSavedLanguageSwitchKey;
public LatinKeyboard(Context context, int xmlLayoutResId) {
super(context, xmlLayoutResId);
}
public LatinKeyboard(Context context, int layoutTemplateResId,
CharSequence characters, int columns, int horizontalPadding) {
super(context, layoutTemplateResId, characters, columns, horizontalPadding);
}
@Override
protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
XmlResourceParser parser) {
Key key = new LatinKey(res, parent, x, y, parser);
if (key.codes[0] == 10) {
mEnterKey = key;
} else if (key.codes[0] == ' ') {
mSpaceKey = key;
} else if (key.codes[0] == Keyboard.KEYCODE_MODE_CHANGE) {
mModeChangeKey = key;
mSavedModeChangeKey = new LatinKey(res, parent, x, y, parser);
} else if (key.codes[0] == LatinKeyboard.KEYCODE_LAYUOUT_SWITCH) {
mLanguageSwitchKey = key;
mSavedLanguageSwitchKey = new LatinKey(res, parent, x, y, parser);
}
return key;
}
/**
* Dynamically change the visibility of the language switch key (a.k.a. globe key).
* @param visible True if the language switch key should be visible.
*/
void setLanguageSwitchKeyVisibility(boolean visible) {
if (visible) {
// The language switch key should be visible. Restore the size of the mode change key
// and language switch key using the saved layout.
mModeChangeKey.width = mSavedModeChangeKey.width;
mModeChangeKey.x = mSavedModeChangeKey.x;
mLanguageSwitchKey.width = mSavedLanguageSwitchKey.width;
mLanguageSwitchKey.icon = mSavedLanguageSwitchKey.icon;
mLanguageSwitchKey.iconPreview = mSavedLanguageSwitchKey.iconPreview;
} else {
// The language switch key should be hidden. Change the width of the mode change key
// to fill the space of the language key so that the user will not see any strange gap.
mModeChangeKey.width = mSavedModeChangeKey.width + mSavedLanguageSwitchKey.width;
mLanguageSwitchKey.width = 0;
mLanguageSwitchKey.icon = null;
mLanguageSwitchKey.iconPreview = null;
}
}
/**
* This looks at the ime options given by the current editor, to set the
* appropriate label on the keyboard's enter key (if it has one).
*/
void setImeOptions(Resources res, int options) {
if (mEnterKey == null) {
return;
}
switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) {
case EditorInfo.IME_ACTION_GO:
mEnterKey.iconPreview = null;
mEnterKey.icon = null;
mEnterKey.label = "ENT";
break;
case EditorInfo.IME_ACTION_NEXT:
mEnterKey.iconPreview = null;
mEnterKey.icon = null;
mEnterKey.label = "N";
break;
case EditorInfo.IME_ACTION_SEARCH:
// mEnterKey.icon = "K";
mEnterKey.label = null;
break;
case EditorInfo.IME_ACTION_SEND:
mEnterKey.iconPreview = null;
mEnterKey.icon = null;
mEnterKey.label = "HH";
break;
default:
// mEnterKey.icon = "U";
mEnterKey.label = null;
break;
}
}
public void setRowNumber(short number){
rowNumber = number;
}
void setSpaceIcon(final Drawable icon) {
if (mSpaceKey != null) {
mSpaceKey.icon = icon;
}
}
public void changeKeyHeight(double height_modifier){
int height = 0;
for(Keyboard.Key key : getKeys()) {
key.height *= height_modifier;
key.y *= height_modifier;
height = key.height;
}
setKeyHeight(height);
getNearestKeys(0, 0); //somehow adding this fixed a weird bug where bottom row keys could not be pressed if keyboard height is too tall.. from the Keyboard source code seems like calling this will recalculate some values used in keypress detection calculation
}
/** This piece of code is intended to help us to resize the keyboard at runtime,
* thus giving us the opportunity to customize its height. It's a bit tricky though.
* And StackOverflow inspired me to be honest.
* **/
@Override
public int getHeight(){
return getKeyHeight() * rowNumber;
}
public void setKeyHeight(int height) {
super.setKeyHeight(height);
}
static class LatinKey extends Keyboard.Key {
public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
XmlResourceParser parser) {
super(res, parent, x, y, parser);
}
/**
* Overriding this method so that we can reduce the target area for the key that
* closes the keyboard.
*/
@Override
public boolean isInside(int x, int y) {
return super.isInside(x, codes[0] == KEYCODE_CANCEL ? y - 10 : y);
}
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/Main.java
================================================
package com.vlath.keyboard;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class Main extends AppCompatActivity {
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
private Button btnSkip, btnNext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!getPresentationShown()) {
// Checking for first time launch - before calling setContentView()
// Making notification bar transparent
if (Build.VERSION.SDK_INT >= 21) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
setContentView(R.layout.main);
getSupportActionBar().hide();
viewPager = (ViewPager) findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(R.id.layoutDots);
btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
R.layout.slide1,
R.layout.slide2,
R.layout.slide3,
R.layout.slide4
};
// adding bottom dots
addBottomDots(0);
// making notification bar transparent
changeStatusBarColor();
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
btnSkip.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setPresentationShown();
launchHomeScreen();
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// checking for last page
// if last page home screen will be launched
int current = getItem(+1);
if (current < layouts.length) {
// move to next screen
viewPager.setCurrentItem(current);
} else {
setPresentationShown();
launchHomeScreen();
}
}
});
}
else{
setContentView(R.layout.activate);
TextView t2 = (TextView) findViewById(R.id.textView2);
t2.setMovementMethod(LinkMovementMethod.getInstance());
showTwitterDialog();
}
}
private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];
int[] colorsActive = getResources().getIntArray(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(R.array.array_dot_inactive);
dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(this);
dots[i].setText(Html.fromHtml("•"));
dots[i].setTextSize(35);
dots[i].setTextColor(colorsInactive[currentPage]);
dotsLayout.addView(dots[i]);
}
if (dots.length > 0)
dots[currentPage].setTextColor(colorsActive[currentPage]);
}
private int getItem(int i) {
return viewPager.getCurrentItem() + i;
}
private void launchHomeScreen() {
Intent intent = getIntent();
finish();
startActivity(intent);
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
// viewpager change listener
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
addBottomDots(position);
// changing the next button text 'NEXT' / 'GOT IT'
if (position == layouts.length - 1) {
// last page. make button text to GOT IT
btnNext.setText("GOT IT");
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText("NEXT");
btnSkip.setVisibility(View.VISIBLE);
}
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
};
/**
* Making notification bar transparent
*/
private void changeStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
}
private void normalStatusBar(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(getResources().getColor(R.color.colorPrimaryDark));
}
}
/**
* View pager adapter
*/
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPagerAdapter() {
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layouts[position], container, false);
container.addView(view);
return view;
}
@Override
public int getCount() {
return layouts.length;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
public boolean getPresentationShown(){
try {
return PreferenceManager.getDefaultSharedPreferences(this).getBoolean("presentation", false);
}
catch (Exception e){
return false;
}
}
public void setPresentationShown(){
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("presentation", true).commit();
}
public void showTwitterDialog(){
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("shown",false)) {}
else {
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setTitle(getString(R.string.up))
.setMessage(getString(R.string.follow))
.setPositiveButton("Follow", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/VlathXDA"));
startActivity(intent);
}
})
.setNegativeButton("No thanks", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.show();
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("shown",true).apply();
}
}
public void settings(View v){
Intent intent = new Intent(this, Preference.class);
startActivity(intent);
}
public void enable(View v){
this.startActivity(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
}
public void select(View v){
InputMethodManager imeManager = (InputMethodManager) getApplicationContext().getSystemService(INPUT_METHOD_SERVICE);
if (imeManager != null) {
imeManager.showInputMethodPicker();
} else {
Toast.makeText(this, "Not possible" , Toast.LENGTH_LONG).show();
}
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/PCKeyboard.java
================================================
package com.vlath.keyboard;
/*
* Copyright (C) 2008-2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.app.Dialog;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.os.IBinder;
import android.os.Vibrator;
import android.preference.*;
import android.text.InputType;
import android.text.method.MetaKeyKeyListener;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SpellCheckerSession;
import android.view.textservice.SuggestionsInfo;
import android.view.textservice.TextInfo;
import android.view.textservice.TextServicesManager;
import android.widget.PopupWindow;
import java.util.ArrayList;
import java.util.List;
/** Main class of the keyboard, extending InputMethodService. Here we handle all the user interaction with the keyboard itself. */
public class PCKeyboard extends InputMethodService
implements KeyboardView.OnKeyboardActionListener, SpellCheckerSession.SpellCheckerSessionListener {
/**
* As we don't want to bother changing the app theme, we use filters to theme the keyboard.
* Each filter needs an array of colors. The arrays are declared below.
*/
// TODO: Add the arrays in a separate, static class, so they are eay to access and modify
private static final float[] sNoneColorArray = {
1.0f, 0, 0, 0, 0, // red
0, 1.0f, 0, 0, 0, // green
0, 0, 1.0f, 0, 0, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sNegativeColorArray = {
-1.0f, 0, 0, 0, 255, // red
0, -1.0f, 0, 0, 255, // green
0, 0, -1.0f, 0, 255, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sBlueBlackColorArray = {
-0.6f, 0, 0, 0, 41, // red
0, -0.6f, 0, 0, 128, // green
0, 0, -0.6f, 0, 185, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sBlueWhiteColorArray = {
1.0f, 0, 0, 0, 41, // red
0, 1.0f, 0, 0, 128, // green
0, 0, 1.0f, 0, 185, // blue
0, 0, 0, 1.0f, 1 // alpha
};
private static final float[] sRedWhiteColorArray = {
1.0f, 0, 0, 0, 192, // red
0, 1.0f, 0, 0, 57, // green
0, 0, 1.0f, 0, 43, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sRedBlackColorArray = {
-0.6f, 0, 0, 0, 192, // red
0, -0.6f, 0, 0, 57, // green
0, 0, -0.6f, 0, 43, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sOrangeBlackColorArray = {
1.0f, 0, 0, 0, 230, // red
0, 1.0f, 0, 0, 126, // green
0, 0, 1.0f, 0, 34, // blue
0, 0, 0, 1.0f, 0 // alpha
};
private static final float[] sMaterialDarkColorArray = {
1.0f, 0, 0, 0, 55, // red
0, 1.0f, 0, 0, 71, // green
0, 0, 1.0f, 0, 79, // blue
0, 0, 0, 1.0f, 1 // alpha
};
static final boolean PROCESS_HARD_KEYS = true;
private InputMethodManager mInputMethodManager;
private CustomKeyboard mInputView;
private CandidateView mCandidateView;
private CompletionInfo[] mCompletions;
private StringBuilder mComposing = new StringBuilder();
private boolean mPredictionOn;
private boolean mCompletionOn;
private int mLastDisplayWidth;
private boolean mCapsLock;
private long mLastShiftTime;
private long mMetaState;
private LatinKeyboard mSymbolsKeyboard;
private LatinKeyboard mSymbolsShiftedKeyboard;
private LatinKeyboard mStandardKeyboard;
private String mWordSeparators;
private SpellCheckerSession mScs;
private List mSuggestions;
private boolean firstCaps = false;
private boolean isSysmbols = false;
private boolean shiftSim = false;
private boolean isDpad = false;
private boolean isProgramming = false;
private InputMethodManager mServ;
private float[] mDefaultFilter;
long shift_pressed=0;
private short rowNumber = 4;
private CustomKeyboard kv;
private LatinKeyboard currentKeyboard;
private LatinKeyboard mCurKeyboard;
private LatinKeyboard standardKeyboard;
private int standardKeyboardID = R.xml.qwerty;
/**
* Main initialization of the input method component. Be sure to call
* to super class.
*/
@Override public void onCreate() {
super.onCreate();
mInputMethodManager = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
mWordSeparators = getResources().getString(R.string.word_separators);
final TextServicesManager tsm = (TextServicesManager) getSystemService(
Context.TEXT_SERVICES_MANAGER_SERVICE);
mScs = tsm.newSpellCheckerSession(null, null, this, true);
}
/**
* This is the point where you can do all of your UI initialization. It
* is called after creation and any configuration change.
*/
@Override public void onInitializeInterface() {
if (mStandardKeyboard != null) {
// Configuration changes can happen after the keyboard gets recreated,
// so we need to be able to re-build the keyboards if the available
// space has changed.
int displayWidth = getMaxWidth();
if (displayWidth == mLastDisplayWidth) return;
mLastDisplayWidth = displayWidth;
}
mStandardKeyboard = new LatinKeyboard(this, standardKeyboardID);
mSymbolsKeyboard = new LatinKeyboard(this, R.xml.symbols);
mSymbolsShiftedKeyboard = new LatinKeyboard(this, R.xml.symbols2);
}
/**
* Called by the framework when your view for creating input needs to
* be generated. This will be called the first time your input method
* is displayed, and every time it needs to be re-created such as due to
* a configuration change.
*
* We also s
*/
@Override public View onCreateInputView() {
mInputView = (CustomKeyboard) getLayoutInflater().inflate(
R.layout.keyboard, null);
mInputView.setOnKeyboardActionListener(this);
mInputView.setPreviewEnabled(false);
setLatinKeyboard(mStandardKeyboard);
return mInputView;
}
private void setLatinKeyboard(LatinKeyboard nextKeyboard) {
mInputView.setKeyboard(nextKeyboard);
}
/**
* Called by the framework when your view for showing candidates needs to
* be generated, like {@link #onCreateInputView}.
*/
@Override public View onCreateCandidatesView() {
mCandidateView = new CandidateView(this);
mCandidateView.setService(this);
setTheme();
Paint mPaint = new Paint();
ColorMatrixColorFilter filterInvert = new ColorMatrixColorFilter(mDefaultFilter);
mPaint.setColorFilter(filterInvert);
mCandidateView.setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
return mCandidateView;
}
/**
* This is the main point where we do our initialization of the input method
* to begin operating on an application. At this point we have been
* bound to the client, and are now receiving all of the detailed information
* about the target of our edits.
*
*
* And we have to reinitialize all we've one to make sure the keyboard aspect matches
* The one selected in settings.
*/
@Override public void onStartInput(EditorInfo attribute, boolean restarting) {
super.onStartInput(attribute, restarting);
setTheme();
mComposing.setLength(0);
updateCandidates();
/**
* Some code on here is based on the SoftKeyboard Sample. I don't fully understand it.
* I need to look it up and delete any unnecessary stuff.
* */
if (!restarting) {
// Clear shift states.
mMetaState = 0;
}
mCompletions = null;
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("bord",false)){
kv = (CustomKeyboard) getLayoutInflater().inflate(R.layout.keyboard_key_back, null);
}
else {
kv = (CustomKeyboard) getLayoutInflater().inflate(R.layout.keyboard, null);
}
setStandardKeyboard();
setInputType();
Paint mPaint = new Paint();
ColorMatrixColorFilter filterInvert = new ColorMatrixColorFilter(mDefaultFilter);
mPaint.setColorFilter(filterInvert);
mCandidateView = new CandidateView(this);
mCandidateView.setService(this);
kv.setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
currentKeyboard.setRowNumber(getRowNumber());
kv.setKeyboard(currentKeyboard);
capsOnFirst();
kv.setOnKeyboardActionListener(this);
mPredictionOn = PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("pred", false);
mCompletionOn = false;
mCandidateView.setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
setInputView(kv);
kv.getLatinKeyboard().changeKeyHeight(getHeightKeyModifier());
setCandidatesView(mCandidateView);
}
/**
* This is called when the user is done editing a field. We can use
* this to reset our state.
*/
@Override public void onFinishInput() {
super.onFinishInput();
// Clear current composing text and candidates.
mComposing.setLength(0);
updateCandidates();
// We only hide the candidates window when finishing input on
// a particular editor, to avoid popping the underlying application
// up and down if the user is entering text into the bottom of
// its window.
setCandidatesViewShown(false);
mCurKeyboard = mStandardKeyboard;
if (mInputView != null) {
mInputView.closing();
}
}
/**
* Deal with the editor reporting movement of its cursor.
*/
@Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
int candidatesStart, int candidatesEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
candidatesStart, candidatesEnd);
// If the current selection in the text view changes, we should
// clear whatever candidate text we have.
if (mComposing.length() > 0 && (newSelStart != candidatesEnd
|| newSelEnd != candidatesEnd)) {
mComposing.setLength(0);
updateCandidates();
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
ic.finishComposingText();
}
}
}
/**
* This tells us about completions that the editor has determined based
* on the current text in it. We want to use this in fullscreen mode
* to show the completions ourself, since the editor can not be seen
* in that situation.
*/
@Override public void onDisplayCompletions(CompletionInfo[] completions) {
if (mCompletionOn) {
mCompletions = completions;
if (completions == null) {
setSuggestions(null, false, false);
return;
}
List stringList = new ArrayList();
for (int i = 0; i < completions.length; i++) {
CompletionInfo ci = completions[i];
if (ci != null) stringList.add(ci.getText().toString());
}
setSuggestions(stringList, true, true);
}
}
/**
* This translates incoming hard key events in to edit operations on an
* InputConnection. It is only needed when using the
* PROCESS_HARD_KEYS option.
*/
private boolean translateKeyDown(int keyCode, KeyEvent event) {
mMetaState = MetaKeyKeyListener.handleKeyDown(mMetaState,
keyCode, event);
int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(mMetaState));
mMetaState = MetaKeyKeyListener.adjustMetaAfterKeypress(mMetaState);
InputConnection ic = getCurrentInputConnection();
if (c == 0 || ic == null) {
return false;
}
boolean dead = false;
if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
dead = true;
c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
}
if (mComposing.length() > 0) {
char accent = mComposing.charAt(mComposing.length() -1 );
int composed = KeyEvent.getDeadChar(accent, c);
if (composed != 0) {
c = composed;
mComposing.setLength(mComposing.length()-1);
}
}
onKey(c, null);
return true;
}
/**
* Use this to monitor key events being delivered to the application.
* We get first crack at them, and can either resume them or let them
* continue to the app.
*/
@Override public boolean onKeyUp(int keyCode, KeyEvent event) {
return super.onKeyUp(keyCode, event);
}
@Override public boolean onKeyDown(int keyCode, KeyEvent event) {
return super.onKeyDown(keyCode, event);
}
/**
* Helper function to commit any text being composed in to the editor.
*/
private void commitTyped(InputConnection inputConnection) {
if (mComposing.length() > 0) {
inputConnection.commitText(mComposing, mComposing.length());
mComposing.setLength(0);
updateCandidates();
}
}
/**
* Helper to update the shift state of our keyboard based on the initial
* editor state.
*/
private void updateShiftKeyState(EditorInfo attr) {
if (attr != null
&& mInputView != null && mStandardKeyboard == mInputView.getKeyboard()) {
int caps = 0;
EditorInfo ei = getCurrentInputEditorInfo();
if (ei != null && ei.inputType != InputType.TYPE_NULL) {
caps = getCurrentInputConnection().getCursorCapsMode(attr.inputType);
}
mInputView.setShifted(mCapsLock || caps != 0);
}
}
/**
* Helper to determine if a given character code is alphabetic.
*/
private boolean isAlphabet(int code) {
if (Character.isLetter(code)) {
return true;
} else {
return false;
}
}
/**
* Helper to send a key down / key up pair to the current editor.
*/
private void keyDownUp(int keyEventCode) {
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, keyEventCode));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, keyEventCode));
}
/**
* Helper to send a character to the editor as raw key events.
*/
private void sendKey(int keyCode) {
switch (keyCode) {
case '\n':
keyDownUp(KeyEvent.KEYCODE_ENTER);
break;
default:
if (keyCode >= '0' && keyCode <= '9') {
keyDownUp(keyCode - '0' + KeyEvent.KEYCODE_0);
} else {
getCurrentInputConnection().commitText(String.valueOf((char) keyCode), 1);
}
break;
}
}
public void onText(CharSequence text) {
InputConnection ic = getCurrentInputConnection();
if (ic == null) return;
ic.beginBatchEdit();
if (mComposing.length() > 0) {
commitTyped(ic);
}
ic.commitText(text, 0);
ic.endBatchEdit();
updateShiftKeyState(getCurrentInputEditorInfo());
}
@Override
public void swipeLeft() {
}
@Override
public void swipeRight() {
}
@Override
public void swipeDown() {
}
@Override
public void swipeUp() {
}
/**
* Update the list of available candidates from the current composing
* text. This will need to be filled in by however you are determining
* candidates.
*/
private void updateCandidates() {
if (!mCompletionOn) {
if (mComposing.length() > 0) {
ArrayList list = new ArrayList();
list.add(mComposing.toString());
mScs.getSentenceSuggestions(new TextInfo[] {new TextInfo(mComposing.toString())}, 5);
setSuggestions(list, true, true);
} else {
setSuggestions(null, false, false);
}
}
}
public void setSuggestions(List suggestions, boolean completions,
boolean typedWordValid) {
if (suggestions != null && suggestions.size() > 0) {
setCandidatesViewShown(true);
} else if (isExtractViewShown()) {
setCandidatesViewShown(true);
}
mSuggestions = suggestions;
if (mCandidateView != null) {
mCandidateView.setSuggestions(suggestions, completions, typedWordValid);
}
}
private void handleBackspace() {
final int length = mComposing.length();
if (length > 1) {
mComposing.delete(length - 1, length);
getCurrentInputConnection().setComposingText(mComposing, 1);
updateCandidates();
} else if (length > 0) {
mComposing.setLength(0);
getCurrentInputConnection().commitText("", 0);
updateCandidates();
} else {
keyDownUp(KeyEvent.KEYCODE_DEL);
}
updateShiftKeyState(getCurrentInputEditorInfo());
}
private void handleCharacter(int primaryCode, int[] keyCodes) {
if (isInputViewShown()) {
if (kv.isShifted()) {
primaryCode = Character.toUpperCase(primaryCode);
}
}
if (mPredictionOn && !mWordSeparators.contains(String.valueOf((char)primaryCode))) {
mComposing.append((char) primaryCode);
getCurrentInputConnection().setComposingText(mComposing, 1);
updateShiftKeyState(getCurrentInputEditorInfo());
updateCandidates();
}
if(mPredictionOn && mWordSeparators.contains(String.valueOf((char)primaryCode))){
char code = (char) primaryCode;
if (Character.isLetter(code) && firstCaps || Character.isLetter(code) && Variables.isShift()) {
code = Character.toUpperCase(code);
}
getCurrentInputConnection().setComposingRegion(0,0);
getCurrentInputConnection().commitText(String.valueOf(code), 1);
firstCaps = false;
setCapsOn(false);
}
if(!mPredictionOn){
char code = (char) primaryCode;
if (Character.isLetter(code) && firstCaps || Character.isLetter(code) && Variables.isShift()) {
code = Character.toUpperCase(code);
}
getCurrentInputConnection().setComposingRegion(0,0);
getCurrentInputConnection().commitText(String.valueOf(code), 1);
firstCaps = false;
setCapsOn(false);
}
}
private void handleClose() {
commitTyped(getCurrentInputConnection());
requestHideSelf(0);
mInputView.closing();
}
private IBinder getToken() {
final Dialog dialog = getWindow();
if (dialog == null) {
return null;
}
final Window window = dialog.getWindow();
if (window == null) {
return null;
}
return window.getAttributes().token;
}
private void handleLanguageSwitch() {
mInputMethodManager.switchToNextInputMethod(getToken(), false /* onlyCurrentIme */);
}
private void checkToggleCapsLock() {
long now = System.currentTimeMillis();
if (mLastShiftTime + 800 > now) {
mCapsLock = !mCapsLock;
mLastShiftTime = 0;
} else {
mLastShiftTime = now;
}
}
private String getWordSeparators() {
return mWordSeparators;
}
public boolean isWordSeparator(String s) {
if(s.contains(". ") || s.contains("? ") || s.contains("! ")){
return true;
}
return false;
}
public void pickDefaultCandidate() {
pickSuggestionManually(0);
}
public void pickSuggestionManually(int index) {
if (mCompletionOn && mCompletions != null && index >= 0
&& index < mCompletions.length) {
CompletionInfo ci = mCompletions[index];
getCurrentInputConnection().commitCompletion(ci);
if (mCandidateView != null) {
mCandidateView.clear();
}
updateShiftKeyState(getCurrentInputEditorInfo());
} else if (mComposing.length() > 0) {
if (mPredictionOn && mSuggestions != null && index >= 0) {
mComposing.replace(0, mComposing.length(), mSuggestions.get(index));
}
commitTyped(getCurrentInputConnection());
}
}
public void onPress(int primaryCode) {
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("vib", false)) {
Vibrator v = (Vibrator) getBaseContext().getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(40);
}
}
public void onRelease(int primaryCode) {
}
/**
* http://www.tutorialspoint.com/android/android_spelling_checker.htm
* Sort of copy-paste, huh.
*
* I need to find time to refine this code
*
*
* @param results results
*/
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
final StringBuilder sb = new StringBuilder();
for (SuggestionsInfo result : results) {
// Returned suggestions are contained in SuggestionsInfo
final int len = result.getSuggestionsCount();
sb.append('\n');
for (int j = 0; j < len; ++j) {
sb.append(",").append(result.getSuggestionAt(j));
}
sb.append(" (").append(len).append(")");
}
}
private void dumpSuggestionsInfoInternal(
final List sb, final SuggestionsInfo si, final int length, final int offset) {
// Returned suggestions are contained in SuggestionsInfo
final int len = si.getSuggestionsCount();
for (int j = 0; j < len; ++j) {
sb.add(si.getSuggestionAt(j));
}
}
@Override
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
try {
final List sb = new ArrayList<>();
for (final SentenceSuggestionsInfo ssi : results) {
for (int j = 0; j < ssi.getSuggestionsCount(); ++j) {
dumpSuggestionsInfoInternal(
sb, ssi.getSuggestionsInfoAt(j), ssi.getOffsetAt(j), ssi.getLengthAt(j));
}
}
setSuggestions(sb, true, true);
}
catch(Exception ignored){}
}
private void setCapsOn(boolean on) {
/** Simple function that enables us to rapidly set the keyboard shifted or not.
* */
if(Variables.isShift()){
kv.getKeyboard().setShifted(true);
kv.invalidateAllKeys();
}
else {
kv.getKeyboard().setShifted(on);
kv.invalidateAllKeys();
}
}
private void processKeyCombo(int keycode) {
/** Ass the function name says, we process key combinations here*/
if (Variables.isAnyOn()) {
if (Variables.isCtrl() && Variables.isAlt()) {
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, getHardKeyCode(keycode), 0, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON));
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_UP, getHardKeyCode(keycode), 0, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON));
} else {
if (Variables.isCtrl()) {
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, getHardKeyCode(keycode), 0, KeyEvent.META_CTRL_ON));
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_UP, getHardKeyCode(keycode), 0, KeyEvent.META_CTRL_ON));
}
if (Variables.isAlt()) {
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, getHardKeyCode(keycode), 0, KeyEvent.META_ALT_ON));
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_UP, getHardKeyCode(keycode), 0, KeyEvent.META_ALT_ON));
}
}
}
}
private int getHardKeyCode(int keycode) {
/** Seems like the actual soft key code doesn't match the hard key code*/
PopupWindow p = new PopupWindow();
char code = (char) keycode;
switch (String.valueOf(code)) {
case "a":
return KeyEvent.KEYCODE_A;
case "b":
return KeyEvent.KEYCODE_B;
case "c":
return KeyEvent.KEYCODE_C;
case "d":
return KeyEvent.KEYCODE_D;
case "e":
return KeyEvent.KEYCODE_E;
case "f":
return KeyEvent.KEYCODE_F;
case "g":
return KeyEvent.KEYCODE_G;
case "h":
return KeyEvent.KEYCODE_H;
case "i":
return KeyEvent.KEYCODE_I;
case "j":
return KeyEvent.KEYCODE_J;
case "k":
return KeyEvent.KEYCODE_K;
case "l":
return KeyEvent.KEYCODE_L;
case "m":
return KeyEvent.KEYCODE_M;
case "n":
return KeyEvent.KEYCODE_N;
case "o":
return KeyEvent.KEYCODE_O;
case "p":
return KeyEvent.KEYCODE_P;
case "q":
return KeyEvent.KEYCODE_Q;
case "r":
return KeyEvent.KEYCODE_R;
case "s":
return KeyEvent.KEYCODE_S;
case "t":
return KeyEvent.KEYCODE_T;
case "u":
return KeyEvent.KEYCODE_U;
case "v":
return KeyEvent.KEYCODE_V;
case "w":
return KeyEvent.KEYCODE_W;
case "x":
return KeyEvent.KEYCODE_X;
case "y":
return KeyEvent.KEYCODE_Y;
case "z":
return KeyEvent.KEYCODE_Z;
default:
return keycode;
}
}
private void handleAction() {
EditorInfo curEditor = getCurrentInputEditorInfo();
switch (curEditor.imeOptions & EditorInfo.IME_MASK_ACTION) {
case EditorInfo.IME_ACTION_DONE:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_DONE);
break;
case EditorInfo.IME_ACTION_GO:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_GO);
break;
case EditorInfo.IME_ACTION_NEXT:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
case EditorInfo.IME_ACTION_SEARCH:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_SEARCH);
break;
case EditorInfo.IME_ACTION_SEND:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_SEND);
break;
default:
break;
}
}
public void setTheme() {
switch (PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("theme", "2")) {
case "1":
mDefaultFilter = sNoneColorArray;
break;
case "2":
mDefaultFilter = sNegativeColorArray;
break;
case "3":
mDefaultFilter = sBlueWhiteColorArray;
break;
case "4":
mDefaultFilter = sBlueBlackColorArray;
break;
case "5":
mDefaultFilter = sRedWhiteColorArray;
break;
case "6":
mDefaultFilter = sRedBlackColorArray;
break;
case "7":
mDefaultFilter = sOrangeBlackColorArray;
break;
case "8":
mDefaultFilter = sMaterialDarkColorArray;
break;
}
}
private void setInputType() {
/** Checks the preferences for the default keyboard layout.
* If standard, we start out whether in standard or numbers, depending on the input type.
* */
EditorInfo attribute = getCurrentInputEditorInfo();
if (PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("start", "1").equals("1")) {
switch (attribute.inputType & InputType.TYPE_MASK_CLASS) {
case InputType.TYPE_CLASS_NUMBER:
case InputType.TYPE_CLASS_DATETIME:
case InputType.TYPE_CLASS_PHONE:
currentKeyboard = new LatinKeyboard(this, R.xml.numbers);
break;
case InputType.TYPE_CLASS_TEXT:
int webInputType = attribute.inputType & InputType.TYPE_MASK_VARIATION;
if (webInputType == InputType.TYPE_TEXT_VARIATION_URI ||
webInputType == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT ||
webInputType == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| webInputType == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS) {
currentKeyboard = new LatinKeyboard(this, standardKeyboardID);
} else {
currentKeyboard = new LatinKeyboard(this, standardKeyboardID);
}
break;
default:
currentKeyboard = new LatinKeyboard(this, standardKeyboardID);
break;
}
} else {
setDefaultKeyboard();
}
if (kv != null) {
kv.setKeyboard(currentKeyboard);
}
}
public void setDefaultKeyboard() {
switch (PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("start", "1")) {
case "1":
currentKeyboard = standardKeyboard;
break;
case "2":
currentKeyboard = new LatinKeyboard(this, R.xml.arrow_keys);
setRowNumber(4);
currentKeyboard.setRowNumber(getRowNumber());
break;
case "3":
currentKeyboard = new LatinKeyboard(this, R.xml.programming);
setRowNumber(5);
currentKeyboard.setRowNumber(getRowNumber());
break;
}
}
private void capsOnFirst() {
/** Huh, a method that calls getCursorCapsMode() and performs a check.
* Accordingly to the official android documentation, if the caps mode is not equal to 0,
* We should start in caps mode. Although, tests have proven that additionally checks are needed.
* I'll see what I can do on this.
* */
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("caps",true)){
if (getCursorCapsMode(getCurrentInputConnection(), getCurrentInputEditorInfo()) != 0) {
firstCaps = true;
setCapsOn(true);
}
}
else {
firstCaps = false;
setCapsOn(false);
}
}
private int getCursorCapsMode(InputConnection ic, EditorInfo attr) {
/** A rudimentary method to find out whether we should start with caps on or not.
* */
// TODO: Perform additional checks.
int caps = 0;
EditorInfo ei = getCurrentInputEditorInfo();
if (ei != null && ei.inputType != EditorInfo.TYPE_NULL) {
caps = ic.getCursorCapsMode(attr.inputType);
}
return caps;
}
@Override
public void onKey(int primaryCode, int[] keyCodes) {
InputConnection ic = getCurrentInputConnection();
/** Here we handle the key events. */
switch (primaryCode) {
case Keyboard.KEYCODE_DELETE:
handleBackspace();
break;
case Keyboard.KEYCODE_SHIFT:
/** We need to check whether we are on symbols layout or not.
* Then, perform the operation accordingly.
* Also, we check for double tab on the shift, and, if detected
* We set a global variable that tells us that the Shift is in the lock position.
* */
if (isSysmbols) {
if (!shiftSim) {
currentKeyboard = new LatinKeyboard(this, R.xml.symbols2);
kv.setKeyboard(currentKeyboard);
shiftSim = true;
} else {
currentKeyboard = new LatinKeyboard(this, R.xml.symbols);
kv.setKeyboard(currentKeyboard);
shiftSim = false;
}
} else {
if (shift_pressed + 200 > System.currentTimeMillis()){
Variables.setShiftOn();
setCapsOn(true);
kv.draw(new Canvas());
}
else{
if(Variables.isShift()){
Variables.setShiftOff();
firstCaps = false;
setCapsOn(firstCaps);
shift_pressed = System.currentTimeMillis();
}
else{
firstCaps = !firstCaps;
setCapsOn(firstCaps);
shift_pressed = System.currentTimeMillis();
}
}
}
break;
case 10:
/** Handle the 'done' action accordingly to the IME Options. */
EditorInfo curEditor = getCurrentInputEditorInfo();
switch (curEditor.imeOptions & EditorInfo.IME_MASK_ACTION) {
case EditorInfo.IME_ACTION_DONE:
keyDownUp(66);
break;
case EditorInfo.IME_ACTION_GO:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_GO);
break;
case EditorInfo.IME_ACTION_NEXT:
keyDownUp(66);
break;
case EditorInfo.IME_ACTION_SEARCH:
getCurrentInputConnection().performEditorAction(EditorInfo.IME_ACTION_SEARCH);
break;
case EditorInfo.IME_ACTION_SEND:
keyDownUp(66);
break;
default:
keyDownUp(66);
break;
}
break;
case Keyboard.KEYCODE_MODE_CHANGE:
/** Switch between standard/symbols layout. */
if (!isSysmbols) {
isSysmbols = !isSysmbols;
currentKeyboard = new LatinKeyboard(this, R.xml.symbols);
kv.setKeyboard(currentKeyboard);
} else {
isSysmbols = false;
currentKeyboard = new LatinKeyboard(this, standardKeyboardID);
kv.setKeyboard(currentKeyboard);
}
kv.getLatinKeyboard().changeKeyHeight(getHeightKeyModifier());
break;
case LatinKeyboard.KEYCODE_LAYUOUT_SWITCH:
/** Language Switch is a custom value defined in the LatinKeyboard class.
* We use it to switch between standard/arrow keys/programming layouts. */
if (isDpad || isProgramming) {
if (isProgramming) {
currentKeyboard = new LatinKeyboard(this, standardKeyboardID);
kv.invalidateAllKeys();
currentKeyboard.setRowNumber(getStandardRowNumber());
kv.setKeyboard(currentKeyboard);
isProgramming = false;
isDpad = false;
}
if (isDpad) {
currentKeyboard = new LatinKeyboard(this, R.xml.programming);
kv.invalidateAllKeys();
setRowNumber(5);
currentKeyboard.setRowNumber(getRowNumber());
kv.setKeyboard(currentKeyboard);
isDpad = false;
isProgramming = true;
}
} else {
currentKeyboard = new LatinKeyboard(this, R.xml.arrow_keys);
kv.invalidateAllKeys();
setRowNumber(4);
currentKeyboard.setRowNumber(getRowNumber());
kv.setKeyboard(currentKeyboard);
isDpad = true;
}
kv.getLatinKeyboard().changeKeyHeight(getHeightKeyModifier());
break;
case LatinKeyboard.KEYCODE_DPAD_L:
/** Another custom keycode. */
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_LEFT));
break;
case LatinKeyboard.KEYCODE_DPAD_R:
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_RIGHT));
break;
case LatinKeyboard.KEYCODE_DPAD_U:
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_UP));
break;
case LatinKeyboard.KEYCODE_DPAD_DO:
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_DOWN));
break;
case LatinKeyboard.KEYCODE_ESCAPE:
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ESCAPE, 0));
getCurrentInputConnection().sendKeyEvent(
new KeyEvent(100, 100, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ESCAPE, 0));
break;
case LatinKeyboard.KEYCODE_CTRL:
if (Variables.isCtrl()) {
Variables.setCtrlOff();
kv.draw(new Canvas());
} else {
Variables.setCtrlOn();
kv.draw(new Canvas());
}
break;
case LatinKeyboard.KEYCODE_ALT:
if (Variables.isAlt()) {
Variables.setAltOff();
kv.draw(new Canvas());
} else {
Variables.setAltOn();
kv.draw(new Canvas());
}
break;
case LatinKeyboard.KEYCODE_STANDARD_SWITCH:
/** This key enables the user to switch rapidly between standard/arrow keys layouts.*/
currentKeyboard = new LatinKeyboard(getBaseContext(), standardKeyboardID);
currentKeyboard.setRowNumber(getStandardRowNumber());
kv.setKeyboard(currentKeyboard);
kv.getLatinKeyboard().changeKeyHeight(getHeightKeyModifier());
isDpad = false;
break;
case LatinKeyboard.KEYCODE_DELL_PROCESS:
/** Procces DEL key*/
if(Variables.isAnyOn()){
if(Variables.isCtrl() && Variables.isAlt()) {
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON));
}
if(Variables.isAlt()){
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_ALT_ON));
}
if(Variables.isCtrl()){
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_CTRL_ON));
}
}
else{
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL , 0));
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL, 0));
}
break;
case LatinKeyboard.KEYCODE_I_DONT_KNOW_WHY_I_PUT_THAT_HERE:
if(Variables.isAnyOn()){
if(Variables.isCtrl() && Variables.isAlt()) {
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB, 0, KeyEvent.META_CTRL_ON | KeyEvent.META_ALT_ON));
}
if(Variables.isAlt()){
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB, 0, KeyEvent.META_ALT_ON));
}
if(Variables.isCtrl()){
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB, 0, KeyEvent.META_CTRL_ON));
}
}
else{
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB , 0));
getCurrentInputConnection().sendKeyEvent(new KeyEvent(100, 100, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_TAB, 0));
}
break;
default:
if (Variables.isAnyOn()) {
processKeyCombo(primaryCode);
} else {
handleCharacter(primaryCode, keyCodes);
}
}
try {
/** Some text processing. Helps some guys improve their writing skills, huh*/
if(PreferenceManager.getDefaultSharedPreferences(this).getBoolean("caps",true)) {
if (isWordSeparator(ic.getTextBeforeCursor(2, 0).toString())) {
setCapsOn(true);
firstCaps = true;
}
}
} catch (Exception e) {
}
}
public short getRowNumber(){
return rowNumber;
}
public void setRowNumber(int number){
rowNumber = (short) number;
}
public short getStandardRowNumber(){
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("arr_qrt", false) && PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("nbr_qrt", false)){
return 5;
}
else{
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("arr_qrt", false)){
return 4;
}
else if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("nbr_qrt", false)){
return 5;
}
else {
return 4;
}
}
}
public void setStandardKeyboard(){
int layout = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getString("layout", "1"));
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("arr_qrt", false) && PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("nbr_qrt", false)){
switch (layout) {
case 2:
standardKeyboardID = R.xml.azerty_arrow_numbers;
break;
case 3:
standardKeyboardID = R.xml.qwertz_arrow_numbers;
break;
default:
standardKeyboardID = R.xml.qwerty_arrow_numbers;
}
setRowNumber(5);
}
else{
if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("arr_qrt", false)){
switch (layout) {
case 2:
standardKeyboardID = R.xml.azerty_arrows;
break;
case 3:
standardKeyboardID = R.xml.qwertz_arrows;
break;
default:
standardKeyboardID = R.xml.qwerty_arrows;
}
setRowNumber(4);
}
else if(PreferenceManager.getDefaultSharedPreferences(getBaseContext()).getBoolean("nbr_qrt", false)){
switch (layout) {
case 2:
standardKeyboardID = R.xml.azerty_numbers;
break;
case 3:
standardKeyboardID = R.xml.qwertz_numbers;
break;
default:
standardKeyboardID = R.xml.qwerty_numbers;
}
setRowNumber(5);
}
else {
switch (layout) {
case 2:
standardKeyboardID = R.xml.azerty;
break;
case 3:
standardKeyboardID = R.xml.qwertz;
break;
default:
standardKeyboardID = R.xml.qwerty;
}
setRowNumber(4);
}
}
}
public double getHeightKeyModifier() {
return (double)PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getInt("height", 50) / (double)50;
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/Preference.java
================================================
package com.vlath.keyboard;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
/**
* Created by Vlad on 6/20/2017.
*/
public class Preference extends ActionBarActivity {
@Override
public void onCreate(Bundle h){
super.onCreate(h);
setContentView(R.layout.pref);
getFragmentManager().beginTransaction().replace(R.id.main, new PreferenceFragment()).commit();
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/PreferenceFragment.java
================================================
package com.vlath.keyboard;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.*;
import android.preference.Preference;
/**
* Created by todo on 30.06.2017.
*/
public class PreferenceFragment extends android.preference.PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
ListPreference listTheme;
ListPreference listStart;
ListPreference listLayout;
@Override
public void onCreate(Bundle s){
super.onCreate(s);
addPreferencesFromResource(R.xml.ime_preferences);
listTheme = (ListPreference) findPreference("theme");
listStart = (ListPreference) findPreference("start");
listLayout = (ListPreference) findPreference("layout");
listTheme.setSummary(listTheme.getEntry());
listStart.setSummary(listStart.getEntry());
listLayout.setSummary(listLayout.getEntry());
PreferenceManager.getDefaultSharedPreferences(getActivity().getBaseContext()).registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
listTheme.setSummary(listTheme.getEntry());
listStart.setSummary(listStart.getEntry());
listLayout.setSummary(listLayout.getEntry());
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/SeekPreference.java
================================================
package com.vlath.keyboard;
/**
* Created by todo on 01.12.2017.
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class SeekPreference extends Preference implements OnSeekBarChangeListener {
private SeekBar mSeekBar;
private int mProgress;
public SeekPreference(Context context) {
this(context, null, 0);
}
public SeekPreference(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SeekPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setLayoutResource(R.layout.seek_dialog);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
mSeekBar.setProgress(mProgress);
mSeekBar.setOnSeekBarChangeListener(this);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (!fromUser)
return;
setValue(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// not used
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// not used
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
setValue(restoreValue ? getPersistedInt(mProgress) : (Integer) defaultValue);
}
public void setValue(int value) {
if (shouldPersist()) {
persistInt(value);
}
if (value != mProgress) {
mProgress = value;
notifyChanged();
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getInt(index, 0);
}
}
================================================
FILE: app/src/main/java/com/vlath/keyboard/Variables.java
================================================
package com.vlath.keyboard;
/**
* Created by Vlad on 6/22/2017.
*/
public class Variables {
/**
* Here we handle global variables
*/
private static boolean IS_CTRL = false;
private static boolean IS_ALT = false;
private static boolean IS_SHIFT = false;
public static boolean isAnyOn() {
return IS_CTRL || IS_ALT;
}
public static boolean isCtrl() {
return IS_CTRL;
}
public static boolean isAlt() {
return IS_ALT;
}
public static void setIsCtrl(boolean on) {
IS_CTRL = on;
}
public static void setIsAlt(boolean on) {
IS_ALT = on;
}
public static void setAltOn() {
IS_ALT = true;
}
public static void setAltOff() {
IS_ALT = false;
}
public static void setCtrlOn() {
IS_CTRL = true;
}
public static void setCtrlOff() {
IS_CTRL = false;
}
public static void setShiftOn() {
IS_SHIFT = true;
}
public static void setShiftOff() {
IS_SHIFT = false;
}
public static boolean isShift() {
return IS_SHIFT;
}
}
================================================
FILE: app/src/main/res/drawable/key_background.xml
================================================
================================================
FILE: app/src/main/res/drawable/key_background_back.xml
================================================
================================================
FILE: app/src/main/res/drawable/normal.xml
================================================
================================================
FILE: app/src/main/res/drawable/preview_background.xml
================================================
================================================
FILE: app/src/main/res/drawable/round_corners.xml
================================================
================================================
FILE: app/src/main/res/layout/activate.xml
================================================
================================================
FILE: app/src/main/res/layout/keyboard.xml
================================================
================================================
FILE: app/src/main/res/layout/keyboard_key_back.xml
================================================
================================================
FILE: app/src/main/res/layout/main.xml
================================================
================================================
FILE: app/src/main/res/layout/popup.xml
================================================
================================================
FILE: app/src/main/res/layout/pref.xml
================================================
================================================
FILE: app/src/main/res/layout/preview.xml
================================================
================================================
FILE: app/src/main/res/layout/seek_dialog.xml
================================================
================================================
FILE: app/src/main/res/layout/slide1.xml
================================================
================================================
FILE: app/src/main/res/layout/slide2.xml
================================================
================================================
FILE: app/src/main/res/layout/slide3.xml
================================================
================================================
FILE: app/src/main/res/layout/slide4.xml
================================================
================================================
FILE: app/src/main/res/values/attr.xml
================================================
================================================
FILE: app/src/main/res/values/colors.xml
================================================
#3F51B5#303F9F#FF4081@android:color/black#4CAF50#42A5F5#EF5350#26C6DA#26A69A#FFC107#D4E157#AB47BC#FFFF#424242#212121#a5a7aa#FF000000#000000#ff808080#bbffffff#009688#00bcd4#4caf50#8bc34a#00897b#00acc1#43a047#7cb342#26a69a#26c6da#66bb6a#9ccc65@color/dot_light_screen1@color/dot_light_screen2@color/dot_light_screen3@color/dot_light_screen4@color/dot_dark_screen1@color/dot_dark_screen2@color/dot_dark_screen3@color/dot_dark_screen4
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
52dip20sp16sp16dp16dp16dp30dp20dp120dp30dp16dp40dp
================================================
FILE: app/src/main/res/values/strings.xml
================================================
BeHe Keyboard%sWelcome to BeHe!Please click the enable button below to navigate to keyboard settings. Find BeHe Keyboard in the list and enable it. A warning dialog will appear, click ok. BeHe Keyboard does NOT collect any data. Then, navigate back and click the select button below and choose BeHe Keyboard from the list. After that you can test the keyboard using the text field below. To open the settings, tap the button below and click on BeHe Keyboard. \n\nSpecial thanks to Matt and Thomas for donating!If you like the app, please consider supporting me. Thanks!Stay up to dateFollow me on Twitter to find news about my apps. @VlathXDAVersion 1.1.2Auto capitalizationVibrate on key pressKey bordersEnable text predictionEnjoy a full-fledged PC keyboard on your android deviceSwitch easily between three keyboard faces, all with adjustable heightMultiple facesNo spying, no data collecting. All the source code can be found on GitHubOpen sourceTotally freeIf you want, you can support me by donating. E-mail me for detailsBeHe Keyboard is licensed under Apache License 2.0. A copy of the license can be found here. \n\nAlso, the source code is hosted on GitHub. \n\n Got any problems or suggestions? E-mail me!Also, the source code is hosted on GitHub12345678Black - white textWhite - black textBlue - white textBlue - black textRed - white textRed - black textOrange - white textMaterial Dark - white textStandardArrow KeysProgramming123QWERTY (en-us)AZERTY (fr-fr)QWERTZ (de-de)123\u0020.,;:!?\n()[]*&@{}/<>_+=|"
================================================
FILE: app/src/main/res/values/styles.xml
================================================
================================================
FILE: app/src/main/res/values-pt-rBR/strings.xml
================================================
Teclado BeHe%sBem-vindo ao Teclado BeHe!Por favor, clique no botão \"Ativar\" abaixo para navegar até as configurações do teclado. Encontre o teclado BeHe na lista e habilite-o. Uma aviso aparecerá, clique em OK. O Teclado BeHe NÃO coleta nenhum dado. Em seguida, navegue de volta, clique no botão \"Selecionar\" abaixo e escolha o Teclado BeHe na lista. Depois disso, você pode testar o teclado usando o campo de texto abaixo. Para abrir as configurações, toque no botão abaixo e clique em Teclado BeHe.Se você gosta do aplicativo, considere me apoiar. Obrigado!Mantenha-se atualizadoSiga-me no Twitter para encontrar novidade sobre meus aplicativos. @VlathXDAAuto capitalizaçãoVibrar ao pressionar uma teclaBordas do teclado12345678Preto - texto brancoBranco - texto pretoAzul - texto brancoAzul - black textVermelho - texto brancoVermelho - texto pretoLaranja - texto brancoMaterial Escuro - texto brancoQWERTYTeclas de setaProgramação123
================================================
FILE: app/src/main/res/xml/arrow_keys.xml
================================================
================================================
FILE: app/src/main/res/xml/azerty.xml
================================================
================================================
FILE: app/src/main/res/xml/azerty_arrow_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/azerty_arrows.xml
================================================
================================================
FILE: app/src/main/res/xml/azerty_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/dvorak.xml
================================================
================================================
FILE: app/src/main/res/xml/emoji.xml
================================================
================================================
FILE: app/src/main/res/xml/emoji2.xml
================================================
================================================
FILE: app/src/main/res/xml/ime_preferences.xml
================================================
================================================
FILE: app/src/main/res/xml/method.xml
================================================
================================================
FILE: app/src/main/res/xml/numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/popup_template.xml
================================================
================================================
FILE: app/src/main/res/xml/programming.xml
================================================
================================================
FILE: app/src/main/res/xml/qwerty.xml
================================================
================================================
FILE: app/src/main/res/xml/qwerty_arrow_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/qwerty_arrows.xml
================================================
================================================
FILE: app/src/main/res/xml/qwerty_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/qwertz.xml
================================================
================================================
FILE: app/src/main/res/xml/qwertz_arrow_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/qwertz_arrows.xml
================================================
================================================
FILE: app/src/main/res/xml/qwertz_numbers.xml
================================================
================================================
FILE: app/src/main/res/xml/symbols.xml
================================================
================================================
FILE: app/src/main/res/xml/symbols2.xml
================================================
================================================
FILE: app/src/test/java/com/vlath/keyboard/ExampleUnitTest.java
================================================
package com.vlath.keyboard;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see Testing documentation
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Wed Jun 14 12:07:36 EEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
================================================
FILE: gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app'