//{HEADER
/**
* This class is part of jnex 'Nexirius Application Framework for Java'
*
* Copyright (C) Nexirius GmbH, CH-4450 Sissach, Switzerland (www.nexirius.ch)
*
* <p>This library is free software; you can redistribute it and/or<br>
* modify it under the terms of the GNU Lesser General Public<br>
* License as published by the Free Software Foundation; either<br>
* version 2.1 of the License, or (at your option) any later version.</p>
*
* <p>This library is distributed in the hope that it will be useful,<br>
* but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU<br>
* Lesser General Public License for more details.</p>
*
* <p>You should have received a copy of the GNU Lesser General Public<br>
* License along with this library; if not, write to the Free Software<br>
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p>
* </blockquote>
*
* <p>
* Nexirius GmbH, hereby disclaims all copyright interest in<br>
* the library jnex' 'Nexirius Application Framework for Java' written<br>
* by Marcel Baumann.</p>
*/
//}HEADER
package com.nexirius.framework.gadgets.datechooser;
import com.nexirius.framework.datamodel.DataModelAdaptor;
import com.nexirius.framework.datamodel.DataModelEvent;
import com.nexirius.framework.datamodel.DayMonthYearModel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class DateChooserPanel extends JPanel {
public static final long DAY_MILLIS = 3600000L * 24L;
static String[] DAY = {"Mo", "Tu", "We", "Th", "Fr", "Sa", "So"};
DayMonthYearModel selectedDate;
Calendar showMonth;
NavigatePanel navigate;
CenterPanel center;
JTextField inputField;
JLabel output;
Dimension preferredSize = new Dimension(200, 200);
boolean higlightMousePosition = false;
Date mouseDay = new Date(0);
public int twidth;
public int theight;
public DateChooserPanel() {
this(new Date());
}
public DateChooserPanel(Date date) {
selectedDate = new DayMonthYearModel(date);
selectedDate.addDataModelListener(new SelectedDateListener());
showMonth = Calendar.getInstance();
showMonth.setTime(date);
initPanel();
}
public DayMonthYearModel getSelectedDateModel() {
return selectedDate;
}
private void initPanel() {
setLayout(new BorderLayout());
navigate = new NavigatePanel();
add(navigate, BorderLayout.NORTH);
center = new CenterPanel();
center.addMouseListener(new CenterMouseListener());
center.addMouseMotionListener(new CenterMouseListener());
center.addKeyListener(new DirectionKeyListener());
center.setFocusable(true);
add(center, BorderLayout.CENTER);
inputField = new JTextField(selectedDate.getText());
inputField.addKeyListener(new InputFieldListener());
inputField.setHorizontalAlignment(JLabel.HORIZONTAL);
JButton todayButton = new JButton(".");
JPanel textEditPanel = new JPanel(new BorderLayout());
JPanel south = new JPanel(new GridLayout(0, 1));
todayButton.addActionListener(new TodayButtonListener());
todayButton.setToolTipText("today");
todayButton.setMargin(new Insets(1, 3, 1, 3));
textEditPanel.add(inputField, BorderLayout.CENTER);
textEditPanel.add(todayButton, BorderLayout.EAST);
output = new JLabel(selectedDate.getText());
output.setHorizontalAlignment(JLabel.HORIZONTAL);
south.add(textEditPanel);
south.add(output);
add(south, BorderLayout.SOUTH);
setPreferredSize(preferredSize);
}
public void setDate(Date date) {
selectedDate.setDate(date);
updateView();
}
public Date getDate() {
return selectedDate.getDate();
}
public void reset() {
setDate(new Date());
}
public void updateView() {
showMonth.setTime(selectedDate.getDate());
navigate.updateLabel();
center.repaint();
output.setText(selectedDate.getText());
}
public void prePaint(Calendar cal, Graphics g, int x, int y, int w, int h) {
// Calendar bd = Calendar.getInstance();
// bd.set(Calendar.YEAR, 1965);
// bd.set(Calendar.MONTH, Calendar.JUNE);
// bd.set(Calendar.DAY_OF_MONTH, 20);
// if (sameDay(bd, cal)) {
// g.setColor(Color.green);
// }
}
public void postPaint(Calendar cal, Graphics g, int x, int y, int w, int h) {
}
public static boolean sameDay(Calendar cal1, Calendar cal2) {
return cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH)
&& cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)
&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
}
public static boolean sameDay(Date d1, Date d2) {
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.setTime(d1);
c2.setTime(d2);
return sameDay(c1, c2);
}
private int getFirstDay(Calendar cal) {
cal.setTime(showMonth.getTime());
int actMonth = cal.get(Calendar.MONTH);
cal.set(Calendar.DAY_OF_MONTH, 1);
while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
cal.setTime(new Date(cal.getTime().getTime() - DAY_MILLIS));
}
return actMonth;
}
public Calendar getDate(Point p) {
Calendar cal = Calendar.getInstance();
getFirstDay(cal);
// avoid division by zero problem
if (twidth == 0) {
twidth = 10;
}
if (theight == 0) {
theight = 10;
}
int xd = p.x / twidth;
int yd = p.y / theight;
int cell = xd + (7 * yd) - 7;
if (cell >= 0) {
long newTime = cal.getTimeInMillis() + cell * DAY_MILLIS;
cal.setTimeInMillis(newTime);
return cal;
}
return null;
}
class CenterPanel extends JButton {
int maxWeeks = 7;
int hgap = 2;
int vgap = 2;
public int hcell;
public int wcell;
public CenterPanel() {
super("");
}
public void paint(Graphics g) {
super.paint(g);
recalc();
int hfont = (int) ((wcell < hcell ? wcell : hcell) * 0.8);
Font font = new Font("Arial", Font.PLAIN, hfont);
g.setFont(font);
int charWidth = g.getFontMetrics().charWidth('0');
Calendar cal = Calendar.getInstance();
cal.setTime(selectedDate.getDate());
Calendar ical = Calendar.getInstance();
int actMonth = getFirstDay(ical);
for (int y = 0; y < maxWeeks; ++y) {
for (int x = 0; x < 7; ++x) {
int xpos = x * twidth + hgap;
int ypos = y * theight + vgap;
if (y == 0) {
g.drawString(DAY[x], xpos + 2, ypos + 2 + hfont);
continue;
}
if (sameDay(ical, cal)) {
g.setColor(Color.blue);
g.fillRect(xpos, ypos, wcell, hcell);
g.setColor(Color.white);
} else {
if (sameDay(ical.getTime(), mouseDay)) {
g.setColor(Color.yellow);
g.fillRect(xpos, ypos, wcell, hcell);
}
if (actMonth == ical.get(Calendar.MONTH)) {
if (Calendar.SUNDAY == ical.get(Calendar.DAY_OF_WEEK)) {
g.setColor(Color.red);
} else {
g.setColor(Color.black);
}
if (sameDay(ical.getTime(), new Date())) {
g.setColor(Color.blue);
}
} else {
g.setColor(Color.gray);
}
}
prePaint(ical, g, xpos, ypos, wcell, hcell);
g.drawRect(xpos, ypos, wcell, hcell);
int day = ical.get(Calendar.DAY_OF_MONTH);
g.drawString(Integer.toString(day), (day < 10 ? charWidth : 0) + xpos + 2, ypos + 2 + hfont);
postPaint(ical, g, xpos, ypos, wcell, hcell);
ical.setTime(new Date(ical.getTime().getTime() + DAY_MILLIS));
}
}
}
private void recalc() {
twidth = getSize().width / 7;
theight = getSize().height / maxWeeks;
hcell = theight - vgap - vgap;
wcell = twidth - hgap - hgap;
}
public void click(Point p) {
Calendar cal = getDate(p);
if (cal != null) {
setDate(cal.getTime());
inputField.setText(output.getText());
}
}
}
class NavigatePanel extends JPanel {
String labelText;
JLabel label;
public NavigatePanel() {
setLayout(new BorderLayout());
init();
}
private void init() {
JButton left = new JButton("<");
JButton right = new JButton(">");
left.setToolTipText("CTRL-Click decremets year");
right.setToolTipText("CTRL-Click incremets year");
Insets insets = new Insets(1, 3, 1, 3);
left.setMargin(insets);
right.setMargin(insets);
labelText = "";
label = new JLabel();
label.setHorizontalAlignment(JLabel.CENTER);
add(label, BorderLayout.CENTER);
add(left, BorderLayout.WEST);
add(right, BorderLayout.EAST);
left.addActionListener(new StepMonthListener(-1));
right.addActionListener(new StepMonthListener(1));
updateLabel();
}
public void updateLabel() {
SimpleDateFormat format = new SimpleDateFormat("MMM yyyy");
labelText = format.format(showMonth.getTime());
label.setText(labelText);
}
class StepMonthListener implements ActionListener {
int increment = 0;
public StepMonthListener(int increment) {
this.increment = increment;
}
public void actionPerformed(ActionEvent e) {
if ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0) {
showMonth.roll(Calendar.YEAR, increment);
} else {
showMonth.roll(Calendar.MONTH, increment);
if (increment > 0 && showMonth.get(Calendar.MONTH) == Calendar.JANUARY) {
showMonth.roll(Calendar.YEAR, 1);
} else if (increment < 0 && showMonth.get(Calendar.MONTH) == Calendar.DECEMBER) {
showMonth.roll(Calendar.YEAR, -1);
}
}
updateLabel();
center.repaint();
}
}
}
class SelectedDateListener extends DataModelAdaptor {
public void dataModelChangeValue(DataModelEvent event) {
updateView();
}
}
class InputFieldListener implements KeyListener {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
try {
selectedDate.setText(inputField.getText());
} catch (Exception ex) {
}
}
}
class CenterMouseListener implements MouseListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
center.click(e.getPoint());
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
mouseDay = new Date(0);
repaint();
}
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
Calendar date = getDate(e.getPoint());
if (date == null) {
mouseDay = new Date(0);
} else {
Date day = date.getTime();
if (!sameDay(day, mouseDay)) {
mouseDay = day;
repaint();
}
}
}
}
class DirectionKeyListener implements KeyListener {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
long increment = 0;
if (e.getKeyCode() == KeyEvent.VK_UP) {
increment = -7;
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
increment = 7;
} else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
increment = -1;
} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
increment = 1;
}
Date d = selectedDate.getDate();
d.setTime(d.getTime() + increment * DAY_MILLIS);
setDate(d);
inputField.setText(output.getText());
}
}
class TodayButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
selectedDate.setDate(cal.getTime());
inputField.setText(output.getText());
}
}
public static void main(String[] argv) {
String plaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
try {
UIManager.setLookAndFeel(plaf);
} catch (Exception e) {
System.out.println("Can't set '" + plaf + "' look and feel");
System.exit(0);
}
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(new DateChooserPanel());
frame.pack();
frame.setVisible(true);
}
}