更新包+readme
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "com.huangzj"
|
group = "com.huangzj"
|
||||||
version = "0.1.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// 国内镜像,失败再走中央仓库
|
// 国内镜像,失败再走中央仓库
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
package com.huangzj.protoplugin.memo;
|
package com.huangzj.protoplugin.memo;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/** 备忘录条目(字段需可被持久化组件序列化)。 */
|
/** 备忘录条目(字段需可被持久化组件序列化)。 */
|
||||||
public class MemoItem {
|
public class MemoItem {
|
||||||
|
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
|
||||||
public String id = "";
|
public String id = "";
|
||||||
public String title = "";
|
public String title = "";
|
||||||
public String content = "";
|
public String content = "";
|
||||||
@@ -23,4 +28,24 @@ public class MemoItem {
|
|||||||
}
|
}
|
||||||
return "(无标题)";
|
return "(无标题)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String displayDate() {
|
||||||
|
if (updated <= 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return DATE_FORMAT.format(new Date(updated));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String contentPreview() {
|
||||||
|
if (content == null || content.trim().isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
String trimmed = content.trim();
|
||||||
|
int newlineIdx = trimmed.indexOf('\n');
|
||||||
|
String firstLine = newlineIdx >= 0 ? trimmed.substring(0, newlineIdx) : trimmed;
|
||||||
|
if (firstLine.length() > 50) {
|
||||||
|
return firstLine.substring(0, 50) + "...";
|
||||||
|
}
|
||||||
|
return firstLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.huangzj.protoplugin.memo;
|
package com.huangzj.protoplugin.memo;
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.ui.JBColor;
|
||||||
import com.intellij.ui.components.JBList;
|
import com.intellij.ui.components.JBList;
|
||||||
import com.intellij.ui.components.JBScrollPane;
|
import com.intellij.ui.components.JBScrollPane;
|
||||||
import com.intellij.ui.components.JBTextArea;
|
import com.intellij.ui.components.JBTextArea;
|
||||||
@@ -13,13 +14,16 @@ import java.awt.Component;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.FlowLayout;
|
import java.awt.FlowLayout;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComboBox;
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
@@ -51,17 +55,25 @@ public final class MemoPanel extends JPanel {
|
|||||||
private final JPanel leftButtonBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
|
private final JPanel leftButtonBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
|
||||||
private final JPanel themeChooserBar = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
|
private final JPanel themeChooserBar = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
|
||||||
private final JPanel topStack = new JPanel(new BorderLayout());
|
private final JPanel topStack = new JPanel(new BorderLayout());
|
||||||
private final JSplitPane split;
|
private JSplitPane split;
|
||||||
private final JBScrollPane listScroll;
|
private JBScrollPane listScroll;
|
||||||
private final JBScrollPane contentScroll;
|
private JBScrollPane contentScroll;
|
||||||
private final JPanel titleBlock = new JPanel(new BorderLayout(4, 4));
|
private final JPanel titleBlock = new JPanel(new BorderLayout(4, 4));
|
||||||
private final JPanel contentBlock = new JPanel(new BorderLayout(4, 4));
|
private final JPanel contentBlock = new JPanel(new BorderLayout(4, 4));
|
||||||
private final JPanel right = new JPanel(new BorderLayout(8, 8));
|
private final JPanel right = new JPanel(new BorderLayout(8, 8));
|
||||||
|
private final JBTextField searchField = new JBTextField();
|
||||||
|
private final JLabel countLabel = new JLabel(" ");
|
||||||
|
private final JLabel modifiedLabel = new JLabel(" ");
|
||||||
|
private final JPanel leftPanel = new JPanel(new BorderLayout(0, 4));
|
||||||
|
private final JPanel searchPanel = new JPanel(new BorderLayout(4, 0));
|
||||||
|
private final JLabel searchIcon = new JLabel("\uD83D\uDD0D");
|
||||||
|
private final JPanel editorStatusBar = new JPanel(new BorderLayout());
|
||||||
|
|
||||||
private boolean loadingSelection;
|
private boolean loadingSelection;
|
||||||
private boolean themeComboSuppress;
|
private boolean themeComboSuppress;
|
||||||
private MemoUiTheme currentTheme = MemoUiTheme.IDE_DEFAULT;
|
private MemoUiTheme currentTheme = MemoUiTheme.IDE_DEFAULT;
|
||||||
private final Font defaultLabelFont;
|
private final Font defaultLabelFont;
|
||||||
|
private List<MemoItem> allItems = new ArrayList<>();
|
||||||
|
|
||||||
public MemoPanel(@NotNull Project project) {
|
public MemoPanel(@NotNull Project project) {
|
||||||
super(new BorderLayout(8, 8));
|
super(new BorderLayout(8, 8));
|
||||||
@@ -69,7 +81,25 @@ public final class MemoPanel extends JPanel {
|
|||||||
defaultLabelFont = titleLabel.getFont();
|
defaultLabelFont = titleLabel.getFont();
|
||||||
setBorder(JBUI.Borders.empty(8));
|
setBorder(JBUI.Borders.empty(8));
|
||||||
|
|
||||||
|
initToolbar();
|
||||||
|
initFlair();
|
||||||
|
initTopStack();
|
||||||
|
initSearchPanel();
|
||||||
|
initList();
|
||||||
|
initLeftPanel();
|
||||||
|
initEditor();
|
||||||
|
initSplit();
|
||||||
|
initTheme();
|
||||||
|
initListeners();
|
||||||
|
|
||||||
|
reloadListModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
leftButtonBar.setOpaque(false);
|
leftButtonBar.setOpaque(false);
|
||||||
|
newBtn.setToolTipText("新建一条备忘录");
|
||||||
|
saveBtn.setToolTipText("保存当前备忘录");
|
||||||
|
deleteBtn.setToolTipText("删除选中的备忘录");
|
||||||
leftButtonBar.add(newBtn);
|
leftButtonBar.add(newBtn);
|
||||||
leftButtonBar.add(saveBtn);
|
leftButtonBar.add(saveBtn);
|
||||||
leftButtonBar.add(deleteBtn);
|
leftButtonBar.add(deleteBtn);
|
||||||
@@ -81,21 +111,48 @@ public final class MemoPanel extends JPanel {
|
|||||||
toolbar.setOpaque(false);
|
toolbar.setOpaque(false);
|
||||||
toolbar.add(leftButtonBar, BorderLayout.WEST);
|
toolbar.add(leftButtonBar, BorderLayout.WEST);
|
||||||
toolbar.add(themeChooserBar, BorderLayout.EAST);
|
toolbar.add(themeChooserBar, BorderLayout.EAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFlair() {
|
||||||
flairLabel.setOpaque(true);
|
flairLabel.setOpaque(true);
|
||||||
flairLabel.setFont(flairLabel.getFont().deriveFont(Font.PLAIN, 12f));
|
flairLabel.setFont(flairLabel.getFont().deriveFont(Font.PLAIN, 12f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTopStack() {
|
||||||
topStack.setOpaque(false);
|
topStack.setOpaque(false);
|
||||||
topStack.add(flairLabel, BorderLayout.NORTH);
|
topStack.add(flairLabel, BorderLayout.NORTH);
|
||||||
topStack.add(toolbar, BorderLayout.CENTER);
|
topStack.add(toolbar, BorderLayout.CENTER);
|
||||||
add(topStack, BorderLayout.NORTH);
|
add(topStack, BorderLayout.NORTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSearchPanel() {
|
||||||
|
searchField.getEmptyText().setText("搜索备忘录...");
|
||||||
|
searchField.setToolTipText("输入关键字过滤备忘录标题和内容");
|
||||||
|
searchPanel.setOpaque(false);
|
||||||
|
searchPanel.add(searchIcon, BorderLayout.WEST);
|
||||||
|
searchPanel.add(searchField, BorderLayout.CENTER);
|
||||||
|
searchPanel.setBorder(JBUI.Borders.empty(0, 0, 4, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initList() {
|
||||||
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
installListRenderer();
|
installListRenderer();
|
||||||
|
|
||||||
listScroll = new JBScrollPane(list);
|
listScroll = new JBScrollPane(list);
|
||||||
listScroll.setPreferredSize(new Dimension(200, 300));
|
listScroll.setPreferredSize(new Dimension(200, 300));
|
||||||
|
|
||||||
|
countLabel.setFont(countLabel.getFont().deriveFont(Font.PLAIN, 11f));
|
||||||
|
countLabel.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||||
|
countLabel.setBorder(JBUI.Borders.empty(2, 4, 0, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initLeftPanel() {
|
||||||
|
leftPanel.setOpaque(false);
|
||||||
|
leftPanel.add(searchPanel, BorderLayout.NORTH);
|
||||||
|
leftPanel.add(listScroll, BorderLayout.CENTER);
|
||||||
|
leftPanel.add(countLabel, BorderLayout.SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initEditor() {
|
||||||
contentArea.setLineWrap(true);
|
contentArea.setLineWrap(true);
|
||||||
contentArea.setWrapStyleWord(true);
|
contentArea.setWrapStyleWord(true);
|
||||||
contentScroll = new JBScrollPane(contentArea);
|
contentScroll = new JBScrollPane(contentArea);
|
||||||
@@ -108,22 +165,34 @@ public final class MemoPanel extends JPanel {
|
|||||||
contentBlock.add(contentLabel, BorderLayout.NORTH);
|
contentBlock.add(contentLabel, BorderLayout.NORTH);
|
||||||
contentBlock.add(contentScroll, BorderLayout.CENTER);
|
contentBlock.add(contentScroll, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
modifiedLabel.setFont(modifiedLabel.getFont().deriveFont(Font.PLAIN, 11f));
|
||||||
|
modifiedLabel.setBorder(JBUI.Borders.empty(2, 0, 0, 0));
|
||||||
|
editorStatusBar.setOpaque(false);
|
||||||
|
editorStatusBar.add(modifiedLabel, BorderLayout.EAST);
|
||||||
|
|
||||||
right.setOpaque(false);
|
right.setOpaque(false);
|
||||||
right.add(titleBlock, BorderLayout.NORTH);
|
right.add(titleBlock, BorderLayout.NORTH);
|
||||||
right.add(contentBlock, BorderLayout.CENTER);
|
right.add(contentBlock, BorderLayout.CENTER);
|
||||||
|
right.add(editorStatusBar, BorderLayout.SOUTH);
|
||||||
titleField.setPreferredSize(new Dimension(200, 28));
|
titleField.setPreferredSize(new Dimension(200, 28));
|
||||||
|
}
|
||||||
|
|
||||||
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, listScroll, right);
|
private void initSplit() {
|
||||||
|
split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, right);
|
||||||
split.setResizeWeight(0.28);
|
split.setResizeWeight(0.28);
|
||||||
split.setOpaque(false);
|
split.setOpaque(false);
|
||||||
add(split, BorderLayout.CENTER);
|
add(split, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTheme() {
|
||||||
MemoUiTheme initial = MemoProjectService.getInstance(project).getMemoTheme();
|
MemoUiTheme initial = MemoProjectService.getInstance(project).getMemoTheme();
|
||||||
themeComboSuppress = true;
|
themeComboSuppress = true;
|
||||||
themeCombo.setSelectedItem(initial);
|
themeCombo.setSelectedItem(initial);
|
||||||
themeComboSuppress = false;
|
themeComboSuppress = false;
|
||||||
applyTheme(initial);
|
applyTheme(initial);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListeners() {
|
||||||
themeCombo.addActionListener(
|
themeCombo.addActionListener(
|
||||||
e -> {
|
e -> {
|
||||||
if (themeComboSuppress) {
|
if (themeComboSuppress) {
|
||||||
@@ -136,8 +205,6 @@ public final class MemoPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
reloadListModel();
|
|
||||||
|
|
||||||
list.addListSelectionListener(
|
list.addListSelectionListener(
|
||||||
new ListSelectionListener() {
|
new ListSelectionListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -172,6 +239,26 @@ public final class MemoPanel extends JPanel {
|
|||||||
refreshSelectedTitleInList();
|
refreshSelectedTitleInList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
searchField
|
||||||
|
.getDocument()
|
||||||
|
.addDocumentListener(
|
||||||
|
new javax.swing.event.DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(javax.swing.event.DocumentEvent e) {
|
||||||
|
filterList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(javax.swing.event.DocumentEvent e) {
|
||||||
|
filterList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(javax.swing.event.DocumentEvent e) {
|
||||||
|
filterList();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installListRenderer() {
|
private void installListRenderer() {
|
||||||
@@ -184,27 +271,57 @@ public final class MemoPanel extends JPanel {
|
|||||||
int index,
|
int index,
|
||||||
boolean isSelected,
|
boolean isSelected,
|
||||||
boolean cellHasFocus) {
|
boolean cellHasFocus) {
|
||||||
super.getListCellRendererComponent(
|
JLabel label = (JLabel) super.getListCellRendererComponent(
|
||||||
jList, value, index, isSelected, cellHasFocus);
|
jList, value, index, isSelected, cellHasFocus);
|
||||||
if (value instanceof MemoItem) {
|
if (value instanceof MemoItem) {
|
||||||
setText(((MemoItem) value).displayTitle());
|
MemoItem item = (MemoItem) value;
|
||||||
|
String title = escapeHtml(item.displayTitle());
|
||||||
|
String date = item.displayDate();
|
||||||
|
String preview = item.contentPreview();
|
||||||
|
|
||||||
|
StringBuilder html = new StringBuilder(128);
|
||||||
|
html.append("<html><body style='width:160px'>");
|
||||||
|
html.append("<b>").append(title).append("</b>");
|
||||||
|
if (!date.isEmpty()) {
|
||||||
|
html.append("<br><span style='font-size:10px;color:")
|
||||||
|
.append(isSelected ? "#inherit" : "#888888")
|
||||||
|
.append("'>").append(date).append("</span>");
|
||||||
|
}
|
||||||
|
if (!preview.isEmpty()) {
|
||||||
|
html.append("<br><span style='font-size:10px;color:")
|
||||||
|
.append(isSelected ? "#inherit" : "#AAAAAA")
|
||||||
|
.append("'>").append(escapeHtml(preview)).append("</span>");
|
||||||
|
}
|
||||||
|
html.append("</body></html>");
|
||||||
|
label.setText(html.toString());
|
||||||
}
|
}
|
||||||
if (currentTheme != MemoUiTheme.IDE_DEFAULT) {
|
if (currentTheme != MemoUiTheme.IDE_DEFAULT) {
|
||||||
MemoThemeSpec spec = MemoThemeSpec.forTheme(currentTheme);
|
MemoThemeSpec spec = MemoThemeSpec.forTheme(currentTheme);
|
||||||
setOpaque(true);
|
label.setOpaque(true);
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
setBackground(spec.listSelectedBg);
|
label.setBackground(spec.listSelectedBg);
|
||||||
setForeground(spec.listSelectedFg);
|
label.setForeground(spec.listSelectedFg);
|
||||||
} else {
|
} else {
|
||||||
setBackground(spec.listBg);
|
label.setBackground(spec.listBg);
|
||||||
setForeground(spec.text);
|
label.setForeground(spec.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
label.setBorder(JBUI.Borders.empty(4, 8, 4, 8));
|
||||||
|
return label;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String escapeHtml(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return text.replace("&", "&")
|
||||||
|
.replace("<", "<")
|
||||||
|
.replace(">", ">")
|
||||||
|
.replace("\"", """);
|
||||||
|
}
|
||||||
|
|
||||||
private void applyTheme(@NotNull MemoUiTheme theme) {
|
private void applyTheme(@NotNull MemoUiTheme theme) {
|
||||||
currentTheme = theme;
|
currentTheme = theme;
|
||||||
installListRenderer();
|
installListRenderer();
|
||||||
@@ -235,6 +352,9 @@ public final class MemoPanel extends JPanel {
|
|||||||
flairLabel.setBackground(panelBg);
|
flairLabel.setBackground(panelBg);
|
||||||
flairLabel.setForeground(spec.text);
|
flairLabel.setForeground(spec.text);
|
||||||
split.setBackground(panelBg);
|
split.setBackground(panelBg);
|
||||||
|
leftPanel.setBackground(panelBg);
|
||||||
|
searchPanel.setBackground(panelBg);
|
||||||
|
searchIcon.setForeground(spec.text);
|
||||||
listScroll.setBackground(panelBg);
|
listScroll.setBackground(panelBg);
|
||||||
listScroll.getViewport().setBackground(spec.listBg);
|
listScroll.getViewport().setBackground(spec.listBg);
|
||||||
list.setBackground(spec.listBg);
|
list.setBackground(spec.listBg);
|
||||||
@@ -244,12 +364,15 @@ public final class MemoPanel extends JPanel {
|
|||||||
contentBlock.setBackground(panelBg);
|
contentBlock.setBackground(panelBg);
|
||||||
titleLabel.setForeground(spec.text);
|
titleLabel.setForeground(spec.text);
|
||||||
contentLabel.setForeground(spec.text);
|
contentLabel.setForeground(spec.text);
|
||||||
|
countLabel.setForeground(spec.text);
|
||||||
|
modifiedLabel.setForeground(spec.text);
|
||||||
|
editorStatusBar.setBackground(panelBg);
|
||||||
|
|
||||||
if (theme == MemoUiTheme.CUTE_CANDY) {
|
if (theme == MemoUiTheme.CUTE_CANDY) {
|
||||||
flairLabel.setVisible(true);
|
flairLabel.setVisible(true);
|
||||||
flairLabel.setText("✨ 今天也要甜甜哒~ 选一条备忘,把想法留下来吧 💕");
|
flairLabel.setText("\u2728 今天也要甜甜哒\uFF5E 选一条备忘,把想法留下来吧 \uD83D\uDC95");
|
||||||
titleLabel.setText("📝 标题");
|
titleLabel.setText("\uD83D\uDCDD 标题");
|
||||||
contentLabel.setText("💗 正文");
|
contentLabel.setText("\uD83D\uDC97 正文");
|
||||||
titleLabel.setFont(defaultLabelFont.deriveFont(Font.BOLD, defaultLabelFont.getSize() + 1f));
|
titleLabel.setFont(defaultLabelFont.deriveFont(Font.BOLD, defaultLabelFont.getSize() + 1f));
|
||||||
contentLabel.setFont(
|
contentLabel.setFont(
|
||||||
defaultLabelFont.deriveFont(Font.BOLD, defaultLabelFont.getSize() + 1f));
|
defaultLabelFont.deriveFont(Font.BOLD, defaultLabelFont.getSize() + 1f));
|
||||||
@@ -263,6 +386,7 @@ public final class MemoPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
styleTextField(titleField, spec, softField);
|
styleTextField(titleField, spec, softField);
|
||||||
|
styleTextField(searchField, spec, softField);
|
||||||
styleTextArea(contentArea, contentScroll, spec, softField);
|
styleTextArea(contentArea, contentScroll, spec, softField);
|
||||||
|
|
||||||
styleAccentButton(newBtn, spec);
|
styleAccentButton(newBtn, spec);
|
||||||
@@ -281,6 +405,7 @@ public final class MemoPanel extends JPanel {
|
|||||||
Color editorBg = UIUtil.getTextFieldBackground();
|
Color editorBg = UIUtil.getTextFieldBackground();
|
||||||
Color fg = UIUtil.getTextFieldForeground();
|
Color fg = UIUtil.getTextFieldForeground();
|
||||||
Color listBg = UIUtil.getListBackground();
|
Color listBg = UIUtil.getListBackground();
|
||||||
|
Color labelFg = UIUtil.getLabelForeground();
|
||||||
|
|
||||||
setBackground(panelBg);
|
setBackground(panelBg);
|
||||||
topStack.setOpaque(false);
|
topStack.setOpaque(false);
|
||||||
@@ -289,12 +414,15 @@ public final class MemoPanel extends JPanel {
|
|||||||
toolbar.setOpaque(false);
|
toolbar.setOpaque(false);
|
||||||
leftButtonBar.setOpaque(false);
|
leftButtonBar.setOpaque(false);
|
||||||
themeChooserBar.setOpaque(false);
|
themeChooserBar.setOpaque(false);
|
||||||
themeChooserLabel.setForeground(UIUtil.getLabelForeground());
|
themeChooserLabel.setForeground(labelFg);
|
||||||
flairLabel.setVisible(false);
|
flairLabel.setVisible(false);
|
||||||
flairLabel.setText(" ");
|
flairLabel.setText(" ");
|
||||||
flairLabel.setBackground(panelBg);
|
flairLabel.setBackground(panelBg);
|
||||||
flairLabel.setForeground(UIUtil.getLabelForeground());
|
flairLabel.setForeground(labelFg);
|
||||||
split.setBackground(panelBg);
|
split.setBackground(panelBg);
|
||||||
|
leftPanel.setBackground(panelBg);
|
||||||
|
searchPanel.setBackground(panelBg);
|
||||||
|
searchIcon.setForeground(labelFg);
|
||||||
listScroll.setBackground(panelBg);
|
listScroll.setBackground(panelBg);
|
||||||
listScroll.getViewport().setBackground(listBg);
|
listScroll.getViewport().setBackground(listBg);
|
||||||
list.setBackground(listBg);
|
list.setBackground(listBg);
|
||||||
@@ -306,14 +434,19 @@ public final class MemoPanel extends JPanel {
|
|||||||
contentLabel.setText("内容");
|
contentLabel.setText("内容");
|
||||||
titleLabel.setFont(defaultLabelFont);
|
titleLabel.setFont(defaultLabelFont);
|
||||||
contentLabel.setFont(defaultLabelFont);
|
contentLabel.setFont(defaultLabelFont);
|
||||||
titleLabel.setForeground(UIUtil.getLabelForeground());
|
titleLabel.setForeground(labelFg);
|
||||||
contentLabel.setForeground(UIUtil.getLabelForeground());
|
contentLabel.setForeground(labelFg);
|
||||||
|
countLabel.setForeground(JBColor.GRAY);
|
||||||
|
modifiedLabel.setForeground(JBColor.GRAY);
|
||||||
|
editorStatusBar.setBackground(panelBg);
|
||||||
|
|
||||||
resetFieldLook(titleField, editorBg, fg);
|
resetFieldLook(titleField, editorBg, fg);
|
||||||
|
resetFieldLook(searchField, editorBg, fg);
|
||||||
resetFieldLook(contentArea, editorBg, fg);
|
resetFieldLook(contentArea, editorBg, fg);
|
||||||
contentScroll.getViewport().setBackground(editorBg);
|
contentScroll.getViewport().setBackground(editorBg);
|
||||||
contentArea.setCaretColor(fg);
|
contentArea.setCaretColor(fg);
|
||||||
titleField.setCaretColor(fg);
|
titleField.setCaretColor(fg);
|
||||||
|
searchField.setCaretColor(fg);
|
||||||
|
|
||||||
resetButton(newBtn);
|
resetButton(newBtn);
|
||||||
resetButton(saveBtn);
|
resetButton(saveBtn);
|
||||||
@@ -392,19 +525,68 @@ public final class MemoPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void reloadListModel() {
|
private void reloadListModel() {
|
||||||
|
allItems = MemoProjectService.getInstance(project).getItems();
|
||||||
|
filterList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterList() {
|
||||||
|
String query = searchField.getText().trim().toLowerCase();
|
||||||
listModel.clear();
|
listModel.clear();
|
||||||
List<MemoItem> items = MemoProjectService.getInstance(project).getItems();
|
|
||||||
for (MemoItem m : items) {
|
List<MemoItem> filtered;
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
filtered = allItems;
|
||||||
|
} else {
|
||||||
|
filtered = allItems.stream()
|
||||||
|
.filter(m -> matchesQuery(m, query))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MemoItem m : filtered) {
|
||||||
listModel.addElement(m);
|
listModel.addElement(m);
|
||||||
}
|
}
|
||||||
if (!items.isEmpty() && list.getSelectedIndex() < 0) {
|
|
||||||
|
updateCountLabel(filtered.size());
|
||||||
|
|
||||||
|
if (!filtered.isEmpty() && list.getSelectedIndex() < 0) {
|
||||||
list.setSelectedIndex(0);
|
list.setSelectedIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filtered.isEmpty() && !allItems.isEmpty() && !query.isEmpty()) {
|
||||||
|
clearEditor();
|
||||||
|
modifiedLabel.setText("无匹配结果");
|
||||||
|
} else if (filtered.isEmpty() && allItems.isEmpty()) {
|
||||||
|
clearEditor();
|
||||||
|
modifiedLabel.setText(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean matchesQuery(MemoItem m, String query) {
|
||||||
|
if (m.title != null && m.title.toLowerCase().contains(query)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (m.content != null && m.content.toLowerCase().contains(query)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateCountLabel(int visibleCount) {
|
||||||
|
int total = allItems.size();
|
||||||
|
if (total == 0) {
|
||||||
|
countLabel.setText(" ");
|
||||||
|
} else if (visibleCount == total) {
|
||||||
|
countLabel.setText("共 " + total + " 条");
|
||||||
|
} else {
|
||||||
|
countLabel.setText("显示 " + visibleCount + " / " + total + " 条");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createMemo() {
|
private void createMemo() {
|
||||||
MemoItem m = MemoProjectService.getInstance(project).createMemo();
|
MemoItem m = MemoProjectService.getInstance(project).createMemo();
|
||||||
listModel.addElement(m);
|
allItems = MemoProjectService.getInstance(project).getItems();
|
||||||
|
searchField.setText("");
|
||||||
|
filterList();
|
||||||
list.setSelectedValue(m, true);
|
list.setSelectedValue(m, true);
|
||||||
titleField.requestFocusInWindow();
|
titleField.requestFocusInWindow();
|
||||||
}
|
}
|
||||||
@@ -417,7 +599,9 @@ public final class MemoPanel extends JPanel {
|
|||||||
m.title = titleField.getText();
|
m.title = titleField.getText();
|
||||||
m.content = contentArea.getText();
|
m.content = contentArea.getText();
|
||||||
m.updated = System.currentTimeMillis();
|
m.updated = System.currentTimeMillis();
|
||||||
|
allItems = MemoProjectService.getInstance(project).getItems();
|
||||||
list.repaint();
|
list.repaint();
|
||||||
|
updateModifiedLabel(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteCurrent() {
|
private void deleteCurrent() {
|
||||||
@@ -425,9 +609,21 @@ public final class MemoPanel extends JPanel {
|
|||||||
if (m == null) {
|
if (m == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String itemTitle = m.displayTitle();
|
||||||
|
int result = JOptionPane.showConfirmDialog(
|
||||||
|
this,
|
||||||
|
"确定要删除「" + itemTitle + "」吗?\n此操作不可撤销。",
|
||||||
|
"确认删除",
|
||||||
|
JOptionPane.YES_NO_OPTION,
|
||||||
|
JOptionPane.WARNING_MESSAGE);
|
||||||
|
if (result != JOptionPane.YES_OPTION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int idx = list.getSelectedIndex();
|
int idx = list.getSelectedIndex();
|
||||||
MemoProjectService.getInstance(project).removeById(m.id);
|
MemoProjectService.getInstance(project).removeById(m.id);
|
||||||
|
allItems = MemoProjectService.getInstance(project).getItems();
|
||||||
listModel.removeElement(m);
|
listModel.removeElement(m);
|
||||||
|
updateCountLabel(listModel.getSize());
|
||||||
if (!listModel.isEmpty()) {
|
if (!listModel.isEmpty()) {
|
||||||
int next = Math.min(idx, listModel.getSize() - 1);
|
int next = Math.min(idx, listModel.getSize() - 1);
|
||||||
list.setSelectedIndex(Math.max(0, next));
|
list.setSelectedIndex(Math.max(0, next));
|
||||||
@@ -445,15 +641,26 @@ public final class MemoPanel extends JPanel {
|
|||||||
} else {
|
} else {
|
||||||
titleField.setText(m.title != null ? m.title : "");
|
titleField.setText(m.title != null ? m.title : "");
|
||||||
contentArea.setText(m.content != null ? m.content : "");
|
contentArea.setText(m.content != null ? m.content : "");
|
||||||
|
updateModifiedLabel(m);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
loadingSelection = false;
|
loadingSelection = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateModifiedLabel(MemoItem m) {
|
||||||
|
String date = m.displayDate();
|
||||||
|
if (!date.isEmpty()) {
|
||||||
|
modifiedLabel.setText("最后修改: " + date);
|
||||||
|
} else {
|
||||||
|
modifiedLabel.setText(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void clearEditor() {
|
private void clearEditor() {
|
||||||
titleField.setText("");
|
titleField.setText("");
|
||||||
contentArea.setText("");
|
contentArea.setText("");
|
||||||
|
modifiedLabel.setText(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshSelectedTitleInList() {
|
private void refreshSelectedTitleInList() {
|
||||||
@@ -462,4 +669,4 @@ public final class MemoPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
javax.swing.SwingUtilities.invokeLater(() -> list.repaint());
|
javax.swing.SwingUtilities.invokeLater(() -> list.repaint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<idea-plugin>
|
<idea-plugin>
|
||||||
<id>com.huangzj.protoPlugin</id>
|
<id>com.huangzj.protoPlugin</id>
|
||||||
<name>Idea-Plugin</name>
|
<name>Huangzhijun-Idea-Plugin</name>
|
||||||
<vendor email="support@example.com" url="https://example.com">huangzj</vendor>
|
<vendor email="support@example.com" url="https://example.com">huangzj</vendor>
|
||||||
|
|
||||||
<description><![CDATA[
|
<description><![CDATA[
|
||||||
|
|||||||
Reference in New Issue
Block a user