/*
* Copyright (C) 2017 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.
*/
package com.googlecode.android_scripting.facade.ui;
import android.app.ProgressDialog;
import android.app.Service;
import android.util.AndroidRuntimeException;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import com.googlecode.android_scripting.BaseApplication;
import com.googlecode.android_scripting.FutureActivityTaskExecutor;
import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcDefault;
import com.googlecode.android_scripting.rpc.RpcOptional;
import com.googlecode.android_scripting.rpc.RpcParameter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.json.JSONArray;
import org.json.JSONException;
/**
* User Interface Facade.
*
* Usage Notes
*
* The UI facade provides access to a selection of dialog boxes for general user interaction, and
* also hosts the {@link #webViewShow} call which allows interactive use of html pages.
* The general use of the dialog functions is as follows:
*
*
Create a dialog using one of the following calls:
*
*
{@link #dialogCreateInput}
*
{@link #dialogCreateAlert}
*
{@link #dialogCreateDatePicker}
*
{@link #dialogCreateHorizontalProgress}
*
{@link #dialogCreatePassword}
*
{@link #dialogCreateSeekBar}
*
{@link #dialogCreateSpinnerProgress}
*
*
Set additional features to your dialog
*
*
{@link #dialogSetItems} Set a list of items. Used like a menu.
*
{@link #dialogSetMultiChoiceItems} Set a multichoice list of items.
*
{@link #dialogSetSingleChoiceItems} Set a single choice list of items.
*
{@link #dialogSetPositiveButtonText}
*
{@link #dialogSetNeutralButtonText}
*
{@link #dialogSetNegativeButtonText}
*
{@link #dialogSetMaxProgress} Set max progress for your progress bar.
*
*
Display the dialog using {@link #dialogShow}
*
Update dialog information if needed
*
*
{@link #dialogSetCurrentProgress}
*
*
Get the results
*
*
Using {@link #dialogGetResponse}, which will wait until the user performs an action to close
* the dialog box, or
*
Use eventPoll to wait for a "dialog" event.
*
You can find out which list items were selected using {@link #dialogGetSelectedItems}, which
* returns an array of numeric indices to your list. For a single choice list, there will only ever
* be one of these.
*
*
Once done, use {@link #dialogDismiss} to remove the dialog.
*
*
* You can also manipulate menu options. The menu options are available for both {@link #dialogShow}
* and {@link #fullShow}.
*
*
{@link #clearOptionsMenu}
*
{@link #addOptionsMenuItem}
*
*
* Some notes:
* Not every dialogSet function is relevant to every dialog type, ie, dialogSetMaxProgress obviously
* only applies to dialogs created with a progress bar. Also, an Alert Dialog may have a message or
* items, not both. If you set both, items will take priority.
* In addition to the above functions, {@link #dialogGetInput} and {@link #dialogGetPassword} are
* convenience functions that create, display and return the relevant dialogs in one call.
* There is only ever one instance of a dialog. Any dialogCreate call will cause the existing dialog
* to be destroyed.
*
*/
public class UiFacade extends RpcReceiver {
// This value should not be used for menu groups outside this class.
private static final int MENU_GROUP_ID = Integer.MAX_VALUE;
private static final String blankLayout = ""
+ "";
private final Service mService;
private final FutureActivityTaskExecutor mTaskQueue;
private DialogTask mDialogTask;
private FullScreenTask mFullScreenTask;
private final List mContextMenuItems;
private final List mOptionsMenuItems;
private final AtomicBoolean mMenuUpdated;
private final EventFacade mEventFacade;
private List mOverrideKeys = Collections.synchronizedList(new ArrayList());
private float mLastXPosition;
public UiFacade(FacadeManager manager) {
super(manager);
mService = manager.getService();
mTaskQueue = ((BaseApplication) mService.getApplication()).getTaskExecutor();
mContextMenuItems = new CopyOnWriteArrayList();
mOptionsMenuItems = new CopyOnWriteArrayList();
mEventFacade = manager.getReceiver(EventFacade.class);
mMenuUpdated = new AtomicBoolean(false);
}
/**
* For inputType, see InputTypes. Some useful ones are text, number, and textUri. Multiple flags can be
* supplied, seperated by "|", ie: "textUri|textAutoComplete"
*/
@Rpc(description = "Create a text input dialog.")
public void dialogCreateInput(
@RpcParameter(name = "title", description = "title of the input box") @RpcDefault("Value") final String title,
@RpcParameter(name = "message", description = "message to display above the input box") @RpcDefault("Please enter value:") final String message,
@RpcParameter(name = "defaultText", description = "text to insert into the input box") @RpcOptional final String text,
@RpcParameter(name = "inputType", description = "type of input data, ie number or text") @RpcOptional final String inputType)
throws InterruptedException {
dialogDismiss();
mDialogTask = new AlertDialogTask(title, message);
((AlertDialogTask) mDialogTask).setTextInput(text);
if (inputType != null) {
((AlertDialogTask) mDialogTask).setEditInputType(inputType);
}
}
@Rpc(description = "Create a password input dialog.")
public void dialogCreatePassword(
@RpcParameter(name = "title", description = "title of the input box") @RpcDefault("Password") final String title,
@RpcParameter(name = "message", description = "message to display above the input box") @RpcDefault("Please enter password:") final String message) {
dialogDismiss();
mDialogTask = new AlertDialogTask(title, message);
((AlertDialogTask) mDialogTask).setPasswordInput();
}
/**
* The result is the user's input, or None (null) if cancel was hit.
* Example (python)
*
*