📄 main.java
字号:
/* * k5nCal - Java Swing Desktop Calendar App * Copyright (C) 2005-2007 Craig Knudsen, craig@k5n.us * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */package us.k5n.k5ncal;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Component;import java.awt.Container;import java.awt.FlowLayout;import java.awt.Font;import java.awt.Frame;import java.awt.Graphics;import java.awt.GridLayout;import java.awt.Toolkit;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ComponentEvent;import java.awt.event.ComponentListener;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.io.BufferedReader;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.URL;import java.util.Collections;import java.util.HashMap;import java.util.Vector;import javax.swing.BorderFactory;import javax.swing.Box;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JDialog;import javax.swing.JFileChooser;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JList;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JSplitPane;import javax.swing.JTextArea;import javax.swing.JTextField;import javax.swing.JToolBar;import javax.swing.KeyStroke;import javax.swing.LookAndFeel;import javax.swing.SwingUtilities;import javax.swing.UIManager;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;import us.k5n.ical.BogusDataException;import us.k5n.ical.Constants;import us.k5n.ical.DataStore;import us.k5n.ical.Date;import us.k5n.ical.Event;import us.k5n.ical.ICalendarParser;import us.k5n.k5ncal.data.Calendar;import us.k5n.k5ncal.data.HttpClient;import us.k5n.k5ncal.data.HttpClientStatus;import us.k5n.k5ncal.data.Repository;import us.k5n.k5ncal.data.RepositoryChangeListener;import us.k5n.k5ncal.data.SingleEvent;import us.k5n.ui.AccordionPane;import us.k5n.ui.calendar.CalendarPanel;import us.k5n.ui.calendar.CalendarPanelSelectionListener;import us.k5n.ui.calendar.EventInstance;import edu.stanford.ejalbert.BrowserLauncher;/** * Main class for k5nCal application. This application makes use of the k5n * iCalendar library (part of Java Calendar Tools) as well as many other 3rd * party libraries and tools. See the README.txt file for details. Please see * the License.html file for licensing details. * * @author Craig Knudsen, craig@k5n.us * @version $Id: Main.java,v 1.67 2008/01/19 00:50:45 cknudsen Exp $ * */public class Main extends JFrame implements Constants, ComponentListener, PropertyChangeListener, RepositoryChangeListener, CalendarPanelSelectionListener, CalendarRefresher { public static final String DEFAULT_DIR_NAME = "k5nCal"; public String version = null;; public static final String CALENDARS_XML_FILE = "calendars.xml"; static final String APP_ICON = "images/k5nCal-128x128.png"; static final String APP_URL = "http://www.k5n.us/k5ncal.php"; static final String DONATE_URL = "https://sourceforge.net/donate/index.php?group_id=195315"; static final String REPORT_BUG_URL = "https://sourceforge.net/tracker/?group_id=195315&atid=952950"; static final String REQUEST_FEATURE_URL = "https://sourceforge.net/tracker/?group_id=195315&atid=952953"; static final String SUPPORT_REQUEST_URL = "https://sourceforge.net/tracker/?group_id=195315&atid=952951"; static final String LICENSE_FILE = "License.html"; static ClassLoader cl = null; JFrame parent; EventViewPanel eventViewPanel; JButton newButton, editButton, deleteButton, largerButton, smallerButton; JLabel messageArea; Repository dataRepository; CalendarPanel calendarPanel; JSplitPane horizontalSplit = null, leftVerticalSplit = null; AccordionPane ap; JListWithCheckBoxes calendarJList; JList categoryJList; String searchText = null; private static File lastExportDirectory = null; AppPreferences prefs; File dataDir = null; static final String MENU_CALENDAR_EDIT = "Edit Calendar..."; static final String MENU_CALENDAR_REFRESH = "Refresh Calendar"; static final String MENU_CALENDAR_DELETE = "Delete Calendar"; static final String MENU_CALENDAR_ADD_EVENT = "Add Event..."; static final String MENU_CALENDAR_VIEW_ERRORS = "View Errors/Warnings..."; static final String ADD_EVENT_LABEL = "New..."; static final String EDIT_EVENT_LABEL = "Edit..."; static final String DELETE_EVENT_LABEL = "Delete"; static final String LARGER_FONT_LABEL = "Larger"; static final String SMALLER_FONT_LABEL = "Smaller"; private boolean fontsInitialized = false; private boolean isMac = false; public Main() { super ( "k5nCal" ); this.parent = this; this.isMac = ( System.getProperty ( "mrj.version" ) != null ); // Get version from ChangeLog this.getVersionFromChangeLog (); prefs = AppPreferences.getInstance (); // prefs.clearAll (); setInitialLAF (); setSize ( prefs.getMainWindowWidth (), prefs.getMainWindowHeight () ); this.setLocation ( prefs.getMainWindowX (), prefs.getMainWindowY () ); setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE ); Container contentPane = getContentPane (); // Load data File dataDir = getDataDirectory (); dataRepository = new Repository ( dataDir, loadCalendars ( dataDir ), false ); // Ask to be notified when the repository changes (user adds/edits // an entry) dataRepository.addChangeListener ( this ); // Create a menu bar setJMenuBar ( createMenu () ); contentPane.setLayout ( new BorderLayout () ); // Add message/status bar at bottom JPanel messagePanel = new JPanel (); messagePanel.setLayout ( new BorderLayout () ); messagePanel.setBorder ( BorderFactory.createEmptyBorder ( 2, 4, 2, 4 ) ); messageArea = new JLabel ( "Welcome to k5nCal..." ); messagePanel.add ( messageArea, BorderLayout.CENTER ); contentPane.add ( messagePanel, BorderLayout.SOUTH ); ap = new AccordionPane (); ap.addPanel ( "Calendars", createCalendarSelectionPanel ( dataRepository .getCalendars () ) ); ap.addPanel ( "Categories", createCategorySelectionPanel ( dataRepository .getCategories () ) ); ap.setTooltipTextAt ( 0, "Manage Calendars" ); ap.setTooltipTextAt ( 1, "Filter displayed events by category" ); eventViewPanel = new EventViewPanel (); eventViewPanel.setBorder ( BorderFactory .createTitledBorder ( "Event Details" ) ); leftVerticalSplit = new JSplitPane ( JSplitPane.VERTICAL_SPLIT, ap, eventViewPanel ); leftVerticalSplit.setOneTouchExpandable ( true ); leftVerticalSplit.setDividerLocation ( prefs .getMainWindowLeftVerticalSplitPosition () ); leftVerticalSplit.addPropertyChangeListener ( this ); JPanel rightPanel = new JPanel (); rightPanel.setLayout ( new BorderLayout () ); rightPanel.add ( createToolBar (), BorderLayout.NORTH ); calendarPanel = new MyCalendarPanel ( dataRepository ); calendarPanel.addSelectionListener ( this ); calendarPanel.setShowTime ( prefs.getDisplayHourInMonthView () ); rightPanel.add ( calendarPanel, BorderLayout.CENTER ); horizontalSplit = new JSplitPane ( JSplitPane.HORIZONTAL_SPLIT, leftVerticalSplit, rightPanel ); horizontalSplit.setOneTouchExpandable ( true ); horizontalSplit.setDividerLocation ( prefs .getMainWindowHorizontalSplitPosition () ); horizontalSplit.addPropertyChangeListener ( this ); this.add ( horizontalSplit, BorderLayout.CENTER ); this.addComponentListener ( this ); updateToolbar (); this.setVisible ( true ); // Start a thread to update the remote calendars as needed. RemoteCalendarUpdater updater = new RemoteCalendarUpdater ( this.dataRepository, this ); updater.start (); } public void paint ( Graphics g ) { if ( !this.fontsInitialized ) { this.fontsInitialized = true; Font currentFont = g.getFont (); Font newFont = new Font ( currentFont.getFamily (), currentFont .getStyle (), currentFont.getSize () + prefs.getDisplayFontSize () ); eventViewPanel.setAllFonts ( newFont ); calendarPanel.setFont ( newFont ); } super.paint ( g ); } public Vector<Calendar> loadCalendars ( File dir ) { Vector<Calendar> ret = new Vector<Calendar> (); File f = new File ( dir, CALENDARS_XML_FILE ); if ( !f.exists () ) { String name = (String) System.getProperty ( "user.name" ); if ( name == null ) name = "Unnamed Calendar"; Calendar def = new Calendar ( dir, name ); this.showMessage ( "A new calendar named was created for you" + ": " + name ); ret.addElement ( def ); } else { try { ret = Calendar.readCalendars ( f ); } catch ( Exception e1 ) { this.fatalError ( "Error reading calendar file " + f + "\n\n" + "Error" + ":\n" + e1.getMessage () ); e1.printStackTrace (); } } return ret; } public void saveCalendars ( File dir ) { File f = new File ( dir, CALENDARS_XML_FILE ); try { Calendar.writeCalendars ( f, dataRepository.getCalendars () ); } catch ( IOException e1 ) { this.showError ( "Error writing calendars" + ":\n" + e1.getMessage () ); e1.printStackTrace (); } } public void setMessage ( String msg ) { this.messageArea.setText ( msg ); } public JMenuBar createMenu () { JMenuItem item; JMenuBar bar = new JMenuBar (); JMenu fileMenu = new JMenu ( "File" ); // On Mac, we will hook into the native preferences menu object (see // MacStuff.java). So, if we're on a Mac, don't add the Preferences menu // item to the File menu. if ( !isMac ) { item = new JMenuItem ( "Preferences..." ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { showPreferences (); } } ); fileMenu.add ( item ); } JMenu importMenu = new JMenu ( "Import" ); // exportMenu.setMnemonic ( 'X' ); fileMenu.add ( importMenu ); item = new JMenuItem ( "iCalendar File" ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { importICalendar (); } } ); importMenu.add ( item ); item = new JMenuItem ( "CSV File" ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { importCSV (); } } ); importMenu.add ( item ); fileMenu.addSeparator (); JMenu exportMenu = new JMenu ( "Export" ); // exportMenu.setMnemonic ( 'X' ); fileMenu.add ( exportMenu ); item = new JMenuItem ( "All Calendars" ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { exportAll (); } } ); exportMenu.add ( item ); item = new JMenuItem ( "Selected Calendars" ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { exportVisible (); } } ); exportMenu.add ( item ); // On Mac, we will be using the native "Quit" (see MacStuff.java), // so do not add it to the file menu. if ( !isMac ) { fileMenu.addSeparator (); item = new JMenuItem ( "Exit" ); item.setAccelerator ( KeyStroke.getKeyStroke ( 'Q', Toolkit .getDefaultToolkit ().getMenuShortcutKeyMask () ) ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { quit (); } } ); fileMenu.add ( item ); } bar.add ( fileMenu ); JMenu calMenu = new JMenu ( "Calendar" ); item = new JMenuItem ( "New Local..." ); item.setAccelerator ( KeyStroke.getKeyStroke ( 'L', Toolkit .getDefaultToolkit ().getMenuShortcutKeyMask () ) ); item.addActionListener ( new ActionListener () { public void actionPerformed ( ActionEvent event ) { editLocalCalendar ( null ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -