diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenu.java b/core/src/cz/nic/tablexia/menu/user/UserMenu.java index 0333213fc68479638febf24d6d6f970814be3433..7a22d759eefbbe3c1863c4b63bb19737044648f1 100644 --- a/core/src/cz/nic/tablexia/menu/user/UserMenu.java +++ b/core/src/cz/nic/tablexia/menu/user/UserMenu.java @@ -31,18 +31,17 @@ import cz.nic.tablexia.sync.work.DownloadUser; import cz.nic.tablexia.sync.work.PushDataToServer; import cz.nic.tablexia.sync.work.SyncWork; import cz.nic.tablexia.util.ui.ClickListenerWithSound; -import cz.nic.tablexia.util.ui.dialog.TablexiaComponentDialog; import cz.nic.tablexia.util.ui.dialog.TablexiaComponentDialogFactory; import cz.nic.tablexia.util.ui.dialog.components.AdaptiveSizeDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.BackButtonHideComponent; import cz.nic.tablexia.util.ui.dialog.components.CenterPositionDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.DimmerDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.FixedSpaceContentDialogComponent; +import cz.nic.tablexia.util.ui.dialog.components.PositiveNegativeButtonContentDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.ResizableSpaceContentDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.TextContentDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.TextFiledDialogComponent; import cz.nic.tablexia.util.ui.dialog.components.ViewportMaximumSizeComponent; -import cz.nic.tablexia.util.ui.dialog.components.PositiveNegativeButtonContentDialogComponent; /** * UserMenu container @@ -56,10 +55,14 @@ public class UserMenu extends AbstractMenu { private static final int USER_ITEM_HEIGHT = 80; private static final float DOWNLOAD_DIALOG_INPUT_WIDTH_PERCENT = 0.8f; - private static final int SYNC_REQUEST_DIALOG_WIDTH = 450; - private static final int SYNC_REQUEST_DIALOG_HEIGHT = 300; - private static final String SYNC_REQUEST_DIALOG_PLACEHOLDER_TEXT = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; - private static final int SYNC_REQUEST_DIALOG_MAXIMUM_LENGTH = 40; + private static final int SYNC_REQUEST_DIALOG_WIDTH = 450; + private static final int SYNC_REQUEST_DIALOG_HEIGHT = 300; + private static final String SYNC_REQUEST_DIALOG_PLACEHOLDER_TEXT = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; + private static final int SYNC_REQUEST_DIALOG_MAXIMUM_LENGTH = 36; + private static final float SYNC_DIALOG_TITLE_PAD = 0.15f; + private static final float SYNC_DIALOG_TEXT_FIELD_PAD = 0.05f; + + public static final String CODE_REGEX = "(([0-9]|[a-f]){8})-(([0-9]|[a-f]){4})-(([0-9]|[a-f]){4})-(([0-9]|[a-f]){4})-(([0-9]|[a-f]){12})$"; private List<User> users; @@ -156,23 +159,25 @@ public class UserMenu extends AbstractMenu { new DimmerDialogComponent(), new ViewportMaximumSizeComponent(), new AdaptiveSizeDialogComponent(), - new ResizableSpaceContentDialogComponent(), + new FixedSpaceContentDialogComponent(SYNC_DIALOG_TITLE_PAD), new TextContentDialogComponent(ApplicationTextManager.getInstance().getText(ApplicationTextManager.ApplicationTextsAssets.SYNC_REQUEST_DIALOG_TEXT)), - new ResizableSpaceContentDialogComponent(), + new FixedSpaceContentDialogComponent(SYNC_DIALOG_TEXT_FIELD_PAD), textFiledDialogComponent, new ResizableSpaceContentDialogComponent(), new PositiveNegativeButtonContentDialogComponent(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { super.clicked(event, x, y); - DownloadUser syncWork = new DownloadUser(textFiledDialogComponent.getText()); - syncWork.registerListener(new SyncWork.RestSyncListener() { - @Override - public void onSuccess(User user) { - ApplicationBus.getInstance().post(new RefreshUserMenu()).asynchronously(); - } - }); - RestSynchronizationService.doSyncWork(syncWork); + if (textFiledDialogComponent.getText().length()>0 && textFiledDialogComponent.getText().toLowerCase().matches(CODE_REGEX)) { + DownloadUser syncWork = new DownloadUser(textFiledDialogComponent.getText()); + syncWork.registerListener(new SyncWork.RestSyncListener() { + @Override + public void onSuccess(User user) { + ApplicationBus.getInstance().post(new RefreshUserMenu()).asynchronously(); + } + }); + RestSynchronizationService.doSyncWork(syncWork); + } //Prevents keyboard getting stuck Gdx.input.setOnscreenKeyboardVisible(false); } diff --git a/core/src/cz/nic/tablexia/util/ui/TextFieldWithPlaceholder.java b/core/src/cz/nic/tablexia/util/ui/TextFieldWithPlaceholder.java index 93d8dbcfb9d74096a43c6509c42a6d2efbb47706..94f2ac1383698f86f6abc844cf2efa19cf5a5329 100644 --- a/core/src/cz/nic/tablexia/util/ui/TextFieldWithPlaceholder.java +++ b/core/src/cz/nic/tablexia/util/ui/TextFieldWithPlaceholder.java @@ -59,7 +59,7 @@ public class TextFieldWithPlaceholder extends TextField { } private static final Color DEFAULT_PLACEHOLDER_COLOR = Color.GRAY; - private static final int DEFAULT_PLACEHOLDER_ALIGN = Align.left; + private static final int DEFAULT_PLACEHOLDER_ALIGN = Align.center; private TablexiaTextFieldStyle tablexiaTextFieldStyle; private TablexiaLabel placeholder; diff --git a/core/src/cz/nic/tablexia/util/ui/dialog/components/TextFiledDialogComponent.java b/core/src/cz/nic/tablexia/util/ui/dialog/components/TextFiledDialogComponent.java index 3c178ea2f0ef4f0bdeea7354c02ba77b50948c0d..dea34d8933e31eddef4aeffab0c0c463de9cdbe4 100644 --- a/core/src/cz/nic/tablexia/util/ui/dialog/components/TextFiledDialogComponent.java +++ b/core/src/cz/nic/tablexia/util/ui/dialog/components/TextFiledDialogComponent.java @@ -1,15 +1,20 @@ package cz.nic.tablexia.util.ui.dialog.components; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.InputListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Cell; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; -import com.badlogic.gdx.scenes.scene2d.utils.FocusListener; import com.badlogic.gdx.utils.Align; +import java.util.Timer; +import java.util.TimerTask; + import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; @@ -25,8 +30,10 @@ public class TextFiledDialogComponent extends TablexiaDialogComponentAdapter { private static final ApplicationFontManager.FontType_NEW DEFAULT_FONT_TYPE = ApplicationFontManager.FontType_NEW.REGULAR_20; private static final int FONT_SIZE_RESIZE_THRESHOLD_STEP = 10; private static final String DEFAULT_PLACEHOLDER_TEXT = ""; - private static final int DEFAULT_TEXTFIELD_ALIGN = Align.left; + private static final int DEFAULT_TEXTFIELD_ALIGN = Align.center; private static final float DEFAULT_TEXT_FIELD_WIDTH_PERCENT = 1; + + public static final int DIALOG_REPLACE_TIMEOUT = 7000; private boolean isScaled; private final Color fontColor; @@ -39,7 +46,10 @@ public class TextFiledDialogComponent extends TablexiaDialogComponentAdapter { private TextFieldWithPlaceholder textField; private Cell content; - private FocusListener changePositionFocusListener; + private Timer timer; + private boolean timerSet; + + private InputListener repositionOnTypeListener, repositionOnTouchListener; public TextFiledDialogComponent() { this(null, DEFAULT_PLACEHOLDER_TEXT, DEFAULT_FONT_TYPE, DEFAULT_FONT_COLOR); @@ -59,7 +69,7 @@ public class TextFiledDialogComponent extends TablexiaDialogComponentAdapter { this.actualFontType = fontType; this.fontColor = fontColor; this.maximumLength = maximumLength; - + timerSet = false; textField = prepareTextField(placeholderText); } @@ -104,7 +114,6 @@ public class TextFiledDialogComponent extends TablexiaDialogComponentAdapter { if (maximumLength != null) { fieldWithPlaceholder.setMaxLength(maximumLength); } - fieldWithPlaceholder.setAlignment(DEFAULT_TEXTFIELD_ALIGN); return fieldWithPlaceholder; } @@ -119,31 +128,93 @@ public class TextFiledDialogComponent extends TablexiaDialogComponentAdapter { public void setRepositionOnFocusOnMobileDevices(boolean repositionOnFocus) { if(repositionOnFocus && TablexiaSettings.getInstance().isRunningOnMobileDevice()) { - if(changePositionFocusListener == null) prepareChangePositionFocusListener(); - textField.addListener(changePositionFocusListener); + if (repositionOnTypeListener == null) prepareOnTypeListener(); + if (repositionOnTouchListener == null) prepareOnTouchListener(); + textField.addListener(repositionOnTypeListener); + textField.addListener(repositionOnTouchListener); } else { - if(changePositionFocusListener != null) textField.removeListener(changePositionFocusListener); + if (repositionOnTypeListener != null) textField.removeListener(repositionOnTypeListener); + if (repositionOnTouchListener != null) textField.removeListener(repositionOnTouchListener); } } - private void prepareChangePositionFocusListener() { - this.changePositionFocusListener = new FocusListener() { + private void prepareOnTypeListener() { + this.repositionOnTypeListener = new InputListener() { + private static final int COMMON_INT_CODE_FOR_ENTER = 13; + private static final int ANDROID_INT_CODE_FOR_ENTER = 10; + + @Override + public boolean keyTyped(InputEvent event, char character) { + if (timerSet) timer.cancel(); + // have to check also (int)character because of some bug in iOS keyboard. It returns code Input.Keys.ENTER for every key after "done" button pressed + if ((event.getKeyCode() != Input.Keys.ENTER || ((int) character != ANDROID_INT_CODE_FOR_ENTER || (int) character != COMMON_INT_CODE_FOR_ENTER))) { + resetTimer(); + } else { + repositionDialog(DialogPosition.CENTER); + } + return false; + } + }; + } + + + public void prepareOnTouchListener(){ + this.repositionOnTouchListener = new InputListener(){ + @Override - public void keyboardFocusChanged(FocusListener.FocusEvent event, Actor actor, boolean focused) { - if(focused) repositionDialog(); + public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { + if (timerSet) timer.cancel(); + repositionDialog(DialogPosition.TOP); + resetTimer(); + return super.touchDown(event, x, y, pointer, button); } }; } - private void repositionDialog() { + private void resetTimer() { + timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + repositionDialog(DialogPosition.CENTER); + timerSet = false; + } + }, DIALOG_REPLACE_TIMEOUT); + timerSet = true; + } + + private void repositionDialog(DialogPosition dialogPosition) { TablexiaComponentDialog dialog = getDialog(); Stage stage = getStage(); if(dialog == null || (stage == null)) return; dialog.setPosition( - TablexiaSettings.getViewportLeftX(stage) + TablexiaSettings.getViewportWidth(stage) / 2f - dialog.getInnerWidth()/2f, - TablexiaSettings.getViewportBottomY(stage) + TablexiaSettings.getViewportHeight(stage) - dialog.getOutterHeight() + TablexiaSettings.getViewportLeftX(stage) + TablexiaSettings.getViewportWidth(stage) * 0.5f - dialog.getInnerWidth() * 0.5f, + TablexiaSettings.getViewportBottomY(stage) + TablexiaSettings.getViewportHeight(stage) * dialogPosition.getShift() - dialog.getOutterHeight() * dialogPosition.getShift() ); + + Gdx.input.setOnscreenKeyboardVisible(dialogPosition.isShowKeyboard()); + } + + private enum DialogPosition { + TOP(1f, true), + CENTER(0.5f, false); + + private float shift; + private boolean showKeyboard; + + DialogPosition(float shift, boolean showKeyboard) { + this.shift = shift; + this.showKeyboard = showKeyboard; + } + + public float getShift() { + return shift; + } + + public boolean isShowKeyboard() { + return showKeyboard; + } } }