|
|
|
|
@ -57,6 +57,8 @@ import android.widget.Toast;
|
|
|
|
|
import net.micode.notes.R;
|
|
|
|
|
import net.micode.notes.data.Notes;
|
|
|
|
|
import net.micode.notes.data.Notes.TextNote;
|
|
|
|
|
import net.micode.notes.model.NoteCommand;
|
|
|
|
|
import net.micode.notes.model.UndoRedoManager;
|
|
|
|
|
import net.micode.notes.model.WorkingNote;
|
|
|
|
|
import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
|
|
|
|
|
import net.micode.notes.tool.DataUtils;
|
|
|
|
|
@ -77,8 +79,11 @@ import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
|
import com.google.android.material.appbar.MaterialToolbar;
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.databinding.NoteEditBinding;
|
|
|
|
|
import net.micode.notes.tool.RichTextHelper;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import net.micode.notes.data.FontManager;
|
|
|
|
|
|
|
|
|
|
public class NoteEditActivity extends AppCompatActivity implements OnClickListener,
|
|
|
|
|
NoteSettingChangedListener, OnTextViewChangeListener {
|
|
|
|
|
/**
|
|
|
|
|
@ -101,24 +106,6 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
public EditText etTitle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
|
|
|
|
|
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
|
|
|
|
|
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<Integer, Integer>();
|
|
|
|
|
static {
|
|
|
|
|
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
|
|
|
|
|
@ -145,6 +132,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
|
|
|
|
|
private View mFontSizeSelector;
|
|
|
|
|
|
|
|
|
|
private View mRichTextSelector;
|
|
|
|
|
|
|
|
|
|
private EditText mNoteEditor;
|
|
|
|
|
|
|
|
|
|
private View mNoteEditorPanel;
|
|
|
|
|
@ -170,25 +159,11 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
|
|
|
|
|
private NoteEditBinding binding;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 辅助方法:根据ID获取背景颜色选择视图
|
|
|
|
|
*/
|
|
|
|
|
private View getBgSelectorView(int viewId) {
|
|
|
|
|
switch (viewId) {
|
|
|
|
|
case R.id.iv_bg_yellow_select:
|
|
|
|
|
return binding.ivBgYellowSelect;
|
|
|
|
|
case R.id.iv_bg_red_select:
|
|
|
|
|
return binding.ivBgRedSelect;
|
|
|
|
|
case R.id.iv_bg_blue_select:
|
|
|
|
|
return binding.ivBgBlueSelect;
|
|
|
|
|
case R.id.iv_bg_green_select:
|
|
|
|
|
return binding.ivBgGreenSelect;
|
|
|
|
|
case R.id.iv_bg_white_select:
|
|
|
|
|
return binding.ivBgWhiteSelect;
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown view ID: " + viewId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private UndoRedoManager mUndoRedoManager;
|
|
|
|
|
private boolean mInUndoRedo = false;
|
|
|
|
|
|
|
|
|
|
private androidx.recyclerview.widget.RecyclerView mColorSelectorRv;
|
|
|
|
|
private NoteColorAdapter mColorAdapter;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 辅助方法:根据ID获取字体选择视图
|
|
|
|
|
@ -215,6 +190,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
// 使用ViewBinding设置布局
|
|
|
|
|
binding = NoteEditBinding.inflate(getLayoutInflater());
|
|
|
|
|
setContentView(binding.getRoot());
|
|
|
|
|
mUndoRedoManager = new UndoRedoManager();
|
|
|
|
|
|
|
|
|
|
// 初始化Toolbar(使用MaterialToolbar,与列表页面一致)
|
|
|
|
|
setSupportActionBar(binding.toolbar);
|
|
|
|
|
@ -368,10 +344,16 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
mNoteEditor = binding.noteEditView;
|
|
|
|
|
mNoteEditorPanel = binding.svNoteEdit;
|
|
|
|
|
mNoteBgColorSelector = binding.noteBgColorSelector;
|
|
|
|
|
mColorSelectorRv = binding.rvBgColorSelector;
|
|
|
|
|
|
|
|
|
|
mNoteEditor.addTextChangedListener(new TextWatcher() {
|
|
|
|
|
private CharSequence mBeforeText;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
|
|
|
if (!mInUndoRedo) {
|
|
|
|
|
mBeforeText = s.subSequence(start, start + count).toString();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@ -379,6 +361,13 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
if (mNoteHeaderHolder != null && mNoteHeaderHolder.tvCharCount != null) {
|
|
|
|
|
mNoteHeaderHolder.tvCharCount.setText(String.valueOf(s.length()) + " 字");
|
|
|
|
|
}
|
|
|
|
|
if (!mInUndoRedo) {
|
|
|
|
|
CharSequence afterText = s.subSequence(start, start + count).toString();
|
|
|
|
|
if (!TextUtils.equals(mBeforeText, afterText)) {
|
|
|
|
|
mUndoRedoManager.addCommand(new NoteCommand(mNoteEditor, start, mBeforeText, afterText));
|
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@ -406,30 +395,34 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 设置背景颜色选择器的点击事件
|
|
|
|
|
for (int id : sBgSelectorBtnsMap.keySet()) {
|
|
|
|
|
ImageView iv;
|
|
|
|
|
switch (id) {
|
|
|
|
|
case R.id.iv_bg_yellow:
|
|
|
|
|
iv = binding.ivBgYellow;
|
|
|
|
|
break;
|
|
|
|
|
case R.id.iv_bg_red:
|
|
|
|
|
iv = binding.ivBgRed;
|
|
|
|
|
break;
|
|
|
|
|
case R.id.iv_bg_blue:
|
|
|
|
|
iv = binding.ivBgBlue;
|
|
|
|
|
break;
|
|
|
|
|
case R.id.iv_bg_green:
|
|
|
|
|
iv = binding.ivBgGreen;
|
|
|
|
|
break;
|
|
|
|
|
case R.id.iv_bg_white:
|
|
|
|
|
iv = binding.ivBgWhite;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new IllegalArgumentException("Unknown view ID: " + id);
|
|
|
|
|
// Initialize Color Adapter
|
|
|
|
|
java.util.List<Integer> colors = java.util.Arrays.asList(
|
|
|
|
|
ResourceParser.YELLOW,
|
|
|
|
|
ResourceParser.BLUE,
|
|
|
|
|
ResourceParser.WHITE,
|
|
|
|
|
ResourceParser.GREEN,
|
|
|
|
|
ResourceParser.RED,
|
|
|
|
|
ResourceParser.MIDNIGHT_BLACK,
|
|
|
|
|
ResourceParser.EYE_CARE_GREEN,
|
|
|
|
|
ResourceParser.WARM,
|
|
|
|
|
ResourceParser.COOL,
|
|
|
|
|
ResourceParser.CUSTOM_COLOR_BUTTON_ID,
|
|
|
|
|
ResourceParser.WALLPAPER_BUTTON_ID
|
|
|
|
|
);
|
|
|
|
|
mColorAdapter = new NoteColorAdapter(colors, ResourceParser.YELLOW, new NoteColorAdapter.OnColorClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onColorClick(int colorId) {
|
|
|
|
|
if (colorId == ResourceParser.CUSTOM_COLOR_BUTTON_ID) {
|
|
|
|
|
showColorPickerDialog();
|
|
|
|
|
} else if (colorId == ResourceParser.WALLPAPER_BUTTON_ID) {
|
|
|
|
|
pickWallpaper();
|
|
|
|
|
} else {
|
|
|
|
|
mWorkingNote.setBgColorId(colorId);
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
iv.setOnClickListener(this);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
mColorSelectorRv.setAdapter(mColorAdapter);
|
|
|
|
|
|
|
|
|
|
mFontSizeSelector = binding.fontSizeSelector;
|
|
|
|
|
for (int id : sFontSizeBtnsMap.keySet()) {
|
|
|
|
|
@ -464,6 +457,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
mFontSizeId = ResourceParser.BG_DEFAULT_FONT_SIZE;
|
|
|
|
|
}
|
|
|
|
|
mEditTextList = binding.noteEditList;
|
|
|
|
|
initRichTextToolbar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@ -487,21 +481,28 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
private void initNoteScreen() {
|
|
|
|
|
mNoteEditor.setTextAppearance(this, TextAppearanceResources
|
|
|
|
|
.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
// Apply custom font
|
|
|
|
|
FontManager.getInstance(this).applyFont(mNoteEditor);
|
|
|
|
|
|
|
|
|
|
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
switchToListMode(mWorkingNote.getContent());
|
|
|
|
|
} else {
|
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
|
|
|
|
|
String content = mWorkingNote.getContent();
|
|
|
|
|
if (content.contains("<") && content.contains(">")) {
|
|
|
|
|
mNoteEditor.setText(RichTextHelper.fromHtml(content));
|
|
|
|
|
} else {
|
|
|
|
|
mNoteEditor.setText(getHighlightQueryResult(content, mUserQuery));
|
|
|
|
|
}
|
|
|
|
|
mNoteEditor.setSelection(mNoteEditor.getText().length());
|
|
|
|
|
}
|
|
|
|
|
mNoteHeaderHolder.etTitle.setText(mWorkingNote.getTitle());
|
|
|
|
|
for (Integer id : sBgSelectorSelectionMap.keySet()) {
|
|
|
|
|
View view = getBgSelectorView(sBgSelectorSelectionMap.get(id));
|
|
|
|
|
if (view != null) {
|
|
|
|
|
view.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update Color Adapter selection
|
|
|
|
|
if (mColorAdapter != null) {
|
|
|
|
|
mColorAdapter.setSelectedColor(mWorkingNote.getBgColorId());
|
|
|
|
|
}
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
|
|
|
|
|
updateNoteBackgrounds();
|
|
|
|
|
|
|
|
|
|
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
|
|
|
|
|
mWorkingNote.getModifiedDate(), DateUtils.FORMAT_SHOW_DATE
|
|
|
|
|
@ -678,17 +679,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
int id = v.getId();
|
|
|
|
|
if (id == R.id.btn_set_bg_color) {
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.VISIBLE);
|
|
|
|
|
View bgView = getBgSelectorView(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId()));
|
|
|
|
|
if (bgView != null) {
|
|
|
|
|
bgView.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
} else if (sBgSelectorBtnsMap.containsKey(id)) {
|
|
|
|
|
View bgView = getBgSelectorView(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId()));
|
|
|
|
|
if (bgView != null) {
|
|
|
|
|
bgView.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
// Note: Adapter selection is already set in onBackgroundColorChanged or init
|
|
|
|
|
} else if (sFontSizeBtnsMap.containsKey(id)) {
|
|
|
|
|
View fontView = getFontSelectorView(sFontSelectorSelectionMap.get(mFontSizeId));
|
|
|
|
|
if (fontView != null) {
|
|
|
|
|
@ -706,6 +697,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
} else {
|
|
|
|
|
mNoteEditor.setTextAppearance(this,
|
|
|
|
|
TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
// Apply custom font again as setTextAppearance might reset it
|
|
|
|
|
FontManager.getInstance(this).applyFont(mNoteEditor);
|
|
|
|
|
}
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
@ -758,12 +751,143 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
* </p>
|
|
|
|
|
*/
|
|
|
|
|
public void onBackgroundColorChanged() {
|
|
|
|
|
View bgView = getBgSelectorView(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId()));
|
|
|
|
|
if (bgView != null) {
|
|
|
|
|
bgView.setVisibility(View.VISIBLE);
|
|
|
|
|
if (mColorAdapter != null) {
|
|
|
|
|
mColorAdapter.setSelectedColor(mWorkingNote.getBgColorId());
|
|
|
|
|
}
|
|
|
|
|
updateNoteBackgrounds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateNoteBackgrounds() {
|
|
|
|
|
int colorId = mWorkingNote.getBgColorId();
|
|
|
|
|
String wallpaperPath = mWorkingNote.getWallpaperPath();
|
|
|
|
|
|
|
|
|
|
if (wallpaperPath != null) {
|
|
|
|
|
// Load wallpaper
|
|
|
|
|
android.net.Uri uri = android.net.Uri.parse(wallpaperPath);
|
|
|
|
|
try {
|
|
|
|
|
java.io.InputStream inputStream = getContentResolver().openInputStream(uri);
|
|
|
|
|
android.graphics.Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(inputStream);
|
|
|
|
|
android.graphics.drawable.BitmapDrawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), bitmap);
|
|
|
|
|
|
|
|
|
|
// Tiling mode (can be configurable later)
|
|
|
|
|
drawable.setTileModeXY(android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
|
|
|
|
|
|
|
|
|
|
// Add Blur Effect for Android 12+
|
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
|
|
|
|
mNoteEditorPanel.setBackground(drawable);
|
|
|
|
|
mNoteEditorPanel.setRenderEffect(android.graphics.RenderEffect.createBlurEffect(
|
|
|
|
|
20f, 20f, android.graphics.Shader.TileMode.CLAMP));
|
|
|
|
|
} else {
|
|
|
|
|
mNoteEditorPanel.setBackground(drawable);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Header always uses original wallpaper (or maybe slightly darker?)
|
|
|
|
|
mHeadViewPanel.setBackground(drawable.getConstantState().newDrawable());
|
|
|
|
|
|
|
|
|
|
// Dynamic Coloring with Palette
|
|
|
|
|
androidx.palette.graphics.Palette.from(bitmap).generate(palette -> {
|
|
|
|
|
if (palette != null) {
|
|
|
|
|
applyPaletteColors(palette);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.e(TAG, "Failed to load wallpaper", e);
|
|
|
|
|
// Fallback to color
|
|
|
|
|
applyColorBackground(colorId);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
applyColorBackground(colorId);
|
|
|
|
|
// Reset toolbar colors to default/theme
|
|
|
|
|
resetToolbarColors();
|
|
|
|
|
}
|
|
|
|
|
updateTextColor(colorId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void applyPaletteColors(androidx.palette.graphics.Palette palette) {
|
|
|
|
|
int primaryColor = palette.getDominantColor(getResources().getColor(R.color.primary_color));
|
|
|
|
|
int onPrimaryColor = getResources().getColor(R.color.on_primary_color);
|
|
|
|
|
|
|
|
|
|
// Ensure contrast for onPrimaryColor
|
|
|
|
|
if (androidx.core.graphics.ColorUtils.calculateContrast(onPrimaryColor, primaryColor) < 3.0) {
|
|
|
|
|
onPrimaryColor = android.graphics.Color.WHITE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
binding.toolbar.setBackgroundColor(primaryColor);
|
|
|
|
|
binding.toolbar.setTitleTextColor(onPrimaryColor);
|
|
|
|
|
if (binding.toolbar.getNavigationIcon() != null) {
|
|
|
|
|
binding.toolbar.getNavigationIcon().setTint(onPrimaryColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getWindow().setStatusBarColor(primaryColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void resetToolbarColors() {
|
|
|
|
|
int primaryColor = getResources().getColor(R.color.primary_color);
|
|
|
|
|
int onPrimaryColor = getResources().getColor(R.color.on_primary_color);
|
|
|
|
|
binding.toolbar.setBackgroundColor(primaryColor);
|
|
|
|
|
binding.toolbar.setTitleTextColor(onPrimaryColor);
|
|
|
|
|
if (binding.toolbar.getNavigationIcon() != null) {
|
|
|
|
|
binding.toolbar.getNavigationIcon().setTint(onPrimaryColor);
|
|
|
|
|
}
|
|
|
|
|
getWindow().setStatusBarColor(primaryColor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void updateTextColor(int colorId) {
|
|
|
|
|
// Default to black for light backgrounds
|
|
|
|
|
int textColor = android.graphics.Color.BLACK;
|
|
|
|
|
|
|
|
|
|
if (colorId == ResourceParser.MIDNIGHT_BLACK) {
|
|
|
|
|
textColor = android.graphics.Color.WHITE;
|
|
|
|
|
} else if (colorId < 0) {
|
|
|
|
|
// Custom color: Calculate luminance
|
|
|
|
|
// colorId is the ARGB value for custom colors
|
|
|
|
|
if (isColorDark(colorId)) {
|
|
|
|
|
textColor = android.graphics.Color.WHITE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For wallpaper, we might want to check palette, but for now default to black or keep current
|
|
|
|
|
// If wallpaper is set, this method is called with the underlying colorId.
|
|
|
|
|
// We should probably rely on the underlying color or default to white/black.
|
|
|
|
|
|
|
|
|
|
mNoteEditor.setTextColor(textColor);
|
|
|
|
|
// Also update title color if needed
|
|
|
|
|
if (mNoteHeaderHolder != null && mNoteHeaderHolder.etTitle != null) {
|
|
|
|
|
mNoteHeaderHolder.etTitle.setTextColor(textColor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean isColorDark(int color) {
|
|
|
|
|
double darkness = 1 - (0.299 * android.graphics.Color.red(color) +
|
|
|
|
|
0.587 * android.graphics.Color.green(color) +
|
|
|
|
|
0.114 * android.graphics.Color.blue(color)) / 255;
|
|
|
|
|
return darkness >= 0.5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void applyColorBackground(int colorId) {
|
|
|
|
|
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
|
|
|
|
|
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
|
|
|
|
|
|
|
|
|
|
if (colorId >= ResourceParser.MIDNIGHT_BLACK || colorId < 0) {
|
|
|
|
|
int color = ResourceParser.getNoteBgColor(this, colorId);
|
|
|
|
|
if (mNoteEditorPanel.getBackground() != null) {
|
|
|
|
|
mNoteEditorPanel.getBackground().setTint(color);
|
|
|
|
|
mNoteEditorPanel.getBackground().setTintMode(android.graphics.PorterDuff.Mode.MULTIPLY);
|
|
|
|
|
}
|
|
|
|
|
if (mHeadViewPanel.getBackground() != null) {
|
|
|
|
|
mHeadViewPanel.getBackground().setTint(color);
|
|
|
|
|
mHeadViewPanel.getBackground().setTintMode(android.graphics.PorterDuff.Mode.MULTIPLY);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Clear tint for legacy resources
|
|
|
|
|
if (mNoteEditorPanel.getBackground() != null) {
|
|
|
|
|
mNoteEditorPanel.getBackground().clearColorFilter();
|
|
|
|
|
}
|
|
|
|
|
if (mHeadViewPanel.getBackground() != null) {
|
|
|
|
|
mHeadViewPanel.getBackground().clearColorFilter();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -790,6 +914,18 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
getMenuInflater().inflate(R.menu.call_note_edit, menu);
|
|
|
|
|
} else {
|
|
|
|
|
getMenuInflater().inflate(R.menu.note_edit, menu);
|
|
|
|
|
MenuItem undoItem = menu.findItem(R.id.menu_undo);
|
|
|
|
|
MenuItem redoItem = menu.findItem(R.id.menu_redo);
|
|
|
|
|
MenuItem clearItem = menu.findItem(R.id.menu_clear_history);
|
|
|
|
|
if (undoItem != null) {
|
|
|
|
|
undoItem.setEnabled(mUndoRedoManager.canUndo());
|
|
|
|
|
}
|
|
|
|
|
if (redoItem != null) {
|
|
|
|
|
redoItem.setEnabled(mUndoRedoManager.canRedo());
|
|
|
|
|
}
|
|
|
|
|
if (clearItem != null) {
|
|
|
|
|
clearItem.setEnabled(mUndoRedoManager.canUndo() || mUndoRedoManager.canRedo());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
menu.findItem(R.id.menu_list_mode).setTitle(R.string.menu_normal_mode);
|
|
|
|
|
@ -825,6 +961,33 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
@Override
|
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
|
case R.id.menu_rich_text:
|
|
|
|
|
if (mRichTextSelector.getVisibility() == View.VISIBLE) {
|
|
|
|
|
mRichTextSelector.setVisibility(View.GONE);
|
|
|
|
|
} else {
|
|
|
|
|
mRichTextSelector.setVisibility(View.VISIBLE);
|
|
|
|
|
mFontSizeSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_undo:
|
|
|
|
|
mInUndoRedo = true;
|
|
|
|
|
mUndoRedoManager.undo();
|
|
|
|
|
mInUndoRedo = false;
|
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
|
showToast(R.string.undo_success);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_redo:
|
|
|
|
|
mInUndoRedo = true;
|
|
|
|
|
mUndoRedoManager.redo();
|
|
|
|
|
mInUndoRedo = false;
|
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
|
showToast(R.string.redo_success);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_clear_history:
|
|
|
|
|
mUndoRedoManager.clear();
|
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
|
showToast(R.string.menu_clear_history);
|
|
|
|
|
break;
|
|
|
|
|
case R.id.menu_new_note:
|
|
|
|
|
createNewNote();
|
|
|
|
|
break;
|
|
|
|
|
@ -1143,6 +1306,9 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null);
|
|
|
|
|
final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text);
|
|
|
|
|
edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId));
|
|
|
|
|
// Apply custom font
|
|
|
|
|
FontManager.getInstance(this).applyFont(edit);
|
|
|
|
|
|
|
|
|
|
CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item));
|
|
|
|
|
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
|
@ -1202,6 +1368,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
* @param newMode 新的模式
|
|
|
|
|
*/
|
|
|
|
|
public void onCheckListModeChanged(int oldMode, int newMode) {
|
|
|
|
|
mUndoRedoManager.clear();
|
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
|
if (newMode == TextNote.MODE_CHECK_LIST) {
|
|
|
|
|
switchToListMode(mNoteEditor.getText().toString());
|
|
|
|
|
} else {
|
|
|
|
|
@ -1245,7 +1413,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
}
|
|
|
|
|
mWorkingNote.setWorkingText(sb.toString());
|
|
|
|
|
} else {
|
|
|
|
|
mWorkingNote.setWorkingText(mNoteEditor.getText().toString());
|
|
|
|
|
mWorkingNote.setWorkingText(RichTextHelper.toHtml(mNoteEditor.getText()));
|
|
|
|
|
}
|
|
|
|
|
return hasChecked;
|
|
|
|
|
}
|
|
|
|
|
@ -1336,6 +1504,92 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void showColorPickerDialog() {
|
|
|
|
|
final View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_color_picker, null);
|
|
|
|
|
final View colorPreview = dialogView.findViewById(R.id.view_color_preview);
|
|
|
|
|
android.widget.SeekBar sbRed = dialogView.findViewById(R.id.sb_red);
|
|
|
|
|
android.widget.SeekBar sbGreen = dialogView.findViewById(R.id.sb_green);
|
|
|
|
|
android.widget.SeekBar sbBlue = dialogView.findViewById(R.id.sb_blue);
|
|
|
|
|
|
|
|
|
|
int currentColor = android.graphics.Color.WHITE;
|
|
|
|
|
if (mWorkingNote.getBgColorId() < 0) {
|
|
|
|
|
currentColor = mWorkingNote.getBgColorId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final int[] rgb = new int[]{
|
|
|
|
|
android.graphics.Color.red(currentColor),
|
|
|
|
|
android.graphics.Color.green(currentColor),
|
|
|
|
|
android.graphics.Color.blue(currentColor)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
colorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
|
|
|
|
|
sbRed.setProgress(rgb[0]);
|
|
|
|
|
sbGreen.setProgress(rgb[1]);
|
|
|
|
|
sbBlue.setProgress(rgb[2]);
|
|
|
|
|
|
|
|
|
|
android.widget.SeekBar.OnSeekBarChangeListener listener = new android.widget.SeekBar.OnSeekBarChangeListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onProgressChanged(android.widget.SeekBar seekBar, int progress, boolean fromUser) {
|
|
|
|
|
if (seekBar.getId() == R.id.sb_red) rgb[0] = progress;
|
|
|
|
|
else if (seekBar.getId() == R.id.sb_green) rgb[1] = progress;
|
|
|
|
|
else if (seekBar.getId() == R.id.sb_blue) rgb[2] = progress;
|
|
|
|
|
colorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onStartTrackingTouch(android.widget.SeekBar seekBar) {}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onStopTrackingTouch(android.widget.SeekBar seekBar) {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
sbRed.setOnSeekBarChangeListener(listener);
|
|
|
|
|
sbGreen.setOnSeekBarChangeListener(listener);
|
|
|
|
|
sbBlue.setOnSeekBarChangeListener(listener);
|
|
|
|
|
|
|
|
|
|
new AlertDialog.Builder(this)
|
|
|
|
|
.setTitle("Custom Color")
|
|
|
|
|
.setView(dialogView)
|
|
|
|
|
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
|
|
|
|
int newColor = android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]);
|
|
|
|
|
// Use negative integer for custom color. Ensure it's negative.
|
|
|
|
|
// ARGB color with alpha 255 is negative in Java int.
|
|
|
|
|
// If alpha is 0, it might be positive. We assume full opacity.
|
|
|
|
|
newColor |= 0xFF000000;
|
|
|
|
|
mWorkingNote.setBgColorId(newColor);
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
})
|
|
|
|
|
.setNegativeButton(android.R.string.cancel, null)
|
|
|
|
|
.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final int REQUEST_CODE_PICK_WALLPAPER = 105;
|
|
|
|
|
|
|
|
|
|
private void pickWallpaper() {
|
|
|
|
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
|
|
|
|
intent.setType("image/*");
|
|
|
|
|
startActivityForResult(intent, REQUEST_CODE_PICK_WALLPAPER);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
|
|
|
if (requestCode == REQUEST_CODE_PICK_WALLPAPER && resultCode == RESULT_OK && data != null) {
|
|
|
|
|
android.net.Uri uri = data.getData();
|
|
|
|
|
if (uri != null) {
|
|
|
|
|
// Take persistent permissions
|
|
|
|
|
try {
|
|
|
|
|
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
Log.e(TAG, "Failed to take persistable uri permission", e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mWorkingNote.setWallpaper(uri.toString());
|
|
|
|
|
mNoteBgColorSelector.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示Toast提示
|
|
|
|
|
* <p>
|
|
|
|
|
@ -1358,4 +1612,78 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
|
|
|
|
|
private void showToast(int resId, int duration) {
|
|
|
|
|
Toast.makeText(this, resId, duration).show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void initRichTextToolbar() {
|
|
|
|
|
mRichTextSelector = findViewById(R.id.rich_text_selector);
|
|
|
|
|
findViewById(R.id.btn_bold).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyBold(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_italic).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyItalic(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_underline).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyUnderline(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_strikethrough).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyStrikethrough(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_header).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
final CharSequence[] items = {"H1 (Largest)", "H2", "H3", "H4", "H5", "H6 (Smallest)", "Normal"};
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(NoteEditActivity.this);
|
|
|
|
|
builder.setTitle("Header Level");
|
|
|
|
|
builder.setItems(items, new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog, int item) {
|
|
|
|
|
// item index maps to level: 0->1, 1->2, ..., 5->6, 6->0 (Normal)
|
|
|
|
|
int level = (item == 6) ? 0 : (item + 1);
|
|
|
|
|
RichTextHelper.applyHeading(mNoteEditor, level);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_list).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyBullet(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_quote).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyQuote(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_code).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.applyCode(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_link).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.insertLink(NoteEditActivity.this, mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_divider).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) { RichTextHelper.insertDivider(mNoteEditor); }
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_color_text).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
final CharSequence[] items = {"Black", "Red", "Blue"};
|
|
|
|
|
final int[] colors = {android.graphics.Color.BLACK, android.graphics.Color.RED, android.graphics.Color.BLUE};
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(NoteEditActivity.this);
|
|
|
|
|
builder.setTitle("Text Color");
|
|
|
|
|
builder.setItems(items, new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog, int item) {
|
|
|
|
|
RichTextHelper.applyColor(mNoteEditor, colors[item], false);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
findViewById(R.id.btn_color_fill).setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
final CharSequence[] items = {"None", "Yellow", "Green", "Cyan"};
|
|
|
|
|
final int[] colors = {android.graphics.Color.TRANSPARENT, android.graphics.Color.YELLOW, android.graphics.Color.GREEN, android.graphics.Color.CYAN};
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(NoteEditActivity.this);
|
|
|
|
|
builder.setTitle("Background Color");
|
|
|
|
|
builder.setItems(items, new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog, int item) {
|
|
|
|
|
RichTextHelper.applyColor(mNoteEditor, colors[item], true);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|