You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
git-test/src/main/java/net/micode/notes/model/WorkingNote.java

767 lines
21 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.micode.notes.model;
import android.appwidget.AppWidgetManager;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.data.Notes.TextNote;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser.NoteBgResources;
import java.util.HashSet;
/**
* 工作笔记类负责管理笔记的业务逻辑和UI状态。
* <p>
* 该类是笔记应用的业务逻辑封装类,提供了笔记的创建、加载、保存等功能,
* 负责管理笔记的UI状态和业务逻辑是UI层与数据层之间的桥梁。
* </p>
*/
public class WorkingNote {
/**
* 内部笔记数据对象
*/
private Note mNote;
/**
* 笔记ID
*/
private long mNoteId;
/**
* 笔记内容
*/
private String mContent;
/**
* 笔记模式(普通模式或清单模式)
*/
private int mMode;
/**
* 提醒日期时间戳
*/
private long mAlertDate;
/**
* 最后修改日期时间戳
*/
private long mModifiedDate;
/**
* 背景颜色ID
*/
private int mBgColorId;
/**
* 小部件ID
*/
private int mWidgetId;
/**
* 小部件类型
*/
private int mWidgetType;
/**
* 文件夹ID
*/
private long mFolderId;
/**
* 应用上下文
*/
private Context mContext;
/**
* 日志标签
*/
private static final String TAG = WorkingNote.class.getSimpleName();
/**
* 删除标记
*/
private boolean mIsDeleted;
/**
* 笔记设置变更监听器
*/
private NoteSettingChangedListener mNoteSettingStatusListener;
/**
* 数据查询投影用于从ContentResolver获取笔记数据
*/
public static final String[] DATA_PROJECTION = new String[] {
DataColumns.ID,
DataColumns.CONTENT,
DataColumns.MIME_TYPE,
DataColumns.DATA1,
DataColumns.DATA2,
DataColumns.DATA3,
DataColumns.DATA4,
};
/**
* 笔记查询投影用于从ContentResolver获取笔记基本信息
*/
public static final String[] NOTE_PROJECTION = new String[] {
NoteColumns.PARENT_ID,
NoteColumns.ALERTED_DATE,
NoteColumns.BG_COLOR_ID,
NoteColumns.WIDGET_ID,
NoteColumns.WIDGET_TYPE,
NoteColumns.MODIFIED_DATE
};
/**
* 数据查询结果列索引数据ID
*/
private static final int DATA_ID_COLUMN = 0;
/**
* 数据查询结果列索引:数据内容
*/
private static final int DATA_CONTENT_COLUMN = 1;
/**
* 数据查询结果列索引:数据类型
*/
private static final int DATA_MIME_TYPE_COLUMN = 2;
/**
* 数据查询结果列索引:数据模式
*/
private static final int DATA_MODE_COLUMN = 3;
/**
* 笔记查询结果列索引父文件夹ID
*/
private static final int NOTE_PARENT_ID_COLUMN = 0;
/**
* 笔记查询结果列索引:提醒日期
*/
private static final int NOTE_ALERTED_DATE_COLUMN = 1;
/**
* 笔记查询结果列索引背景颜色ID
*/
private static final int NOTE_BG_COLOR_ID_COLUMN = 2;
/**
* 笔记查询结果列索引小部件ID
*/
private static final int NOTE_WIDGET_ID_COLUMN = 3;
/**
* 笔记查询结果列索引:小部件类型
*/
private static final int NOTE_WIDGET_TYPE_COLUMN = 4;
/**
* 笔记查询结果列索引:修改日期
*/
private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
// New note construct
/**
* 构造新笔记的私有构造方法
* <p>
* 初始化一个新的工作笔记对象,设置默认属性值。
* </p>
*
* @param context 应用上下文
* @param folderId 笔记所属文件夹ID
*/
private WorkingNote(Context context, long folderId) {
mContext = context;
mAlertDate = 0;
mModifiedDate = System.currentTimeMillis();
mFolderId = folderId;
mNote = new Note();
mNoteId = 0;
mIsDeleted = false;
mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
}
// Existing note construct
/**
* 构造现有笔记的私有构造方法
* <p>
* 根据笔记ID初始化一个工作笔记对象并从数据库加载笔记数据。
* </p>
*
* @param context 应用上下文
* @param noteId 笔记ID
* @param folderId 笔记所属文件夹ID
*/
private WorkingNote(Context context, long noteId, long folderId) {
mContext = context;
mNoteId = noteId;
mFolderId = folderId;
mIsDeleted = false;
mNote = new Note();
loadNote();
}
/**
* 从数据库加载笔记基本信息
* <p>
* 从ContentResolver中查询并加载笔记的基本信息包括文件夹ID、背景颜色、
* 小部件信息、提醒日期和修改日期等。
* </p>
*/
private void loadNote() {
Cursor cursor = mContext.getContentResolver().query(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN);
mBgColorId = cursor.getInt(NOTE_BG_COLOR_ID_COLUMN);
mWidgetId = cursor.getInt(NOTE_WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN);
mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN);
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
}
cursor.close();
} else {
Log.e(TAG, "No note with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note with id " + mNoteId);
}
loadNoteData();
}
/**
* 从数据库加载笔记详细数据
* <p>
* 从ContentResolver中查询并加载笔记的详细数据包括文本内容和模式等。
* </p>
*/
private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] {
String.valueOf(mNoteId)
}, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String type = cursor.getString(DATA_MIME_TYPE_COLUMN);
if (DataConstants.NOTE.equals(type)) {
mContent = cursor.getString(DATA_CONTENT_COLUMN);
mMode = cursor.getInt(DATA_MODE_COLUMN);
mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN));
} else if (DataConstants.CALL_NOTE.equals(type)) {
mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN));
} else {
Log.d(TAG, "Wrong note type with type:" + type);
}
} while (cursor.moveToNext());
}
cursor.close();
} else {
Log.e(TAG, "No data with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId);
}
}
/**
* 创建空笔记的静态工厂方法
* <p>
* 创建一个新的空工作笔记对象,并设置默认属性值。
* </p>
*
* @param context 应用上下文
* @param folderId 笔记所属文件夹ID
* @param widgetId 小部件ID
* @param widgetType 小部件类型
* @param defaultBgColorId 默认背景颜色ID
* @return 创建的空工作笔记
*/
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) {
WorkingNote note = new WorkingNote(context, folderId);
note.setBgColorId(defaultBgColorId);
note.setWidgetId(widgetId);
note.setWidgetType(widgetType);
return note;
}
/**
* 加载现有笔记的静态工厂方法
* <p>
* 根据笔记ID加载一个现有的工作笔记对象。
* </p>
*
* @param context 应用上下文
* @param id 笔记ID
* @return 加载的工作笔记
*/
public static WorkingNote load(Context context, long id) {
return new WorkingNote(context, id, 0);
}
/**
* 保存笔记到数据库
* <p>
* 将当前工作笔记保存到数据库中。如果笔记不存在,则创建新笔记;
* 如果笔记已存在,则更新现有笔记。
* 如果笔记内容为空且已存在于数据库,则将其移动到回收站。
* </p>
*
* @return 保存成功返回true否则返回false
*/
public synchronized boolean saveNote() {
if (isWorthSaving()) {
if (!existInDatabase()) {
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false;
}
}
mNote.syncNote(mContext, mNoteId);
/**
* Update widget content if there exist any widget of this note
*/
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE
&& mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged();
}
return true;
} else {
// 添加删除逻辑:如果笔记内容为空且已存在于数据库,则将其移动到回收站
if (existInDatabase() && TextUtils.isEmpty(mContent)) {
HashSet<Long> ids = new HashSet<Long>();
ids.add(mNoteId);
// 无论是否在同步模式,都将空便签移动到回收站
if (!DataUtils.batchMoveToFolder(mContext.getContentResolver(), ids, Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move empty note to trash error");
}
mIsDeleted = true;
}
return false;
}
}
/**
* 检查笔记是否存在于数据库
* <p>
* 检查当前工作笔记是否已存在于数据库中。
* </p>
*
* @return 存在返回true否则返回false
*/
public boolean existInDatabase() {
return mNoteId > 0;
}
/**
* 检查笔记是否值得保存
* <p>
* 检查当前工作笔记是否值得保存到数据库中。如果笔记已删除、
* 内容为空,或者存在于数据库但未修改,则不值得保存。
* </p>
*
* @return 值得保存返回true否则返回false
*/
private boolean isWorthSaving() {
if (mIsDeleted || TextUtils.isEmpty(mContent)
|| (existInDatabase() && !mNote.isLocalModified())) {
return false;
} else {
return true;
}
}
/**
* 设置笔记设置变更监听器
* <p>
* 设置笔记设置变更监听器,用于监听笔记设置的变化,如背景颜色、
* 提醒日期、小部件等的变化。
* </p>
*
* @param l 监听器实例
*/
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
mNoteSettingStatusListener = l;
}
/**
* 设置提醒日期
* <p>
* 设置笔记的提醒日期,并通知监听器。
* </p>
*
* @param date 提醒日期时间戳
* @param set 是否设置提醒
*/
public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) {
mAlertDate = date;
mNote.setNoteValue(NoteColumns.ALERTED_DATE, String.valueOf(mAlertDate));
}
if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onClockAlertChanged(date, set);
}
}
/**
* 标记笔记是否删除
* <p>
* 标记笔记是否已删除,并通知监听器。
* </p>
*
* @param mark 删除标记
*/
public void markDeleted(boolean mark) {
mIsDeleted = mark;
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged();
}
}
/**
* 设置笔记背景颜色ID
* <p>
* 设置笔记的背景颜色ID并通知监听器。
* </p>
*
* @param id 背景颜色ID
*/
public void setBgColorId(int id) {
if (id != mBgColorId) {
mBgColorId = id;
if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onBackgroundColorChanged();
}
mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id));
}
}
/**
* 设置笔记的清单模式
* <p>
* 设置笔记的模式(普通模式或清单模式),并通知监听器。
* </p>
*
* @param mode 清单模式
*/
public void setCheckListMode(int mode) {
if (mMode != mode) {
if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode);
}
mMode = mode;
mNote.setTextData(TextNote.MODE, String.valueOf(mMode));
}
}
/**
* 设置小部件类型
* <p>
* 设置与当前笔记关联的小部件类型。
* </p>
*
* @param type 小部件类型
*/
public void setWidgetType(int type) {
if (type != mWidgetType) {
mWidgetType = type;
mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType));
}
}
/**
* 设置小部件ID
* <p>
* 设置与当前笔记关联的小部件ID。
* </p>
*
* @param id 小部件ID
*/
public void setWidgetId(int id) {
if (id != mWidgetId) {
mWidgetId = id;
mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId));
}
}
/**
* 设置笔记的基本属性值
* <p>
* 直接调用内部Note对象的setNoteValue方法用于更新笔记的基本属性。
* </p>
*
* @param key 属性键名对应NoteColumns中的字段名
* @param value 属性值
*/
public void setNoteValue(String key, String value) {
mNote.setNoteValue(key, value);
}
/**
* 设置笔记内容
* <p>
* 设置笔记的文本内容,支持富文本格式。
* </p>
*
* @param text 笔记内容支持Spannable等富文本格式
*/
public void setWorkingText(CharSequence text) {
String textStr = text.toString();
if (!TextUtils.equals(mContent, textStr)) {
mContent = textStr;
mNote.setTextData(DataColumns.CONTENT, mContent);
}
}
/**
* 设置笔记内容(字符串重载)
* <p>
* 设置笔记的文本内容。
* </p>
*
* @param text 笔记内容
*/
public void setWorkingText(String text) {
setWorkingText((CharSequence) text);
}
/**
* 将笔记转换为通话笔记
* <p>
* 将当前笔记转换为通话笔记,并设置通话相关信息,如电话号码和通话日期。
* </p>
*
* @param phoneNumber 电话号码
* @param callDate 通话日期
*/
public void convertToCallNote(String phoneNumber, long callDate) {
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER));
}
/**
* 检查笔记是否有闹钟提醒
* <p>
* 检查当前笔记是否设置了提醒日期。
* </p>
*
* @return 有提醒返回true否则返回false
*/
public boolean hasClockAlert() {
return (mAlertDate > 0 ? true : false);
}
/**
* 获取笔记内容
* <p>
* 获取当前笔记的文本内容。
* </p>
*
* @return 笔记内容
*/
public String getContent() {
return mContent;
}
/**
* 获取提醒日期
* <p>
* 获取当前笔记的提醒日期时间戳。
* </p>
*
* @return 提醒日期时间戳
*/
public long getAlertDate() {
return mAlertDate;
}
/**
* 获取修改日期
* <p>
* 获取当前笔记的最后修改日期时间戳。
* </p>
*
* @return 修改日期时间戳
*/
public long getModifiedDate() {
return mModifiedDate;
}
/**
* 获取背景颜色资源ID
* <p>
* 根据背景颜色ID获取对应的背景颜色资源ID。
* </p>
*
* @return 背景颜色资源ID
*/
public int getBgColorResId() {
return NoteBgResources.getNoteBgResource(mBgColorId);
}
/**
* 获取背景颜色ID
* <p>
* 获取当前笔记的背景颜色ID。
* </p>
*
* @return 背景颜色ID
*/
public int getBgColorId() {
return mBgColorId;
}
/**
* 获取标题背景资源ID
* <p>
* 根据背景颜色ID获取对应的标题背景资源ID。
* </p>
*
* @return 标题背景资源ID
*/
public int getTitleBgResId() {
return NoteBgResources.getNoteTitleBgResource(mBgColorId);
}
/**
* 获取清单模式
* <p>
* 获取当前笔记的模式(普通模式或清单模式)。
* </p>
*
* @return 清单模式
*/
public int getCheckListMode() {
return mMode;
}
/**
* 获取笔记ID
* <p>
* 获取当前笔记的ID。
* </p>
*
* @return 笔记ID
*/
public long getNoteId() {
return mNoteId;
}
/**
* 获取文件夹ID
* <p>
* 获取当前笔记所属的文件夹ID。
* </p>
*
* @return 文件夹ID
*/
public long getFolderId() {
return mFolderId;
}
/**
* 获取小部件ID
* <p>
* 获取与当前笔记关联的小部件ID。
* </p>
*
* @return 小部件ID
*/
public int getWidgetId() {
return mWidgetId;
}
/**
* 获取小部件类型
* <p>
* 获取与当前笔记关联的小部件类型。
* </p>
*
* @return 小部件类型
*/
public int getWidgetType() {
return mWidgetType;
}
/**
* 笔记设置变更监听器,用于监听笔记设置的变化。
* <p>
* 该接口定义了笔记设置变化的回调方法,如背景颜色、提醒日期、
* 小部件等的变化回调。
* </p>
*/
public interface NoteSettingChangedListener {
/**
* 当笔记背景颜色改变时调用
* <p>
* 当笔记的背景颜色发生变化时,会调用该方法。
* </p>
*/
void onBackgroundColorChanged();
/**
* 当笔记闹钟设置改变时调用
* <p>
* 当笔记的提醒日期发生变化时,会调用该方法。
* </p>
*
* @param date 闹钟日期时间戳
* @param set 是否设置闹钟
*/
void onClockAlertChanged(long date, boolean set);
/**
* 当笔记小部件改变时调用
* <p>
* 当与笔记关联的小部件发生变化时,会调用该方法。
* </p>
*/
void onWidgetChanged();
/**
* 当笔记在清单模式和普通模式之间切换时调用
* <p>
* 当笔记的模式在普通模式和清单模式之间切换时,会调用该方法。
* </p>
*
* @param oldMode 切换前的模式
* @param newMode 切换后的新模式
*/
void onCheckListModeChanged(int oldMode, int newMode);
}
}