refactor(ui): toolbar menu design;

This commit is contained in:
hyb1996
2018-09-07 12:36:13 +08:00
parent 457141d6c0
commit e5e1b567e7
19 changed files with 528 additions and 192 deletions

Binary file not shown.

View File

@@ -12,6 +12,7 @@ import com.stardust.app.OnActivityResultDelegate;
import com.stardust.autojs.core.permission.OnRequestPermissionsResultCallback; import com.stardust.autojs.core.permission.OnRequestPermissionsResultCallback;
import com.stardust.autojs.core.permission.PermissionRequestProxyActivity; import com.stardust.autojs.core.permission.PermissionRequestProxyActivity;
import com.stardust.autojs.core.permission.RequestPermissionCallbacks; import com.stardust.autojs.core.permission.RequestPermissionCallbacks;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import org.autojs.autojs.R; import org.autojs.autojs.R;
@@ -91,6 +92,13 @@ public class EditActivity extends BaseActivity implements OnActivityResultDelega
return mEditorMenu.onOptionsItemSelected(item); return mEditorMenu.onOptionsItemSelected(item);
} }
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID;
MenuItem forceStopItem = menu.findItem(R.id.action_force_stop);
forceStopItem.setEnabled(isScriptRunning);
return super.onPrepareOptionsMenu(menu);
}
@Override @Override
public void onActionModeStarted(ActionMode mode) { public void onActionModeStarted(ActionMode mode) {

View File

@@ -1,12 +1,17 @@
package org.autojs.autojs.ui.edit; package org.autojs.autojs.ui.edit;
import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -18,36 +23,41 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.Callback;
import com.stardust.util.ViewUtils;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.model.autocomplete.AutoCompletion; import org.autojs.autojs.model.autocomplete.AutoCompletion;
import org.autojs.autojs.model.autocomplete.CodeCompletion; import org.autojs.autojs.model.autocomplete.CodeCompletion;
import org.autojs.autojs.model.autocomplete.CodeCompletions;
import org.autojs.autojs.model.autocomplete.Symbols;
import org.autojs.autojs.model.indices.Module; import org.autojs.autojs.model.indices.Module;
import org.autojs.autojs.model.indices.Property; import org.autojs.autojs.model.indices.Property;
import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.model.script.Scripts;
import org.autojs.autojs.ui.doc.ManualDialog; import org.autojs.autojs.ui.doc.ManualDialog;
import org.autojs.autojs.model.autocomplete.CodeCompletions;
import org.autojs.autojs.ui.edit.completion.CodeCompletionBar; import org.autojs.autojs.ui.edit.completion.CodeCompletionBar;
import org.autojs.autojs.model.autocomplete.Symbols;
import org.autojs.autojs.ui.edit.editor.CodeEditor; import org.autojs.autojs.ui.edit.editor.CodeEditor;
import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardHelper; import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardHelper;
import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardView; import org.autojs.autojs.ui.edit.keyboard.FunctionsKeyboardView;
import org.autojs.autojs.ui.edit.theme.Theme; import org.autojs.autojs.ui.edit.theme.Theme;
import org.autojs.autojs.ui.edit.theme.Themes; import org.autojs.autojs.ui.edit.theme.Themes;
import org.autojs.autojs.ui.edit.toolbar.NormalToolbarFragment;
import org.autojs.autojs.ui.edit.toolbar.NormalToolbarFragment_;
import org.autojs.autojs.ui.edit.toolbar.SearchToolbarFragment;
import org.autojs.autojs.ui.edit.toolbar.SearchToolbarFragment_;
import org.autojs.autojs.ui.edit.toolbar.ToolbarFragment;
import org.autojs.autojs.ui.log.LogActivity_; import org.autojs.autojs.ui.log.LogActivity_;
import org.autojs.autojs.ui.widget.EWebView; import org.autojs.autojs.ui.widget.EWebView;
import org.autojs.autojs.ui.widget.SimpleTextWatcher; import org.autojs.autojs.ui.widget.SimpleTextWatcher;
import org.autojs.autojs.ui.widget.ToolbarMenuItem;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.ViewUtils;
import com.stardust.widget.ViewSwitcher;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@@ -62,7 +72,7 @@ import static org.autojs.autojs.model.script.Scripts.ACTION_ON_EXECUTION_FINISHE
* Created by Stardust on 2017/9/28. * Created by Stardust on 2017/9/28.
*/ */
@EViewGroup(R.layout.editor_view) @EViewGroup(R.layout.editor_view)
public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener, FunctionsKeyboardView.ClickCallback { public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener, FunctionsKeyboardView.ClickCallback, ToolbarFragment.OnMenuItemClickListener {
public static final String EXTRA_PATH = "path"; public static final String EXTRA_PATH = "path";
public static final String EXTRA_NAME = "name"; public static final String EXTRA_NAME = "name";
@@ -77,12 +87,6 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
@ViewById(R.id.code_completion_bar) @ViewById(R.id.code_completion_bar)
CodeCompletionBar mCodeCompletionBar; CodeCompletionBar mCodeCompletionBar;
@ViewById(R.id.toolbar_switcher)
ViewSwitcher mToolbarSwitcher;
@ViewById(R.id.replace)
ToolbarMenuItem mReplaceMenuItem;
@ViewById(R.id.input_method_enhance_bar) @ViewById(R.id.input_method_enhance_bar)
View mInputMethodEnhanceBar; View mInputMethodEnhanceBar;
@@ -104,7 +108,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
private String mName; private String mName;
private File mFile; private File mFile;
private boolean mReadOnly = false; private boolean mReadOnly = false;
private ScriptExecution mScriptExecution; private int mScriptExecutionId;
private AutoCompletion mAutoCompletion; private AutoCompletion mAutoCompletion;
private Theme mEditorTheme; private Theme mEditorTheme;
private FunctionsKeyboardHelper mFunctionsKeyboardHelper; private FunctionsKeyboardHelper mFunctionsKeyboardHelper;
@@ -112,7 +116,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
if (ACTION_ON_EXECUTION_FINISHED.equals(intent.getAction())) { if (ACTION_ON_EXECUTION_FINISHED.equals(intent.getAction())) {
mScriptExecution = null; mScriptExecutionId = ScriptExecution.NO_ID;
setMenuItemStatus(R.id.run, true); setMenuItemStatus(R.id.run, true);
String msg = intent.getStringExtra(Scripts.EXTRA_EXCEPTION_MESSAGE); String msg = intent.getStringExtra(Scripts.EXTRA_EXCEPTION_MESSAGE);
int line = intent.getIntExtra(Scripts.EXTRA_EXCEPTION_LINE_NUMBER, -1); int line = intent.getIntExtra(Scripts.EXTRA_EXCEPTION_LINE_NUMBER, -1);
@@ -127,6 +131,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
} }
}; };
private String mRestoredText; private String mRestoredText;
private NormalToolbarFragment mNormalToolbar = new NormalToolbarFragment_();
public EditorView(Context context) { public EditorView(Context context) {
super(context); super(context);
@@ -199,6 +204,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
} }
@SuppressLint("CheckResult")
private void loadFile(final File file) { private void loadFile(final File file) {
mEditor.setProgress(true); mEditor.setProgress(true);
Observable.fromCallable(() -> PFiles.read(file)) Observable.fromCallable(() -> PFiles.read(file))
@@ -225,7 +231,13 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
private void setMenuItemStatus(int id, boolean enabled) { private void setMenuItemStatus(int id, boolean enabled) {
findViewById(id).setEnabled(enabled); ToolbarFragment fragment = (ToolbarFragment) getActivity().getSupportFragmentManager()
.findFragmentById(R.id.toolbar_menu);
if (fragment == null) {
mNormalToolbar.setMenuItemStatus(id, enabled);
} else {
fragment.setMenuItemStatus(id, enabled);
}
} }
@@ -238,9 +250,15 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
setMenuItemStatus(R.id.save, false); setMenuItemStatus(R.id.save, false);
mDocsWebView.getWebView().getSettings().setDisplayZoomControls(true); mDocsWebView.getWebView().getSettings().setDisplayZoomControls(true);
mDocsWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html"); mDocsWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html");
Themes.getCurrent(getContext()). Themes.getCurrent(getContext())
observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(this::setTheme); .subscribe(this::setTheme);
initNormalToolbar();
}
private void initNormalToolbar() {
mNormalToolbar.setOnMenuItemClickListener(this);
showNormalToolbar();
} }
private void setUpFunctionsKeyboard() { private void setUpFunctionsKeyboard() {
@@ -299,8 +317,36 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
return false; return false;
} }
@Override
public void onToolbarMenuItemClick(int id) {
switch (id) {
case R.id.run:
runAndSaveFileIfNeeded();
break;
case R.id.save:
saveFile();
break;
case R.id.undo:
undo();
break;
case R.id.redo:
redo();
break;
case R.id.replace:
replace();
break;
case R.id.find_next:
findNext();
break;
case R.id.find_prev:
findPrev();
break;
case R.id.cancel_search:
cancelSearch();
break;
}
}
@Click(R.id.run)
public void runAndSaveFileIfNeeded() { public void runAndSaveFileIfNeeded() {
save().observeOn(AndroidSchedulers.mainThread()) save().observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> run()); .subscribe(s -> run());
@@ -308,17 +354,15 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
public void run() { public void run() {
Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show(); Snackbar.make(this, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
mScriptExecution = Scripts.runWithBroadcastSender(mFile); mScriptExecutionId = Scripts.runWithBroadcastSender(mFile).getId();
setMenuItemStatus(R.id.run, false); setMenuItemStatus(R.id.run, false);
} }
@Click(R.id.undo)
public void undo() { public void undo() {
mEditor.undo(); mEditor.undo();
} }
@Click(R.id.redo)
public void redo() { public void redo() {
mEditor.redo(); mEditor.redo();
} }
@@ -335,32 +379,49 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
} }
public void forceStop() { public void forceStop() {
if (mScriptExecution != null) { doWithCurrentEngine(ScriptEngine::forceStop);
mScriptExecution.getEngine().forceStop(); }
private void doWithCurrentEngine(Callback<ScriptEngine> callback) {
ScriptExecution execution = AutoJs.getInstance().getScriptEngineService().getScriptExecution(mScriptExecutionId);
if (execution != null) {
ScriptEngine engine = execution.getEngine();
if (engine != null) {
callback.call(engine);
}
} }
} }
@Click(R.id.save)
public void saveFile() { public void saveFile() {
save().subscribe(); save().subscribe();
} }
@Click(R.id.find_next)
void findNext() { void findNext() {
mEditor.findNext(); mEditor.findNext();
} }
@Click(R.id.find_prev)
void findPrev() { void findPrev() {
mEditor.findPrev(); mEditor.findPrev();
} }
@Click(R.id.cancel)
void cancelSearch() { void cancelSearch() {
mToolbarSwitcher.showFirst(); showNormalToolbar();
}
private void showNormalToolbar() {
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.toolbar_menu, mNormalToolbar)
.commit();
}
FragmentActivity getActivity() {
Context context = getContext();
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (FragmentActivity) context;
} }
@Click(R.id.replace)
void replace() { void replace() {
mEditor.replaceSelection(); mEditor.replaceSelection();
} }
@@ -374,9 +435,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
} }
public void showConsole() { public void showConsole() {
if (mScriptExecution != null) { doWithCurrentEngine(engine -> ((JavaScriptEngine) engine).getRuntime().console.show());
((JavaScriptEngine) mScriptExecution.getEngine()).getRuntime().console.show();
}
} }
public void openByOtherApps() { public void openByOtherApps() {
@@ -433,14 +492,22 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
public void find(String keywords, boolean usingRegex) { public void find(String keywords, boolean usingRegex) {
mEditor.find(keywords, usingRegex); mEditor.find(keywords, usingRegex);
mReplaceMenuItem.setVisibility(GONE); showSearchToolbar(false);
mToolbarSwitcher.showSecond(); }
private void showSearchToolbar(boolean showReplaceItem) {
SearchToolbarFragment searchToolbarFragment = SearchToolbarFragment_.builder()
.arg(SearchToolbarFragment.ARGUMENT_SHOW_REPLACE_ITEM, showReplaceItem)
.build();
searchToolbarFragment.setOnMenuItemClickListener(this);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.toolbar_menu, searchToolbarFragment)
.commit();
} }
public void replace(String keywords, String replacement, boolean usingRegex) { public void replace(String keywords, String replacement, boolean usingRegex) {
mEditor.replace(keywords, replacement, usingRegex); mEditor.replace(keywords, replacement, usingRegex);
mReplaceMenuItem.setVisibility(VISIBLE); showSearchToolbar(true);
mToolbarSwitcher.showSecond();
} }
public void replaceAll(String keywords, String replacement, boolean usingRegex) { public void replaceAll(String keywords, String replacement, boolean usingRegex) {
@@ -511,5 +578,26 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
} }
} }
public int getScriptExecutionId() {
return mScriptExecutionId;
}
@Nullable
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
Parcelable superData = super.onSaveInstanceState();
bundle.putParcelable("super_data", superData);
bundle.putInt("script_execution_id", mScriptExecutionId);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
Parcelable superData = bundle.getParcelable("super_data");
mScriptExecutionId = bundle.getInt("script_execution_id", ScriptExecution.NO_ID);
super.onRestoreInstanceState(superData);
setMenuItemStatus(R.id.run, mScriptExecutionId == ScriptExecution.NO_ID);
}
} }

View File

@@ -0,0 +1,44 @@
package org.autojs.autojs.ui.edit.toolbar;
import android.os.Looper;
import android.util.Log;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.tools.debugger.Dim;
import org.mozilla.javascript.tools.debugger.GuiCallback;
public class DebugToolbarFragment implements GuiCallback {
private Dim mDim;
public void attachDebugger(){
mDim.attachTo(ContextFactory.getGlobal());
}
public void deattchDebugger(){
mDim.detach();
}
public void breakpoint(){
mDim.setGuiCallback(this);
}
@Override
public void updateSourceText(Dim.SourceInfo sourceInfo) {
}
@Override
public void enterInterrupt(Dim.StackFrame stackFrame, String s, String s1) {
}
@Override
public boolean isGuiEventThread() {
return Looper.getMainLooper() == Looper.myLooper();
}
@Override
public void dispatchNextGuiEvent() throws InterruptedException {
}
}

View File

@@ -0,0 +1,20 @@
package org.autojs.autojs.ui.edit.toolbar;
import android.support.v4.app.Fragment;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EFragment;
import org.autojs.autojs.R;
import java.util.Arrays;
import java.util.List;
@EFragment(R.layout.fragment_normal_toolbar)
public class NormalToolbarFragment extends ToolbarFragment {
@Override
public List<Integer> getMenuItemIds() {
return Arrays.asList(R.id.run, R.id.undo, R.id.redo, R.id.save);
}
}

View File

@@ -0,0 +1,31 @@
package org.autojs.autojs.ui.edit.toolbar;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.View;
import org.androidannotations.annotations.EFragment;
import org.autojs.autojs.R;
import java.util.Arrays;
import java.util.List;
@EFragment(R.layout.fragment_search_toolbar)
public class SearchToolbarFragment extends ToolbarFragment {
public static final String ARGUMENT_SHOW_REPLACE_ITEM = "show_replace_item";
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
boolean showReplaceItem = getArguments().getBoolean(ARGUMENT_SHOW_REPLACE_ITEM, false);
view.findViewById(R.id.replace).setVisibility(showReplaceItem ? View.VISIBLE : View.GONE);
}
@Override
public List<Integer> getMenuItemIds() {
return Arrays.asList(R.id.replace, R.id.find_next, R.id.find_prev, R.id.cancel_search);
}
}

View File

@@ -0,0 +1,75 @@
package org.autojs.autojs.ui.edit.toolbar;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.SparseBooleanArray;
import android.view.View;
import java.util.List;
public abstract class ToolbarFragment extends Fragment implements View.OnClickListener {
public interface OnMenuItemClickListener {
void onToolbarMenuItemClick(int id);
}
private OnMenuItemClickListener mOnMenuItemClickListener;
private List<Integer> mMenuItemIds;
private SparseBooleanArray mMenuItemStatus = new SparseBooleanArray();
public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
mOnMenuItemClickListener = listener;
}
public abstract List<Integer> getMenuItemIds();
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
updateMenuItemStatus();
}
private void updateMenuItemStatus() {
View rootView = getView();
if (rootView == null) {
return;
}
if (mMenuItemIds == null) {
mMenuItemIds = getMenuItemIds();
}
for (int id : mMenuItemIds) {
View view = rootView.findViewById(id);
view.setOnClickListener(this);
view.setEnabled(mMenuItemStatus.get(id, view.isEnabled()));
}
}
@Override
public void onClick(View view) {
if (mOnMenuItemClickListener != null) {
mOnMenuItemClickListener.onToolbarMenuItemClick(view.getId());
}
}
public void setMenuItemStatus(int id, boolean enabled) {
if (mMenuItemIds == null) {
mMenuItemIds = getMenuItemIds();
}
if (!mMenuItemIds.contains(id)) {
return;
}
mMenuItemStatus.put(id, enabled);
View rootView = getView();
if (rootView == null) {
return;
}
View view = rootView.findViewById(id);
if (view == null) {
return;
}
view.setEnabled(enabled);
}
}

View File

@@ -1,18 +1,13 @@
package org.autojs.autojs.ui.main.task; package org.autojs.autojs.ui.main.task;
import android.os.Parcel;
import android.os.Parcelable;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.engine.ScriptEngineFactory; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.script.AutoFileSource; import com.stardust.autojs.script.AutoFileSource;
import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.JavaScriptSource;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.pio.PFile;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import org.autojs.autojs.App;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.timing.TimedTask; import org.autojs.autojs.timing.TimedTask;
import org.autojs.autojs.timing.TimedTaskManager; import org.autojs.autojs.timing.TimedTaskManager;
@@ -23,7 +18,7 @@ import org.joda.time.format.DateTimeFormat;
* Created by Stardust on 2017/11/28. * Created by Stardust on 2017/11/28.
*/ */
public abstract class Task { public abstract class Task {
public abstract String getName(); public abstract String getName();
@@ -78,46 +73,37 @@ public abstract class Task {
} }
public static class RunningTask extends Task { public static class RunningTask extends Task {
private final ScriptEngine mScriptEngine; private final ScriptExecution mScriptExecution;
public RunningTask(ScriptEngine scriptEngine) { public RunningTask(ScriptExecution scriptExecution) {
mScriptEngine = scriptEngine; mScriptExecution = scriptExecution;
} }
public ScriptEngine getScriptEngine() { public ScriptExecution getScriptExecution() {
return mScriptEngine; return mScriptExecution;
} }
@Override @Override
public String getName() { public String getName() {
ScriptSource source = (ScriptSource) mScriptEngine.getTag(ScriptEngine.TAG_SOURCE); return mScriptExecution.getSource().getName();
if (source == null) {
return null;
}
return source.getName();
} }
@Override @Override
public String getDesc() { public String getDesc() {
ScriptSource source = (ScriptSource) mScriptEngine.getTag(ScriptEngine.TAG_SOURCE); return mScriptExecution.getSource().toString();
if (source == null) {
return null;
}
return source.toString();
} }
@Override @Override
public void cancel() { public void cancel() {
mScriptEngine.forceStop(); ScriptEngine engine = mScriptExecution.getEngine();
if (engine != null) {
engine.forceStop();
}
} }
@Override @Override
public String getEngineName() { public String getEngineName() {
ScriptSource source = (ScriptSource) mScriptEngine.getTag(ScriptEngine.TAG_SOURCE); return mScriptExecution.getSource().getEngineName();
if (source == null) {
return null;
}
return source.getEngineName();
} }
} }
} }

View File

@@ -4,12 +4,15 @@ import android.content.Context;
import com.bignerdranch.expandablerecyclerview.model.Parent; import com.bignerdranch.expandablerecyclerview.model.Parent;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.execution.ScriptExecution;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.timing.TimedTask; import org.autojs.autojs.timing.TimedTask;
import org.autojs.autojs.timing.TimedTaskManager; import org.autojs.autojs.timing.TimedTaskManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -98,20 +101,20 @@ public abstract class TaskGroup implements Parent<Task> {
@Override @Override
public void refresh() { public void refresh() {
Set<ScriptEngine> scriptEngines = AutoJs.getInstance().getScriptEngineService().getEngines(); Collection<ScriptExecution> executions = AutoJs.getInstance().getScriptEngineService().getScriptExecutions();
mTasks.clear(); mTasks.clear();
for (ScriptEngine engine : scriptEngines) { for (ScriptExecution execution : executions) {
mTasks.add(new Task.RunningTask(engine)); mTasks.add(new Task.RunningTask(execution));
} }
} }
public int addTask(ScriptEngine engine) { public int addTask(ScriptExecution engine) {
int pos = mTasks.size(); int pos = mTasks.size();
mTasks.add(new Task.RunningTask(engine)); mTasks.add(new Task.RunningTask(engine));
return pos; return pos;
} }
public int removeTask(ScriptEngine engine) { public int removeTask(ScriptExecution engine) {
int i = indexOf(engine); int i = indexOf(engine);
if (i >= 0) { if (i >= 0) {
mTasks.remove(i); mTasks.remove(i);
@@ -119,9 +122,9 @@ public abstract class TaskGroup implements Parent<Task> {
return i; return i;
} }
public int indexOf(ScriptEngine engine) { public int indexOf(ScriptExecution engine) {
for (int i = 0; i < mTasks.size(); i++) { for (int i = 0; i < mTasks.size(); i++) {
if (((Task.RunningTask) mTasks.get(i)).getScriptEngine().equals(engine)) { if (((Task.RunningTask) mTasks.get(i)).getScriptExecution().equals(engine)) {
return i; return i;
} }
} }

View File

@@ -12,6 +12,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.stardust.autojs.workground.WrapContentLinearLayoutManager; import com.stardust.autojs.workground.WrapContentLinearLayoutManager;
import com.bignerdranch.expandablerecyclerview.ChildViewHolder; import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
@@ -25,6 +26,7 @@ import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.script.AutoFileSource; import com.stardust.autojs.script.AutoFileSource;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.storage.database.ModelChange; import org.autojs.autojs.storage.database.ModelChange;
@@ -32,6 +34,7 @@ import org.autojs.autojs.timing.TaskReceiver;
import org.autojs.autojs.timing.TimedTask; import org.autojs.autojs.timing.TimedTask;
import org.autojs.autojs.timing.TimedTaskManager; import org.autojs.autojs.timing.TimedTaskManager;
import org.autojs.autojs.ui.timing.TimedTaskSettingActivity_; import org.autojs.autojs.ui.timing.TimedTaskSettingActivity_;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import java.util.ArrayList; import java.util.ArrayList;
@@ -47,7 +50,7 @@ import io.reactivex.disposables.Disposable;
* Created by Stardust on 2017/3/24. * Created by Stardust on 2017/3/24.
*/ */
public class TaskListRecyclerView extends ThemeColorRecyclerView implements ScriptEngineManager.EngineLifecycleCallback { public class TaskListRecyclerView extends ThemeColorRecyclerView {
private static final String LOG_TAG = "TaskListRecyclerView"; private static final String LOG_TAG = "TaskListRecyclerView";
@@ -61,15 +64,26 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Scri
private ScriptExecutionListener mScriptExecutionListener = new SimpleScriptExecutionListener() { private ScriptExecutionListener mScriptExecutionListener = new SimpleScriptExecutionListener() {
@Override @Override
public void onStart(final ScriptExecution execution) { public void onStart(final ScriptExecution execution) {
post(() -> { mAdapter.notifyChildInserted(0, mRunningTaskGroup.addTask(execution));
int position = mRunningTaskGroup.indexOf(execution.getEngine()); }
if (position >= 0) {
mAdapter.notifyChildChanged(0, position);
} else {
refresh();
}
});
@Override
public void onSuccess(ScriptExecution execution, Object result) {
onFinish(execution);
}
@Override
public void onException(ScriptExecution execution, Exception e) {
onFinish(execution);
}
private void onFinish(ScriptExecution execution){
final int i = mRunningTaskGroup.removeTask(execution);
if (i >= 0) {
mAdapter.notifyChildRemoved(0, i);
} else {
refresh();
}
} }
}; };
@@ -116,7 +130,6 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Scri
@Override @Override
protected void onAttachedToWindow() { protected void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
mScriptEngineService.registerEngineLifecycleCallback(this);
AutoJs.getInstance().getScriptEngineService().registerGlobalScriptExecutionListener(mScriptExecutionListener); AutoJs.getInstance().getScriptEngineService().registerGlobalScriptExecutionListener(mScriptExecutionListener);
mTimedTaskChangeDisposable = TimedTaskManager.getInstance().getTimeTaskChanges() mTimedTaskChangeDisposable = TimedTaskManager.getInstance().getTimeTaskChanges()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
@@ -134,7 +147,6 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Scri
@Override @Override
protected void onDetachedFromWindow() { protected void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
mScriptEngineService.unregisterEngineLifecycleCallback(this);
AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener); AutoJs.getInstance().getScriptEngineService().unregisterGlobalScriptExecutionListener(mScriptExecutionListener);
mTimedTaskChangeDisposable.dispose(); mTimedTaskChangeDisposable.dispose();
} }
@@ -162,26 +174,6 @@ public class TaskListRecyclerView extends ThemeColorRecyclerView implements Scri
} }
} }
@Override
public void onEngineCreate(final ScriptEngine engine) {
post(() ->
mAdapter.notifyChildInserted(0, mRunningTaskGroup.addTask(engine))
);
}
@Override
public void onEngineRemove(final ScriptEngine engine) {
post(() -> {
final int i = mRunningTaskGroup.removeTask(engine);
if (i >= 0) {
mAdapter.notifyChildRemoved(0, i);
} else {
refresh();
}
});
}
private class Adapter extends ExpandableRecyclerAdapter<TaskGroup, Task, TaskGroupViewHolder, TaskViewHolder> { private class Adapter extends ExpandableRecyclerAdapter<TaskGroup, Task, TaskGroupViewHolder, TaskViewHolder> {
public Adapter(@NonNull List<TaskGroup> parentList) { public Adapter(@NonNull List<TaskGroup> parentList) {

View File

@@ -19,89 +19,11 @@
android:title="@string/_app_name" android:title="@string/_app_name"
app:popupTheme="@style/AppTheme.PopupOverlay"> app:popupTheme="@style/AppTheme.PopupOverlay">
<com.stardust.widget.ViewSwitcher <FrameLayout
android:id="@+id/toolbar_switcher" android:id="@+id/toolbar_menu"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="right"> android:layout_gravity="right"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:orientation="horizontal">
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/run"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_play_arrow_white_48dp"
app:icon_color="@android:color/white"
app:text="@string/text_run"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/undo"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_undo_white_48dp"
app:text="@string/text_undo"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/redo"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_redo_white_48dp"
app:text="@string/text_redo"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/save"
android:layout_width="40dp"
android:layout_height="match_parent"
android:enabled="false"
app:icon="@drawable/ic_save_white_48dp"
app:text="@string/text_save"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:orientation="horizontal">
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/replace"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_replace"
app:text="@string/text_replace"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/find_prev"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_up"
app:text="@string/text_find_prev"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/find_next"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_down"
app:text="@string/text_find_next"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/cancel"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_close_white_48dp"
app:text="@string/text_cancel"/>
</LinearLayout>
</com.stardust.widget.ViewSwitcher>
</com.stardust.theme.widget.ThemeColorToolbar> </com.stardust.theme.widget.ThemeColorToolbar>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:orientation="horizontal">
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/run"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_play_arrow_white_48dp"
app:icon_color="@android:color/white"
app:text="@string/text_run"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/undo"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_undo_white_48dp"
app:text="@string/text_undo"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/redo"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_redo_white_48dp"
app:text="@string/text_redo"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/save"
android:layout_width="40dp"
android:layout_height="match_parent"
android:enabled="false"
app:icon="@drawable/ic_save_white_48dp"
app:text="@string/text_save"/>
</LinearLayout>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:orientation="horizontal">
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/replace"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_replace"
app:text="@string/text_replace"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/find_prev"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_up"
app:text="@string/text_find_prev"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/find_next"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_ali_down"
app:text="@string/text_find_next"/>
<org.autojs.autojs.ui.widget.ToolbarMenuItem
android:id="@+id/cancel_search"
android:layout_width="40dp"
android:layout_height="match_parent"
app:icon="@drawable/ic_close_white_48dp"
app:text="@string/text_cancel"/>
</LinearLayout>

View File

@@ -1,6 +1,7 @@
package com.stardust.autojs; package com.stardust.autojs;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable;
import com.stardust.autojs.engine.JavaScriptEngine; import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.engine.ScriptEngine; import com.stardust.autojs.engine.ScriptEngine;
@@ -30,6 +31,9 @@ import java.io.IOException;
import java.io.PipedReader; import java.io.PipedReader;
import java.io.PipedWriter; import java.io.PipedWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
@@ -83,8 +87,16 @@ public class ScriptEngineService {
private UiHandler mUiHandler; private UiHandler mUiHandler;
private final Console mGlobalConsole; private final Console mGlobalConsole;
private final ScriptEngineManager mScriptEngineManager; private final ScriptEngineManager mScriptEngineManager;
private final EngineLifecycleObserver mEngineLifecycleObserver = new EngineLifecycleObserver(); private final EngineLifecycleObserver mEngineLifecycleObserver = new EngineLifecycleObserver() {
@Override
public void onEngineRemove(ScriptEngine engine) {
mScriptExecutions.remove(engine.getId());
super.onEngineRemove(engine);
}
};
private ScriptExecutionObserver mScriptExecutionObserver = new ScriptExecutionObserver(); private ScriptExecutionObserver mScriptExecutionObserver = new ScriptExecutionObserver();
private LinkedHashMap<Integer, ScriptExecution> mScriptExecutions = new LinkedHashMap<>();
ScriptEngineService(ScriptEngineServiceBuilder builder) { ScriptEngineService(ScriptEngineServiceBuilder builder) {
mUiHandler = builder.mUiHandler; mUiHandler = builder.mUiHandler;
@@ -119,6 +131,12 @@ public class ScriptEngineService {
} }
public ScriptExecution execute(ScriptExecutionTask task) { public ScriptExecution execute(ScriptExecutionTask task) {
ScriptExecution execution = executeInternal(task);
mScriptExecutions.put(execution.getId(), execution);
return execution;
}
private ScriptExecution executeInternal(ScriptExecutionTask task) {
if (task.getListener() != null) { if (task.getListener() != null) {
task.setExecutionListener(new ScriptExecutionObserver.Wrapper(mScriptExecutionObserver, task.getListener())); task.setExecutionListener(new ScriptExecutionObserver.Wrapper(mScriptExecutionObserver, task.getListener()));
} else { } else {
@@ -185,6 +203,18 @@ public class ScriptEngineService {
return mScriptEngineManager.getEngines(); return mScriptEngineManager.getEngines();
} }
public Collection<ScriptExecution> getScriptExecutions() {
return mScriptExecutions.values();
}
@Nullable
public ScriptExecution getScriptExecution(int id) {
if(id == ScriptExecution.NO_ID){
return null;
}
return mScriptExecutions.get(id);
}
private static class EngineLifecycleObserver implements ScriptEngineManager.EngineLifecycleCallback { private static class EngineLifecycleObserver implements ScriptEngineManager.EngineLifecycleCallback {
private final Set<ScriptEngineManager.EngineLifecycleCallback> mEngineLifecycleCallbacks = new LinkedHashSet<>(); private final Set<ScriptEngineManager.EngineLifecycleCallback> mEngineLifecycleCallbacks = new LinkedHashSet<>();

View File

@@ -2,11 +2,13 @@ package com.stardust.autojs.engine;
import android.support.annotation.CallSuper; import android.support.annotation.CallSuper;
import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.runtime.exception.ScriptException; import com.stardust.autojs.runtime.exception.ScriptException;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
@@ -46,6 +48,9 @@ public interface ScriptEngine<S extends ScriptSource> {
Exception getUncaughtException(); Exception getUncaughtException();
void setId(int id);
int getId();
/** /**
* @hide * @hide
@@ -68,7 +73,7 @@ public interface ScriptEngine<S extends ScriptSource> {
private OnDestroyListener mOnDestroyListener; private OnDestroyListener mOnDestroyListener;
private boolean mDestroyed = false; private boolean mDestroyed = false;
private Exception mUncaughtException; private Exception mUncaughtException;
private volatile AtomicInteger mId = new AtomicInteger(ScriptExecution.NO_ID);
@Override @Override
public synchronized void setTag(String key, Object value) { public synchronized void setTag(String key, Object value) {
@@ -116,5 +121,15 @@ public interface ScriptEngine<S extends ScriptSource> {
public Exception getUncaughtException() { public Exception getUncaughtException() {
return mUncaughtException; return mUncaughtException;
} }
@Override
public void setId(int id) {
mId.compareAndSet(ScriptExecution.NO_ID, id);
}
@Override
public int getId() {
return mId.get();
}
} }
} }

View File

@@ -77,4 +77,14 @@ public class ScriptEngineProxy<S extends ScriptSource> implements ScriptEngine<S
public void init() { public void init() {
mScriptEngine.init(); mScriptEngine.init();
} }
@Override
public int getId() {
return mScriptEngine.getId();
}
@Override
public void setId(int id) {
mScriptEngine.setId(id);
}
} }

View File

@@ -29,6 +29,7 @@ public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecu
public Object execute() { public Object execute() {
mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource()); mScriptEngine = mScriptEngineManager.createEngineOfSourceOrThrow(getSource());
mScriptEngine.setId(getId());
return execute(mScriptEngine); return execute(mScriptEngine);
} }

View File

@@ -4,12 +4,17 @@ import com.stardust.autojs.engine.ScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* Created by Stardust on 2017/4/3. * Created by Stardust on 2017/4/3.
*/ */
public interface ScriptExecution { public interface ScriptExecution {
int NO_ID = -1;
ScriptEngine getEngine(); ScriptEngine getEngine();
ScriptSource getSource(); ScriptSource getSource();
@@ -18,12 +23,18 @@ public interface ScriptExecution {
ExecutionConfig getConfig(); ExecutionConfig getConfig();
int getId();
abstract class AbstractScriptExecution implements ScriptExecution { abstract class AbstractScriptExecution implements ScriptExecution {
private static AtomicInteger sMaxId = new AtomicInteger(0);
protected ScriptExecutionTask mScriptExecutionTask; protected ScriptExecutionTask mScriptExecutionTask;
protected int mId;
public AbstractScriptExecution(ScriptExecutionTask task) { public AbstractScriptExecution(ScriptExecutionTask task) {
mScriptExecutionTask = task; mScriptExecutionTask = task;
mId = sMaxId.getAndIncrement();
} }
@Override @Override
@@ -43,5 +54,23 @@ public interface ScriptExecution {
public ExecutionConfig getConfig() { public ExecutionConfig getConfig() {
return mScriptExecutionTask.getConfig(); return mScriptExecutionTask.getConfig();
} }
@Override
public int getId() {
return mId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AbstractScriptExecution that = (AbstractScriptExecution) o;
return mId == that.mId;
}
@Override
public int hashCode() {
return mId;
}
} }
} }

View File

@@ -3,11 +3,14 @@ package com.stardust.autojs.runtime.exception;
import org.mozilla.javascript.EvaluatorException; import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.RhinoException; import org.mozilla.javascript.RhinoException;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* Created by Stardust on 2017/1/29. * Created by Stardust on 2017/1/29.
*/ */
public class ScriptException extends RuntimeException { public class ScriptException extends RuntimeException {
public ScriptException(String message, Throwable cause) { public ScriptException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }