📄 dayselection.java
字号:
/*--------------------------------------------------------------------------*
| Copyright (C) 2006 Christopher Kohlhaas |
| |
| 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. A copy of the license has been included with |
| these distribution in the COPYING file, if not go to www.fsf.org |
| |
| As a special exception, you are granted the permissions to link this |
| program with every library, which license fulfills the Open Source |
| Definition as published by the Open Source Initiative (OSI). |
*--------------------------------------------------------------------------*/
package org.rapla.components.calendar;
import javax.swing.JComponent;
import javax.swing.UIManager;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.FontMetrics;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Calendar;
import java.util.Locale;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
/** The graphical date-selection field
* @author Christopher Kohlhaas
*/
final class DaySelection extends JComponent implements DateChangeListener,MouseListener {
private static final long serialVersionUID = 1L;
// 7 rows and 7 columns
static final int ROWS = 7; //including the header row
static final int COLUMNS = 7;
// 6 * 7 Fields for the Month + 7 Fields for the Header
static final int FIELDS = (ROWS - 1) * COLUMNS;
static final int HBORDER = 0; // horizontal BORDER of the component
static final int VBORDER = 0; // vertical BORDER of the component
static final int VGAP = 2; // vertical gap between the cells
static final int HGAP = 2; // horizontal gap between the cells
static final Color DARKBLUE = new Color(0x00, 0x00, 0x88);
static final Color LIGHTGRAY = new Color(0xdf, 0xdf, 0xdf);
static final Color FOCUSCOLOR = UIManager.getColor("Button.focus");
static final Color DEFAULT_CELL_BACKGROUND = Color.white;
static final Color HEADER = Color.white;
static final Color HEADER_BACKGROUND = DARKBLUE;
static final Color SELECTION = Color.white;
static final Color SELECTION_BACKGROUND = DARKBLUE;
static final Color SELECTION_BORDER = Color.red;
static final Color SELECTABLE = Color.black;
static final Color UNSELECTABLE = LIGHTGRAY;
/** stores the weekdays order e.g so,mo,tu,.. or mo,tu.
* Requirement: The week has seven days
*/
private int[] weekday2slot = new int[8];
/** stores the weekdayNames mon - sun.
* Requirement: The week has seven days.
*/
private String[] weekdayNames = new String[7];
/** stores the days 1 - 31 days[1] = 1
* <br>maximum days per month 40
*/
private String[] days = new String[40];
private int selectedField = 10;
private int focusedField = 10;
private DateModel model;
private DateModel focusModel;
private int lastFocusedMonth; // performance improvement
private int lastFocusedYear; // performance improvement
private PaintEnvironment e;
private DateRenderer dateRenderer = null;
public DaySelection(DateModel model,DateModel focusModel) {
this.model = model;
this.focusModel = focusModel;
focusModel.addDateChangeListener(this);
addMouseListener(this);
createWeekdays(model.getLocale());
createDays(model.getLocale());
// setFont(DEFAULT_FONT);
}
/** Implementation-specific. Should be private.*/
public void mousePressed(MouseEvent me) {
me.consume();
selectField(me.getX(),me.getY());
}
/** Implementation-specific. Should be private.*/
public void mouseReleased(MouseEvent me) {
me.consume();
}
/** Implementation-specific. Should be private.*/
public void mouseClicked(MouseEvent me) {
me.consume();
}
/** Implementation-specific. Should be private.*/
public void mouseEntered(MouseEvent me) {
}
/** You must call javax.swing.ToolTipManager.sharedInstance().registerComponent(thisComponent)
to enable ToolTip text.
*/
public String getToolTipText(MouseEvent me) {
int day = calcDay(me.getX(),me.getY());
if (day >=0 && dateRenderer != null)
return dateRenderer.getToolTipText(focusModel.getWeekday(day), day, focusModel.getMonth(), focusModel.getYear());
else
return "";
}
/** Implementation-specific. Should be private.*/
public void mouseExited(MouseEvent me) {
}
public void setDateRenderer(DateRenderer dateRenderer) {
this.dateRenderer = dateRenderer;
}
// Recalculate the Components minimum and maximum sizes
private void calculateSizes() {
if (e == null)
e = new PaintEnvironment();
int maxWidth =0;
FontMetrics fm = getFontMetrics(getFont());
e.fontHeight = fm.getHeight();
e.cellHeight = fm.getHeight() + VGAP *2;
for (int i=0;i<weekdayNames.length;i++) {
int len = fm.stringWidth(weekdayNames[i]);
if (len>maxWidth)
maxWidth = len;
}
if (fm.stringWidth("33")> maxWidth)
maxWidth = fm.stringWidth("33");
e.fontWidth = maxWidth;
e.cellWidth = maxWidth + HGAP * 2 ;
int width = COLUMNS * e.cellWidth + HBORDER *2;
setPreferredSize(new Dimension( width,(ROWS) * e.cellHeight + 2*HBORDER));
setMinimumSize(new Dimension( width,(ROWS) * e.cellHeight + 2*VBORDER));
invalidate();
}
public void setFont(Font font) {
super.setFont(font);
if (font == null)
return;
else
// We need the font-size to calculate the component size
calculateSizes();
}
public Dimension getPreferredSize() {
if (getFont() != null && e==null)
// We need the font-size to calculate the component size
calculateSizes();
return super.getPreferredSize();
}
public void dateChanged(DateChangeEvent evt) {
if (e==null)
// We need the font-size to calculate the component size
if (getFont() != null )
calculateSizes();
else
return;
int lastSelectedField = selectedField;
if (model.getMonth() == focusModel.getMonth() &&
model.getYear() == focusModel.getYear())
// #BUGFIX consider index shift.
// weekdays 1..7 and days 1..31 but field 0..40
selectedField = weekday2slot[model.firstWeekday()]+ (model.getDay() - 1) ;
else
selectedField = -1;
int lastFocusedField = focusedField;
// #BUGFIX consider index shift.
// weekdays 1..7 and days 1..31 but field 0..40
int newFocusedField = weekday2slot[focusModel.firstWeekday()] + (focusModel.getDay() - 1) ;
if (lastSelectedField == selectedField
&& lastFocusedMonth == focusModel.getMonth()
&& lastFocusedYear == focusModel.getYear()
) {
// Only repaint the focusedField (Performance improvement)
focusedField = -1;
calculateRectangle(lastFocusedField);
repaint(e.r);
focusedField = newFocusedField;
calculateRectangle(focusedField);
repaint(e.r);
} else {
// repaint everything
focusedField = newFocusedField;
repaint();
}
lastFocusedMonth = focusModel.getMonth();
lastFocusedYear = focusModel.getYear();
}
/** calculate the day of month from the specified field. 1..31
*/
private int calcDay(int field) {
return (field + 1) - weekday2slot[focusModel.firstWeekday()] ;
}
/** calculate the day of month from the x and y coordinates.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -