diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/AboutNotepadDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/AboutNotepadDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..e5a34ffb930cec9e14301b0d08d908387b870f6b --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/AboutNotepadDialog.java" @@ -0,0 +1,75 @@ +package king.notepad.view; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import king.notepad.actionlistener.ActionListenerFactory; + +//“关于小米便签” +public class AboutNotepadDialog extends JDialog { + + public AboutNotepadDialog(NotepadFrame frame){ + super(frame, "关于 \"小米便签\""); + add(createTitle(), BorderLayout.NORTH); + add(createMainBody()); + add(createEnterButton(), BorderLayout.SOUTH); + //设置对话框在Frame正中 + int frameX = (int)frame.getBounds().getX(); + int frameY = (int)frame.getBounds().getY(); + setBounds(frameX+80, frameY+150, 0, 0); + pack(); + setVisible(true); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setResizable(false); + } + + + + //确定按钮 + private JPanel createEnterButton(){ + JButton button = new JButton("确定"); + button.addActionListener(ActionListenerFactory.getActionListener(this, "确定")); + JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + panel.add(button); + return panel; + } + + //正文 + private JPanel createMainBody(){ + String text = "" + + "作者:我的团队" + "
" + + "邮箱:2321139456@qq.com" + "
" + + "版本:0.1 beta" + "
" + + "由于时间关系,本产品只是最原始版本以后有机会再完善。"+ "
" + + "功能更新日志:" + "
" + +" ●实现内容查找"+"
" + +" ●实现笔记创建、存储、打开"+"
" + +" ●字体修改等"+"
" + + "2019/10/28 " + " 实现类似 Win 10 记事本(小米便签) " + "
" + + ""; + JLabel label = new JLabel(text); + label.setFont(new Font("微软雅黑", Font.PLAIN, 13)); + label.setBorder(BorderFactory.createEmptyBorder(10, 10, 40, 10)); + JPanel panel = new JPanel(); + panel.add(label); + panel.setBorder(BorderFactory.createEtchedBorder()); + return panel; + } + + // 标题栏 + private JPanel createTitle(){ + JLabel label = new JLabel("小米便签"); + label.setFont(new Font("微软雅黑", Font.BOLD, 30)); + JPanel panel = new JPanel(); + panel.add(label); + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + return panel; + } +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/FontDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/FontDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..971e23b63db3ac543434645817f2e90529fb6ca1 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/FontDialog.java" @@ -0,0 +1,230 @@ +package king.notepad.view; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.awt.GridLayout; +import java.awt.Rectangle; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; + +import king.notepad.actionlistener.ActionListenerFactory; +import king.notepad.itemlistener.ItemListenerFactory; +import king.notepad.Fontlistselectionlistener.ListSelectionListenerFactory; + +//“字体”对话框 +public class FontDialog extends JDialog { + //获取系统字体 + private String[] font = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + //加入列表框 + private JList fontList = new JList(font); + private JTextField fontText = new JTextField(10); + //字形 + public static final String[] fontStyle = {"常规", "粗体", "倾斜", "粗偏斜体"}; //对应的字形常量值分别为0, 1, 2, 3 + private JList fontStyleList = new JList(fontStyle); + private JTextField fontStyleText = new JTextField(10); + //字体大小 + private Integer[] fontSize = {8, 9, 10,11,12,14,16,18,20,22,24,26,28,36,48,72}; + private JList fontSizeList = new JList(fontSize); + private JTextField fontSizeText = new JTextField(10); + //示例框 + private JLabel exampleLabel = new JLabel("AaBbYyZz"); + //脚本 + private String[] scenario = {"西欧语言", "中文 GB2312"}; + private String[] example = {"AaBbYyZz", "习定凝神,惩忿窒欲"}; + private JComboBox scenarioList = new JComboBox(scenario); + private NotepadFrame frame; + + public FontDialog(NotepadFrame frame){ + super(frame, "字体"); + this.frame = frame; + //设置对话框在Frame正中 + int frameX = (int)frame.getBounds().getX(); + int frameY = (int)frame.getBounds().getY(); + setBounds(frameX+40, frameY+80, 0, 0); + //最上面的面板 + JPanel up = new JPanel(); + up.add(createFontList()); + up.add(createFontStyleList()); + up.add(createFontSizeList()); + add(up, BorderLayout.NORTH); + //下方面板 + JPanel center = new JPanel(); + center.add(createExamplePanel()); + center.add(createScenarioPanel()); + //右下 + JPanel downRight = new JPanel(new GridLayout(2, 1, 0, 10)); + JButton ensure = new JButton("确定"); + ensure.addActionListener(ActionListenerFactory.getActionListener(this, "确定")); + JButton cancel = new JButton("取消"); + cancel.addActionListener(ActionListenerFactory.getActionListener(this, "取消")); + downRight.add(ensure); + downRight.add(cancel); + center.add(downRight); + add(center); + pack(); + setVisible(true); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setResizable(false); + } + + // 设置对应的TextArea的字体 + public void setTextAreaFont(Font font){ + frame.setTextAreaFont(font); + } + + //根据示例ComboBox的选择值返回示例文本 + public String getScenarioListValue(){ + String select = (String)this.scenarioList.getSelectedItem(); + if("西欧语言".equals(select)){ + return example[0]; + }else{ + return example[1]; + } + } + + // 设置示例JLabel的文字 + public void setExampleText(String text){ + this.exampleLabel.setText(text); + } + + // 设置示例JLabel的字体 + public void setExampleFont(Font font){ + this.exampleLabel.setFont(font); + } + + //设置字体大小List上方的文本框的值 + public void setFontSizeTextField(int n){ + this.fontSizeText.setText(String.valueOf(n)); + } + + //获取字体大小列表框的选择值 + public int getFontSizeListValue(){ + return (Integer)this.fontSizeList.getSelectedValue(); + } + + // 设置字形List上方的文本框的值 + public void setFontStyleTextField(String text){ + this.fontStyleText.setText(text); + } + + //获取字形列表框的选中值,将它转化成字形常量值 + public int getFontStyleListValue(){ + String fontStyleName = (String)this.fontStyleList.getSelectedValue(); + for(int i = 0; i < fontStyle.length; i++){ + if(fontStyle[i].equals(fontStyleName)) return i; + } + return 0; + } + + //设置字体JList上方的文本框的值 + public void setFontTextField(String text){ + this.fontText.setText(text); + } + + //获取字体列表框的选择值 + public String getFontListValue(){ + return (String)this.fontList.getSelectedValue(); + } + + // 示例框用的脚本 + private JPanel createScenarioPanel(){ + JLabel label = new JLabel("脚本:"); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(label, BorderLayout.NORTH); + panel.add(scenarioList); + scenarioList.addItemListener(ItemListenerFactory.getListener(this, "脚本")); + panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10)); + return panel; + } + + // 示例框 + private JPanel createExamplePanel(){ + exampleLabel.setFont(frame.getTextAreaFont()); + exampleLabel.setHorizontalAlignment(SwingConstants.CENTER); + exampleLabel.setPreferredSize(new Dimension(200,40)); +// exampleLabel.setBorder(BorderFactory.createEmptyBorder(10, 40, 10, 40)); + JPanel panel = new JPanel(); + panel.add(exampleLabel); + panel.setBorder(BorderFactory.createTitledBorder("示例")); +// panel.setBorder(BorderFactory.createTitledBorder( +// BorderFactory.createEmptyBorder(10, 10, 10, 10), "示例")); + return panel; + } + + //字体大小列表框 + private JPanel createFontSizeList(){ + fontSizeList.setVisibleRowCount(7); + fontSizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + JScrollPane jsp = new JScrollPane(fontSizeList); + //当前使用的字形 + int fontSize = frame.getTextAreaFont().getSize(); + fontSizeList.setSelectedValue(fontSize, true); + fontSizeText.setText(String.valueOf(fontSizeList.getSelectedValue())); + fontSizeList.addListSelectionListener(ListSelectionListenerFactory.getListener(this, "大小")); + JLabel label = new JLabel("大小:"); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(label, BorderLayout.NORTH); + panel.add(this.fontSizeText); + panel.add(jsp, BorderLayout.SOUTH); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return panel; + } + + //字形列表框 + private JPanel createFontStyleList(){ + fontStyleList.setVisibleRowCount(7); + fontStyleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + JScrollPane jsp = new JScrollPane(fontStyleList); + //当前使用的字形 + int fontStyleConst = frame.getTextAreaFont().getStyle(); + fontStyleList.setSelectedValue(fontStyle[fontStyleConst], true); + fontStyleText.setText((String)fontStyleList.getSelectedValue()); + fontStyleList.addListSelectionListener(ListSelectionListenerFactory.getListener(this, "字形")); + JLabel label = new JLabel("字形:"); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(label, BorderLayout.NORTH); + panel.add(this.fontStyleText); + panel.add(jsp, BorderLayout.SOUTH); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return panel; + } + + // 字体列表框 + private JPanel createFontList(){ +// 设置自定义文本渲染器,使每条列表显示它本身的字体 +// 如果用此方法,则打开字体对话框时会卡几秒,故先取消 +// fontList.setCellRenderer(new MyCellRenderer()); + fontList.setVisibleRowCount(7); + JScrollPane jsp = new JScrollPane(fontList); //必须写在scrollRectToVisible之前才能使后者生效 + fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + //当前使用的字体 + String fontName = frame.getTextAreaFont().getFamily(); //文本域使用的当前字体 + fontList.setSelectedValue(fontName, true); //选中字体 + fontText.setText((String)fontList.getSelectedValue()); + int index = fontList.getSelectedIndex(); //返回选中的索引 + Rectangle rect = fontList.getCellBounds(index, index); + fontList.scrollRectToVisible(rect); //选中行显示在第一行 + fontList.addListSelectionListener(ListSelectionListenerFactory.getListener(this, "字体")); + //放入滚动条 + //列表框上方的标签和输入框 + JLabel label = new JLabel("字体:"); + JPanel panel = new JPanel(new BorderLayout()); + panel.add(label, BorderLayout.NORTH); + panel.add(fontText); + panel.add(jsp, BorderLayout.SOUTH); + panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return panel; + } +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/GotoDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/GotoDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..9f199251424eb2aa2c7a8ac0372be1884c67166b --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/GotoDialog.java" @@ -0,0 +1,106 @@ +package king.notepad.view; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import king.notepad.actionlistener.ActionListenerFactory; +import king.notepad.keylistener.KeyListenerFactory; + +//“转到”输入框,只此一例,故不使用工厂模式 +public class GotoDialog extends JDialog { + private JTextField input = new JTextField(30); + private NotepadFrame frame; + + public GotoDialog(NotepadFrame frame){ + super(frame, "转到指定行"); + this.frame = frame; + JPanel all = new JPanel(new BorderLayout()); + JLabel label = new JLabel("行号:"); + JPanel up = new JPanel(new FlowLayout(FlowLayout.LEFT)); + up.add(label); + all.add(up, BorderLayout.NORTH); + all.add(input); + input.addKeyListener(KeyListenerFactory.getKeyListener("仅输入数字")); + JButton gotoButton = new JButton("转到"); + gotoButton.addActionListener(ActionListenerFactory.getActionListener(this, "转到")); + JButton cancelButton = new JButton("取消"); + cancelButton.addActionListener(ActionListenerFactory.getActionListener(this, "取消")); + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); + buttonPanel.add(gotoButton); + buttonPanel.add(cancelButton); + all.add(buttonPanel, BorderLayout.SOUTH); + all.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + add(all); + //设置对话框在Frame正中 + int frameX = (int)frame.getBounds().getX(); + int frameY = (int)frame.getBounds().getY(); + setBounds(frameX+80, frameY+150, 0, 0); + pack(); + setVisible(true); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setResizable(false); + } + + //获取对应的记事本实例 + public NotepadFrame getNotepadFrame(){ + return frame; + } + + //设置行数 + public void setLineNum(int n){ + this.input.setText(String.valueOf(n)); + this.input.selectAll(); + } + + //获取行数,前面已经通过KeyListener指定只能输入数字,故直接转成数字 + public int getLineNum(){ + return Integer.valueOf(input.getText()); + } + + //获取文本域的全部文本 + public String getWholeText() { + return frame.getWholeText(); + } + + // 获取文本域的总行数 + public int getLineCount(){ + return frame.getLineCount(); + } + + // 设置文本域中光标的位置 + public void setCaretPosition(int index){ + frame.setCaretPosition(index); + } + + //以下为调试用 +// public GotoDialog(){ +// JPanel all = new JPanel(new BorderLayout()); +// JLabel label = new JLabel("行号:"); +// JPanel up = new JPanel(new FlowLayout(FlowLayout.LEFT)); +// up.add(label); +// all.add(up, BorderLayout.NORTH); +// all.add(input); +// JButton gotoButton = new JButton("转到"); +// JButton cancelButton = new JButton("取消"); +// JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); +// buttonPanel.add(gotoButton); +// buttonPanel.add(cancelButton); +// all.add(buttonPanel, BorderLayout.SOUTH); +// all.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); +// add(all); +// pack(); +// setVisible(true); +// setDefaultCloseOperation(DISPOSE_ON_CLOSE); +// setResizable(false); +// } +// public static void main(String[] args){ +// new GotoDialog(); +// } +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/Main.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/Main.java" new file mode 100644 index 0000000000000000000000000000000000000000..b664342529ebc3c3d91e8aa8601868cb87a26f9d --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/Main.java" @@ -0,0 +1,7 @@ +package king.notepad.view; + +public class Main { + public static void main(String[] args){ + new NotepadFrame(); + } +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/MyCellRenderer.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/MyCellRenderer.java" new file mode 100644 index 0000000000000000000000000000000000000000..3d09c37502b9e981fa5ae73fbe45c4ab9cbfea87 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/MyCellRenderer.java" @@ -0,0 +1,31 @@ +package king.notepad.view; + +import java.awt.Component; +import java.awt.Font; + +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + +//自定义JList使用的单元渲染器 +public class MyCellRenderer extends JLabel implements ListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, + String item, int index, boolean isSelected, boolean cellHasFocus) { + setText(item); + if(isSelected){ + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + }else{ + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + setEnabled(list.isEnabled()); + Font font = list.getFont(); + setFont(new Font(item, font.getStyle(), font.getSize())); + setOpaque(true); //此组件不透明 + return this; + } + +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/NotepadFrame.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/NotepadFrame.java" new file mode 100644 index 0000000000000000000000000000000000000000..af41e1e0ceeb0843321358ec64050697a8ee1dc0 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/NotepadFrame.java" @@ -0,0 +1,325 @@ +package king.notepad.view; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.Toolkit; +import java.io.File; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import javax.swing.*; + +import king.notepad.actionlistener.ActionListenerFactory; +import king.notepad.caretlistener.CaretListenerFactory; +import king.notepad.documentlistener.DocumentListenerFactory; +import king.notepad.windowlistener.WindowFactory; + + +public class NotepadFrame extends JFrame { + public static final String PROGRAM_NAME = "-Windows小米便签"; // 窗口标题的后半部分 + private String tmpText = ""; //临时存档 + private static Map openedFiles = new HashMap();//仅保存已经打开的文件 + private JTextArea textArea = new JTextArea(); + private JPanel statePanel = new JPanel(); + private File file; //用来保存textArea的文件 + private Font menuFont = new Font("微软雅黑", Font.PLAIN, 13); //菜单默认字体 + private Font defaultTextAreaFont = new Font("微软雅黑", Font.PLAIN, 14); //文本区默认字体 + private boolean hasChangedNOSave = false; //文本是否有未保存的更改 + private JLabel stateLabel = new JLabel(); + private JCheckBoxMenuItem stateMenuItem; //“状态栏”菜单项 + private JMenuItem repealMenuItem; //“撤消”菜单项 + private JMenuItem gotoMenuItem;//“转到”菜单项 + private LinkedList repealList = new LinkedList(); // 保存每次操作的文本,用于撤消 + + //构造器 + public NotepadFrame(){ + super("无标题"+PROGRAM_NAME); + try{ + //LookAndFeel lookAndFeel = UIManager.getLookAndFeel(); + + +// UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); //默认LAF + UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); +// UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); //比老式Windows更老 +// UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); //与Windows一样 +// UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");//老式Windows +// UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); //当前系统风格 +// UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());//跨平台的Java风格,也就是默认LAF +// UIManager.setLookAndFeel("com.apple.mrj.swing.MacLookAndFeel"); //网上找的,实测报错 + } + catch (Exception e){ + e.printStackTrace(); + } + this.setJMenuBar(this.createMenuBar()); + this.add(this.createTextArea()); + this.add(this.createStatePanel(), BorderLayout.SOUTH); + this.setPreferredSize(new Dimension(600, 600)); + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //改用重写的WindowListener + this.addWindowListener(WindowFactory.getWindowListener(this, "Closing")); + this.pack(); + //设置窗口居中 + int screenSizeX = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth(); + int screenSizeY = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight(); + int frameSizeX = (int)this.getSize().getWidth(); + int frameSizeY = (int)this.getSize().getHeight(); + this.setBounds((screenSizeX-frameSizeX)/2, (screenSizeY-frameSizeY)/2, frameSizeX, frameSizeY); + this.setVisible(true); + } + + //创建菜单栏,放到JPanel里返回 + private JMenuBar createMenuBar(){ + //菜单栏 + String[] menuArr = {"文件(F)", "编辑(E)", "格式(O)", "查看(V)", "帮助(H)"}; + //菜单项 + String[][] menuItemArr = { + {"新建(N)", "打开(O)...", "保存(S)", "另存为(A)...", "-", "退出(X)"}, + {"撤消(U)", "-", "剪切(T)", "复制(C)", "粘贴(P)", "删除(L)", "-", + "查找(F)...", "替换(R)...", "转到(G)...", "-", "全选(A)", "时间/日期(D)"}, + {"自动换行(W)", "字体(F)..."}, + {"状态栏(S)"}, + {"查看帮助(H)", "-", "关于小米便签(A)"}}; + //组合菜单栏 + JMenuBar menuBar = new JMenuBar(); + for(int i = 0; i < menuArr.length; i++){ + JMenu menu = new JMenu(menuArr[i]); + menu.setFont(menuFont); + for(int j = 0; j < menuItemArr[i].length; j++){ + //如果是-,添加分隔符 + if (menuItemArr[i][j].equals("-")){ + menu.addSeparator(); + } + else if (menuItemArr[i][j].equals("自动换行(W)") || menuItemArr[i][j].equals("状态栏(S)") ){ //自动换行要用JCheckBoxMenuItem + //JCheckBoxMenuItem默认未选中 + JCheckBoxMenuItem checkboxMenuItem = new JCheckBoxMenuItem(menuItemArr[i][j]); + if (menuItemArr[i][j].equals("状态栏(S)")) stateMenuItem = checkboxMenuItem; + checkboxMenuItem.addActionListener(ActionListenerFactory.getActionListener(this, menuItemArr[i][j])); + checkboxMenuItem.setFont(menuFont); + menu.add(checkboxMenuItem); + } + else{ + JMenuItem menuItem = new JMenuItem(menuItemArr[i][j]); + menuItem.addActionListener(ActionListenerFactory.getActionListener(this, menuItemArr[i][j])); + //“撤消”菜单初始为不可点击 + if(menuItem.getText().equals("撤消(U)")){ + this.repealMenuItem = menuItem; + menuItem.setEnabled(false); + }else if (menuItemArr[i][j].equals("查看帮助(H)")){ + menuItem.setEnabled(false); + }else if(menuItemArr[i][j].equals("转到(G)...")){ + this.gotoMenuItem = menuItem; + } + menuItem.setFont(menuFont); + menu.add(menuItem); + //页面设置和打印功能取消,菜单项改为灰色 + } + } + if (!menu.getText().equals("自动换行(W)")){ + menuBar.add(menu); + } + } + return menuBar; + } + + //创建底部的状态栏 + private JPanel createStatePanel(){ + this.statePanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); + this.statePanel.add(this.stateLabel); + this.stateLabel.setFont(this.defaultTextAreaFont); + this.setStateLabel(1,1); + //默认不可见 + statePanel.setVisible(false); + return statePanel; + } + + //创建加了滚动条的JTextArea + private JScrollPane createTextArea(){ + //添加监听器 + textArea.getDocument().addDocumentListener( + DocumentListenerFactory.getDocumentListener(this, "NotepadFrameTextArea")); + textArea.addCaretListener(CaretListenerFactory.getCaretListener(this)); + //默认不自动换行 + textArea.setLineWrap(false); + //如果要换行,单词边界处换行 + textArea.setWrapStyleWord(true); + //字体,默认使用menuFont + textArea.setFont(this.defaultTextAreaFont); + JScrollPane scrollPane = new JScrollPane(textArea); + return scrollPane; + } + + // 选中文本 + public void select(int start, int end){ + textArea.select(start, end); + } + + // 设置文本域中光标的位置 + public void setCaretPosition(int index){ + textArea.setCaretPosition(index); + } + + // 获取文本域的总行数 + public int getLineCount(){ + return textArea.getLineCount(); + } + + // 设置文本域的文字 + public void setTextAreaFont(Font font){ + textArea.setFont(font); + } + + // 获取文本域的字体 + public Font getTextAreaFont(){ + return textArea.getFont(); + } + + // 改变文本域自动换行的状态 + public void setLineWrap(boolean b){ + textArea.setLineWrap(b); + } + + // 获取文本域自动换行的状态 + public boolean getLineWrap(){ + return textArea.getLineWrap(); + } + + //获取光标开始的位置 + public int getSelectionStart(){ + return textArea.getSelectionStart(); + } + + // 获取文本域光标结束的位置 + public int getSelectionEnd(){ + return textArea.getSelectionEnd(); + } + + //往文本域内追加文本 + public void append(String text){ + textArea.append(text); + } + + // 获取文本域内的全部文本 + public String getWholeText(){ + return textArea.getText(); + } + + // 设置文本域的文本 + public void setText(String text){ + textArea.setText(text); + } + + // 获取选中文本 + public String getSelectedText(){ + return textArea.getSelectedText(); + } + + // 全选 + public void selectAll(){ + textArea.selectAll(); + } + + // 替换选中文本 + public void replaceSelection(String text){ + textArea.replaceSelection(text); + } + + //设置底部状态栏的行数 + public void setStateLabel(int row, int column){ + this.stateLabel.setText("第" + row + "行,第" + column + "列 "); + } + + // 设置状态栏的可见性 + public void setStatePanelVisible(boolean b){ + statePanel.setVisible(b); + } + + // 获取状态栏的可见性状态 + public boolean getStatePanelVisible(){ + return statePanel.isVisible(); + } + + //设置保存的文件 + //改变窗口名 + //存入已打开文件Map + public void setFile(File file){ + this.file = file; + this.setTitle(file.getName() + PROGRAM_NAME); + openedFiles.put(file, this); + } + + //获取textArea保存的文件 + public File getFile(){ + return this.file; + } + + //存取tmpText + public void setTmpText(String txt){ + this.tmpText = txt; + } + public String getTmpText(){ + return this.tmpText; + } + + //设置JTextArea的未保存更改标记 + public void setHasChangedNoSave(boolean b){ + this.hasChangedNOSave = b; + } + + //获取JTextArea的未保存更改标记 + public boolean getHasChangedNoSave(){ + return this.hasChangedNOSave; + } + + //设置“状态栏”、“转到”菜单的可用性 + public void setStateMenuItemEnabled(boolean b){ + this.stateMenuItem.setEnabled(b); + this.gotoMenuItem.setEnabled(b); + } + + //获取“状态栏”菜单的选中情况 + public boolean getStatePanelMenuItem(){ + return this.stateMenuItem.getState(); + } + + //设置“撤消”菜单的可见性 + public void setRepealMenuItemEnabled(boolean b){ + this.repealMenuItem.setEnabled(b); + } + + // 获取保存的文本的栈的大小 + public int getStackSize(){ + return repealList.size(); + } + + // 将内容从栈中取出 + public String popFromStack(){ + if (repealList.size() > 1){ + return repealList.pop(); + } + return null; + } + + // 将内容推入保存文件的栈 + public void pushToStack(String text){ + repealList.push(text); + } + + //根据File获取NotepadFrame,由于是操作类相关的属性,用静态方法 + public static NotepadFrame getNotepadFrame(File file){ + return openedFiles.get(file); + } + + //删除openedFiles中指定的File,由于这是类相关的属性,改用静态方法 + public static void deleteOpenedFile(File file){ + openedFiles.remove(file); + } + + + //判断某File是否已经打开,类相关属性,用静态方法 + public static boolean isFileOpened(File file){ + return openedFiles.containsKey(file); + } + +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..d636cc10d736ca40db27d6aef70bb7e963e76100 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindDialog.java" @@ -0,0 +1,194 @@ +package king.notepad.view.findreplacedialog; + +import java.awt.BorderLayout; +import java.awt.GridLayout; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.border.TitledBorder; + +import king.notepad.actionlistener.ActionListenerFactory; +import king.notepad.documentlistener.DocumentListenerFactory; +import king.notepad.view.NotepadFrame; +/** + * “查找”对话框 + * 分为左右两个JPanel,左侧JPanel分为上下两部分 + * 每个NotepadFrame对应的JPanel都不同,所以此处不使用全静态方法 + * 一律为非模式 + */ +public class FindDialog extends MyDialog{ + private JTextField text = new JTextField(10); // 参数设置的是最小宽度 + private JCheckBox caseCheckBox = new JCheckBox("区分大小写(C)"); + private JRadioButton up = new JRadioButton("向上(U)"); + private JRadioButton down = new JRadioButton("向下(D)", true); + private NotepadFrame frame; + private JButton findNext; + + public FindDialog(NotepadFrame frame){ + super(frame, "查找"); + this.frame = frame; + add(createLeftPanel(), BorderLayout.WEST); + add(createRightPanel()); + pack(); + if (text.getText() != null + && text.getText().length() > 0) setButtonEnable(true); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setVisible(true); + setResizable(false); + } + + + + /** + * 左半部分对话框 + * @return + */ + private Box createLeftPanel(){ + //上半部分 + JLabel label = new JLabel("查找内容(N):"); + label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); + Box upBox = new Box(BoxLayout.X_AXIS); + upBox.add(label); + text.setText(lastFindText); //上次查找的字符串 + text.getDocument().addDocumentListener( + DocumentListenerFactory.getDocumentListener(this, "FindReplaceTextField")); + text.selectAll(); + upBox.add(text); + //下半部分 + //下左 + caseCheckBox.setBorder(BorderFactory.createEmptyBorder(35, 0, 0, 20)); + //带边框的二个单选按钮 + //下右 + ButtonGroup directionButtonGroup = new ButtonGroup(); + directionButtonGroup.add(up); + directionButtonGroup.add(down); + JPanel direction = new JPanel(); + direction.add(up); //ButtonGroup只起到组合作用,不是容器 + direction.add(down); + direction.setBorder(BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(), "方向", TitledBorder.LEFT + , TitledBorder.TOP)); + Box downBox = new Box(BoxLayout.X_AXIS); + downBox.add(caseCheckBox); + downBox.add(direction); + downBox.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + //组合上下两部分 + Box left = new Box(BoxLayout.Y_AXIS); + left.add(upBox); + left.add(downBox); + left.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return left; + } + + /** + * 返回右半部分对话框 + * @return + */ + private JPanel createRightPanel(){ + JPanel right = new JPanel(new GridLayout(2, 1, 0, 10)); + findNext = new JButton("查找下一个(F)"); + setButtonEnable(false); + findNext.addActionListener(ActionListenerFactory.getActionListener(this, "查找下一个(F)")); + JButton cancel = new JButton("取消"); + cancel.addActionListener(ActionListenerFactory.getActionListener(this, "取消")); + right.add(findNext); + right.add(cancel); + right.setBorder(BorderFactory.createEmptyBorder(10, 0, 30, 20)); + return right; + } + +// //调试用 +// public FindDialog(){ +// add(createLeftPanel(), BorderLayout.WEST); +// add(createRightPanel()); +// pack(); +// setDefaultCloseOperation(DISPOSE_ON_CLOSE); +// setVisible(true); +// } +// public static void main(String[] args){ +// new FindDialog(); +// } + + //是否区分大小写 + @Override + public boolean isMatchCase() { + return caseCheckBox.isSelected(); + } + + //返回待查找的目标字符串,同时将它保存进lastFindText + @Override + public String getFindText() { + lastFindText = text.getText(); + return lastFindText; + } + + //是否向下查找 + @Override + public boolean isDownward() { + return down.isSelected()?true:false; + } + + //获取所属的NotepadFrame + @Override + public NotepadFrame getNotepadFrame() { + return frame; + } + + //获取待查找字符串,此处为查找对话框,用不到此方法,可以任意返回。 + @Override + public String getReplaceText() { + return ""; + } + + //改变“查找下一个”按钮的可用性 + @Override + public void setButtonEnable(boolean b) { + findNext.setEnabled(b); + } + + //获取文本域的全部文本 + @Override + public String getWholeText() { + return frame.getWholeText(); + } + + //获取被选择文本的尾部 + @Override + public int getSelectionEnd() { + return frame.getSelectionEnd(); + } + + //选择对应的文本域 + @Override + public void select(int start, int end) { + frame.select(start, end); + } + + //获取文本域的开始位置 + @Override + public int getSelectionStart() { + return frame.getSelectionStart(); + } + + // 目前选中的文本 + @Override + public String getSelectedText() { + return frame.getSelectedText(); + } + + // 替换选中文本,查找对话框不对文本域进行操作 + @Override + public void replaceSelection(String text) {} + + //设置文本域的文本,查找对话框不对文本域进行操作 + @Override + public void setText(String text) {} +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindReplaceDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindReplaceDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..5c6058ecf1776a5238be4e5e750a131f4aec2917 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/FindReplaceDialog.java" @@ -0,0 +1,198 @@ +package king.notepad.view.findreplacedialog; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridLayout; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import king.notepad.actionlistener.ActionListenerFactory; +import king.notepad.documentlistener.DocumentListenerFactory; +import king.notepad.view.NotepadFrame; + +//替换对话框 +public class FindReplaceDialog extends MyDialog { + private JTextField textFind = new JTextField(20); // 参数设置的是最小宽度 + private JTextField textReplace = new JTextField(20); + private JCheckBox caseCheckBox = new JCheckBox("区分大小写(C)"); + private JRadioButton up = new JRadioButton("向上(U)"); + private JRadioButton down = new JRadioButton("向下(D)", true); + private NotepadFrame frame; + private JButton[] buttonArr = new JButton[4]; //对话框中的四个按钮 + + public FindReplaceDialog(NotepadFrame frame){ + super(frame, "替换"); + this.frame = frame; + add(createLeftPanel(), BorderLayout.WEST); + add(createRightPanel()); + if (textFind.getText() != null && textFind.getText().length() > 0) setButtonEnable(true); + pack(); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setVisible(true); + setResizable(false); + } + +// //以下为调试用 +// public FindReplaceDialog(){ +// super(); +// this.frame = frame; +// add(createLeftPanel(), BorderLayout.WEST); +// add(createRightPanel()); +// pack(); +// setDefaultCloseOperation(DISPOSE_ON_CLOSE); +// setVisible(true); +// setResizable(false); +// } +// public static void main(String[] args){ +// new FindReplaceDialog(); +// } + + + /** + * 左半部分对话框 + * @return + */ + private Box createLeftPanel(){ + //上半部分 + //两个标签 + JLabel findLabel = new JLabel("查找内容(N):"); + findLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 10)); + JLabel replaceLabel = new JLabel("替换为(P):"); + Box upLeftBox = new Box(BoxLayout.Y_AXIS); + upLeftBox.add(findLabel); + upLeftBox.add(replaceLabel); + //两个文本框 +// textFind.setText(TextService.getClipboardText()); //初始搜索文本为剪贴板 + textFind.setText(lastFindText); //上次查找的字符串 + textFind.getDocument().addDocumentListener( + DocumentListenerFactory.getDocumentListener(this, "FindReplaceTextField")); + Box upRightBox = new Box(BoxLayout.Y_AXIS); + upRightBox.add(textFind); + upRightBox.add(Box.createVerticalStrut(10)); + upRightBox.add(textReplace); + //上半部分组装一起 + Box upBox = new Box(BoxLayout.X_AXIS); + upBox.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); + upBox.add(upLeftBox); + upBox.add(upRightBox); + //下半部分 + //下左 + caseCheckBox.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + JPanel downPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + downPanel.add(caseCheckBox); + //组合上下两部分 + Box left = new Box(BoxLayout.Y_AXIS); + left.add(upBox); + left.add(downPanel); + left.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + return left; + } + + /** + * 返回右半部分对话框 + * @return + */ + private JPanel createRightPanel(){ + JPanel right = new JPanel(new GridLayout(2, 2, 15, 15)); + //把JButton放入JPanel,可以减小Button的大小 + String[] buttonNameArr = {"查找下一个(F)", "替换(R)", "全部替换(A)", "取消"}; + for(int i = 0; i < buttonArr.length; i++){ + buttonArr[i] = new JButton(buttonNameArr[i]); + buttonArr[i].addActionListener(ActionListenerFactory.getActionListener(this, buttonNameArr[i])); + right.add(buttonArr[i]); + } + setButtonEnable(false); + right.setBorder(BorderFactory.createEmptyBorder(15, 0, 30, 20)); + return right; + } + + // 设置前三个按钮的可用性 + public void setButtonEnable(boolean b){ + for(int i = 0; i < 3; i++){ + buttonArr[i].setEnabled(b); + } + } + + //是否区分大小写 + @Override + public boolean isMatchCase() { + return caseCheckBox.isSelected(); + } + + //返回待查找的目标字符串 + @Override + public String getFindText() { + lastFindText = textFind.getText(); + return lastFindText; + } + + //是否向下查找,替换对话框无此选项,一律为true + @Override + public boolean isDownward() { + return true; + } + + //获取所属的NotepadFrame + @Override + public NotepadFrame getNotepadFrame() { + return frame; + } + + //获取待替换的字符串 + @Override + public String getReplaceText() { + lastReplaceText = textReplace.getText(); + return lastReplaceText; + } + + //获取文本域的全部文本 + @Override + public String getWholeText() { + return frame.getWholeText(); + } + + //获取被选择文本的尾部 + @Override + public int getSelectionEnd() { + return frame.getSelectionEnd(); + } + + //选择对应的文本域 + @Override + public void select(int start, int end) { + frame.select(start, end); + } + + //获取文本域的开始位置 + @Override + public int getSelectionStart() { + return frame.getSelectionStart(); + } + + // 目前选中的文本 + @Override + public String getSelectedText() { + return frame.getSelectedText(); + } + + // 替换选中文本 + @Override + public void replaceSelection(String text) { + frame.replaceSelection(text); + } + + //设置文本域的文本 + @Override + public void setText(String text) { + frame.setText(text); + } + +} diff --git "a/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/MyDialog.java" "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/MyDialog.java" new file mode 100644 index 0000000000000000000000000000000000000000..8c52e7882838baeaaf9bf08c27257d301794ed47 --- /dev/null +++ "b/\344\270\252\344\272\272\344\275\234\344\270\232\346\217\220\344\272\244/\345\210\230\345\270\205/view/findreplacedialog/MyDialog.java" @@ -0,0 +1,40 @@ +package king.notepad.view.findreplacedialog; + +import java.awt.Frame; + +import javax.swing.JDialog; + +import king.notepad.view.NotepadFrame; + +public abstract class MyDialog extends JDialog { + protected static String lastFindText = ""; + protected static String lastReplaceText = ""; + + //调试用 + public MyDialog(){ + super(); + } + + public MyDialog(Frame owner, String title){ + super(owner, title); + //设置对话框在Frame正中 + int frameX = (int)owner.getBounds().getX(); + int frameY = (int)owner.getBounds().getY(); + setBounds(frameX+80, frameY+150, 0, 0); + } + + public abstract void setButtonEnable(boolean b); //设置查找替换对话框三个按钮的状态 + public abstract boolean isMatchCase(); //是否区分大小写 + public abstract boolean isDownward(); //是否向下查找 + public abstract String getFindText(); //需要查找的目标字符串 + public abstract String getReplaceText(); //需要替换的目标字符串 + public abstract String getWholeText(); //获取文本域的全部文本 + public abstract String getSelectedText(); //目前选中的文本 + public abstract NotepadFrame getNotepadFrame(); //返回所属NotepadFrame + public abstract int getSelectionStart(); //获取文本域的开始位置 + public abstract int getSelectionEnd(); //获取文本域选择的尾部位置 + public abstract void select(int start, int end); //选择对应的文本域 + public abstract void replaceSelection(String text); //替换选中文本 + public abstract void setText(String text); //设置文本域的文本 + +}