diff --git a/README.md b/README.md index e3434af..06e1a9f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,17 @@ Working yet Install: [#1](https://github.com/MUedsa/TextReaderSiderTool/issues/1) +## Setting + +- 解析限制: 章节的标题如果过长可以适量增加此限制 +- 章节前缀: 章节的标题前缀 +- 章节后缀: 章节的标题后缀 +- 固定标题: 如果存在如‘前言’‘引子’等标题可以放在此列表中,使用`|`分隔 + +*以上设置修改后,清空‘正则设置’,然后点击'file'选择文件* + +- 正则设置: 匹配章节标题的正则,可自定义正则,如果不存在,会把上面的设置解析为正则 + ## note #### 【Dev】.iml something diff --git a/src/com/muedsa/intellij/textReader/Chapter.java b/src/com/muedsa/intellij/textReader/Chapter.java index 4e4b851..6004196 100644 --- a/src/com/muedsa/intellij/textReader/Chapter.java +++ b/src/com/muedsa/intellij/textReader/Chapter.java @@ -6,7 +6,9 @@ import java.io.*; import java.util.Vector; +import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; public class Chapter { private int startOffset; @@ -53,23 +55,24 @@ public String toString() { return "●" + title; } - public static Vector getChapters(TextFile textFile, String chapterPrefix, String chapterSuffix){ + public static Vector getChapters(TextFile textFile, int maxLineSize, Pattern pattern) { Vector list = new Vector<>(); int offset = 0; - try{ + try { InputStreamReader reader = new InputStreamReader(textFile.getInputStream(), textFile.getCharset()); MyBufferedReader bufferedReader = new MyBufferedReader(reader); String lineContent; Chapter previousChapter = null; while ((lineContent = bufferedReader.readLineWithCRLF()) != null){ - int startIndex = lineContent.indexOf(chapterPrefix); - int endIndex = lineContent.indexOf(chapterSuffix); - if (startIndex >= 0 && endIndex > 0 && endIndex > startIndex && endIndex - startIndex < 10 && lineContent.length()-endIndex < 50 && Pattern.matches("[0-9]+|[零一二三四五六七八九十百千万]+", lineContent.substring(startIndex + 1, endIndex))) { - if(previousChapter != null){ - previousChapter.setLength(offset - previousChapter.getStartOffset()); + if(lineContent.length() <= maxLineSize){ + Matcher matcher = pattern.matcher(lineContent); + if(matcher.find()){ + if(previousChapter != null){ + previousChapter.setLength(offset - previousChapter.getStartOffset()); + } + previousChapter = new Chapter(offset, lineContent.trim()); + list.add(previousChapter); } - previousChapter = new Chapter(offset, lineContent.trim()); - list.add(previousChapter); } offset += lineContent.getBytes(textFile.getCharset()).length; } @@ -82,6 +85,10 @@ public static Vector getChapters(TextFile textFile, String chapterPrefi e.printStackTrace(); NotificationFactory.sendNotify("加载失败", e.getLocalizedMessage(), NotificationType.WARNING); } + catch (PatternSyntaxException error){ + error.printStackTrace(); + NotificationFactory.sendNotify("正则错误", error.getLocalizedMessage(), NotificationType.ERROR); + } return list; } diff --git a/src/com/muedsa/intellij/textReader/Page.java b/src/com/muedsa/intellij/textReader/Page.java deleted file mode 100644 index 115db81..0000000 --- a/src/com/muedsa/intellij/textReader/Page.java +++ /dev/null @@ -1,65 +0,0 @@ -//package com.muedsa.intellij.textReader; -// -//import java.io.File; -//import java.io.IOException; -//import java.io.RandomAccessFile; -//import java.nio.charset.Charset; -//import java.nio.charset.StandardCharsets; -// -//public class Page { -// -// private Integer previousOffset; -// -// private Integer offset; -// -// private StringBuilder content; -// -// private Integer pageRows; -// -// private Integer pageColumns; -// -// private RandomAccessFile book; -// private Charset charset; -// -// public Page(Integer offset, Integer width, Integer height, Integer fontSize, Integer rowHeight, Charset charset, String filePath)throws IOException { -// this.previousOffset = offset; -// this.offset = offset; -// pageColumns = (int) (width / (fontSize * 1.2)); -// pageRows = (int) (height / (rowHeight * 1.1)); -// content = new StringBuilder(); -// this.charset = charset; -// book = new RandomAccessFile(new File(filePath), "r"); -// } -// -// public String nextPage(){ -// try{ -// book.seek(offset); -// previousOffset = offset; -// Integer rows = 0; -// while(rows < pageRows){ -// String lineContent = new String(book.readLine().getBytes(StandardCharsets.ISO_8859_1), charset); -// Integer tempRows = (int)Math.ceil(lineContent.length() / pageColumns); -// Integer needRows = pageRows - tempRows; -// if(needRows < tempRows){ -// rows += needRows; -// lineContent = lineContent.substring(0, pageColumns * needRows); -// }else{ -// rows += tempRows; -// } -// content.append(lineContent); -// content.append("\r\n"); -// } -// } -// catch (IOException e){ -// e.printStackTrace(); -// } -// offset += content.toString().getBytes().length; -// return content.toString(); -// } -// -// public void previousPage(){ -// offset = previousOffset; -// -// previousOffset = previousOffset - content.toString().getBytes().length; -// } -//} diff --git a/src/com/muedsa/intellij/textReader/composes/ReaderWindow.form b/src/com/muedsa/intellij/textReader/composes/ReaderWindow.form index f88992e..0d37a9d 100644 --- a/src/com/muedsa/intellij/textReader/composes/ReaderWindow.form +++ b/src/com/muedsa/intellij/textReader/composes/ReaderWindow.form @@ -3,7 +3,7 @@ - + @@ -112,12 +112,9 @@ - + - - - - + @@ -125,8 +122,8 @@ - - + + @@ -136,7 +133,7 @@ - + @@ -160,7 +157,7 @@ - + @@ -175,7 +172,7 @@ - + @@ -190,7 +187,7 @@ - + @@ -203,7 +200,7 @@ - + @@ -215,11 +212,168 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/muedsa/intellij/textReader/composes/ReaderWindow.java b/src/com/muedsa/intellij/textReader/composes/ReaderWindow.java index aeaf852..71ce494 100644 --- a/src/com/muedsa/intellij/textReader/composes/ReaderWindow.java +++ b/src/com/muedsa/intellij/textReader/composes/ReaderWindow.java @@ -16,9 +16,14 @@ import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.text.*; +import java.awt.*; import java.awt.event.*; import java.io.IOException; +import java.util.Arrays; import java.util.Vector; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; public class ReaderWindow { private JPanel readerPanel; @@ -27,11 +32,17 @@ public class ReaderWindow { private JSpinner fontSizeSpinner; private JButton previousButton; private JButton nextButton; - private JTextArea textContent; + private JTextPane textContent; private JTabbedPane tab; private JScrollPane textContentScroll; - private JTextField chapterPrefix; - private JTextField chapterSuffix; + private JTextField chapterPrefixEl; + private JTextField chapterSuffixEl; + private JTextField regexStringEl; + private JTextField fixTitleEl; + private JSpinner maxLineSizeSpinner; + private JSpinner lineSpaceSpinner; + private JSpinner firstLineIndentSpinner; + private JComboBox fontFamilyEl; private Project project; private ToolWindow toolWindow; @@ -46,46 +57,93 @@ public ReaderWindow(Project project, ToolWindow toolWindow) { new NotificationFactory(project); createUIComponents(); init(); + updateRegex(); } private void createUIComponents(){ - SpinnerModel spinnerModel = new SpinnerNumberModel(12, 0, 100, 1); + //字体 + String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); - fontSizeSpinner.setModel(spinnerModel); + DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel<>(fontFamilyNames); + fontFamilyEl.setModel(comboBoxModel); + fontFamilyEl.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED){ + updateFontFamily(); + } + } + }); + String currentFontFamily = textContent.getFont().getFamily(); + int index = Arrays.binarySearch(fontFamilyNames, currentFontFamily); + if(index > 0){ + fontFamilyEl.setSelectedIndex(index); + } + //字体大小 + SpinnerModel fontSizeSpinnerModel = new SpinnerNumberModel(12, 0, 100, 1); + fontSizeSpinner.setModel(fontSizeSpinnerModel); fontSizeSpinner.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { - float fontSize = (float)((int)fontSizeSpinner.getValue()); - textContent.setFont(textContent.getFont().deriveFont(fontSize)); + updateFontSize(); + } + }); + //字体行间距 + SpinnerModel lineSpaceSpinnerModel = new SpinnerNumberModel(0.5, 0, 2.5, 0.1); + lineSpaceSpinner.setModel(lineSpaceSpinnerModel); + lineSpaceSpinner.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updateLineSpace(); + } + }); + //首行缩进 + SpinnerModel firstLineIndentSpinnerModel = new SpinnerNumberModel(0, 0, 4, 1); + firstLineIndentSpinner.setModel(firstLineIndentSpinnerModel); + firstLineIndentSpinner.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + updateFirstLineIndent(); } }); + //标题解析最大字数限制设置 + SpinnerModel maxLineSizeSpinnerModel = new SpinnerNumberModel(20, 1, 200, 1); + maxLineSizeSpinner.setModel(maxLineSizeSpinnerModel); + + //添加文件 fileButton.addActionListener(new ActionListener() { - /** - * Invoked when an action occurs. - * - * @param e - */ @Override public void actionPerformed(ActionEvent e) { VirtualFile file = FileChooser.chooseFile(new TextFileChooserDescriptor(), project, null); if(file != null){ try { + updateRegex(); + Pattern pattern = Pattern.compile(regexStringEl.getText().trim()); textFile = new TextFile(file); - Vector list = Chapter.getChapters(textFile, chapterPrefix.getText(), chapterSuffix.getText()); + Vector list = Chapter.getChapters(textFile, (int)maxLineSizeSpinner.getValue(), pattern); titleList.setListData(list); textReaderStateService.setFilePath(textFile.getFilePath()); textReaderStateService.setChapters(list); } + catch (PatternSyntaxException error){ + error.printStackTrace(); + NotificationFactory.sendNotify("正则错误", error.getLocalizedMessage(), NotificationType.ERROR); + } catch (IOException error){ error.printStackTrace(); NotificationFactory.sendNotify("文件读取错误", error.getLocalizedMessage(), NotificationType.ERROR); } + catch (Exception error){ + error.printStackTrace(); + NotificationFactory.sendNotify("其他错误", error.getLocalizedMessage(), NotificationType.ERROR); + } } } }); + //点击章节 titleList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -96,6 +154,7 @@ public void mouseClicked(MouseEvent e) { } }); + //下一章 nextButton.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -109,6 +168,7 @@ public void mouseClicked(MouseEvent e) { }); + //上一章 previousButton.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -122,6 +182,7 @@ public void mouseClicked(MouseEvent e) { } private void init(){ + //持久化配置初始化 textReaderStateService = ServiceManager.getService(TextReaderStateService.class); if(textReaderStateService != null && textReaderStateService.getFilePath() != null && textReaderStateService.getChapters() != null){ try { @@ -133,6 +194,62 @@ private void init(){ NotificationFactory.sendNotify("持久化文件加载错误", error.getLocalizedMessage(), NotificationType.ERROR); } } + + //字体风格初始化 + updateFontSize(); + updateLineSpace(); + updateFirstLineIndent(); + } + + private void updateRegex(){ + StringBuilder regexString = new StringBuilder(regexStringEl.getText().trim()); + if(regexString.length() == 0){ + //章节 + regexString = new StringBuilder(chapterPrefixEl.getText().trim()); + regexString.append("[0-9零一二三四五六七八九十百千万]+"); + regexString.append(chapterSuffixEl.getText().trim()); + + //固定标题 + String[] fixTitles = fixTitleEl.getText().trim().split("\\|"); + for(String fixTitle : fixTitles){ + if(fixTitle.length() > 0){ + regexString.append("|\\s*").append(fixTitle).append("\\s*"); + } + } + regexStringEl.setText(regexString.toString()); + } + } + + private void updateFontFamily(){ + String fontFamily = (String)fontFamilyEl.getSelectedItem(); + StyledDocument styledDocument = textContent.getStyledDocument(); + SimpleAttributeSet attributes = new SimpleAttributeSet(); + StyleConstants.setFontFamily(attributes, fontFamily); + styledDocument.setParagraphAttributes(0, styledDocument.getLength(), attributes, false); + } + + private void updateFontSize(){ + int fontSize = (int)fontSizeSpinner.getValue(); + StyledDocument styledDocument = textContent.getStyledDocument(); + SimpleAttributeSet attributes = new SimpleAttributeSet(); + StyleConstants.setFontSize(attributes, fontSize); + styledDocument.setParagraphAttributes(0, styledDocument.getLength(), attributes, false); + } + + private void updateLineSpace(){ + float lineSpace = ((Double)lineSpaceSpinner.getValue()).floatValue(); + StyledDocument styledDocument = textContent.getStyledDocument(); + SimpleAttributeSet attributes = new SimpleAttributeSet(); + StyleConstants.setLineSpacing(attributes, lineSpace); + styledDocument.setParagraphAttributes(0, styledDocument.getLength(), attributes, false); + } + + private void updateFirstLineIndent(){ + float firstLineIndent = ((Integer)firstLineIndentSpinner.getValue()) * ((Integer)fontSizeSpinner.getValue()).floatValue(); + StyledDocument styledDocument = textContent.getStyledDocument(); + SimpleAttributeSet attributes = new SimpleAttributeSet(); + StyleConstants.setFirstLineIndent(attributes, firstLineIndent); + styledDocument.setParagraphAttributes(0, styledDocument.getLength(), attributes, false); } public JPanel getContent(){