feat: functions keyboard

This commit is contained in:
hyb1996 2017-12-10 00:44:57 +08:00
parent 0e6616c1dc
commit f939dac3fd
21 changed files with 1968 additions and 124 deletions

View File

@ -92,7 +92,6 @@ dependencies {
exclude group: 'com.afollestad.material-dialogs'
exclude group: 'com.android.support'
})
//
compile 'com.github.hyb1996:android-multi-level-listview:1.1'
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1'
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
package com.stardust.scriptdroid.model.indices;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Stardust on 2017/12/9.
*/
public class Module {
@SerializedName("properties")
private List<Property> mProperties = new ArrayList<>();
@SerializedName("url")
private String mUrl;
@SerializedName("name")
private String mName;
@SerializedName("summary")
private String mSummary;
public List<Property> getProperties() {
return mProperties;
}
public void setProperties(List<Property> properties) {
mProperties = properties;
}
public String getUrl() {
return mUrl;
}
public void setUrl(String url) {
mUrl = url;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
}

View File

@ -0,0 +1,50 @@
package com.stardust.scriptdroid.model.indices;
import android.content.Context;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.Callable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
/**
* Created by Stardust on 2017/12/9.
*/
public class Modules {
private static final Type MODULE_LIST_TYPE = new TypeToken<List<Module>>() {
}.getType();
private static final String MODULES_JSON_PATH = "indices/all.json";
private static Modules sInstance = new Modules();
private List<Module> mModules;
private List<Module> loadModulesFrom(InputStream inputStream) {
Gson gson = new Gson();
return gson.fromJson(new InputStreamReader(inputStream), MODULE_LIST_TYPE);
}
public Observable<List<Module>> getModules(Context context) {
if (mModules != null)
return Observable.just(mModules);
return Observable.fromCallable(() -> loadModulesFrom(context.getAssets().open(MODULES_JSON_PATH)))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(modules -> mModules = modules);
}
public static Modules getInstance() {
return sInstance;
}
}

View File

@ -0,0 +1,54 @@
package com.stardust.scriptdroid.model.indices;
import com.google.gson.annotations.SerializedName;
/**
* Created by Stardust on 2017/12/9.
*/
public class Property {
@SerializedName("url")
private String mUrl;
@SerializedName("key")
private String mKey;
@SerializedName("summary")
private String mSummary;
@SerializedName("global")
private boolean mGlobal;
public String getUrl() {
return mUrl;
}
public void setUrl(String url) {
mUrl = url;
}
public String getKey() {
return mKey;
}
public void setKey(String key) {
mKey = key;
}
public String getSummary() {
return mSummary;
}
public void setSummary(String summary) {
mSummary = summary;
}
public boolean isGlobal() {
return mGlobal;
}
public void setGlobal(boolean global) {
mGlobal = global;
}
}

View File

@ -0,0 +1,19 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
/**
* Created by Stardust on 2017/12/9.
*/
public class InputMethodTool {
public static void dismissInputMethod(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null)
return;
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}

View File

@ -1,5 +1,6 @@
package com.stardust.scriptdroid.ui.edit;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -8,6 +9,7 @@ import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.DrawerLayout;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@ -21,15 +23,20 @@ import com.stardust.autojs.script.JavaScriptFileSource;
import com.stardust.pio.PFiles;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.model.indices.Module;
import com.stardust.scriptdroid.model.indices.Property;
import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.ui.doc.ManualDialog;
import com.stardust.scriptdroid.ui.edit.completion.CodeCompletions;
import com.stardust.scriptdroid.ui.edit.completion.CodeCompletionBar;
import com.stardust.scriptdroid.ui.edit.completion.InputMethodEnhancedBarColors;
import com.stardust.scriptdroid.ui.edit.completion.Symbols;
import com.stardust.scriptdroid.ui.edit.keyboard.FunctionsKeyboardHelper;
import com.stardust.scriptdroid.ui.edit.keyboard.FunctionsKeyboardView;
import com.stardust.scriptdroid.ui.log.LogActivity_;
import com.stardust.scriptdroid.ui.widget.EWebView;
import com.stardust.scriptdroid.ui.widget.ToolbarMenuItem;
import com.stardust.util.BackPressedHandler;
import com.stardust.widget.ViewSwitcher;
import org.androidannotations.annotations.AfterViews;
@ -50,7 +57,7 @@ import static com.stardust.scriptdroid.model.script.Scripts.ACTION_ON_EXECUTION_
* Created by Stardust on 2017/9/28.
*/
@EViewGroup(R.layout.editor_view)
public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener {
public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintClickListener, FunctionsKeyboardView.ClickCallback {
public static final String EXTRA_PATH = "Still Love Eating 17.4.5";
public static final String EXTRA_NAME = "Still love you 17.6.29 But....(ಥ_ಥ)";
@ -77,8 +84,11 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
@ViewById(R.id.symbol_bar)
CodeCompletionBar mSymbolBar;
@ViewById(R.id.functions)
ImageView mFunctions;
@ViewById(R.id.properties)
ImageView mShowFunctionsButton;
@ViewById(R.id.functions_keyboard)
FunctionsKeyboardView mFunctionsKeyboard;
@ViewById(R.id.docs)
EWebView mEWebView;
@ -94,6 +104,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
private ScriptExecution mScriptExecution;
private boolean mTextChanged = false;
private FunctionsKeyboardHelper mFunctionsKeyboardHelper;
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@ -129,12 +140,18 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
protected void onAttachedToWindow() {
super.onAttachedToWindow();
getContext().registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_EXECUTION_FINISHED));
if (getContext() instanceof BackPressedHandler.HostActivity) {
((BackPressedHandler.HostActivity) getContext()).getBackPressedObserver().registerHandler(mFunctionsKeyboardHelper);
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
getContext().unregisterReceiver(mOnRunFinishedReceiver);
if (getContext() instanceof BackPressedHandler.HostActivity) {
((BackPressedHandler.HostActivity) getContext()).getBackPressedObserver().unregisterHandler(mFunctionsKeyboardHelper);
}
}
public File getFile() {
@ -182,12 +199,23 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
void init() {
setUpEditor();
setUpInputMethodEnhancedBar();
setUpFunctionsKeyboard();
setMenuItemStatus(R.id.save, false);
mEWebView.getWebView().getSettings().setDisplayZoomControls(true);
mEWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html");
}
private void setUpFunctionsKeyboard() {
mFunctionsKeyboardHelper = FunctionsKeyboardHelper.with((Activity) getContext())
.setContent(mEditor)
.setFunctionsTrigger(mShowFunctionsButton)
.setFunctionsView(mFunctionsKeyboard)
.setEditView(mEditor.getWebView())
.build();
mFunctionsKeyboard.setClickCallback(this);
}
private void setUpInputMethodEnhancedBar() {
mSymbolBar.setCodeCompletions(Symbols.getSymbols());
mCodeCompletionBar.setOnHintClickListener(this);
@ -226,13 +254,9 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
int textColor = InputMethodEnhancedBarColors.getTextColor(theme);
mCodeCompletionBar.setTextColor(textColor);
mSymbolBar.setTextColor(textColor);
mFunctions.setColorFilter(textColor);
mShowFunctionsButton.setColorFilter(textColor);
}
@Click(R.id.functions)
void showFunctionList() {
}
@Click(R.id.run)
public void runAndSaveFileIfNeeded() {
@ -369,7 +393,6 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
public void onHintClick(CodeCompletions completions, int pos) {
if (completions.shouldBeInserted()) {
mEditor.insert(completions.getHints().get(pos));
showFunctionList();
return;
}
mEditor.replace(completions.getHints().get(pos), completions.getFrom().line, completions.getFrom().ch,
@ -381,9 +404,14 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
String url = completions.getUrltAt(pos);
if (url == null)
return;
showManual(url, completions.getHints().get(pos));
}
private void showManual(String url, String title) {
String absUrl = Pref.getDocumentationUrl() + url;
new ManualDialog(getContext())
.title(completions.getHints().get(pos))
.title(title)
.url(absUrl)
.pinToLeft(v -> {
mEWebView.getWebView().loadUrl(absUrl);
@ -391,4 +419,28 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
})
.show();
}
@Override
public void onModuleLongClick(Module module) {
showManual(module.getUrl(), module.getName());
}
@Override
public void onPropertyClick(Module m, Property property) {
if (property.isGlobal()) {
mEditor.insert(property.getKey());
} else {
mEditor.insert(m.getName() + "." + property.getKey());
}
mFunctionsKeyboardHelper.hideFunctionsLayout(true);
}
@Override
public void onPropertyLongClick(Module m, Property property) {
if (TextUtils.isEmpty(property.getUrl())) {
showManual(m.getUrl(), property.getKey());
} else {
showManual(property.getUrl(), property.getKey());
}
}
}

View File

@ -0,0 +1,192 @@
package com.stardust.scriptdroid.ui.edit.keyboard;
/**
* Created by Stardust on 2017/12/9.
*/
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;
import com.stardust.util.BackPressedHandler;
/**
* https://github.com/dss886/Android-FunctionsInputDetector
*/
public class FunctionsKeyboardHelper implements BackPressedHandler {
private static final String SHARE_PREFERENCE_NAME = "FunctionsKeyboardHelper";
private static final String SHARE_PREFERENCE_SOFT_INPUT_HEIGHT = "soft_input_height";
private Activity mActivity;
private InputMethodManager mInputManager;
private SharedPreferences mPreferences;
private View mFunctionsLayout;
private View mEditView;
private View mContentView;
private FunctionsKeyboardHelper(Activity activity) {
mActivity = activity;
mInputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
mPreferences = activity.getSharedPreferences(SHARE_PREFERENCE_NAME, Context.MODE_PRIVATE);
}
public static FunctionsKeyboardHelper with(Activity activity) {
return new FunctionsKeyboardHelper(activity);
}
public FunctionsKeyboardHelper setContent(View contentView) {
mContentView = contentView;
return this;
}
public void onSoftKeyboardShown() {
if (mFunctionsLayout.isShown()) {
lockContentHeight();
hideFunctionsLayout(false);
mEditView.postDelayed(FunctionsKeyboardHelper.this::unlockContentHeightDelayed, 200L);
}
}
@SuppressLint("ClickableViewAccessibility")
public FunctionsKeyboardHelper setEditView(View editView) {
mEditView = editView;
mEditView.requestFocus();
editView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN)
onSoftKeyboardShown();
return false;
});
return this;
}
public FunctionsKeyboardHelper setFunctionsTrigger(View triggerButton) {
triggerButton.setOnClickListener(v -> {
if (mFunctionsLayout.isShown()) {
lockContentHeight();
hideFunctionsLayout(true);
unlockContentHeightDelayed();
} else {
if (isSoftInputShown()) {
lockContentHeight();
showFunctionsLayout();
unlockContentHeightDelayed();
} else {
showFunctionsLayout();//两者都没显示直接显示表情布局
}
}
});
return this;
}
public FunctionsKeyboardHelper setFunctionsView(View FunctionsView) {
mFunctionsLayout = FunctionsView;
return this;
}
public FunctionsKeyboardHelper build() {
mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN |
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
hideSoftInput();
return this;
}
private void showFunctionsLayout() {
int softInputHeight = getSupportSoftInputHeight();
if (softInputHeight == 0) {
softInputHeight = mPreferences.getInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, 400);
}
hideSoftInput();
mFunctionsLayout.getLayoutParams().height = softInputHeight;
mFunctionsLayout.setVisibility(View.VISIBLE);
}
public void hideFunctionsLayout(boolean showSoftInput) {
if (mFunctionsLayout.isShown()) {
mFunctionsLayout.setVisibility(View.GONE);
if (showSoftInput) {
showSoftInput();
}
}
}
private void lockContentHeight() {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mContentView.getLayoutParams();
params.height = mContentView.getHeight();
params.weight = 0.0F;
}
private void unlockContentHeightDelayed() {
mEditView.postDelayed(() -> ((LinearLayout.LayoutParams) mContentView.getLayoutParams()).weight = 1.0F, 200L);
}
private void showSoftInput() {
mEditView.requestFocus();
mEditView.post(() -> mInputManager.showSoftInput(mEditView, InputMethodManager.SHOW_FORCED));
}
private void hideSoftInput() {
mInputManager.hideSoftInputFromWindow(mEditView.getWindowToken(), 0);
}
private boolean isSoftInputShown() {
return getSupportSoftInputHeight() != 0;
}
private int getSupportSoftInputHeight() {
Rect r = new Rect();
mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
int screenHeight = mActivity.getWindow().getDecorView().getRootView().getHeight();
int softInputHeight = screenHeight - r.bottom;
if (Build.VERSION.SDK_INT >= 20) {
// When SDK Level >= 20 (Android L), the softInputHeight will contain the height of softButtonsBar (if has)
softInputHeight = softInputHeight - getSoftKeyButtonsHeight();
}
if (softInputHeight > 0) {
mPreferences.edit().putInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, softInputHeight).apply();
}
return softInputHeight;
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private int getSoftKeyButtonsHeight() {
DisplayMetrics metrics = new DisplayMetrics();
mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
int usableHeight = metrics.heightPixels;
mActivity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
int realHeight = metrics.heightPixels;
if (realHeight > usableHeight) {
return realHeight - usableHeight;
} else {
return 0;
}
}
public int getKeyBoardHeight() {
return mPreferences.getInt(SHARE_PREFERENCE_SOFT_INPUT_HEIGHT, 400);
}
@Override
public boolean onBackPressed(Activity activity) {
if (mFunctionsLayout.isShown()) {
hideFunctionsLayout(false);
return true;
}
return false;
}
}

View File

@ -0,0 +1,306 @@
package com.stardust.scriptdroid.ui.edit.keyboard;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.model.indices.Module;
import com.stardust.scriptdroid.model.indices.Modules;
import com.stardust.scriptdroid.model.indices.Property;
import com.stardust.scriptdroid.ui.widget.GridDividerDecoration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.android.schedulers.AndroidSchedulers;
/**
* Created by Stardust on 2017/12/9.
*/
public class FunctionsKeyboardView extends FrameLayout {
public interface ClickCallback {
void onModuleLongClick(Module module);
void onPropertyClick(Module m, Property property);
void onPropertyLongClick(Module m, Property property);
}
private static final int SPAN_COUNT = 4;
@BindView(R.id.module_list)
RecyclerView mModulesView;
@BindView(R.id.properties)
RecyclerView mPropertiesView;
private List<Module> mModules;
private Map<Module, List<Integer>> mSpanSizes = new HashMap<>();
private Module mSelectedModule;
private View mSelectedModuleView;
private Paint mPaint;
private ClickCallback mClickCallback;
public FunctionsKeyboardView(@NonNull Context context) {
super(context);
init();
}
public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public FunctionsKeyboardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
public void setClickCallback(ClickCallback clickCallback) {
mClickCallback = clickCallback;
}
private void init() {
inflate(getContext(), R.layout.functions_keyboard_view, this);
ButterKnife.bind(this);
initModulesView();
initPropertiesView();
}
private void initPropertiesView() {
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), SPAN_COUNT);
mPropertiesView.setLayoutManager(gridLayoutManager);
mPropertiesView.setAdapter(new PropertiesAdapter());
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return mSpanSizes.get(mSelectedModule).get(position);
}
});
Drawable divider = ContextCompat.getDrawable(getContext(), R.drawable.divider_functions_view);
GridDividerDecoration dividerItemDecoration = new GridDividerDecoration(getContext(), divider);
mPropertiesView.addItemDecoration(dividerItemDecoration);
}
private void initSpanSizes(Module module) {
if (mSpanSizes.containsKey(module))
return;
if (getMeasuredWidth() == 0)
throw new IllegalStateException();
List<Integer> spanSizes = new ArrayList<>();
//初始化spanSizes列表
for (Property property : mSelectedModule.getProperties()) {
int width = Math.max(getTextWidth(property.getKey()), getTextWidth(property.getSummary()));
int spanSize = (int) Math.ceil(width / ((double) getMeasuredWidth() / 4));
spanSizes.add(Math.min(spanSize, 2));
}
//遍历这个列表调整spanSize例如以下这种情况时:
// [] [] []
// [ ] [] []
// [] [] [] []
//把第一行的第三个元素的spanSize设置为2
int column = 0;
for (int i = 0; i < spanSizes.size(); i++) {
int spanSize = spanSizes.get(i);
if (spanSize + column > SPAN_COUNT) {
spanSizes.set(i - 1, 2);
column = spanSize;
} else {
column += spanSize;
}
if (column == 4) {
column = 0;
}
}
mSpanSizes.put(module, spanSizes);
}
private String getDisplayText(Property property) {
if (TextUtils.isEmpty(property.getSummary()))
return property.getKey();
return property.getKey() + "\n" + property.getSummary();
}
private int getTextWidth(String text) {
if (mPaint == null) {
mPaint = new Paint();
mPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.textSize_item_property));
}
Rect r = new Rect();
mPaint.getTextBounds(text, 0, text.length(), r);
return r.width();
}
private void initModulesView() {
mModulesView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayout.HORIZONTAL, false));
mModulesView.setAdapter(new ModulesAdapter());
}
private void loadModules() {
Modules.getInstance().getModules(getContext())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(modules -> {
mModules = modules;
if (modules.size() > 0) {
setSelectedModule(modules.get(0), null);
}
mModulesView.getAdapter().notifyDataSetChanged();
mPropertiesView.getAdapter().notifyDataSetChanged();
});
}
private void setSelectedModule(Module module, @Nullable View moduleView) {
mSelectedModule = module;
if (mSelectedModuleView != null) {
mSelectedModuleView.setSelected(false);
}
mSelectedModuleView = moduleView;
if (mSelectedModuleView != null)
mSelectedModuleView.setSelected(true);
initSpanSizes(mSelectedModule);
mPropertiesView.getAdapter().notifyDataSetChanged();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mModules == null)
loadModules();
}
private class ModuleViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private Module mModule;
ModuleViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView;
mTextView.setOnClickListener(v -> {
if (mModule == null)
return;
setSelectedModule(mModule, mTextView);
});
mTextView.setOnLongClickListener(v -> {
if (mClickCallback != null) {
mClickCallback.onModuleLongClick(mModule);
return true;
}
return false;
});
}
void bind(Module module) {
mModule = module;
mTextView.setText(module.getSummary());
mTextView.setSelected(module == mSelectedModule);
if (module == mSelectedModule) {
mSelectedModuleView = mTextView;
}
}
}
private class PropertyViewHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private Property mProperty;
PropertyViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView;
mTextView.setOnLongClickListener(v -> {
if (mClickCallback != null) {
mClickCallback.onPropertyLongClick(mSelectedModule, mProperty);
return true;
}
return false;
});
mTextView.setOnClickListener(v -> {
if (mClickCallback != null) {
mClickCallback.onPropertyClick(mSelectedModule, mProperty);
}
});
}
void bind(Property property) {
mProperty = property;
mTextView.setText(getDisplayText(property));
}
}
private class ModulesAdapter extends RecyclerView.Adapter<ModuleViewHolder> {
@Override
public ModuleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ModuleViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_module, parent, false));
}
@Override
public void onBindViewHolder(ModuleViewHolder holder, int position) {
holder.bind(mModules.get(position));
}
@Override
public int getItemCount() {
return mModules == null ? 0 : mModules.size();
}
}
private class PropertiesAdapter extends RecyclerView.Adapter<PropertyViewHolder> {
@Override
public PropertyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new PropertyViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_property, parent, false));
}
@Override
public void onBindViewHolder(PropertyViewHolder holder, int position) {
holder.bind(mSelectedModule.getProperties().get(position));
}
@Override
public int getItemCount() {
return mSelectedModule == null ? 0 : mSelectedModule.getProperties().size();
}
}
}

View File

@ -1,104 +0,0 @@
package com.stardust.scriptdroid.ui.floating;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;
import android.view.ContextThemeWrapper;
import android.view.View;
import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.enhancedfloaty.ResizableFloaty;
import com.stardust.enhancedfloaty.ResizableFloatyWindow;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.model.script.ScriptFile;
import com.stardust.scriptdroid.ui.edit.EditActivity_;
import com.stardust.scriptdroid.ui.edit.EditorView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_NAME;
import static com.stardust.scriptdroid.ui.edit.EditorView.EXTRA_PATH;
/**
* Created by Stardust on 2017/9/29.
*/
public class EditorFloaty implements ResizableFloaty {
private Intent mIntent;
@BindView(R.id.resizer)
View mResizeIcon;
@BindView(R.id.move_cursor)
View mMoveIcon;
private ResizableFloatyWindow mWindow;
public EditorFloaty(Intent intent) {
mIntent = intent;
}
public static void floatingEdit(Context context, Intent intent) {
FloatyWindowManger.addWindow(context, new ResizableFloatyWindow(new EditorFloaty(intent)));
}
public static void floatingEdit(Context context, String path) {
floatingEdit(context, null, path);
}
public static void floatingEdit(Context context, String name, String path) {
floatingEdit(context, new Intent(context, EditActivity_.class)
.putExtra(EXTRA_PATH, path)
.putExtra(EXTRA_NAME, name));
}
public static void floatingEdit(Context context, ScriptFile file) {
floatingEdit(context, file.getSimplifiedName(), file.getPath());
}
@Override
public View inflateView(FloatyService floatyService, ResizableFloatyWindow resizableFloatyWindow) {
mWindow = resizableFloatyWindow;
View v = View.inflate(new ContextThemeWrapper(floatyService, R.style.AppTheme), R.layout.floating_editor, null);
setUpViews(v);
return v;
}
private void setUpViews(View v) {
EditorView editorView = (EditorView) v.findViewById(R.id.editor_view);
editorView.handleIntent(mIntent);
ButterKnife.bind(this, v);
}
@OnClick(R.id.move_or_resize)
void showOrHideMoveAndResizeIcon() {
if (mResizeIcon.getVisibility() == View.VISIBLE) {
mResizeIcon.setVisibility(View.GONE);
mMoveIcon.setVisibility(View.GONE);
} else {
mResizeIcon.setVisibility(View.VISIBLE);
mMoveIcon.setVisibility(View.VISIBLE);
}
}
@OnClick(R.id.close)
void close() {
mWindow.close();
}
@Nullable
@Override
public View getResizerView(View view) {
return view.findViewById(R.id.resizer);
}
@Nullable
@Override
public View getMoveCursorView(View view) {
return view.findViewById(R.id.move_cursor);
}
}

View File

@ -24,7 +24,6 @@ import com.stardust.scriptdroid.model.script.Scripts;
import com.stardust.scriptdroid.storage.file.StorageFileProvider;
import com.stardust.scriptdroid.ui.common.ScriptLoopDialog;
import com.stardust.scriptdroid.ui.common.ScriptOperations;
import com.stardust.scriptdroid.ui.floating.EditorFloaty;
import com.stardust.scriptdroid.ui.viewmodel.ScriptList;
import com.stardust.scriptdroid.ui.widget.BindableViewHolder;
@ -229,10 +228,6 @@ public class ScriptListView extends SwipeRefreshLayout implements SwipeRefreshLa
.show();
notifyOperated();
break;
case R.id.floating_edit:
EditorFloaty.floatingEdit(getContext(), mSelectedScriptFile);
notifyOperated();
break;
case R.id.create_shortcut:
new ScriptOperations(getContext(), this)
.createShortcut(mSelectedScriptFile);

View File

@ -0,0 +1,88 @@
package com.stardust.scriptdroid.ui.widget;
/**
* Created by Stardust on 2017/12/9.
*/
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.View;
/**
* ItemDecoration implementation that applies and inset margin
* around each child of the RecyclerView. It also draws item dividers
* that are expected from a vertical list implementation, such as
* ListView.
*/
public class GridDividerDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
private int mInsets;
public GridDividerDecoration(Context context, Drawable divider) {
mDivider = divider;
mInsets = divider.getIntrinsicWidth();
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
drawVertical(c, parent);
drawHorizontal(c, parent);
}
/**
* Draw dividers at each expected grid interval
*/
public void drawVertical(Canvas c, RecyclerView parent) {
if (parent.getChildCount() == 0) return;
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - params.leftMargin - mInsets;
final int right = child.getRight() + params.rightMargin + mInsets;
final int top = child.getBottom() + params.bottomMargin + mInsets;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
/**
* Draw dividers to the right of each child view
*/
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params =
(RecyclerView.LayoutParams) child.getLayoutParams();
final int left = child.getRight() + params.rightMargin + mInsets;
final int right = left + mDivider.getIntrinsicWidth();
final int top = child.getTop() - params.topMargin - mInsets;
final int bottom = child.getBottom() + params.bottomMargin + mInsets;
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
//We can supply forced insets for each item view here in the Rect
outRect.set(mInsets, mInsets, mInsets, mInsets);
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape>
<solid android:color="#e5e5e5"/>
</shape>
</item>
<item>
<shape>
<solid android:color="#ffffff"/>
</shape>
</item>
</selector>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#e5e5e5"/>
</shape>
</item>
<item>
<shape>
<solid android:color="@android:color/transparent"/>
</shape>
</item>
</selector>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp"/>
<solid android:color="@color/divider_functions_keyboard"/>
</shape>

View File

@ -139,7 +139,7 @@
android:layout_alignParentBottom="true"/>
<ImageView
android:id="@+id/functions"
android:id="@+id/properties"
android:layout_width="40dp"
android:layout_height="35dp"
android:layout_alignParentLeft="true"
@ -156,9 +156,16 @@
android:layout_above="@+id/symbol_bar"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="@+id/functions"/>
android:layout_toRightOf="@+id/properties"/>
</RelativeLayout>
<com.stardust.scriptdroid.ui.edit.keyboard.FunctionsKeyboardView
android:id="@+id/functions_keyboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
</LinearLayout>
<com.stardust.scriptdroid.ui.widget.EWebView
@ -166,8 +173,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"/>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_functions_keyboard"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/properties"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#fafafa"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/divider_functions_keyboard"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/module_list"
android:layout_width="match_parent"
android:layout_height="50dp"/>
</LinearLayout>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="@drawable/bg_item_module"
android:gravity="center"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:textColor="#616161"
android:textSize="16sp">
</TextView>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@drawable/bg_item_property"
android:gravity="center"
android:textColor="#414141"
android:textSize="@dimen/textSize_item_property">
</TextView>

View File

@ -9,4 +9,5 @@
<color name="color_j">#99CC99</color>
<color name="prefTextColorSecondary">#9DA0A2</color>
<color name="prefTextColorPrimary">#282C2F</color>
<color name="divider_functions_keyboard">#f0f0f0</color>
</resources>

View File

@ -7,4 +7,6 @@
<dimen name="script_and_folder_list_divider_left_margin">0dp</dimen>
<dimen name="script_and_folder_list_divider_right_margin">0dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="padding_item_property">8dp</dimen>
<dimen name="textSize_item_property">14sp</dimen>
</resources>