EditorView refactored

This commit is contained in:
serso 2016-01-07 21:36:01 +01:00
parent 6b89deee80
commit d1c068edff
31 changed files with 295 additions and 536 deletions

View File

@ -1,179 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.widget.EditText;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
import org.solovyev.common.collections.Collections;
import javax.annotation.Nonnull;
/**
* User: serso
* Date: 9/17/11
* Time: 12:25 AM
*/
public class AndroidCalculatorEditorView extends EditText implements CalculatorEditorView {
@Nonnull
private final Handler uiHandler = new Handler();
private volatile boolean initialized = false;
@SuppressWarnings("UnusedDeclaration")
@Nonnull
private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
private volatile boolean viewStateChange = false;
public AndroidCalculatorEditorView(Context context) {
super(context);
}
public AndroidCalculatorEditorView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AndroidCalculatorEditorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onCheckIsTextEditor() {
// NOTE: code below can be used carefully and should not be copied without special intention
// The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
if (Build.VERSION.SDK_INT >= 11) {
// fix for missing cursor in android 3 and higher
try {
// IDEA: return false always except if method was called from TextView.isCursorVisible() method
for (StackTraceElement stackTraceElement : Collections.asList(Thread.currentThread().getStackTrace())) {
if ("isCursorVisible".equals(stackTraceElement.getMethodName())) {
return true;
}
}
} catch (RuntimeException e) {
// just in case...
}
return false;
} else {
return false;
}
}
@Override
protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
menu.removeItem(android.R.id.selectAll);
}
public void setHighlightText(boolean highlightText) {
//this.highlightText = highlightText;
Locator.getInstance().getEditor().updateViewState();
}
public synchronized void init() {
if (!initialized) {
this.addTextChangedListener(new TextWatcherImpl());
initialized = true;
}
}
@Override
public void setState(@Nonnull final CalculatorEditorViewState viewState) {
synchronized (this) {
uiHandler.post(new Runnable() {
@Override
public void run() {
final AndroidCalculatorEditorView editorView = AndroidCalculatorEditorView.this;
synchronized (AndroidCalculatorEditorView.this) {
try {
editorView.viewStateChange = true;
editorView.viewState = viewState;
if (App.getTheme().light && getContext() instanceof CalculatorOnscreenService) {
// don't need formatting
editorView.setText(viewState.getText());
} else {
editorView.setText(viewState.getTextAsCharSequence(), BufferType.EDITABLE);
}
final int selection = CalculatorEditorImpl.correctSelection(viewState.getSelection(), editorView.getText());
editorView.setSelection(selection);
} finally {
editorView.viewStateChange = false;
}
}
}
});
}
}
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
synchronized (this) {
if (initialized && !viewStateChange) {
// external text change => need to notify editor
super.onSelectionChanged(selStart, selEnd);
if (selStart == selEnd) {
// only if cursor moving, if selection do nothing
Locator.getInstance().getEditor().setSelection(selStart);
}
}
}
}
public void handleTextChange(Editable s) {
synchronized (this) {
if (initialized && !viewStateChange) {
// external text change => need to notify editor
Locator.getInstance().getEditor().setText(String.valueOf(s));
}
}
}
private final class TextWatcherImpl implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
handleTextChange(s);
}
}
}

View File

@ -36,14 +36,14 @@ public interface CalculatorEditor extends CalculatorEventListener {
@Nonnull @Nonnull
String TAG = CalculatorEditor.class.getSimpleName(); String TAG = CalculatorEditor.class.getSimpleName();
void setView(@Nonnull CalculatorEditorView view); void setView(@Nonnull EditorView view);
void clearView(@Nonnull CalculatorEditorView view); void clearView(@Nonnull EditorView view);
@Nonnull @Nonnull
CalculatorEditorViewState getViewState(); EditorState getViewState();
void setViewState(@Nonnull CalculatorEditorViewState viewState); void setViewState(@Nonnull EditorState viewState);
// updates state of view (view.setState()) // updates state of view (view.setState())
void updateViewState(); void updateViewState();
@ -60,25 +60,25 @@ public interface CalculatorEditor extends CalculatorEventListener {
* Method sets the cursor to the beginning * Method sets the cursor to the beginning
*/ */
@Nonnull @Nonnull
public CalculatorEditorViewState setCursorOnStart(); EditorState setCursorOnStart();
/** /**
* Method sets the cursor to the end * Method sets the cursor to the end
*/ */
@Nonnull @Nonnull
public CalculatorEditorViewState setCursorOnEnd(); EditorState setCursorOnEnd();
/** /**
* Method moves cursor to the left of current position * Method moves cursor to the left of current position
*/ */
@Nonnull @Nonnull
public CalculatorEditorViewState moveCursorLeft(); EditorState moveCursorLeft();
/** /**
* Method moves cursor to the right of current position * Method moves cursor to the right of current position
*/ */
@Nonnull @Nonnull
public CalculatorEditorViewState moveCursorRight(); EditorState moveCursorRight();
@Nonnull @Nonnull
CursorControl asCursorControl(); CursorControl asCursorControl();
@ -92,26 +92,26 @@ public interface CalculatorEditor extends CalculatorEventListener {
********************************************************************** **********************************************************************
*/ */
@Nonnull @Nonnull
CalculatorEditorViewState erase(); EditorState erase();
@Nonnull @Nonnull
CalculatorEditorViewState clear(); EditorState clear();
@Nonnull @Nonnull
CalculatorEditorViewState setText(@Nonnull String text); EditorState setText(@Nonnull String text);
@Nonnull @Nonnull
CalculatorEditorViewState setText(@Nonnull String text, int selection); EditorState setText(@Nonnull String text, int selection);
@Nonnull @Nonnull
CalculatorEditorViewState insert(@Nonnull String text); EditorState insert(@Nonnull String text);
@Nonnull @Nonnull
CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset); EditorState insert(@Nonnull String text, int selectionOffset);
@Nonnull @Nonnull
CalculatorEditorViewState moveSelection(int offset); EditorState moveSelection(int offset);
@Nonnull @Nonnull
CalculatorEditorViewState setSelection(int selection); EditorState setSelection(int selection);
} }

View File

@ -29,34 +29,34 @@ import javax.annotation.Nonnull;
* Date: 21.09.12 * Date: 21.09.12
* Time: 13:46 * Time: 13:46
*/ */
public final class CalculatorEditorChangeEventData implements Change<CalculatorEditorViewState> { public final class CalculatorEditorChangeEventData implements Change<EditorState> {
@Nonnull @Nonnull
private CalculatorEditorViewState oldState; private EditorState oldState;
@Nonnull @Nonnull
private CalculatorEditorViewState newState; private EditorState newState;
private CalculatorEditorChangeEventData(@Nonnull CalculatorEditorViewState oldState, private CalculatorEditorChangeEventData(@Nonnull EditorState oldState,
@Nonnull CalculatorEditorViewState newState) { @Nonnull EditorState newState) {
this.oldState = oldState; this.oldState = oldState;
this.newState = newState; this.newState = newState;
} }
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull CalculatorEditorViewState oldState, public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull EditorState oldState,
@Nonnull CalculatorEditorViewState newState) { @Nonnull EditorState newState) {
return new CalculatorEditorChangeEventData(oldState, newState); return new CalculatorEditorChangeEventData(oldState, newState);
} }
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState getOldValue() { public EditorState getOldValue() {
return this.oldState; return this.oldState;
} }
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState getNewValue() { public EditorState getNewValue() {
return this.newState; return this.newState;
} }
} }

View File

@ -54,7 +54,7 @@ public class CalculatorEditorFragment extends Fragment {
private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromEnum(CalculatorMenu.class, AndroidMenuHelper.getInstance()); private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromEnum(CalculatorMenu.class, AndroidMenuHelper.getInstance());
@Nonnull @Nonnull
private AndroidCalculatorEditorView editorView; private EditorView editorView;
public CalculatorEditorFragment() { public CalculatorEditorFragment() {
} }
@ -65,8 +65,7 @@ public class CalculatorEditorFragment extends Fragment {
fragmentUi.onViewCreated(this, view); fragmentUi.onViewCreated(this, view);
editorView = (AndroidCalculatorEditorView) view.findViewById(R.id.calculator_editor); editorView = (EditorView) view.findViewById(R.id.calculator_editor);
editorView.init();
Locator.getInstance().getEditor().setView(editorView); Locator.getInstance().getEditor().setView(editorView);
} }

View File

@ -55,9 +55,9 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nullable @Nullable
private final TextProcessor<TextProcessorEditorResult, String> textProcessor; private final TextProcessor<TextProcessorEditorResult, String> textProcessor;
@Nullable @Nullable
private CalculatorEditorView view; private EditorView view;
@Nonnull @Nonnull
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance(); private EditorState lastViewState = EditorState.empty();
public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) { public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.calculator = calculator; this.calculator = calculator;
@ -66,18 +66,16 @@ public class CalculatorEditorImpl implements CalculatorEditor {
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
} }
public static int correctSelection(int selection, @Nonnull CharSequence text) { public static int clamp(int selection, @Nonnull CharSequence text) {
return correctSelection(selection, text.length()); return clamp(selection, text.length());
} }
public static int correctSelection(int selection, int textLength) { public static int clamp(int selection, int max) {
int result = Math.max(selection, 0); return min(Math.max(selection, 0), max);
result = min(result, textLength);
return result;
} }
@Override @Override
public void setView(@Nonnull CalculatorEditorView view) { public void setView(@Nonnull EditorView view) {
synchronized (viewLock) { synchronized (viewLock) {
this.view = view; this.view = view;
this.view.setState(lastViewState); this.view.setState(lastViewState);
@ -85,7 +83,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
} }
@Override @Override
public void clearView(@Nonnull CalculatorEditorView view) { public void clearView(@Nonnull EditorView view) {
synchronized (viewLock) { synchronized (viewLock) {
if (this.view == view) { if (this.view == view) {
this.view = null; this.view = null;
@ -95,12 +93,12 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState getViewState() { public EditorState getViewState() {
return lastViewState; return lastViewState;
} }
@Override @Override
public void setViewState(@Nonnull CalculatorEditorViewState newViewState) { public void setViewState(@Nonnull EditorState newViewState) {
setViewState(newViewState, true); setViewState(newViewState, true);
} }
@ -109,17 +107,17 @@ public class CalculatorEditorImpl implements CalculatorEditor {
setViewState(this.lastViewState, false); setViewState(this.lastViewState, false);
} }
private void setViewState(@Nonnull CalculatorEditorViewState newViewState, boolean majorChanges) { private void setViewState(@Nonnull EditorState newViewState, boolean majorChanges) {
if (textProcessor != null) { if (textProcessor != null) {
try { try {
final TextProcessorEditorResult result = textProcessor.process(newViewState.getText()); final TextProcessorEditorResult result = textProcessor.process(newViewState.getText());
newViewState = CalculatorEditorViewStateImpl.newInstance(result.getCharSequence(), newViewState.getSelection() + result.getOffset()); newViewState = EditorState.create(result.getCharSequence(), newViewState.getSelection() + result.getOffset());
} catch (CalculatorParseException e) { } catch (CalculatorParseException e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e); Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
} }
} }
synchronized (viewLock) { synchronized (viewLock) {
final CalculatorEditorViewState oldViewState = this.lastViewState; final EditorState oldViewState = this.lastViewState;
this.lastViewState = newViewState; this.lastViewState = newViewState;
if (this.view != null) { if (this.view != null) {
@ -138,7 +136,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
********************************************************************** **********************************************************************
*/ */
private void fireStateChangedEvent(boolean majorChanges, @Nonnull CalculatorEditorViewState oldViewState, @Nonnull CalculatorEditorViewState newViewState) { private void fireStateChangedEvent(boolean majorChanges, @Nonnull EditorState oldViewState, @Nonnull EditorState newViewState) {
if (!Thread.holdsLock(viewLock)) throw new AssertionError(); if (!Thread.holdsLock(viewLock)) throw new AssertionError();
if (majorChanges) { if (majorChanges) {
@ -166,9 +164,9 @@ public class CalculatorEditorImpl implements CalculatorEditor {
} }
@Nonnull @Nonnull
private CalculatorEditorViewState newSelectionViewState(int newSelection) { private EditorState newSelectionViewState(int newSelection) {
if (this.lastViewState.getSelection() != newSelection) { if (this.lastViewState.getSelection() != newSelection) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection); final EditorState result = EditorState.newSelection(this.lastViewState, newSelection);
setViewState(result, false); setViewState(result, false);
return result; return result;
} else { } else {
@ -177,21 +175,21 @@ public class CalculatorEditorImpl implements CalculatorEditor {
} }
@Nonnull @Nonnull
public CalculatorEditorViewState setCursorOnStart() { public EditorState setCursorOnStart() {
synchronized (viewLock) { synchronized (viewLock) {
return newSelectionViewState(0); return newSelectionViewState(0);
} }
} }
@Nonnull @Nonnull
public CalculatorEditorViewState setCursorOnEnd() { public EditorState setCursorOnEnd() {
synchronized (viewLock) { synchronized (viewLock) {
return newSelectionViewState(this.lastViewState.getText().length()); return newSelectionViewState(this.lastViewState.getText().length());
} }
} }
@Nonnull @Nonnull
public CalculatorEditorViewState moveCursorLeft() { public EditorState moveCursorLeft() {
synchronized (viewLock) { synchronized (viewLock) {
if (this.lastViewState.getSelection() > 0) { if (this.lastViewState.getSelection() > 0) {
return newSelectionViewState(this.lastViewState.getSelection() - 1); return newSelectionViewState(this.lastViewState.getSelection() - 1);
@ -210,7 +208,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
*/ */
@Nonnull @Nonnull
public CalculatorEditorViewState moveCursorRight() { public EditorState moveCursorRight() {
synchronized (viewLock) { synchronized (viewLock) {
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) { if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
return newSelectionViewState(this.lastViewState.getSelection() + 1); return newSelectionViewState(this.lastViewState.getSelection() + 1);
@ -228,7 +226,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState erase() { public EditorState erase() {
synchronized (viewLock) { synchronized (viewLock) {
int selection = this.lastViewState.getSelection(); int selection = this.lastViewState.getSelection();
final String text = this.lastViewState.getText(); final String text = this.lastViewState.getText();
@ -236,7 +234,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
final StringBuilder newText = new StringBuilder(text.length() - 1); final StringBuilder newText = new StringBuilder(text.length() - 1);
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length()));
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), selection - 1); final EditorState result = EditorState.create(newText.toString(), selection - 1);
setViewState(result); setViewState(result);
return result; return result;
} else { } else {
@ -247,7 +245,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState clear() { public EditorState clear() {
synchronized (viewLock) { synchronized (viewLock) {
return setText(""); return setText("");
} }
@ -255,9 +253,9 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState setText(@Nonnull String text) { public EditorState setText(@Nonnull String text) {
synchronized (viewLock) { synchronized (viewLock) {
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, text.length()); final EditorState result = EditorState.create(text, text.length());
setViewState(result); setViewState(result);
return result; return result;
} }
@ -265,11 +263,11 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState setText(@Nonnull String text, int selection) { public EditorState setText(@Nonnull String text, int selection) {
synchronized (viewLock) { synchronized (viewLock) {
selection = correctSelection(selection, text); selection = clamp(selection, text);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(text, selection); final EditorState result = EditorState.create(text, selection);
setViewState(result); setViewState(result);
return result; return result;
} }
@ -277,7 +275,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState insert(@Nonnull String text) { public EditorState insert(@Nonnull String text) {
synchronized (viewLock) { synchronized (viewLock) {
return insert(text, 0); return insert(text, 0);
} }
@ -285,10 +283,10 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState insert(@Nonnull String text, int selectionOffset) { public EditorState insert(@Nonnull String text, int selectionOffset) {
synchronized (viewLock) { synchronized (viewLock) {
final String oldText = lastViewState.getText(); final String oldText = lastViewState.getText();
final int selection = correctSelection(lastViewState.getSelection(), oldText); final int selection = clamp(lastViewState.getSelection(), oldText);
int newTextLength = text.length() + oldText.length(); int newTextLength = text.length() + oldText.length();
final StringBuilder newText = new StringBuilder(newTextLength); final StringBuilder newText = new StringBuilder(newTextLength);
@ -297,8 +295,8 @@ public class CalculatorEditorImpl implements CalculatorEditor {
newText.append(text); newText.append(text);
newText.append(oldText.substring(selection)); newText.append(oldText.substring(selection));
int newSelection = correctSelection(text.length() + selection + selectionOffset, newTextLength); int newSelection = clamp(text.length() + selection + selectionOffset, newTextLength);
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newInstance(newText.toString(), newSelection); final EditorState result = EditorState.create(newText.toString(), newSelection);
setViewState(result); setViewState(result);
return result; return result;
} }
@ -306,7 +304,7 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState moveSelection(int offset) { public EditorState moveSelection(int offset) {
synchronized (viewLock) { synchronized (viewLock) {
int selection = this.lastViewState.getSelection() + offset; int selection = this.lastViewState.getSelection() + offset;
@ -316,11 +314,11 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull @Nonnull
@Override @Override
public CalculatorEditorViewState setSelection(int selection) { public EditorState setSelection(int selection) {
synchronized (viewLock) { synchronized (viewLock) {
selection = correctSelection(selection, this.lastViewState.getText()); selection = clamp(selection, this.lastViewState.getText());
final CalculatorEditorViewState result = CalculatorEditorViewStateImpl.newSelection(this.lastViewState, selection); final EditorState result = EditorState.newSelection(this.lastViewState, selection);
setViewState(result, false); setViewState(result, false);
return result; return result;
} }

View File

@ -1,35 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:48
*/
public interface CalculatorEditorView {
void setState(@Nonnull CalculatorEditorViewState viewState);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import java.io.Serializable;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:48
*/
public interface CalculatorEditorViewState extends Serializable {
@Nonnull
String getText();
@Nonnull
CharSequence getTextAsCharSequence();
int getSelection();
}

View File

@ -22,6 +22,14 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState; import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
@ -37,24 +45,14 @@ import org.solovyev.common.text.Strings;
import org.solovyev.common.units.ConversionException; import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions; import org.solovyev.common.units.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
@ -175,21 +173,21 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@Override @Override
public void evaluate() { public void evaluate() {
final CalculatorEditorViewState viewState = getEditor().getViewState(); final EditorState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId()); this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId());
} }
@Override @Override
public void evaluate(@Nonnull Long sequenceId) { public void evaluate(@Nonnull Long sequenceId) {
final CalculatorEditorViewState viewState = getEditor().getViewState(); final EditorState viewState = getEditor().getViewState();
fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId);
this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId);
} }
@Override @Override
public void simplify() { public void simplify() {
final CalculatorEditorViewState viewState = getEditor().getViewState(); final EditorState viewState = getEditor().getViewState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState);
this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId()); this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId());
} }

View File

@ -111,7 +111,7 @@ public class CalculatorKeyboardImpl implements CalculatorKeyboard {
@Override @Override
public void roundBracketsButtonPressed() { public void roundBracketsButtonPressed() {
final CalculatorEditor editor = Locator.getInstance().getEditor(); final CalculatorEditor editor = Locator.getInstance().getEditor();
CalculatorEditorViewState viewState = editor.getViewState(); EditorState viewState = editor.getViewState();
final int cursorPosition = viewState.getSelection(); final int cursorPosition = viewState.getSelection();
final String oldText = viewState.getText(); final String oldText = viewState.getText();

View File

@ -1,43 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/17/11
* Time: 9:37 PM
*/
public interface Editor {
@Nullable
CharSequence getText();
void setText(@Nullable CharSequence text);
int getSelection();
void setSelection(int selection);
}

View File

@ -23,62 +23,53 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.Serializable;
/** public class EditorState implements Serializable {
* User: Solovyev_S
* Date: 21.09.12
* Time: 12:02
*/
public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState {
@Nonnull @Nonnull
private CharSequence text = ""; private CharSequence text = "";
private int selection = 0; private int selection = 0;
private CalculatorEditorViewStateImpl() { private EditorState() {
} }
public CalculatorEditorViewStateImpl(@Nonnull CalculatorEditorViewState viewState) { public EditorState(@Nonnull EditorState state) {
this.text = viewState.getText(); this.text = state.getText();
this.selection = viewState.getSelection(); this.selection = state.getSelection();
} }
@Nonnull @Nonnull
public static CalculatorEditorViewState newDefaultInstance() { public static EditorState empty() {
return new CalculatorEditorViewStateImpl(); return new EditorState();
} }
@Nonnull @Nonnull
public static CalculatorEditorViewState newSelection(@Nonnull CalculatorEditorViewState viewState, int newSelection) { public static EditorState newSelection(@Nonnull EditorState state, int selection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(viewState); final EditorState result = new EditorState(state);
result.selection = selection;
result.selection = newSelection;
return result; return result;
} }
@Nonnull @Nonnull
public static CalculatorEditorViewState newInstance(@Nonnull CharSequence text, int selection) { public static EditorState create(@Nonnull CharSequence text, int selection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(); final EditorState result = new EditorState();
result.text = text; result.text = text;
result.selection = selection; result.selection = selection;
return result; return result;
} }
@Nonnull @Nonnull
@Override
public String getText() { public String getText() {
return this.text.toString(); return this.text.toString();
} }
@Nonnull @Nonnull
@Override
public CharSequence getTextAsCharSequence() { public CharSequence getTextAsCharSequence() {
return this.text; return this.text;
} }
@Override
public int getSelection() { public int getSelection() {
return this.selection; return this.selection;
} }

View File

@ -0,0 +1,157 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.widget.EditText;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
public class EditorView extends EditText {
@Nonnull
private static final String TAG = App.subTag("EditorView");
private boolean initialized;
@Nullable
private Method setShowSoftInputOnFocusMethod;
private boolean externalChange;
public EditorView(Context context) {
super(context);
init();
}
public EditorView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public EditorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public EditorView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
Check.isTrue(!initialized);
addTextChangedListener(new MyTextWatcher());
setShowSoftInputOnFocusCompat(false);
initialized = true;
}
@Override
protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
menu.removeItem(android.R.id.selectAll);
}
public void setState(@Nonnull final EditorState state) {
Check.isMainThread();
try {
externalChange = true;
if (App.getTheme().light && getContext() instanceof CalculatorOnscreenService) {
// don't need formatting
setText(state.getText());
} else {
setText(state.getTextAsCharSequence(), BufferType.EDITABLE);
}
final int selection = CalculatorEditorImpl.clamp(state.getSelection(), length());
setSelection(selection);
} finally {
externalChange = false;
}
}
@Override
protected void onSelectionChanged(int start, int end) {
Check.isMainThread();
if (!initialized || externalChange) {
return;
}
// external text change => need to notify editor
super.onSelectionChanged(start, end);
if (start == end) {
// only if cursor moving, if selection do nothing
Locator.getInstance().getEditor().setSelection(start);
}
}
public void setShowSoftInputOnFocusCompat(boolean show) {
Check.isMainThread();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
setShowSoftInputOnFocus(show);
} else {
setShowSoftInputOnFocusPreLollipop(show);
}
}
private void setShowSoftInputOnFocusPreLollipop(boolean show) {
try {
if (setShowSoftInputOnFocusMethod == null) {
setShowSoftInputOnFocusMethod = EditText.class.getMethod("setShowSoftInputOnFocus", boolean.class);
setShowSoftInputOnFocusMethod.setAccessible(true);
}
setShowSoftInputOnFocusMethod.invoke(this, show);
} catch (Exception e) {
Log.w(TAG, e.getMessage(), e);
}
}
private class MyTextWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!initialized || externalChange) {
return;
}
// external text change => need to notify editor
Locator.getInstance().getEditor().setText(String.valueOf(s));
}
}
}

View File

@ -22,32 +22,20 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.solovyev.android.calculator.Calculator; import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorChangeEventData;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventHolder;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.CalculatorUtils;
import org.solovyev.android.calculator.Locator;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryHelper;
import org.solovyev.common.history.SimpleHistoryHelper; import org.solovyev.common.history.SimpleHistoryHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nonnull; import static org.solovyev.android.calculator.CalculatorEventType.*;
import javax.annotation.Nullable;
import static org.solovyev.android.calculator.CalculatorEventType.display_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.manual_calculation_requested;
/** /**
* User: Solovyev_S * User: Solovyev_S
@ -68,7 +56,7 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); private final CalculatorEventHolder lastEventData = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
@Nullable @Nullable
private volatile CalculatorEditorViewState lastEditorViewState; private volatile EditorState lastEditorViewState;
public CalculatorHistoryImpl(@Nonnull Calculator calculator) { public CalculatorHistoryImpl(@Nonnull Calculator calculator) {
calculator.addCalculatorEventListener(this); calculator.addCalculatorEventListener(this);
@ -267,7 +255,7 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
if (result.isNewAfter() && result.isNewSameOrAfterSequence()) { if (result.isNewAfter() && result.isNewSameOrAfterSequence()) {
switch (calculatorEventType) { switch (calculatorEventType) {
case manual_calculation_requested: case manual_calculation_requested:
lastEditorViewState = (CalculatorEditorViewState) data; lastEditorViewState = (EditorState) data;
break; break;
case editor_state_changed: case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data; final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
@ -276,7 +264,7 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
case display_state_changed: case display_state_changed:
if (result.isSameSequence()) { if (result.isSameSequence()) {
if (lastEditorViewState != null) { if (lastEditorViewState != null) {
final CalculatorEditorViewState editorViewState = lastEditorViewState; final EditorState editorViewState = lastEditorViewState;
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data; final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue(); final CalculatorDisplayViewState displayViewState = displayChangeData.getNewValue();
addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState)); addState(CalculatorHistoryState.newInstance(editorViewState, displayViewState));

View File

@ -27,7 +27,7 @@ import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplay; import org.solovyev.android.calculator.CalculatorDisplay;
import org.solovyev.android.calculator.CalculatorDisplayViewState; import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditor; import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.CalculatorEditorViewState; import org.solovyev.android.calculator.EditorState;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -61,14 +61,14 @@ public class CalculatorHistoryState extends AbstractHistoryState {
@Nonnull @Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditor editor, public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditor editor,
@Nonnull CalculatorDisplay display) { @Nonnull CalculatorDisplay display) {
final CalculatorEditorViewState editorViewState = editor.getViewState(); final EditorState editorViewState = editor.getViewState();
final CalculatorDisplayViewState displayViewState = display.getViewState(); final CalculatorDisplayViewState displayViewState = display.getViewState();
return newInstance(editorViewState, displayViewState); return newInstance(editorViewState, displayViewState);
} }
@Nonnull @Nonnull
public static CalculatorHistoryState newInstance(@Nonnull CalculatorEditorViewState editorViewState, public static CalculatorHistoryState newInstance(@Nonnull EditorState editorViewState,
@Nonnull CalculatorDisplayViewState displayViewState) { @Nonnull CalculatorDisplayViewState displayViewState) {
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editorViewState); final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editorViewState);

View File

@ -26,7 +26,7 @@ import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplayViewState; import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditor; import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.CalculatorEditorViewState; import org.solovyev.android.calculator.EditorState;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -47,7 +47,7 @@ public class EditorHistoryState implements Cloneable {
} }
@Nonnull @Nonnull
public static EditorHistoryState newInstance(@Nonnull CalculatorEditorViewState viewState) { public static EditorHistoryState newInstance(@Nonnull EditorState viewState) {
final EditorHistoryState result = new EditorHistoryState(); final EditorHistoryState result = new EditorHistoryState();
result.text = String.valueOf(viewState.getText()); result.text = String.valueOf(viewState.getText());

View File

@ -1,68 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* 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.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator.history;
import android.widget.EditText;
import android.widget.TextView;
import org.solovyev.android.calculator.Editor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/17/11
* Time: 9:39 PM
*/
public class TextViewEditorAdapter implements Editor {
@Nonnull
private final TextView textView;
public TextViewEditorAdapter(@Nonnull TextView textView) {
this.textView = textView;
}
@Override
public CharSequence getText() {
return textView.getText().toString();
}
@Override
public void setText(@Nullable CharSequence text) {
textView.setText(text);
}
@Override
public int getSelection() {
return textView.getSelectionStart();
}
@Override
public void setSelection(int selection) {
if (textView instanceof EditText) {
((EditText) textView).setSelection(selection);
}
}
}

View File

@ -35,21 +35,12 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.AndroidCalculatorDisplayView;
import org.solovyev.android.calculator.AndroidCalculatorEditorView;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorButton;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R;
import org.solovyev.android.prefs.Preference; import org.solovyev.android.prefs.Preference;
import java.util.Locale;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Locale;
/** /**
* User: serso * User: serso
@ -100,7 +91,7 @@ public class CalculatorOnscreenView {
private Drawable headerTitleDrawable; private Drawable headerTitleDrawable;
@Nonnull @Nonnull
private AndroidCalculatorEditorView editorView; private EditorView editorView;
@Nonnull @Nonnull
private AndroidCalculatorDisplayView displayView; private AndroidCalculatorDisplayView displayView;
@ -202,7 +193,7 @@ public class CalculatorOnscreenView {
********************************************************************** **********************************************************************
*/ */
public void updateEditorState(@Nonnull CalculatorEditorViewState editorState) { public void updateEditorState(@Nonnull EditorState editorState) {
checkInit(); checkInit();
editorView.setState(editorState); editorView.setState(editorState);
} }
@ -253,8 +244,7 @@ public class CalculatorOnscreenView {
displayView = (AndroidCalculatorDisplayView) root.findViewById(R.id.calculator_display); displayView = (AndroidCalculatorDisplayView) root.findViewById(R.id.calculator_display);
displayView.init(this.context, false); displayView.init(this.context, false);
editorView = (AndroidCalculatorEditorView) root.findViewById(R.id.calculator_editor); editorView = (EditorView) root.findViewById(R.id.calculator_editor);
editorView.init();
final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button); final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button);
onscreenFoldButton.setOnClickListener(new View.OnClickListener() { onscreenFoldButton.setOnClickListener(new View.OnClickListener() {

View File

@ -6,7 +6,7 @@ import android.view.View;
import org.solovyev.android.calculator.Calculator; import org.solovyev.android.calculator.Calculator;
import org.solovyev.android.calculator.CalculatorEditor; import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.CalculatorEditorViewState; import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.Locator; import org.solovyev.android.calculator.Locator;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -69,7 +69,7 @@ public final class LongClickEraser implements View.OnTouchListener {
@Override @Override
public void run() { public void run() {
final CalculatorEditorViewState state = editor.erase(); final EditorState state = editor.erase();
if (isEmpty(state.getText())) { if (isEmpty(state.getText())) {
stop(); stop();
return; return;

View File

@ -30,13 +30,16 @@ import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Typeface;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.text.SpannableString;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.SpannedString; import android.text.SpannedString;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import org.solovyev.android.Views; import org.solovyev.android.Views;
import org.solovyev.android.calculator.*; import org.solovyev.android.calculator.*;
@ -78,7 +81,10 @@ public class CalculatorWidget extends AppWidgetProvider {
@Nonnull @Nonnull
private SpannedString initCursorString(@Nonnull Context context) { private SpannedString initCursorString(@Nonnull Context context) {
if (cursorString == null) { if (cursorString == null) {
cursorString = new SpannedString(App.colorString("|", ContextCompat.getColor(context, R.color.cpp_widget_cursor))); final SpannableString s = App.colorString("|", ContextCompat.getColor(context, R.color.cpp_widget_cursor));
// this will override any other style span (f.e. italic)
s.setSpan(new StyleSpan(Typeface.NORMAL), 0, 1, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
cursorString = new SpannedString(s);
} }
return cursorString; return cursorString;
} }
@ -101,7 +107,7 @@ public class CalculatorWidget extends AppWidgetProvider {
private void updateWidget(@Nonnull Context context, private void updateWidget(@Nonnull Context context,
@Nonnull AppWidgetManager manager, @Nonnull AppWidgetManager manager,
@Nonnull int[] widgetIds) { @Nonnull int[] widgetIds) {
final CalculatorEditorViewState editorState = Locator.getInstance().getEditor().getViewState(); final EditorState editorState = Locator.getInstance().getEditor().getViewState();
final CalculatorDisplayViewState displayState = Locator.getInstance().getDisplay().getViewState(); final CalculatorDisplayViewState displayState = Locator.getInstance().getDisplay().getViewState();
final Resources resources = context.getResources(); final Resources resources = context.getResources();
@ -197,7 +203,7 @@ public class CalculatorWidget extends AppWidgetProvider {
views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error))); views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error)));
} }
private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull CalculatorEditorViewState editorState, @Nonnull SimpleTheme theme) { private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull EditorState editorState, @Nonnull SimpleTheme theme) {
final CharSequence text = editorState.getTextAsCharSequence(); final CharSequence text = editorState.getTextAsCharSequence();
final boolean unspan = App.getTheme().light != theme.light; final boolean unspan = App.getTheme().light != theme.light;

View File

@ -34,7 +34,7 @@
a:layout_width="match_parent" a:layout_width="match_parent"
a:layout_height="wrap_content" /> a:layout_height="wrap_content" />
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor" style="@style/CppText.Editor"
a:hint="@string/c_calc_editor_hint" a:hint="@string/c_calc_editor_hint"

View File

@ -34,7 +34,7 @@
a:layout_width="match_parent" a:layout_width="match_parent"
a:layout_height="wrap_content" /> a:layout_height="wrap_content" />
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor" style="@style/CppText.Editor"
a:hint="@string/c_calc_editor_hint" a:hint="@string/c_calc_editor_hint"

View File

@ -30,7 +30,7 @@
a:layout_height="match_parent" a:layout_height="match_parent"
a:padding="@dimen/cpp_editor_padding"> a:padding="@dimen/cpp_editor_padding">
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor" style="@style/CppText.Editor"
a:hint="@string/c_calc_editor_hint" a:hint="@string/c_calc_editor_hint"

View File

@ -30,7 +30,7 @@
a:layout_height="match_parent" a:layout_height="match_parent"
a:padding="@dimen/cpp_editor_padding"> a:padding="@dimen/cpp_editor_padding">
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor.Mobile" style="@style/CppText.Editor.Mobile"
a:hint="@string/c_calc_editor_hint" a:hint="@string/c_calc_editor_hint"

View File

@ -14,7 +14,7 @@
a:layout_height="match_parent" a:layout_height="match_parent"
a:padding="@dimen/cpp_editor_padding"> a:padding="@dimen/cpp_editor_padding">
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor.Onscreen" style="@style/CppText.Editor.Onscreen"
a:textIsSelectable="true" /> a:textIsSelectable="true" />

View File

@ -14,7 +14,7 @@
a:layout_height="match_parent" a:layout_height="match_parent"
a:padding="@dimen/cpp_editor_padding"> a:padding="@dimen/cpp_editor_padding">
<org.solovyev.android.calculator.AndroidCalculatorEditorView <org.solovyev.android.calculator.EditorView
a:id="@+id/calculator_editor" a:id="@+id/calculator_editor"
style="@style/CppText.Editor.Onscreen.Light" style="@style/CppText.Editor.Onscreen.Light"
a:textIsSelectable="true" /> a:textIsSelectable="true" />

View File

@ -61,6 +61,7 @@
<item name="android:layout_height">fill_parent</item> <item name="android:layout_height">fill_parent</item>
<item name="android:textSize">@dimen/cpp_editor_text_size</item> <item name="android:textSize">@dimen/cpp_editor_text_size</item>
<item name="android:textColor">?attr/cpp_text_color</item> <item name="android:textColor">?attr/cpp_text_color</item>
<item name="android:inputType">textMultiLine|textNoSuggestions</item>
</style> </style>
<style name="CppText.Editor.Mobile" parent="CppText.Editor"> <style name="CppText.Editor.Mobile" parent="CppText.Editor">

View File

@ -62,7 +62,7 @@ public class AndroidCalculatorEditorViewTest {
@Test @Test
public void testCreation() throws Exception { public void testCreation() throws Exception {
new AndroidCalculatorEditorView(CalculatorApplication.getInstance()); new EditorView(CalculatorApplication.getInstance());
} }
@Test @Test

View File

@ -75,7 +75,7 @@ public class CalculatorTestUtils {
} }
public static void initViews(@Nonnull Context context) { public static void initViews(@Nonnull Context context) {
final AndroidCalculatorEditorView editor = new AndroidCalculatorEditorView(context); final EditorView editor = new EditorView(context);
editor.init(); editor.init();
Locator.getInstance().getEditor().setView(editor); Locator.getInstance().getEditor().setView(editor);

View File

@ -30,13 +30,13 @@ import org.junit.Test;
* Date: 10/20/12 * Date: 10/20/12
* Time: 12:31 PM * Time: 12:31 PM
*/ */
public class CalculatorEditorViewStateImplTest { public class EditorStateTest {
@Test @Test
public void testSerialization() throws Exception { public void testSerialization() throws Exception {
CalculatorTestUtils.testSerialization(CalculatorEditorViewStateImpl.newDefaultInstance()); CalculatorTestUtils.testSerialization(EditorState.empty());
CalculatorEditorViewState out = CalculatorTestUtils.testSerialization(CalculatorEditorViewStateImpl.newInstance("treter", 2)); EditorState out = CalculatorTestUtils.testSerialization(EditorState.create("treter", 2));
Assert.assertEquals(2, out.getSelection()); Assert.assertEquals(2, out.getSelection());
Assert.assertEquals("treter", out.getText()); Assert.assertEquals("treter", out.getText());
} }

View File

@ -26,7 +26,7 @@ import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl; import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
import org.solovyev.android.calculator.CalculatorEditorViewStateImpl; import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.CalculatorTestUtils; import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.Locator; import org.solovyev.android.calculator.Locator;
@ -71,6 +71,6 @@ public class CalculatorHistoryImplTest {
} }
private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) { private void addState(@Nonnull CalculatorHistory calculatorHistory, @Nonnull String text) {
calculatorHistory.addState(CalculatorHistoryState.newInstance(CalculatorEditorViewStateImpl.newInstance(text, 3), CalculatorDisplayViewStateImpl.newDefaultInstance())); calculatorHistory.addState(CalculatorHistoryState.newInstance(EditorState.create(text, 3), CalculatorDisplayViewStateImpl.newDefaultInstance()));
} }
} }

View File

@ -26,8 +26,7 @@ import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.solovyev.android.calculator.CalculatorDisplayViewState; import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl; import org.solovyev.android.calculator.CalculatorDisplayViewStateImpl;
import org.solovyev.android.calculator.CalculatorEditorViewState; import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.CalculatorEditorViewStateImpl;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.Objects; import org.solovyev.common.Objects;
import org.solovyev.common.equals.CollectionEqualizer; import org.solovyev.common.equals.CollectionEqualizer;
@ -142,7 +141,7 @@ public class HistoryUtilsTest {
CalculatorDisplayViewState calculatorDisplay = CalculatorDisplayViewStateImpl.newErrorState(JsclOperation.simplify, "Error"); CalculatorDisplayViewState calculatorDisplay = CalculatorDisplayViewStateImpl.newErrorState(JsclOperation.simplify, "Error");
CalculatorEditorViewState calculatorEditor = CalculatorEditorViewStateImpl.newInstance("1+1", 3); CalculatorEditorViewState calculatorEditor = EditorState.create("1+1", 3);
CalculatorHistoryState state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); CalculatorHistoryState state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay);
state.setTime(date.getTime()); state.setTime(date.getTime());
@ -157,7 +156,7 @@ public class HistoryUtilsTest {
calculatorDisplay = CalculatorDisplayViewStateImpl.newValidState(JsclOperation.numeric, null, "5/6", 3); calculatorDisplay = CalculatorDisplayViewStateImpl.newValidState(JsclOperation.numeric, null, "5/6", 3);
calculatorEditor = CalculatorEditorViewStateImpl.newInstance("5/6", 2); calculatorEditor = EditorState.create("5/6", 2);
state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay);
state.setSaved(true); state.setSaved(true);
@ -166,7 +165,7 @@ public class HistoryUtilsTest {
calculatorDisplay = CalculatorDisplayViewStateImpl.newErrorState(JsclOperation.elementary, "Error"); calculatorDisplay = CalculatorDisplayViewStateImpl.newErrorState(JsclOperation.elementary, "Error");
calculatorEditor = CalculatorEditorViewStateImpl.newInstance("", 1); calculatorEditor = EditorState.create("", 1);
state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay);
state.setSaved(true); state.setSaved(true);
@ -175,7 +174,7 @@ public class HistoryUtilsTest {
calculatorDisplay = CalculatorDisplayViewStateImpl.newValidState(JsclOperation.numeric, null, "4+5/35sin(41)+dfdsfsdfs", 1); calculatorDisplay = CalculatorDisplayViewStateImpl.newValidState(JsclOperation.numeric, null, "4+5/35sin(41)+dfdsfsdfs", 1);
calculatorEditor = CalculatorEditorViewStateImpl.newInstance("4+5/35sin(41)+dfdsfsdfs", 0); calculatorEditor = EditorState.create("4+5/35sin(41)+dfdsfsdfs", 0);
state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay); state = CalculatorHistoryState.newInstance(calculatorEditor, calculatorDisplay);
state.setSaved(true); state.setSaved(true);