Bug 1086983 - Part 1: Restore editing text when switching between tabs in editing mode. r=lucasr

This commit is contained in:
Michael Comella 2014-11-07 05:27:15 -08:00
parent f827243aac
commit ed0a1c2c2f
4 changed files with 125 additions and 3 deletions

View File

@ -68,6 +68,7 @@ import org.mozilla.gecko.tabs.TabHistoryController.OnShowTabHistory;
import org.mozilla.gecko.tiles.TilesRecorder;
import org.mozilla.gecko.toolbar.AutocompleteHandler;
import org.mozilla.gecko.toolbar.BrowserToolbar;
import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
import org.mozilla.gecko.toolbar.ToolbarProgressView;
import org.mozilla.gecko.util.Clipboard;
import org.mozilla.gecko.util.EventCallback;
@ -245,6 +246,8 @@ public class BrowserApp extends GeckoApp
// The tab to be selected on editing mode exit.
private Integer mTargetTabForEditingMode;
private final TabEditingState mLastTabEditingState = new TabEditingState();
// The animator used to toggle HomePager visibility has a race where if the HomePager is shown
// (starting the animation), the HomePager is hidden, and the HomePager animation completes,
// both the web content and the HomePager will be hidden. This flag is used to prevent the
@ -313,17 +316,56 @@ public class BrowserApp extends GeckoApp
case BOOKMARK_REMOVED:
showBookmarkRemovedToast();
break;
case UNSELECTED:
// We receive UNSELECTED immediately after the SELECTED listeners run
// so we are ensured that the unselectedTabEditingText has not changed.
if (tab.isEditing()) {
// Copy to avoid constructing new objects.
tab.getEditingState().copyFrom(mLastTabEditingState);
}
break;
}
if (NewTabletUI.isEnabled(this) && msg == TabEvents.SELECTED) {
// Note: this is a duplicate call if maybeSwitchToTab
// is called, though the call is idempotent.
mBrowserToolbar.cancelEdit();
updateEditingModeForTab(tab);
}
super.onTabChanged(tab, msg, data);
}
private void updateEditingModeForTab(final Tab selectedTab) {
if (!Tabs.getInstance().isSelectedTab(selectedTab)) {
throw new IllegalStateException("Expected given tab to be selected");
}
saveTabEditingState(mLastTabEditingState);
if (selectedTab.isEditing()) {
enterEditingMode();
restoreTabEditingState(selectedTab.getEditingState());
} else {
mBrowserToolbar.cancelEdit();
}
}
private void saveTabEditingState(final TabEditingState editingState) {
mBrowserToolbar.saveTabEditingState(editingState);
editingState.setIsBrowserSearchShown(mBrowserSearch.getUserVisibleHint());
}
private void restoreTabEditingState(final TabEditingState editingState) {
mBrowserToolbar.restoreTabEditingState(editingState);
// Since changing the editing text will show/hide browser search, this
// must be called after we restore the editing state in the edit text View.
if (editingState.isBrowserSearchShown()) {
showBrowserSearch();
} else {
hideBrowserSearch();
}
}
private void showBookmarkAddedToast() {
getButtonToast().show(false,
getResources().getString(R.string.bookmark_added),
@ -838,6 +880,11 @@ public class BrowserApp extends GeckoApp
mBrowserToolbar.setOnStartEditingListener(new BrowserToolbar.OnStartEditingListener() {
@Override
public void onStartEditing() {
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab != null) {
selectedTab.setIsEditing(true);
}
// Temporarily disable doorhanger notifications.
mDoorHangerPopup.disable();
}
@ -846,6 +893,11 @@ public class BrowserApp extends GeckoApp
mBrowserToolbar.setOnStopEditingListener(new BrowserToolbar.OnStopEditingListener() {
@Override
public void onStopEditing() {
final Tab selectedTab = Tabs.getInstance().getSelectedTab();
if (selectedTab != null) {
selectedTab.setIsEditing(false);
}
selectTargetTabForEditingMode();
// Since the underlying LayerView is set visible in hideHomePager, we would
@ -1817,6 +1869,11 @@ public class BrowserApp extends GeckoApp
return false;
}
final Tab oldTab = tabs.getSelectedTab();
if (oldTab != null) {
oldTab.setIsEditing(false);
}
// Set the target tab to null so it does not get selected (on editing
// mode exit) in lieu of the tab we are about to select.
mTargetTabForEditingMode = null;

View File

@ -22,6 +22,7 @@ import org.mozilla.gecko.favicons.LoadFaviconTask;
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
import org.mozilla.gecko.favicons.RemoteFavicon;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.ContentResolver;
@ -77,6 +78,9 @@ public class Tab {
private volatile int mRecordingCount;
private String mMostRecentHomePanel;
private boolean mIsEditing;
private final TabEditingState mEditingState = new TabEditingState();
public static final int STATE_DELAYED = 0;
public static final int STATE_LOADING = 1;
public static final int STATE_SUCCESS = 2;
@ -845,4 +849,16 @@ public class Tab {
public boolean isRecording() {
return mRecordingCount > 0;
}
public boolean isEditing() {
return mIsEditing;
}
public void setIsEditing(final boolean isEditing) {
this.mIsEditing = isEditing;
}
public TabEditingState getEditingState() {
return mEditingState;
}
}

View File

@ -422,6 +422,18 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
}
}
public void saveTabEditingState(final TabEditingState editingState) {
urlEditLayout.saveTabEditingState(editingState);
}
public void restoreTabEditingState(final TabEditingState editingState) {
if (!isEditing()) {
throw new IllegalStateException("Expected to be editing");
}
urlEditLayout.restoreTabEditingState(editingState);
}
@Override
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
Log.d(LOGTAG, "onTabChanged: " + msg);
@ -916,4 +928,29 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
setBackgroundResource(R.drawable.url_bar_bg);
editCancel.onLightweightThemeReset();
}
public static class TabEditingState {
// The edited text from the most recent time this tab was unselected.
protected String lastEditingText;
protected int selectionStart;
protected int selectionEnd;
public boolean isBrowserSearchShown;
public void copyFrom(final TabEditingState s2) {
lastEditingText = s2.lastEditingText;
selectionStart = s2.selectionStart;
selectionEnd = s2.selectionEnd;
isBrowserSearchShown = s2.isBrowserSearchShown;
}
public boolean isBrowserSearchShown() {
return isBrowserSearchShown;
}
public void setIsBrowserSearchShown(final boolean isShown) {
isBrowserSearchShown = isShown;
}
}
}

View File

@ -11,6 +11,7 @@ import org.mozilla.gecko.animation.PropertyAnimator.PropertyAnimationListener;
import org.mozilla.gecko.toolbar.BrowserToolbar.OnCommitListener;
import org.mozilla.gecko.toolbar.BrowserToolbar.OnDismissListener;
import org.mozilla.gecko.toolbar.BrowserToolbar.OnFilterListener;
import org.mozilla.gecko.toolbar.BrowserToolbar.TabEditingState;
import org.mozilla.gecko.widget.ThemedLinearLayout;
import android.content.Context;
@ -127,4 +128,15 @@ public class ToolbarEditLayout extends ThemedLinearLayout {
String getText() {
return mEditText.getText().toString();
}
protected void saveTabEditingState(final TabEditingState editingState) {
editingState.lastEditingText = getText();
editingState.selectionStart = mEditText.getSelectionStart();
editingState.selectionEnd = mEditText.getSelectionEnd();
}
protected void restoreTabEditingState(final TabEditingState editingState) {
mEditText.setText(editingState.lastEditingText);
mEditText.setSelection(editingState.selectionStart, editingState.selectionEnd);
}
}