📄 schedulepanel.java
字号:
package net.sf.dz.view.component;import java.awt.Color;import java.awt.Component;import java.awt.Dimension;import java.awt.Font;import java.awt.GridBagConstraints;import java.awt.GridBagLayout;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.ItemEvent;import java.awt.event.ItemListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.util.Iterator;import java.util.StringTokenizer;import java.util.SortedSet;import java.util.TreeSet;import java.util.Vector;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JCheckBox;import javax.swing.JComboBox;import javax.swing.JLabel;import javax.swing.JList;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JSpinner;import javax.swing.ListCellRenderer;import javax.swing.ListSelectionModel;import javax.swing.SpinnerDateModel;import javax.swing.event.ListSelectionEvent;import javax.swing.event.ListSelectionListener;/** * Scheduler panel. * * Displays the schedule for an individual zone and allows to edit it. * * @author Copyright © <a href="mailto:vt@freehold.crocodile.org">Vadim Tkachenko</a> 2001-2004 * @version $Id: SchedulePanel.java,v 1.32 2004/07/19 05:38:52 vtt Exp $ */public class SchedulePanel extends JPanel implements ListSelectionListener { /** * Two letter day names. */ public static final String dayName[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" }; /** * Full day names. */ public static final String longDayName[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; /** * Font to be used for the schedule panel. * * Defaults to Times New Roman 10pt. */ public static final Font smallFont = new Font("Times", Font.PLAIN, 10); private GridBagLayout layout; private GridBagConstraints cs; private ScheduleListener listener; private WeekPanel weekPanel; private DayPanel dayPanel; private ControlPanel controlPanel; /** * Collection of event collections for all the week. * * Each element of the vector contains a vector of events for the given * day, 0 being Sunday. */ private SortedSet eventSet[] = new SortedSet[7]; private ScheduleEvent currentEvent = null; /** * This variable controls how deeply nested we are. * * If the nesting level is non-zero, no notifications will be sent * because it means that the events we're parsing are secondary, caused * by enable/disable/select actions up the stack. * * <p> * * <strong>NOTE:</strong> Use {@link #push push()} and {@link #pop * pop()} to change the value - it will protect from stack mismatches. */ int nestingLevel = 0; boolean enabled = true; public SchedulePanel(ScheduleListener listener) { if ( listener == null ) { throw new IllegalArgumentException("Listener can't be null"); } this.listener = listener; for ( int i = 0; i < 7; i++ ) { eventSet[i] = new TreeSet(); } layout = new GridBagLayout(); cs = new GridBagConstraints(); setLayout(layout); // Week panel goes on top left cs.fill = GridBagConstraints.HORIZONTAL; cs.gridx = 0; cs.gridy = 0; cs.gridwidth = 4; cs.weightx = 1; cs.weighty = 0; weekPanel = new WeekPanel(); layout.setConstraints(weekPanel, cs); add(weekPanel); // Control panel goes on right cs.gridx += 4; cs.gridwidth = 2; cs.gridheight = 6; cs.weightx = 0; cs.weighty = 1; cs.fill = GridBagConstraints.BOTH; controlPanel = new ControlPanel(this); controlPanel.setEnabled(false); layout.setConstraints(controlPanel, cs); add(controlPanel); // Day panel goes on bottom left cs.gridx = 0; cs.gridy++; cs.gridwidth = 4; cs.gridheight = 5; cs.weighty = 1; dayPanel = new DayPanel(); dayPanel.list.addListSelectionListener(this); layout.setConstraints(dayPanel, cs); add(dayPanel); } private void push() { nestingLevel++; } private void pop() { nestingLevel--; if ( nestingLevel < 0 ) { throw new IllegalStateException("Nesting level is " + nestingLevel); } } /** * Parse the remaining part of the command. * * @param target Target selector. May be either "event", which means the * rest denotes the content of a particular event, or "current", which * means that the rest denotes the event that is currently running. * * @param st String tokenizer containing the event content. * * <ul> * * <li> First token should contain the two letter day name. * <li> Second token should contain the event name. * * </ul> * * @exception IllegalArgumentException if there is a syntax violation or * unknown target. * * @see #parseEvent */ public void parse(String target, StringTokenizer st) throws Throwable { push(); try { String day = st.nextToken(); String name = st.nextToken(); // Figure out the day int dayOffset = -1; for ( int idx = 0; idx < 7; idx++ ) { if ( dayName[idx].equals(day) ) { dayOffset = idx; break; } } if ( dayOffset == -1 ) { throw new IllegalArgumentException("Invalid day: '" + day + "'"); } if ( "event".equals(target) ) { ScheduleEvent se = parseEvent(dayOffset, name, st); refreshEventSet(se); } else if ( "current".equals(target) ) { ScheduleEvent se = parseEvent(dayOffset, name, st); setCurrent(se); } else { throw new IllegalArgumentException("Unsupported target: '" + target + "'"); } weekPanel.setSelectedDay(weekPanel.getSelectedDay()); } finally { pop(); } } /** * Parse the parameters and instantiate the event. * * @param dayOffset Day offset, with 0 being Sunday. * * @param name Event name. * * @param st Rest of the event parameters. * * <ul> * * <li> First and second tokens should contain the event start time * in 24 hours format. * * <li> Third token should contain the setpoint as double. * * <li> Fourth token should contain information about whether the * zone is enabled during this particular event ("on" means * yes, anything else means no). * * <li> Fifth token should contain information about whether the * zone is voting during this particular event ("voting" means * yes, anything else means no). * * <li> Sixth token should contain the dump priority as integer. * * </ul> */ private ScheduleEvent parseEvent(int dayOffset, String name, StringTokenizer st) throws Throwable { ScheduleEvent e = new ScheduleEvent(); e.dayOffset = dayOffset; e.name = name; String hour = st.nextToken(); String minute = st.nextToken(); // Let's fix the time, just in case if ( "0".equals(minute) ) { minute = "00"; } e.time = hour + ":" + minute; e.setpoint = Double.parseDouble(st.nextToken()); e.enabled = st.nextToken().equals("on"); e.voting = st.nextToken().equals("voting"); e.dumpPriority = Integer.parseInt(st.nextToken()); return e; } /** * Add the event to the event set, or replace an existing one if it is * determined that the parameter represents a modified version of an * existing event. * * @param event Event to match against the known event set. */ private void refreshEventSet(ScheduleEvent event) { try { // Figure out if we have this event yet ScheduleEvent current = null; SortedSet set = eventSet[event.dayOffset]; for ( Iterator i = set.iterator(); i.hasNext(); ) { ScheduleEvent se = (ScheduleEvent)i.next(); if ( event.name.equals(se.name) ) { // We have this event already current = se; break; } } if ( current == null ) { // We haven't seen this before set.add(event); return; } else { // This is an update set.remove(current); set.add(event); } } finally { // If the new event day is the same as selected day in the // dayPanel (actually, weekPanel) we have to redisplay the // events in case their order has been changed if ( event.dayOffset == weekPanel.getSelectedDay()) { SortedSet events = eventSet[event.dayOffset]; ScheduleEvent selectedEvent = (ScheduleEvent)dayPanel.list.getSelectedValue(); if ( selectedEvent != null ) { // If we just set the list data unconditionally, the // notification will be issued, and we'll fall into an // endless loop. Therefore, we need to make sure that // the new data is set only if the update event is // different from the one currently displayed. // VT: NOTE: isEqual won't work because it doesn't // contain all the comparisons (and the reason for that // is that it's used to sort the entries in the set). // One possible solution to that is to use a different // comparator for the set, but this will do too. if ( (event.dayOffset != selectedEvent.dayOffset) || (event.dumpPriority != selectedEvent.dumpPriority) || (event.enabled != selectedEvent.enabled) || (event.setpoint != selectedEvent.setpoint) || (event.voting != selectedEvent.voting) || !event.time.equals(selectedEvent.time) ) { push(); dayPanel.list.setListData(set2vector(events)); // Find that name again for ( Iterator i = events.iterator(); i.hasNext(); ) { ScheduleEvent se = (ScheduleEvent)i.next(); if ( se.name.equals(selectedEvent.name) ) { dayPanel.list.setSelectedValue(se, false); break; } } pop();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -