OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Comparer les révisions

Ignorer les espaces blanc Révision 136 → Révision 137

/trunk/jOpenCalendar/.project
Nouveau fichier
0,0 → 1,17
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>jOpenCalendar</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
/trunk/jOpenCalendar/src/org/jopencalendar/test/DatePickerTest.java
Nouveau fichier
0,0 → 1,30
package org.jopencalendar.test;
 
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
 
import org.jopencalendar.ui.DatePicker;
 
public class DatePickerTest {
 
public static void main(String[] args) {
final Runnable r = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(new DatePicker(true, true));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
 
}
/trunk/jOpenCalendar/src/org/jopencalendar/test/WeekViewTest.java
Nouveau fichier
0,0 → 1,135
package org.jopencalendar.test;
 
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
 
import org.jopencalendar.model.JCalendarItem;
import org.jopencalendar.ui.JCalendarItemProvider;
import org.jopencalendar.ui.WeekView;
import org.jopencalendar.ui.WeekViewHeader;
 
public class WeekViewTest {
 
/**
* @param args
*/
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
JFrame f = new JFrame();
f.setSize(1024, 768);
final JScrollPane contentPane = new JScrollPane();
 
final JCalendarItemProvider manager = new JCalendarItemProvider("WeekViewTest") {
@Override
public List<JCalendarItem> getItemInWeek(int week, int year) {
List<JCalendarItem> l = new ArrayList<JCalendarItem>();
Calendar c = Calendar.getInstance();
c.clear();
//
c.set(2013, 11, 1, 0, 0, 0);
JCalendarItem i1 = new JCalendarItem();
i1.setDtStart(c);
c.set(2014, 0, 3, 0, 0, 0);
i1.setDtEnd(c);
i1.setDayOnly(true);
i1.setSummary("1/11/13-3/1/14");
i1.setDescription("Ceci est un test");
l.add(i1);
//
c.set(2014, 0, 2, 0, 0, 0);
JCalendarItem i2 = new JCalendarItem();
i2.setDtStart(c);
c.set(2014, 0, 4, 0, 0, 0);
i2.setDtEnd(c);
i2.setDayOnly(true);
i2.setSummary("2/1/14-4/1/14");
l.add(i2);
//
c.set(2014, 0, 5, 0, 0, 0);
JCalendarItem i3 = new JCalendarItem();
i3.setDtStart(c);
c.set(2014, 0, 5, 0, 0, 0);
i3.setDtEnd(c);
i3.setDayOnly(true);
i3.setSummary("5/1/14-5/1/14");
i3.setDescription("Hello world");
l.add(i3);
 
//
c.set(2014, 0, 5, 12, 0, 0);
JCalendarItem i4 = new JCalendarItem();
i4.setDtStart(c);
c.set(2014, 0, 5, 13, 0, 0);
i4.setDtEnd(c);
 
i4.setSummary("5/12/14 12h-13h");
i4.setDescription("Hello world");
l.add(i4);
 
//
c.set(2014, 0, 1, 11, 0, 0);
JCalendarItem i5 = new JCalendarItem();
i5.setDtStart(c);
c.set(2014, 0, 3, 13, 0, 0);
i5.setDtEnd(c);
 
i5.setSummary("1/12/14 11h - 3/12/14 13h");
i5.setDescription("Hello world");
l.add(i5);
//
c.set(2014, 0, 5, 10, 0, 0);
JCalendarItem i6 = new JCalendarItem();
i6.setDtStart(c);
c.set(2014, 0, 5, 16, 0, 0);
i6.setDtEnd(c);
 
i6.setSummary("5/12/14 10h-16h");
i6.setDescription("Hello world");
l.add(i6);
return l;
}
};
final WeekView view = new WeekView(manager);
contentPane.setColumnHeaderView(new WeekViewHeader(view));
contentPane.setViewportView(view);
final MouseWheelListener[] l = contentPane.getMouseWheelListeners();
for (int i = 0; i < l.length; i++) {
MouseWheelListener string = l[i];
contentPane.removeMouseWheelListener(string);
}
contentPane.addMouseWheelListener(new MouseWheelListener() {
 
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
view.mouseWheelMoved(e, l);
}
});
 
f.setContentPane(contentPane);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
f.setVisible(true);
 
view.loadWeek(1, 2014, false);
 
final int value = 300;
contentPane.getVerticalScrollBar().setValue(value);
}
};
SwingUtilities.invokeLater(r);
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/test/CalendarWithToolbarTest.java
Nouveau fichier
0,0 → 1,57
package org.jopencalendar.test;
 
import java.util.List;
 
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
 
import org.jopencalendar.model.JCalendarItemPart;
import org.jopencalendar.ui.JCalendarItemProvider;
import org.jopencalendar.ui.CalendarWithToolBar;
import org.jopencalendar.ui.JPopupMenuProvider;
import org.jopencalendar.ui.PrintJComponentAction;
import org.jopencalendar.ui.WeekView;
 
public class CalendarWithToolbarTest {
 
/**
* @param args
*/
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
final JFrame f = new JFrame();
f.setSize(1024, 768);
final CalendarWithToolBar contentPane = new CalendarWithToolBar(new JCalendarItemProvider("Test"));
final WeekView view = contentPane.getWeekView();
view.setHourRange(6, 20);
view.setPopupMenuProvider(new JPopupMenuProvider() {
 
@Override
public JPopupMenu getPopup(List<JCalendarItemPart> selectedItems, List<JCalendarItemPart> currentColumnParts) {
System.err.println("CalendarWithToolbarTest.selected: " + selectedItems);
System.err.println("CalendarWithToolbarTest.inColumn: " + currentColumnParts);
JPopupMenu popup = new JPopupMenu();
for (JCalendarItemPart item : selectedItems) {
popup.add(new JMenuItem(item.getItem().getSummary()));
}
popup.add(new PrintJComponentAction(contentPane.getContentPane()));
return popup;
}
});
f.setContentPane(contentPane);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/test/DayViewTest.java
Nouveau fichier
0,0 → 1,69
package org.jopencalendar.test;
 
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
 
import org.jopencalendar.ui.JCalendarItemProvider;
import org.jopencalendar.ui.DayView;
import org.jopencalendar.ui.MultipleDayViewHeader;
 
public class DayViewTest {
 
/**
* @param args
*/
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
JFrame f = new JFrame();
f.setSize(1024, 768);
final JScrollPane contentPane = new JScrollPane();
 
List<JCalendarItemProvider> managers = new ArrayList<JCalendarItemProvider>();
for (int i = 0; i < 5; i++) {
final JCalendarItemProvider manager = new JCalendarItemProvider("DayViewTest" + i);
managers.add(manager);
}
 
final DayView view = new DayView(managers);
contentPane.setColumnHeaderView(new MultipleDayViewHeader(view));
contentPane.setViewportView(view);
final MouseWheelListener[] l = contentPane.getMouseWheelListeners();
for (int i = 0; i < l.length; i++) {
MouseWheelListener string = l[i];
contentPane.removeMouseWheelListener(string);
}
contentPane.addMouseWheelListener(new MouseWheelListener() {
 
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
view.mouseWheelMoved(e, l);
}
});
 
f.setContentPane(contentPane);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
f.setVisible(true);
 
view.loadDay(1, 2015);
 
final int value = 300;
contentPane.getVerticalScrollBar().setValue(value);
}
};
SwingUtilities.invokeLater(r);
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/model/JCalendarItemGroup.java
Nouveau fichier
0,0 → 1,72
package org.jopencalendar.model;
 
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
 
public class JCalendarItemGroup {
private List<JCalendarItem> items = new ArrayList<JCalendarItem>();
private String name;
private Object cookie;
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
 
public void addItem(JCalendarItem item) {
if (item == null) {
throw new IllegalArgumentException("item cannot be null");
}
if (!this.items.contains(item)) {
this.items.add(item);
if (item.getGroup() != this) {
item.setGroup(this);
}
 
}
}
 
@Override
public String toString() {
return getName();
}
 
public boolean removeItem(JCalendarItem item) {
if (item == null) {
throw new IllegalArgumentException("item cannot be null");
}
if (item.getGroup() != null) {
item.setGroup(null);
}
return this.items.remove(item);
}
 
public int getItemCount() {
return this.items.size();
}
 
public JCalendarItem getItem(int index) {
return this.items.get(index);
}
 
public Object getCookie() {
return this.cookie;
}
 
public void setCookie(Object cookie) {
this.cookie = cookie;
}
 
public static List<JCalendarItemGroup> getGroups(List<JCalendarItem> items) {
LinkedHashSet<JCalendarItemGroup> set = new LinkedHashSet<JCalendarItemGroup>();
for (JCalendarItem jCalendarItem : items) {
set.add(jCalendarItem.getGroup());
}
return new ArrayList<JCalendarItemGroup>(set);
}
 
}
/trunk/jOpenCalendar/src/org/jopencalendar/model/JCalendarItem.java
Nouveau fichier
0,0 → 1,159
package org.jopencalendar.model;
 
import java.awt.Color;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
public class JCalendarItem {
private String summary;
private String description;
private String location;
private Calendar dtStart;
private Calendar dtEnd;
private JCalendarItemGroup group;
private boolean isDayOnly;
private List<Flag> flags = new ArrayList<Flag>();
private Color color = Color.DARK_GRAY;
private Object cookie;
private Object userId;
private String uid;
 
public String getUId() {
return this.uid;
}
 
public void setUId(String uid) {
this.uid = uid;
}
 
public String getSummary() {
return summary;
}
 
public void setSummary(String summary) {
this.summary = summary;
}
 
public String getDescription() {
return description;
}
 
public void setDescription(String description) {
this.description = description;
}
 
public String getLocation() {
return location;
}
 
public void setLocation(String location) {
this.location = location;
}
 
public Calendar getDtStart() {
return dtStart;
}
 
public void setDtStart(Calendar dtStart) {
this.dtStart = (Calendar) dtStart.clone();
fixDayOnly(isDayOnly);
}
 
public Calendar getDtEnd() {
return dtEnd;
}
 
public void setDtEnd(Calendar dtEnd) {
this.dtEnd = (Calendar) dtEnd.clone();
fixDayOnly(isDayOnly);
}
 
public void setGroup(JCalendarItemGroup group) {
if (group == this.group) {
return;
}
if (this.group != null) {
this.group.removeItem(this);
}
this.group = group;
if (this.group != null) {
this.group.addItem(this);
}
}
 
public JCalendarItemGroup getGroup() {
return group;
}
 
public boolean isDayOnly() {
return isDayOnly;
}
 
public void setDayOnly(boolean isDayOnly) {
this.isDayOnly = isDayOnly;
fixDayOnly(isDayOnly);
}
 
private void fixDayOnly(boolean isDayOnly) {
if (isDayOnly) {
this.dtStart.set(Calendar.HOUR_OF_DAY, 0);
this.dtStart.set(Calendar.MINUTE, 0);
this.dtStart.set(Calendar.SECOND, 0);
this.dtStart.set(Calendar.MILLISECOND, 0);
 
this.dtEnd.set(Calendar.HOUR_OF_DAY, 23);
this.dtEnd.set(Calendar.MINUTE, 59);
this.dtEnd.set(Calendar.SECOND, 59);
this.dtEnd.set(Calendar.MILLISECOND, 999);
}
}
 
public void addFlag(Flag f) {
if (f == null) {
throw new IllegalArgumentException("Flag cannot be null");
}
flags.add(f);
}
 
public Color getColor() {
return this.color;
}
 
public void setColor(Color color) {
this.color = color;
}
 
public void removeFlag(Flag f) {
flags.remove(f);
}
 
public Object getUserId() {
return userId;
}
 
public void setUserId(Object userId) {
this.userId = userId;
}
 
public Object getCookie() {
return this.cookie;
}
 
public void setCookie(Object cookie) {
this.cookie = cookie;
}
 
@Override
public String toString() {
return getDtStart().getTime() + " - " + getDtEnd().getTime() + " " + isDayOnly;
}
 
public boolean hasFlag(Flag flag) {
return flags.contains(flag);
}
 
public List<Flag> getFlags() {
return new ArrayList<Flag>(flags);
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/model/JCalendar.java
Nouveau fichier
0,0 → 1,25
package org.jopencalendar.model;
 
import java.util.ArrayList;
import java.util.List;
 
public class JCalendar {
private List<JCalendarItemGroup> groups = new ArrayList<JCalendarItemGroup>();
 
public void addGroup(JCalendarItemGroup g) {
this.groups.add(g);
}
 
public void removeGroup(JCalendarItemGroup g) {
this.groups.remove(g);
}
 
public int getGroupCount() {
return this.groups.size();
}
 
public JCalendarItemGroup getGroup(int index) {
return this.groups.get(index);
}
 
}
/trunk/jOpenCalendar/src/org/jopencalendar/model/Flag.java
Nouveau fichier
0,0 → 1,46
package org.jopencalendar.model;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.swing.Icon;
 
public class Flag {
private String typeId;
private Icon icon;
private String name;
private String description;
private static Map<String, Flag> map = new HashMap<String, Flag>();
 
public Flag(String typeId, Icon icon, String name, String description) {
super();
this.typeId = typeId;
this.icon = icon;
this.name = name;
this.description = description;
}
 
public String getTypeId() {
return typeId;
}
 
public Icon getIcon() {
return icon;
}
 
public String getName() {
return name;
}
 
public String getDescription() {
return description;
}
 
public synchronized static Flag getFlag(String id) {
return map.get(id);
}
 
public synchronized static void register(Flag f) {
map.put(f.typeId, f);
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/model/JCalendarItemPart.java
Nouveau fichier
0,0 → 1,63
package org.jopencalendar.model;
 
public class JCalendarItemPart {
 
private final JCalendarItem item;
private final int year;
private final int dayOfYear;
private final int startHour, startMinute;
private final int durationInMinute;
 
/**
* Part of a JCalendarItem
* */
public JCalendarItemPart(JCalendarItem item, int year, int dayOfYear, int startHour, int startMinute, int durationInMinute) {
if (item == null) {
throw new IllegalArgumentException("null item");
}
this.item = item;
this.year = year;
this.dayOfYear = dayOfYear;
this.startHour = startHour;
this.startMinute = startMinute;
this.durationInMinute = durationInMinute;
}
 
public final JCalendarItem getItem() {
return item;
}
 
public final int getYear() {
return year;
}
 
public final int getDayOfYear() {
return dayOfYear;
}
 
public final int getStartHour() {
return startHour;
}
 
public final int getStartMinute() {
return startMinute;
}
 
public final int getDurationInMinute() {
return durationInMinute;
}
 
public boolean conflictWith(JCalendarItemPart p) {
if (p.year != year || p.dayOfYear != dayOfYear) {
return false;
}
if ((startHour * 60 + startMinute + durationInMinute) <= (p.startHour * 60 + p.startMinute)) {
return false;
}
if ((p.startHour * 60 + p.startMinute + p.durationInMinute) <= (startHour * 60 + startMinute)) {
return false;
}
return true;
}
 
}
/trunk/jOpenCalendar/src/org/jopencalendar/print/CalendarItemPage.java
Nouveau fichier
0,0 → 1,45
package org.jopencalendar.print;
 
import java.util.ArrayList;
import java.util.List;
import org.jopencalendar.model.JCalendarItem;
 
public class CalendarItemPage {
 
private final List<JCalendarItem> items = new ArrayList<JCalendarItem>();
private final List<Double> heights = new ArrayList<Double>();
private final List<Boolean> showDates = new ArrayList<Boolean>();
private int pageIndex;
 
public void add(JCalendarItem item) {
items.add(item);
}
 
public List<JCalendarItem> getItems() {
return items;
}
 
public void addHeight(Double h) {
heights.add(h);
}
 
public List<Double> getHeights() {
return heights;
}
 
public void addShowDate(Boolean showDate) {
showDates.add(showDate);
}
 
public List<Boolean> getShowDates() {
return showDates;
}
 
public int getPageIndex() {
return pageIndex;
}
 
public void setPageIndex(int pageIndex) {
this.pageIndex = pageIndex;
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/print/CalendarItemPrinter.java
Nouveau fichier
0,0 → 1,415
package org.jopencalendar.print;
 
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Pageable;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
 
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.PrintQuality;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
 
import org.jopencalendar.LayoutUtils;
import org.jopencalendar.model.Flag;
import org.jopencalendar.model.JCalendarItem;
 
public class CalendarItemPrinter implements Printable, Pageable {
 
private List<JCalendarItem> items;
 
private List<CalendarItemPage> pages = null;
 
private String title;
 
private boolean showDuration = true;
 
private PageFormat pf;
 
public CalendarItemPrinter(String title, List<JCalendarItem> items, PageFormat pf) {
this.title = title;
this.items = items;
this.pf = pf;
}
 
public String getTitle() {
return title;
}
 
public static final Font FONT_NORMAL = new Font("Arial", Font.PLAIN, 11);
public static final Font FONT_BOLD = FONT_NORMAL.deriveFont(Font.BOLD);
 
public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
 
if (pages == null) {
computeLayout(g, pf);
}
 
if (pageIndex >= pages.size()) {
return NO_SUCH_PAGE;
}
 
final Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
final CalendarItemPage page = this.pages.get(pageIndex);
 
printPage(g, pf, page);
 
/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}
 
public void printPage(Graphics g, PageFormat pf, final CalendarItemPage page) {
final Graphics2D g2d = (Graphics2D) g;
// Title
g.setFont(getTitleFont());
g.setColor(getTitleColor());
final int xTitle = ((int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(getTitle(), g2d).getWidth()) / 2;
g.drawString(getTitle(), xTitle, g2d.getFontMetrics().getHeight());
// Page number
g.setFont(getPageNumberFont());
g.setColor(getPageNumberColor());
int y = getTitleHeight();
final DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
final int size = page.getItems().size();
final String strPages = (page.getPageIndex() + 1) + " / " + pages.size();
int xStrPages = (int) pf.getImageableWidth() - (int) g2d.getFontMetrics().getStringBounds(strPages, g2d).getWidth();
g.drawString(strPages, xStrPages, g2d.getFontMetrics().getHeight());
 
final double hourColumnWidth = getHourColumnWidth();
for (int i = 0; i < size; i++) {
final JCalendarItem item = page.getItems().get(i);
final double lineHeight = page.getHeights().get(i);
int lY = y;
drawBackground(0, lY, (int) pf.getImageableWidth(), (int) lineHeight);
if (page.getShowDates().get(i)) {
g2d.setColor(getHourColor(item));
g.setFont(getHourFont(item));
int dateHeight = g2d.getFontMetrics().getHeight();
lY += dateHeight;
final String format = getDate(df, item);
g2d.drawString(format, 2, lY);
}
// Vertical bar
g2d.setColor(getVerticalBarColor(item));
g2d.drawLine((int) hourColumnWidth - 5, lY + 6, (int) hourColumnWidth - 5, (int) (y + lineHeight));
 
final Calendar dtStart = item.getDtStart();
final Calendar dtEnd = item.getDtEnd();
// Hour
g.setColor(getHourColor(item));
g.setFont(getHourFont(item));
final int hourY = lY + g2d.getFontMetrics().getHeight();
g2d.drawString(formatTime(dtStart) + " - " + formatTime(dtEnd), 3, hourY);
// Duration
if (this.showDuration) {
g.setColor(getDurationColor(item));
g.setFont(getDurationFont(item));
final int durationY = hourY + g2d.getFontMetrics().getHeight();
g2d.drawString(formatDuration(dtStart, dtEnd), 3, durationY);
}
 
final double maxWidth = pf.getImageableWidth() - hourColumnWidth;
// Summary
g.setFont(getLine1Font(item));
 
final List<String> l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), (int) maxWidth);
if (item.hasFlag(Flag.getFlag("warning"))) {
g2d.setColor(new Color(255, 249, 144));
g2d.fillRect((int) hourColumnWidth - 1, lY + 3, (int) maxWidth, (int) g2d.getFontMetrics().getHeight() * l1.size());
}
g.setColor(getLine1Color(item));
for (String string : l1) {
lY += g2d.getFontMetrics().getHeight();
g2d.drawString(string, (int) hourColumnWidth, lY);
}
// Description
g.setFont(getLine2Font(item));
g.setColor(getLine2Color(item));
final List<String> l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), (int) maxWidth);
for (String string : l2) {
lY += g2d.getFontMetrics().getHeight();
g2d.drawString(string, (int) hourColumnWidth, lY);
}
//
y += lineHeight;
}
}
 
public String getDate(final DateFormat df, final JCalendarItem item) {
return LayoutUtils.firstUp(df.format(item.getDtStart().getTime()));
}
 
public String formatDuration(Calendar dtStart, Calendar dtEnd) {
long t2 = dtEnd.getTimeInMillis();
long t1 = dtStart.getTimeInMillis();
long seconds = (t2 - t1) / 1000;
 
final long minutes = seconds / 60;
 
String l = String.valueOf(minutes % 60);
if (l.length() < 2) {
l = "0" + l;
}
return "(" + minutes / 60 + "h" + l + ")";
}
 
public void drawBackground(int x, int y, int w, int h) {
// for subclass to add some background
}
 
public Color getPageNumberColor() {
return Color.BLACK;
}
 
public Font getPageNumberFont() {
return FONT_NORMAL;
}
 
// Title
public Color getTitleColor() {
return Color.BLACK;
}
 
public Font getTitleFont() {
return FONT_NORMAL;
}
 
// Hour
public Color getHourColor(JCalendarItem item) {
return Color.BLACK;
}
 
public Font getHourFont(JCalendarItem item) {
return FONT_BOLD;
}
 
// Duration
public Color getDurationColor(JCalendarItem item) {
return Color.BLACK;
}
 
public Font getDurationFont(JCalendarItem item) {
return FONT_NORMAL;
}
 
// Line 1
public Color getLine1Color(final JCalendarItem item) {
return Color.BLACK;
}
 
public String getLine1Text(final JCalendarItem item) {
return item.getSummary();
}
 
public Font getLine1Font(final JCalendarItem item) {
return FONT_NORMAL;
}
 
// Line 2
public Color getLine2Color(final JCalendarItem item) {
return Color.BLACK;
}
 
public String getLine2Text(final JCalendarItem item) {
return item.getDescription();
}
 
public Font getLine2Font(final JCalendarItem item) {
return FONT_NORMAL;
}
 
public Color getVerticalBarColor(final JCalendarItem item) {
return new Color(0, 68, 128);
}
 
public void setShowDuration(boolean showDuration) {
this.showDuration = showDuration;
}
 
public String formatTime(final Calendar dtStart) {
String h = String.valueOf(dtStart.get(Calendar.HOUR_OF_DAY));
String m = String.valueOf(dtStart.get(Calendar.MINUTE));
if (h.length() < 2) {
h = " " + h;
}
if (m.length() < 2) {
m = "0" + m;
}
return h + ":" + m;
}
 
private void computeLayout(Graphics g, PageFormat pf) {
pages = new ArrayList<CalendarItemPage>();
CalendarItemPage page = new CalendarItemPage();
this.pages.add(page);
if (items.isEmpty()) {
return;
}
double remainingHeight = pf.getImageableHeight() - getTitleHeight();
boolean showDate = true;
Calendar c = Calendar.getInstance();
c.setTimeInMillis(this.items.get(0).getDtStart().getTimeInMillis());
for (int i = 0; i < this.items.size(); i++) {
JCalendarItem item = this.items.get(i);
if (i > 0) {
showDate = (item.getDtStart().get(Calendar.YEAR) != c.get(Calendar.YEAR) || item.getDtStart().get(Calendar.DAY_OF_YEAR) != c.get(Calendar.DAY_OF_YEAR));
}
c = item.getDtStart();
double h = getPrintHeight(g, pf, item);
double secureMargin = 20D;
if (remainingHeight < h + secureMargin) {
page = new CalendarItemPage();
showDate = true;
remainingHeight = pf.getImageableHeight() - getTitleHeight();
this.pages.add(page);
}
if (showDate) {
g.setFont(getHourFont(item));
h += g.getFontMetrics().getHeight();
}
remainingHeight -= h;
 
page.add(item);
page.addHeight(Double.valueOf(h));
page.addShowDate(showDate);
}
 
}
 
public int getHourColumnWidth() {
return 90;
}
 
public int getTitleHeight() {
return 40;
}
 
private double getPrintHeight(Graphics g, PageFormat pf, JCalendarItem item) {
double maxWidth = pf.getImageableWidth() - getHourColumnWidth();
g.setFont(this.getLine1Font(item));
int l1 = LayoutUtils.wrap(getLine1Text(item), g.getFontMetrics(), (int) maxWidth).size();
g.setFont(this.getLine2Font(item));
int l2 = LayoutUtils.wrap(getLine2Text(item), g.getFontMetrics(), (int) maxWidth).size();
return (l1 + l2) * g.getFontMetrics().getHeight();
}
 
public List<CalendarItemPage> getPages() {
return pages;
}
 
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
 
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
final JFrame f = new JFrame("Printing Pagination Example");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton printButton = new JButton("Print test pages");
printButton.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
List<JCalendarItem> items = new ArrayList<JCalendarItem>();
Calendar c = Calendar.getInstance();
Flag.register(new Flag("warning", null, "Warning", "A default warning"));
for (int i = 0; i < 50; i++) {
JCalendarItem item = new JCalendarItem();
item.setSummary("Item " + i);
StringBuilder d = new StringBuilder();
d.append("Description");
for (int j = 0; j < i; j++) {
if (i % 2 == 0)
d.append(" Hello");
else
d.append(" World");
}
d.append("END");
if (i % 6 == 0) {
item.addFlag(Flag.getFlag("warning"));
}
item.setDescription(d.toString());
item.setDtStart(c);
c.add(Calendar.HOUR_OF_DAY, 1);
item.setDtEnd(c);
c.add(Calendar.HOUR_OF_DAY, 1);
items.add(item);
}
final PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
printAttributes.add(PrintQuality.HIGH);
job.setPrintable(new CalendarItemPrinter("OpenConcerto", items, job.getPageFormat(printAttributes)));
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
ex.printStackTrace();
}
}
 
}
});
f.add("Center", printButton);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
 
public List<JCalendarItem> getItems() {
return this.items;
}
 
@Override
public int getNumberOfPages() {
if (this.pages == null) {
BufferedImage off_Image = new BufferedImage((int) pf.getHeight(), (int) pf.getWidth(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = off_Image.createGraphics();
computeLayout(g2, pf);
}
return this.pages.size();
}
 
@Override
public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
return this.pf;
}
 
@Override
public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
final CalendarItemPage page = this.pages.get(pageIndex);
return new Printable() {
 
@Override
public int print(Graphics graphics, PageFormat pageFormat, int i) throws PrinterException {
final Graphics2D g2d = (Graphics2D) graphics;
g2d.translate(pf.getImageableX(), pf.getImageableY());
printPage(graphics, pageFormat, page);
return PAGE_EXISTS;
}
};
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/ui/MultipleDayViewHeader.java
Nouveau fichier
0,0 → 1,24
package org.jopencalendar.ui;
 
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
 
public class MultipleDayViewHeader extends Component {
 
private MultipleDayView view;
 
public MultipleDayViewHeader(MultipleDayView view) {
this.view = view;
}
 
@Override
public void paint(Graphics g) {
view.paintHeader(g);
}
 
@Override
public Dimension getPreferredSize() {
return new Dimension(view.getPreferredSize().width + 100, view.getHeaderHeight());
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/ui/YearActivityPanel.java
Nouveau fichier
0,0 → 1,249
package org.jopencalendar.ui;
 
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.print.PageFormat;
import java.text.DateFormat;
import java.util.Calendar;
 
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.OrientationRequested;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
 
import org.jopencalendar.model.JCalendarItemGroup;
 
public class YearActivityPanel extends JPanel {
private final FixedColumnTable fixedColumnTable;
private JPanel toolbar = new JPanel();
private int year, week2, week1;
private YearActivityTableModel tableModel;
private String title;
private JButton bPrint;
 
public YearActivityPanel(final JCalendarItemProvider manager, final int year) {
this.setLayout(new GridBagLayout());
this.year = year;
this.week1 = 1;
this.week2 = 53;
tableModel = new YearActivityTableModel(manager, year);
final int squareSize = 12;
this.fixedColumnTable = new FixedColumnTable(1, tableModel);
fixedColumnTable.setShowHorizontalLines(false);
fixedColumnTable.setRowHeight(50);
 
Calendar mycal = Calendar.getInstance();
mycal.set(Calendar.YEAR, year);
 
// Get the number of days in that month
for (int i = 1; i < 13; i++) {
mycal.set(Calendar.MONTH, i - 1);
final int daysInMonth = mycal.getActualMaximum(Calendar.DAY_OF_MONTH);
final int w = squareSize * daysInMonth;
fixedColumnTable.setColumnWidth(i, w);
fixedColumnTable.setColumnMinWidth(i, w);
fixedColumnTable.setColumnMaxWidth(i, w);
fixedColumnTable.getColumn(i).setCellRenderer(new MonthActivityStatesCellRenderer(squareSize));
}
fixedColumnTable.setReorderingAllowed(false);
// Scroll to first non null value on double click
fixedColumnTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
int row = fixedColumnTable.getSelectedRow();
for (int i = 1; i < 13; i++) {
final Object value = tableModel.getValueAt(row, i);
final MonthActivityStates m = (MonthActivityStates) value;
if (m.getList() != null) {
fixedColumnTable.ensureVisible(row, i - 1);
break;
}
}
}
 
}
});
 
// Tooltip to show the date
fixedColumnTable.addMouseMotionListener(new MouseAdapter() {
final Calendar c = Calendar.getInstance();
int lastDay = -1;
int lastYear = -1;
 
@Override
public void mouseMoved(MouseEvent evt) {
int d = 1 + evt.getX() / squareSize;
int y = getYear();
if (lastDay != d || lastYear != y) {
c.clear();
c.set(Calendar.YEAR, y);
c.set(Calendar.DAY_OF_YEAR, d);
final String text = DateFormat.getDateInstance(DateFormat.FULL).format(c.getTime());
fixedColumnTable.setToolTipTextOnHeader(text);
lastDay = d;
lastYear = y;
}
}
 
});
 
this.toolbar = createToolbar();
 
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(this.toolbar, c);
c.gridy++;
this.add(new JSeparator(JSeparator.HORIZONTAL), c);
c.gridy++;
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
this.add(fixedColumnTable, c);
}
 
public JCalendarItemGroup getJCalendarItemGroupAt(int index) {
return this.tableModel.getJCalendarItemGroupAt(index);
}
 
public FixedColumnTable getTable() {
return fixedColumnTable;
}
 
public int getYear() {
return this.year;
}
 
public int getWeek1() {
return week1;
}
 
public int getWeek2() {
return week2;
}
 
public void setWeek1(int week1) {
this.week1 = week1;
tableModel.loadContent(this.year, this.week1, this.week2);
}
 
public void setWeek2(int week2) {
this.week2 = week2;
tableModel.loadContent(this.year, this.week1, this.week2);
}
 
public void setTitle(String title) {
this.title = title;
}
 
public void reload() {
tableModel.loadContent(this.year, this.week1, this.week2);
}
 
public void setPrintButtonVisible(boolean b) {
bPrint.setVisible(b);
}
 
public JPanel createToolbar() {
final JPanel p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.LEFT));
p.add(new JLabel("Année"));
final JSpinner spinYear = new JSpinner(new SpinnerNumberModel(year, 1000, 5000, 1));
spinYear.addChangeListener(new ChangeListener() {
 
@Override
public void stateChanged(ChangeEvent e) {
int y = ((Number) spinYear.getValue()).intValue();
setYear(y);
 
}
});
p.add(spinYear);
 
p.add(new JLabel("Semaine"));
final JSpinner spinWeek1 = new JSpinner(new SpinnerNumberModel(1, 1, 53, 1));
spinWeek1.addChangeListener(new ChangeListener() {
 
@Override
public void stateChanged(ChangeEvent e) {
int y = ((Number) spinWeek1.getValue()).intValue();
setWeek1(y);
 
}
});
p.add(spinWeek1);
 
p.add(new JLabel("à"));
final JSpinner spinWeek2 = new JSpinner(new SpinnerNumberModel(53, 1, 53, 1));
spinWeek2.addChangeListener(new ChangeListener() {
 
@Override
public void stateChanged(ChangeEvent e) {
int y = ((Number) spinWeek2.getValue()).intValue();
setWeek2(y);
 
}
});
p.add(spinWeek2);
 
bPrint = new JButton("Imprimer");
bPrint.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent arg0) {
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
printAttributes.add(OrientationRequested.LANDSCAPE);
 
final PrintJComponentAction a = new PrintJComponentAction(YearActivityPanel.this.fixedColumnTable, PageFormat.LANDSCAPE, YearActivityPanel.this.title);
a.actionPerformed(arg0);
}
});
p.add(bPrint);
p.setOpaque(false);
return p;
}
 
protected void setYear(int y) {
this.year = y;
tableModel.loadContent(this.year, this.week1, this.week2);
}
 
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e1) {
e1.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final YearActivityPanel contentPane = new YearActivityPanel(new JCalendarItemProvider("Test 2015"), 2015);
contentPane.getTable().setColumnMinWidth(0, 200);
contentPane.getTable().setColumnWidth(0, 500);
contentPane.setTitle("Planning Gant");
f.setContentPane(contentPane);
f.setSize(1024, 768);
f.setVisible(true);
}
});
 
}
}
/trunk/jOpenCalendar/src/org/jopencalendar/ui/left.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/jOpenCalendar/src/org/jopencalendar/ui/left.png
Nouveau fichier
Changements de propriété:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: jOpenCalendar/src/org/jopencalendar/ui/ItemPartHoverListener.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/ItemPartHoverListener.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/ItemPartHoverListener.java (revision 137)
@@ -0,0 +1,9 @@
+package org.jopencalendar.ui;
+
+import org.jopencalendar.model.JCalendarItemPart;
+
+public interface ItemPartHoverListener {
+
+ public void mouseOn(JCalendarItemPart newSelection);
+
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/WeekViewHeader.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/WeekViewHeader.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/WeekViewHeader.java (revision 137)
@@ -0,0 +1,24 @@
+package org.jopencalendar.ui;
+
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+
+public class WeekViewHeader extends Component {
+
+ private WeekView view;
+
+ public WeekViewHeader(WeekView view) {
+ this.view = view;
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ view.paintHeader(g);
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(view.getPreferredSize().width + 100, view.getHeaderHeight());
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/calendar_small.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jOpenCalendar/src/org/jopencalendar/ui/calendar_small.png
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/calendar_small.png (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/calendar_small.png (revision 137)
/jOpenCalendar/src/org/jopencalendar/ui/calendar_small.png
Changements de propriété:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: jOpenCalendar/src/org/jopencalendar/ui/ItemPartViewLayouter.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/ItemPartViewLayouter.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/ItemPartViewLayouter.java (revision 137)
@@ -0,0 +1,29 @@
+package org.jopencalendar.ui;
+
+import java.util.List;
+
+public class ItemPartViewLayouter {
+
+ public void layout(List<ItemPartView> items) {
+ final int size = items.size();
+ int maxX = 0;
+ for (int i = 0; i < size; i++) {
+ ItemPartView p = items.get(i);
+ for (int j = 0; j < i; j++) {
+ ItemPartView layoutedPart = items.get(j);
+ if (layoutedPart.conflictWith(p)) {
+ if (layoutedPart.getX() == p.getX()) {
+ p.setX(Math.max(p.getX(), layoutedPart.getX() + 1));
+ if (maxX < p.getX()) {
+ maxX = p.getX();
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < size; i++) {
+ ItemPartView p = items.get(i);
+ p.setMaxColumn(maxX + 1);
+ }
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/YearActivityTableModel.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/YearActivityTableModel.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/YearActivityTableModel.java (revision 137)
@@ -0,0 +1,135 @@
+package org.jopencalendar.ui;
+
+import java.text.DateFormatSymbols;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.swing.SwingWorker;
+import javax.swing.table.AbstractTableModel;
+
+import org.jopencalendar.LayoutUtils;
+import org.jopencalendar.model.JCalendarItem;
+import org.jopencalendar.model.JCalendarItemGroup;
+
+public class YearActivityTableModel extends AbstractTableModel {
+ private List<JCalendarItemGroup> groups = new ArrayList<JCalendarItemGroup>();
+ private List<List<MonthActivityStates>> states;
+ private int year;
+ private JCalendarItemProvider calendarManager;
+
+ public YearActivityTableModel(JCalendarItemProvider c, int year) {
+ this.calendarManager = c;
+ loadContent(year);
+ }
+
+ public void loadContent(final int year) {
+ loadContent(year, 1, 53);
+ }
+
+ public void loadContent(final int year, final int week1, final int week2) {
+ this.year = year;
+ final SwingWorker<List<JCalendarItemGroup>, Object> w = new SwingWorker<List<JCalendarItemGroup>, Object>() {
+
+ @Override
+ protected List<JCalendarItemGroup> doInBackground() throws Exception {
+ final List<JCalendarItem> item = calendarManager.getItemInYear(year, week1, week2);
+ Collections.sort(item, new Comparator<JCalendarItem>() {
+ @Override
+ public int compare(JCalendarItem o1, JCalendarItem o2) {
+ return o1.getDtStart().compareTo(o2.getDtStart());
+ }
+
+ });
+
+ final List<JCalendarItemGroup> groups = JCalendarItemGroup.getGroups(item);
+ return groups;
+ }
+
+ protected void done() {
+ try {
+ final List<JCalendarItemGroup> l = get();
+ setItems(l);
+ } catch (Exception e) {
+ throw new IllegalStateException("error while getting items", e);
+ }
+
+ };
+ };
+ w.execute();
+ }
+
+ protected void setItems(List<JCalendarItemGroup> groups) {
+ this.groups = new ArrayList<JCalendarItemGroup>(groups);
+ this.states = new ArrayList<List<MonthActivityStates>>(groups.size());
+ for (JCalendarItemGroup group : groups) {
+ final List<MonthActivityStates> s = createMonthActivityStates(group);
+ this.states.add(s);
+ }
+ fireTableDataChanged();
+ }
+
+ private List<MonthActivityStates> createMonthActivityStates(JCalendarItemGroup group) {
+ final Calendar monthStart = Calendar.getInstance();
+ monthStart.clear();
+ monthStart.set(Calendar.YEAR, this.year);
+ monthStart.set(Calendar.DAY_OF_YEAR, 1);
+ final Calendar monthEnd = Calendar.getInstance();
+ monthEnd.clear();
+ monthEnd.set(Calendar.YEAR, this.year);
+ monthEnd.set(Calendar.DAY_OF_YEAR, 1);
+ monthEnd.add(Calendar.MONTH, 1);
+ final List<MonthActivityStates> result = new ArrayList<MonthActivityStates>(12);
+ for (int i = 0; i < 12; i++) {
+ MonthActivityStates s = new MonthActivityStates(i, year);
+
+ int size = group.getItemCount();
+ for (int j = 0; j < size; j++) {
+ JCalendarItem jCalendarItem = group.getItem(j);
+ Calendar start = jCalendarItem.getDtStart();
+ Calendar end = jCalendarItem.getDtEnd();
+ if (!(end.compareTo(monthStart) <= 0 || start.compareTo(monthEnd) >= 0)) {
+ s.set(jCalendarItem);
+ }
+ }
+ result.add(s);
+
+ monthStart.add(Calendar.MONTH, 1);
+ monthEnd.add(Calendar.MONTH, 1);
+ }
+
+ return result;
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ if (columnIndex == 0) {
+ return "";
+ }
+ return LayoutUtils.firstUp(DateFormatSymbols.getInstance().getMonths()[columnIndex - 1]) + " " + this.year;
+ }
+
+ public JCalendarItemGroup getJCalendarItemGroupAt(int rowIndex) {
+ return this.groups.get(rowIndex);
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (columnIndex == 0) {
+ return this.groups.get(rowIndex);
+ }
+ return this.states.get(rowIndex).get(columnIndex - 1);
+ }
+
+ @Override
+ public int getRowCount() {
+ return this.groups.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 13;
+ }
+};
\ No newline at end of file
Index: jOpenCalendar/src/org/jopencalendar/ui/DayView.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/DayView.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/DayView.java (revision 137)
@@ -0,0 +1,143 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.swing.Scrollable;
+import javax.swing.SwingWorker;
+
+import org.jopencalendar.model.JCalendarItem;
+
+public class DayView extends MultipleDayView implements Scrollable {
+
+ private final List<JCalendarItemProvider> providers;
+ // Current day
+ private int dayOfYear;
+ private int year;
+
+ public DayView(List<JCalendarItemProvider> providers) {
+ if (providers == null) {
+ throw new IllegalArgumentException("null providers");
+ }
+ this.providers = providers;
+ }
+
+ /**
+ * Load day
+ *
+ */
+ public void loadDay(final int dayOfYear, final int year) {
+ this.dayOfYear = dayOfYear;
+ this.year = year;
+
+ final int columnCount = this.getColumnCount();
+
+ SwingWorker<List<List<JCalendarItem>>, Object> w = new SwingWorker<List<List<JCalendarItem>>, Object>() {
+
+ @Override
+ protected List<List<JCalendarItem>> doInBackground() throws Exception {
+ List<List<JCalendarItem>> l = new ArrayList<List<JCalendarItem>>(columnCount);
+ for (int i = 0; i < columnCount; i++) {
+ List<JCalendarItem> items = providers.get(i).getItemInDay(dayOfYear, year);
+ l.add(items);
+ }
+ return l;
+ }
+
+ protected void done() {
+ try {
+ List<List<JCalendarItem>> l = get();
+ setItems(l);
+ } catch (Exception e) {
+ throw new IllegalStateException("error while getting items", e);
+ }
+
+ };
+ };
+ w.execute();
+ }
+
+ public void paintHeader(Graphics g) {
+
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, this.getWidth() + 100, getHeaderHeight());
+ g.setColor(Color.GRAY);
+ // Vertical lines
+ int columnCount = getColumnCount();
+ if (columnCount < 1) {
+ return;
+ }
+ int x = HOURS_LABEL_WIDTH;
+
+ for (int i = 0; i < columnCount - 1; i++) {
+ x += getColumnWidth(i);
+ g.drawLine(x, YEAR_HEIGHT, x, this.getHeaderHeight());
+ }
+ g.setColor(Color.DARK_GRAY);
+ // Text : month & year
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setFont(getFont().deriveFont(13f));
+
+ String strTitle = getTitle();
+
+ Rectangle r = g.getFontMetrics().getStringBounds(strTitle, g).getBounds();
+ int w = 0;
+ for (int i = 0; i < getColumnCount(); i++) {
+ w += getColumnWidth(i);
+ }
+ g.drawString(strTitle, (int) (HOURS_LABEL_WIDTH + (w - r.getWidth()) / 2), 15);
+
+ // Text : day
+ final Font font1 = getFont().deriveFont(12f);
+ g.setFont(font1);
+ x = HOURS_LABEL_WIDTH;
+ Rectangle clipRect = g.getClipBounds();
+ for (int i = 0; i < columnCount; i++) {
+ String str = getColumnTitle(i);
+ int columnWidth = getColumnWidth(i);
+ g.setClip(x, YEAR_HEIGHT, columnWidth - 1, YEAR_HEIGHT + 20);
+ // Centering
+ int x2 = (int) (x + (columnWidth - r.getWidth()) / 2);
+ // If no room, left align
+ if (x2 < x + 2) {
+ x2 = x + 2;
+ }
+ g.drawString(str, x2, YEAR_HEIGHT + 15);
+ x += columnWidth;
+ }
+ g.setClip(clipRect);
+ paintHeaderAlldays(g);
+ }
+
+ public void reload() {
+ loadDay(this.dayOfYear, this.year);
+ }
+
+ @Override
+ public String getColumnTitle(int index) {
+ return providers.get(index).getName();
+ }
+
+ @Override
+ public String getTitle() {
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, this.year);
+ c.set(Calendar.DAY_OF_YEAR, this.dayOfYear);
+ return DateFormat.getDateInstance().format(c.getTime());
+ }
+
+ @Override
+ public int getColumnCount() {
+ return providers.size();
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/auto.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jOpenCalendar/src/org/jopencalendar/ui/auto.png
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/auto.png (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/auto.png (revision 137)
/jOpenCalendar/src/org/jopencalendar/ui/auto.png
Changements de propriété:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: jOpenCalendar/src/org/jopencalendar/ui/DatePicker.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/DatePicker.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/DatePicker.java (revision 137)
@@ -0,0 +1,356 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowFocusListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.text.DateFormat;
+import java.text.Format;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JFormattedTextField;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+public class DatePicker extends JPanel {
+
+ private JFormattedTextField text;
+ private JDialog dialog;
+ private long dialogLostFocusTime;
+ private DatePickerPanel pickerPanel;
+ private Date date;
+ private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
+ private static final long RELEASE_TIME_MS = 500;
+ private JButton button;
+
+ public DatePicker() {
+ this(true);
+ }
+
+ public DatePicker(boolean useEditor) {
+ this(useEditor, false);
+ }
+
+ public DatePicker(boolean useEditor, boolean fillWithCurrentDate) {
+ this(DateFormat.getDateInstance(), useEditor, fillWithCurrentDate);
+ }
+
+ public DatePicker(Format dateFormat, boolean useEditor, boolean fillWithCurrentDate) {
+ this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
+ this.setOpaque(false);
+ if (useEditor) {
+ text = new JFormattedTextField(dateFormat);
+ text.setColumns(12);
+ text.addPropertyChangeListener("value", new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ setDate((Date) evt.getNewValue());
+ }
+ });
+ this.add(text);
+ JPanel spacer = new JPanel();
+ spacer.setOpaque(false);
+ spacer.setMinimumSize(new Dimension(3, 5));
+ spacer.setPreferredSize(new Dimension(3, 5));
+ this.add(spacer);
+ }
+
+ final ImageIcon icon = new ImageIcon(this.getClass().getResource("calendar.png"));
+ button = new JButton(new AbstractAction(null, icon) {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ final JComponent source = (JComponent) e.getSource();
+
+ if (text != null) {
+ // if the button isn't focusable, no FOCUS_LOST will occur and the text won't
+ // get
+ // committed (or reverted). So act as if the user requested a commit, so that
+ // invalidEdit() can be called (usually causing a beep).
+ if (!source.isFocusable()) {
+ for (final Action a : text.getActions()) {
+ final String name = (String) a.getValue(Action.NAME);
+ if (JTextField.notifyAction.equals(name))
+ a.actionPerformed(new ActionEvent(text, e.getID(), null));
+ }
+ }
+
+ // if after trying to commit, the value is invalid then don't show the popup
+ if (!text.isEditValid())
+ return;
+ }
+ if (dialog == null) {
+ final JDialog d = new JDialog(SwingUtilities.getWindowAncestor(DatePicker.this));
+ pickerPanel = new DatePickerPanel();
+
+ d.setContentPane(pickerPanel);
+ d.setUndecorated(true);
+ pickerPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
+ d.setSize(220, 180);
+
+ pickerPanel.addPropertyChangeListener(DatePickerPanel.TIME_IN_MILLIS, new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (!DatePicker.this.isEditable())
+ return;
+ final Long millis = (Long) evt.getNewValue();
+ final Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(millis);
+ setDate(c.getTime());
+ if (dialog != null) {
+ dialog.dispose();
+ dialog = null;
+ }
+ fireActionPerformed();
+ }
+
+ });
+ d.addWindowFocusListener(new WindowFocusListener() {
+
+ public void windowGainedFocus(WindowEvent e) {
+ // do nothing
+ }
+
+ public void windowLostFocus(WindowEvent e) {
+ if (dialog != null) {
+ final Window oppositeWindow = e.getOppositeWindow();
+ if (oppositeWindow != null && SwingUtilities.isDescendingFrom(oppositeWindow, dialog)) {
+ return;
+ }
+ dialog.dispose();
+ dialog = null;
+ }
+ dialogLostFocusTime = System.currentTimeMillis();
+ }
+
+ });
+ dialog = d;
+ }
+ // Set picker panel date
+ final Calendar calendar = Calendar.getInstance();
+ if (date != null) {
+ calendar.setTime(date);
+ pickerPanel.setSelectedDate(calendar);
+ } else {
+ pickerPanel.setSelectedDate(null);
+ }
+ // Show dialog
+ final int x = source.getLocation().x;
+ final int y = source.getLocation().y + source.getHeight();
+ Point p = new Point(x, y);
+ SwingUtilities.convertPointToScreen(p, DatePicker.this);
+ p = adjustPopupLocationToFitScreen(p.x, p.y, dialog.getSize(), source.getSize());
+ dialog.setLocation(p.x, p.y);
+ final long time = System.currentTimeMillis() - dialogLostFocusTime;
+ if (time > RELEASE_TIME_MS) {
+ dialog.setVisible(true);
+ } else {
+ dialogLostFocusTime = System.currentTimeMillis() - RELEASE_TIME_MS;
+ }
+ }
+
+ });
+ button.setContentAreaFilled(false);
+ button.setOpaque(false);
+ button.setFocusable(false);
+ button.setBorder(BorderFactory.createEmptyBorder());
+ this.add(button);
+
+ // init & synchronize text field
+ setDate(fillWithCurrentDate ? new Date() : null, true);
+ }
+
+ public void setDate(Date date) {
+ this.setDate(date, false);
+ }
+
+ public void setButtonVisible(boolean b) {
+ this.button.setVisible(b);
+ }
+
+ private void setDate(Date date, boolean force) {
+ Date oldDate = this.date;
+ if (force || !equals(oldDate, date)) {
+ this.date = date;
+ if (text != null) {
+ text.setValue(date);
+ }
+ firePropertyChange("value", oldDate, date);
+ }
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public JFormattedTextField getEditor() {
+ return text;
+ }
+
+ public void setEditable(boolean b) {
+ if (this.text != null) {
+ this.text.setEditable(b);
+ }
+ }
+
+ public boolean isEditable() {
+ if (this.text != null) {
+ return this.text.isEditable();
+ }
+ return true;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ for (final Component c : this.getComponents())
+ c.setEnabled(enabled);
+ }
+
+ public void addActionListener(ActionListener listener) {
+ this.actionListeners.add(listener);
+
+ }
+
+ public void removeActionListener(ActionListener listener) {
+ this.actionListeners.remove(listener);
+
+ }
+
+ public void fireActionPerformed() {
+ for (ActionListener l : actionListeners) {
+ l.actionPerformed(new ActionEvent(this, 0, "dateChanged"));
+ }
+ }
+
+ /**
+ * Tries to find GraphicsConfiguration that contains the mouse cursor position. Can return null.
+ */
+ private GraphicsConfiguration getCurrentGraphicsConfiguration(Point popupLocation) {
+ GraphicsConfiguration gc = null;
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice[] gd = ge.getScreenDevices();
+ for (int i = 0; i < gd.length; i++) {
+ if (gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
+ GraphicsConfiguration dgc = gd[i].getDefaultConfiguration();
+ if (dgc.getBounds().contains(popupLocation)) {
+ gc = dgc;
+ break;
+ }
+ }
+ }
+
+ return gc;
+ }
+
+ /**
+ * Returns an point which has been adjusted to take into account of the desktop bounds, taskbar
+ * and multi-monitor configuration.
+ * <p>
+ * This adustment may be cancelled by invoking the application with
+ * -Djavax.swing.adjustPopupLocationToFit=false
+ *
+ * @param popupSize
+ */
+ Point adjustPopupLocationToFitScreen(int xPosition, int yPosition, Dimension popupSize, Dimension buttonSize) {
+ Point popupLocation = new Point(xPosition, yPosition);
+
+ if (GraphicsEnvironment.isHeadless()) {
+ return popupLocation;
+ }
+
+ // Get screen bounds
+ Rectangle scrBounds;
+ GraphicsConfiguration gc = getCurrentGraphicsConfiguration(popupLocation);
+ Toolkit toolkit = Toolkit.getDefaultToolkit();
+ if (gc != null) {
+ // If we have GraphicsConfiguration use it to get screen bounds
+ scrBounds = gc.getBounds();
+ } else {
+ // If we don't have GraphicsConfiguration use primary screen
+ scrBounds = new Rectangle(toolkit.getScreenSize());
+ }
+
+ // Calculate the screen size that popup should fit
+
+ long popupRightX = (long) popupLocation.x + (long) popupSize.width;
+ long popupBottomY = (long) popupLocation.y + (long) popupSize.height;
+ int scrWidth = scrBounds.width;
+ int scrHeight = scrBounds.height;
+
+ // Insets include the task bar. Take them into account.
+ Insets scrInsets = toolkit.getScreenInsets(gc);
+ scrBounds.x += scrInsets.left;
+ scrBounds.y += scrInsets.top;
+ scrWidth -= scrInsets.left + scrInsets.right;
+ scrHeight -= scrInsets.top + scrInsets.bottom;
+
+ int scrRightX = scrBounds.x + scrWidth;
+ int scrBottomY = scrBounds.y + scrHeight;
+
+ // Ensure that popup menu fits the screen
+ if (popupRightX > (long) scrRightX) {
+ popupLocation.x = scrRightX - popupSize.width;
+ popupLocation.y = popupLocation.y - buttonSize.height - popupSize.height - 2;
+ }
+
+ if (popupBottomY > (long) scrBottomY) {
+ popupLocation.y = scrBottomY - popupSize.height;
+ if (popupRightX + buttonSize.width < (long) scrRightX) {
+ popupLocation.x += buttonSize.width;
+ }
+ }
+
+ if (popupLocation.x < scrBounds.x) {
+ popupLocation.x = scrBounds.x;
+ }
+
+ if (popupLocation.y < scrBounds.y) {
+ popupLocation.y = scrBounds.y;
+ }
+
+ return popupLocation;
+ }
+
+ public void commitEdit() throws ParseException {
+ if (text != null) {
+ this.text.commitEdit();
+ }
+ }
+
+ static public final boolean equals(Object o1, Object o2) {
+ if (o1 == null && o2 == null)
+ return true;
+ if (o1 == null || o2 == null)
+ return false;
+ return o1.equals(o2);
+ }
+
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/calendar.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jOpenCalendar/src/org/jopencalendar/ui/calendar.png
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/calendar.png (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/calendar.png (revision 137)
/jOpenCalendar/src/org/jopencalendar/ui/calendar.png
Changements de propriété:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: jOpenCalendar/src/org/jopencalendar/ui/DateLabel.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/DateLabel.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/DateLabel.java (revision 137)
@@ -0,0 +1,22 @@
+package org.jopencalendar.ui;
+
+import java.util.Calendar;
+
+import javax.swing.JLabel;
+
+public class DateLabel extends JLabel {
+ private static final long serialVersionUID = -5010955735639970080L;
+ private long time;
+
+ public DateLabel(String label, int align) {
+ super(label, align);
+ }
+
+ public void setDate(Calendar cal) {
+ this.time = cal.getTimeInMillis();
+ }
+
+ public long getTimeInMillis() {
+ return time;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/JCalendarItemProvider.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/JCalendarItemProvider.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/JCalendarItemProvider.java (revision 137)
@@ -0,0 +1,227 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.swing.ImageIcon;
+
+import org.jopencalendar.model.Flag;
+import org.jopencalendar.model.JCalendarItem;
+import org.jopencalendar.model.JCalendarItemGroup;
+
+public class JCalendarItemProvider {
+ private String name;
+
+ public JCalendarItemProvider(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<JCalendarItem> getItemInDay(int dayOfYear, int year) {
+ List<JCalendarItem> l = new ArrayList<JCalendarItem>();
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.DAY_OF_YEAR, dayOfYear);
+ cal.add(Calendar.HOUR_OF_DAY, 8);
+ int gCount = 0;
+ JCalendarItemGroup g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ Flag flag = new Flag("planned", new ImageIcon(JCalendarItemProvider.class.getResource("calendar_small.png")), "Planned", "planned item");
+ for (int d = 0; d < 8; d++) {
+ JCalendarItem i = new JCalendarItem();
+ i.addFlag(flag);
+ i.setSummary(year + ": day " + dayOfYear);
+ i.setDtStart(cal);
+ Calendar cal2 = (Calendar) cal.clone();
+ cal2.add(Calendar.HOUR_OF_DAY, 1);
+ i.setDtEnd(cal2);
+ i.setDayOnly(false);
+ g.addItem(i);
+ l.add(i);
+ if (d % 3 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+ if (d % 2 == 0) {
+ i.setLocation("Location" + d);
+ }
+ }
+
+ return l;
+ }
+
+ /**
+ * @param week 1 - 52
+ * @param year
+ */
+ public List<JCalendarItem> getItemInWeek(int week, int year) {
+ final List<JCalendarItem> l = new ArrayList<JCalendarItem>();
+ JCalendarItem i = new JCalendarItem();
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.WEEK_OF_YEAR, week);
+ cal.set(Calendar.HOUR_OF_DAY, 8);
+ cal.set(Calendar.MINUTE, 0);
+ i.setSummary("In W: " + week + " year:" + year);
+ i.setDtStart(cal);
+ Calendar cal2 = (Calendar) cal.clone();
+ cal2.add(Calendar.HOUR_OF_DAY, 1);
+ i.setDtEnd(cal2);
+ i.setDayOnly(true);
+ l.add(i);
+ int gCount = 0;
+ JCalendarItemGroup g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ final Flag flag = new Flag("planned", new ImageIcon(JCalendarItemProvider.class.getResource("calendar_small.png")), "Planned", "planned item");
+
+ for (int d = 1; d < 6; d++) {
+ {
+ JCalendarItem item = new JCalendarItem();
+ item.addFlag(flag);
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.WEEK_OF_YEAR, week);
+ cal.set(Calendar.HOUR_OF_DAY, 7);
+ cal.set(Calendar.MINUTE, 0);
+ cal.add(Calendar.DAY_OF_WEEK, d);
+ item.setSummary(year + ": day " + d);
+ item.setDtStart(cal);
+ Calendar c2 = (Calendar) cal.clone();
+ c2.set(Calendar.HOUR_OF_DAY, 7 + d);
+ item.setDtEnd(c2);
+ item.setDayOnly(false);
+ g.addItem(item);
+ l.add(item);
+ if (d % 2 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+ if (d % 2 == 0) {
+ i.setLocation("Location" + d);
+ }
+ }
+ {
+ JCalendarItem item = new JCalendarItem();
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.WEEK_OF_YEAR, week);
+ cal.set(Calendar.HOUR_OF_DAY, 7);
+ cal.set(Calendar.MINUTE, 0);
+ cal.add(Calendar.DAY_OF_WEEK, d);
+ item.setSummary(year + ": day " + d);
+ item.setDtStart(cal);
+ Calendar c2 = (Calendar) cal.clone();
+ c2.set(Calendar.HOUR_OF_DAY, 7 + d);
+ item.setDtEnd(c2);
+ item.setDayOnly(false);
+ g.addItem(item);
+ l.add(item);
+ if (d % 2 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+ }
+ {
+ JCalendarItem item = new JCalendarItem();
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.WEEK_OF_YEAR, week);
+ cal.set(Calendar.HOUR_OF_DAY, 7);
+ cal.set(Calendar.MINUTE, 0);
+ cal.add(Calendar.DAY_OF_WEEK, d);
+ item.setSummary(year + ": day " + d);
+ item.setDtStart(cal);
+ Calendar c2 = (Calendar) cal.clone();
+ c2.set(Calendar.HOUR_OF_DAY, 7 + d);
+ item.setDtEnd(c2);
+ item.setDayOnly(false);
+ g.addItem(item);
+ l.add(item);
+ if (d % 2 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+ }
+ {
+ JCalendarItem item = new JCalendarItem();
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.WEEK_OF_YEAR, week);
+ cal.set(Calendar.HOUR_OF_DAY, 8);
+ cal.set(Calendar.MINUTE, 0);
+ cal.add(Calendar.DAY_OF_WEEK, d);
+ item.setSummary(year + ": day " + d);
+ item.setDtStart(cal);
+ Calendar c2 = (Calendar) cal.clone();
+ c2.set(Calendar.HOUR_OF_DAY, 8 + d);
+ item.setDtEnd(c2);
+ item.setDayOnly(false);
+ g.addItem(item);
+ l.add(item);
+ if (d % 2 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+ }
+ }
+
+ return l;
+ }
+
+ public List<JCalendarItem> getItemInYear(int year, int week1, int week2) {
+ List<JCalendarItem> l = new ArrayList<JCalendarItem>();
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ int gCount = 0;
+ JCalendarItemGroup g = new JCalendarItemGroup();
+ JCalendarItemGroup g0 = g;
+ g.setName("Group " + gCount);
+ for (int d = 1; d < 350; d++) {
+ JCalendarItem i = new JCalendarItem();
+ cal.set(Calendar.DAY_OF_YEAR, d);
+ cal.set(Calendar.HOUR_OF_DAY, 8);
+ cal.set(Calendar.MINUTE, 0);
+ i.setSummary(year + ": day " + d);
+ i.setDtStart(cal);
+ Calendar cal2 = (Calendar) cal.clone();
+ cal2.add(Calendar.HOUR_OF_DAY, 1);
+ i.setDtEnd(cal2);
+ i.setDayOnly(false);
+ g.addItem(i);
+ l.add(i);
+ if (d % 8 == 0) {
+ gCount++;
+ g = new JCalendarItemGroup();
+ g.setName("Group " + gCount);
+ }
+
+ }
+ JCalendarItem i = new JCalendarItem();
+ i.setColor(Color.RED);
+ cal.set(Calendar.DAY_OF_YEAR, 3);
+ cal.set(Calendar.HOUR_OF_DAY, 8);
+ cal.set(Calendar.MINUTE, 0);
+ i.setSummary(year + ": day " + 3);
+ i.setDtStart(cal);
+ Calendar cal2 = (Calendar) cal.clone();
+ cal2.add(Calendar.HOUR_OF_DAY, 1);
+ i.setDtEnd(cal2);
+ i.setDayOnly(false);
+ g0.addItem(i);
+ l.add(i);
+
+ return l;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/JComponentPrintable.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/JComponentPrintable.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/JComponentPrintable.java (revision 137)
@@ -0,0 +1,97 @@
+package org.jopencalendar.ui;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.AffineTransform;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+
+import javax.swing.JComponent;
+
+public class JComponentPrintable implements Printable {
+
+ private JComponent comp;
+ private final String title;
+
+ public JComponentPrintable(JComponent comp, String title) {
+ this.comp = comp;
+ this.title = title;
+ }
+
+ @Override
+ public int print(Graphics g, PageFormat pf, int pageNumber) throws PrinterException {
+ if (pageNumber > 0) {
+ return Printable.NO_SUCH_PAGE;
+ }
+ // Get the preferred size ofthe component...
+ Dimension compSize = comp.getSize();
+
+ // Make sure we size to the preferred size
+ comp.setSize(compSize);
+ // Get the the print size
+ Dimension printSize = new Dimension();
+ printSize.setSize(pf.getImageableWidth(), pf.getImageableHeight());
+
+ // Calculate the scale factor
+ double scaleFactor = getScaleFactorToFit(compSize, printSize);
+ // Don't want to scale up, only want to scale down
+ if (scaleFactor > 1d) {
+ scaleFactor = 1d;
+ }
+
+ // Calcaulte the scaled size...
+ double scaleWidth = (compSize.width * scaleFactor) - (this.title == null ? 0 : 0.08);
+ double scaleHeight = compSize.height * scaleFactor - (this.title == null ? 0 : 0.08);
+
+ // Create a clone of the graphics context. This allows us to manipulate
+ // the graphics context without begin worried about what effects
+ // it might have once we're finished
+ Graphics2D g2 = (Graphics2D) g.create();
+ // Calculate the x/y position of the component, this will center
+ // the result on the page if it can
+ double x = ((pf.getImageableWidth() - scaleWidth) / 2d) + pf.getImageableX();
+ double y = ((pf.getImageableHeight() - scaleHeight) / 2d) + pf.getImageableY() + (this.title == null ? 0 : 25);
+ // Create a new AffineTransformation
+ AffineTransform at = new AffineTransform();
+ // Translate the offset to out "center" of page
+ at.translate(x, y);
+ // Set the scaling
+ at.scale(scaleFactor, scaleFactor);
+ if (title != null) {
+ g2.drawString("Planning", 15, 20);
+ }
+ // Apply the transformation
+ g2.transform(at);
+
+ // Print the component
+ comp.printAll(g2);
+ // Dispose of the graphics context, freeing up memory and discarding
+ // our changes
+ g2.dispose();
+ comp.revalidate();
+ return Printable.PAGE_EXISTS;
+ }
+
+ private static final double getScaleFactorToFit(Dimension original, Dimension toFit) {
+ double dScale = 1d;
+ if (original != null && toFit != null) {
+ double dScaleWidth = getScaleFactor(original.width, toFit.width);
+ double dScaleHeight = getScaleFactor(original.height, toFit.height);
+ dScale = Math.min(dScaleHeight, dScaleWidth);
+ }
+ return dScale;
+ }
+
+ private static final double getScaleFactor(int iMasterSize, int iTargetSize) {
+ double dScale = 1;
+ if (iMasterSize > iTargetSize) {
+ dScale = (double) iTargetSize / (double) iMasterSize;
+ } else {
+ dScale = (double) iTargetSize / (double) iMasterSize;
+ }
+ return dScale;
+ }
+
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/JPopupMenuProvider.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/JPopupMenuProvider.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/JPopupMenuProvider.java (revision 137)
@@ -0,0 +1,13 @@
+package org.jopencalendar.ui;
+
+import java.util.List;
+
+import javax.swing.JPopupMenu;
+
+import org.jopencalendar.model.JCalendarItemPart;
+
+public interface JPopupMenuProvider {
+
+ public JPopupMenu getPopup(List<JCalendarItemPart> selectedItems, List<JCalendarItemPart> currentColumnParts);
+
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStatesCellRenderer.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStatesCellRenderer.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStatesCellRenderer.java (revision 137)
@@ -0,0 +1,93 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableCellRenderer;
+
+import org.jopencalendar.model.JCalendarItem;
+
+public class MonthActivityStatesCellRenderer extends DefaultTableCellRenderer {
+ private int squareSize;
+
+ MonthActivityStatesCellRenderer(int squareSize) {
+ this.squareSize = squareSize;
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, boolean hasFocus, final int row, final int column) {
+ JComponent c = new JPanel() {
+ @Override
+ public void paint(Graphics g) {
+
+ MonthActivityStates m = (MonthActivityStates) value;
+ if (!isSelected) {
+ g.setColor(Color.WHITE);
+ } else {
+ g.setColor(table.getSelectionBackground());
+ }
+ final int h = getHeight();
+ g.fillRect(0, 0, getWidth(), h);
+ // Week delimiters
+ List<Integer> lIndexes = m.getMondayIndex();
+
+ if (isSelected) {
+ g.setColor(Color.WHITE);
+ } else {
+ g.setColor(Color.LIGHT_GRAY);
+ }
+ // Draw Week number
+ if (row % 5 == 0) {
+ for (Integer integer : lIndexes) {
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, m.getYear());
+ c.set(Calendar.MONTH, m.getMonth());
+ c.set(Calendar.DAY_OF_MONTH, integer);
+ int w = c.get(Calendar.WEEK_OF_YEAR) + 1;
+ int x = 4 + integer * squareSize;
+ int y = 16;
+ g.drawString(String.valueOf(w), x, y);
+ }
+ }
+ //
+ for (Integer integer : lIndexes) {
+
+ int x = integer * squareSize;
+ if (x != 0) {
+ g.drawLine(x, 0, x, h / 2 - 2);
+ g.drawLine(x, h / 2 + 4, x, h - 4);
+ }
+ }
+ // Days
+ List<List<JCalendarItem>> l = m.getList();
+ if (l != null) {
+ int x = 0;
+
+ for (List<JCalendarItem> list : l) {
+ if (list != null) {
+ int y = 2;
+ int sh = (h - 1) / list.size();
+ for (JCalendarItem jCalendarItem : list) {
+ g.setColor(jCalendarItem.getColor());
+ g.fillRect(x, y, squareSize - 1, sh);
+ y += sh;
+ }
+
+ }
+ x += squareSize;
+ }
+ }
+
+ }
+ };
+
+ return c;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/right.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: jOpenCalendar/src/org/jopencalendar/ui/right.png
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/right.png (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/right.png (revision 137)
/jOpenCalendar/src/org/jopencalendar/ui/right.png
Changements de propriété:
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: jOpenCalendar/src/org/jopencalendar/ui/ItemPartView.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/ItemPartView.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/ItemPartView.java (revision 137)
@@ -0,0 +1,316 @@
+package org.jopencalendar.ui;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.swing.Icon;
+import javax.swing.JPanel;
+
+import org.jopencalendar.LayoutUtils;
+import org.jopencalendar.model.Flag;
+import org.jopencalendar.model.JCalendarItem;
+import org.jopencalendar.model.JCalendarItemPart;
+
+public class ItemPartView {
+ private static final BasicStroke STROKE_1 = new BasicStroke(1f);
+
+ private JCalendarItemPart itemPart;
+
+ private int column;
+
+ private int x;
+
+ private boolean hasTopBorder;
+ private boolean hasBottomBorder;
+
+ private Font fontSummary;
+ private Font fontDescription;
+
+ private Rectangle rectangle;
+ private boolean selected;
+
+ private List<ItemPartView> parts = new ArrayList<ItemPartView>();
+
+ private int maxColumn = 1;
+
+ private int width = 1;
+
+ public static final Color COLOR_HIGHLIGHT_BLUE = new Color(232, 242, 250);
+
+ /**
+ * Part of a JCalendarItem The item is split to 1 ItemPart per day
+ */
+ public ItemPartView(JCalendarItemPart itemPart) {
+ if (itemPart == null) {
+ throw new IllegalArgumentException("null itemPart");
+ }
+ this.itemPart = itemPart;
+ }
+
+ public Font getFontSummary() {
+ if (fontSummary == null) {
+ this.fontSummary = new Font("Arial", Font.BOLD, 12);
+ }
+ return fontSummary;
+ }
+
+ public void setFontSummary(Font fontSummary) {
+ this.fontSummary = fontSummary;
+ }
+
+ public Font getFontDescription() {
+ if (fontDescription == null) {
+ this.fontDescription = new Font("Arial", Font.PLAIN, 12);
+ }
+ return fontDescription;
+ }
+
+ public void setFontDescription(Font fontDescription) {
+ this.fontDescription = fontDescription;
+ }
+
+ public static List<ItemPartView> split(JCalendarItem item) {
+ if (!item.getDtStart().before(item.getDtEnd())) {
+ throw new IllegalArgumentException("Start is not before end. Start " + item.getDtStart().getTime() + " End " + item.getDtEnd().getTime());
+ }
+ final List<ItemPartView> result = new ArrayList<ItemPartView>();
+ final Calendar c = (Calendar) item.getDtStart().clone();
+ while (c.before(item.getDtEnd())) {
+ JCalendarItemPart itemPart = new JCalendarItemPart(item, c.get(Calendar.YEAR), c.get(Calendar.DAY_OF_YEAR), 0, 0, 0);
+ final ItemPartView pv = new ItemPartView(itemPart);
+ result.add(pv);
+ // next
+ c.add(Calendar.HOUR, 24);
+ }
+ final int size = result.size();
+ if (size == 0) {
+ throw new IllegalStateException("No part");
+ } else if (size == 1) {
+ final ItemPartView p = result.get(0);
+ int startHour = item.getDtStart().get(Calendar.HOUR_OF_DAY);
+ int startMinute = item.getDtStart().get(Calendar.MINUTE);
+ final int endH = item.getDtEnd().get(Calendar.HOUR_OF_DAY);
+ final int endM = item.getDtEnd().get(Calendar.MINUTE);
+ int durationInMinute = (endH * 60 + endM) - (startHour * 60 + startMinute);
+ p.setItemPart(new JCalendarItemPart(item, p.getYear(), p.getDayInYear(), startHour, startMinute, durationInMinute));
+ p.hasTopBorder = true;
+ p.hasBottomBorder = true;
+ } else {
+ // First
+ final ItemPartView p0 = result.get(0);
+
+ int p0StartHour = item.getDtStart().get(Calendar.HOUR_OF_DAY);
+ int p0StartMinute = item.getDtStart().get(Calendar.MINUTE);
+ int p0DurationInMinute = (24 * 60) - (p0StartHour * 60 + p0StartMinute);
+ p0.setItemPart(new JCalendarItemPart(item, p0.getYear(), p0.getDayInYear(), p0StartHour, p0StartMinute, p0DurationInMinute));
+
+ p0.hasTopBorder = true;
+ for (int i = 1; i < size - 1; i++) {
+ final ItemPartView p = result.get(i);
+ int pStartHour = 0;
+ int pStartMinute = 0;
+ int pDurationInMinute = 24 * 60;
+ p.setItemPart(new JCalendarItemPart(item, p.getYear(), p.getDayInYear(), pStartHour, pStartMinute, pDurationInMinute));
+ }
+
+ // Last
+ final ItemPartView pLast = result.get(size - 1);
+ int pLastStartHour = 0;
+ int pLastStartMinute = 0;
+ int pLastDurationInMinute = item.getDtEnd().get(Calendar.HOUR_OF_DAY) * 60 + item.getDtEnd().get(Calendar.MINUTE) * 60;
+ pLast.setItemPart(new JCalendarItemPart(item, pLast.getYear(), pLast.getDayInYear(), pLastStartHour, pLastStartMinute, pLastDurationInMinute));
+ pLast.hasBottomBorder = true;
+ }
+ for (ItemPartView itemPart : result) {
+ itemPart.setParts(result);
+ }
+ return result;
+ }
+
+ private void setParts(List<ItemPartView> result) {
+ this.parts.clear();
+ this.parts.addAll(result);
+
+ }
+
+ public void setColumnIndex(int column) {
+ this.column = column;
+
+ }
+
+ public int getColumn() {
+ return column;
+ }
+
+ public int getX() {
+ return this.x;
+ }
+
+ public void setX(int x) {
+ this.x = x;
+ }
+
+ public void draw(Graphics2D g2, int offsetX, int offsetY, int lineHeight, int columnWidth) {
+ int h = (lineHeight * getPart().getDurationInMinute()) / 60 - 1;
+ int w = (getWidth() * columnWidth) / getMaxColumn();
+ int colW = columnWidth / getMaxColumn();
+ final JCalendarItem item = this.itemPart.getItem();
+ final Color color = item.getColor();
+ if (isSelected()) {
+ g2.setColor(COLOR_HIGHLIGHT_BLUE);
+ } else {
+ g2.setColor(WeekView.WHITE_TRANSPARENCY_COLOR);
+ }
+ g2.setStroke(STROKE_1);
+ int y0 = (lineHeight * (this.getPart().getStartHour() * 60 + this.getPart().getStartMinute())) / 60;
+ final int x1 = offsetX + 2 + getX() * colW;
+ final int y1 = y0 + offsetY + 1;
+ final int y2 = y0 + offsetY + h;
+ this.setRect(x1, y1, w, h);
+ g2.fillRect(x1, y1, w - 2, h);
+ // Draw icons
+ List<Flag> flags = itemPart.getItem().getFlags();
+ List<Icon> icons = new ArrayList<Icon>();
+ for (Flag flag : flags) {
+ if (flag.getIcon() != null) {
+ icons.add(flag.getIcon());
+ }
+ }
+ final JPanel c = new JPanel();
+ int yIcon = y1 + h;
+ for (Icon icon : icons) {
+ if (w > icon.getIconWidth()) {
+
+ yIcon -= 1 + icon.getIconHeight();
+ if (yIcon > y1) {
+ icon.paintIcon(c, g2, x1 + w - 4 - icon.getIconWidth(), yIcon);
+ } else {
+ yIcon += 1 + icon.getIconHeight();
+ }
+ }
+ }
+
+ g2.setColor(color);
+ // Right
+ final int x2 = x1 + w - 4;
+ g2.fillRect(x2, y1, 1, h);
+ // Left
+ g2.fillRect(x1, y1, 6, h);
+ // Top
+ if (hasTopBorder) {
+ g2.drawLine(x1, y1, x2, y1);
+ }
+
+ // Bottom
+ if (hasBottomBorder) {
+ g2.drawLine(x1, y2, x2, y2);
+ }
+ // Test
+ String str = item.getSummary();
+ g2.setColor(Color.BLACK);
+ double y = y1;
+ int leftMargin = 8;
+ if (str != null) {
+ g2.setFont(getFontSummary());
+
+ List<String> lines = LayoutUtils.wrap(str, g2.getFontMetrics(), w - leftMargin - 5);
+ for (String string : lines) {
+
+ y += g2.getFontMetrics().getHeight();
+ if (y > y2) {
+ break;
+ }
+ g2.drawString(string, x1 + leftMargin, (int) y);
+
+ }
+ }
+ String str2 = item.getDescription();
+ if (item.getLocation() != null) {
+ str2 += "\n" + item.getLocation();
+ }
+ g2.setColor(Color.BLACK);
+ if (str2 != null) {
+ g2.setFont(getFontDescription());
+ List<String> lines = LayoutUtils.wrap(str2, g2.getFontMetrics(), w - leftMargin - 2);
+ for (String string : lines) {
+
+ y += g2.getFontMetrics().getHeight();
+ if (y > y2) {
+ break;
+ }
+ g2.drawString(string, x1 + leftMargin, (int) y);
+
+ }
+ }
+
+ }
+
+ public int getMaxColumn() {
+ return maxColumn;
+ }
+
+ public void setMaxColumn(int maxColumn) {
+ this.maxColumn = maxColumn;
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public void setWidth(int width) {
+ this.width = width;
+ }
+
+ private void setRect(int x, int y, int w, int h) {
+ Rectangle r = new Rectangle(x, y, w, h);
+ this.rectangle = r;
+ }
+
+ public boolean contains(int x, int y) {
+ if (rectangle == null) {
+ return false;
+ }
+ return this.rectangle.contains(x, y);
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ for (ItemPartView item : this.parts) {
+ if (item != this) {
+ if (item.isSelected() != selected) {
+ item.setSelected(selected);
+ }
+ }
+ }
+ }
+
+ public int getDayInYear() {
+ return this.itemPart.getDayOfYear();
+ }
+
+ public int getYear() {
+ return this.itemPart.getYear();
+ }
+
+ public boolean conflictWith(ItemPartView p) {
+ return this.itemPart.conflictWith(p.itemPart);
+ }
+
+ public JCalendarItemPart getPart() {
+ return this.itemPart;
+ }
+
+ public void setItemPart(JCalendarItemPart itemPart) {
+ this.itemPart = itemPart;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/MultipleDayView.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/MultipleDayView.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/MultipleDayView.java (revision 137)
@@ -0,0 +1,597 @@
+package org.jopencalendar.ui;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.Scrollable;
+import javax.swing.SwingUtilities;
+
+import org.jopencalendar.model.JCalendarItem;
+import org.jopencalendar.model.JCalendarItemPart;
+
+public abstract class MultipleDayView extends JPanel implements Scrollable {
+ public static final String CALENDARD_ITEMS_PROPERTY = "calendard_items_changed";
+ public final static Color WHITE_TRANSPARENCY_COLOR = new Color(255, 255, 255, 180);
+ public static final Color LIGHT_BLUE = new Color(202, 212, 220);
+ public final static Color LIGHT = new Color(222, 222, 222);
+ public static final int TITLE_HEIGHT = 20;
+ public static final int HOURS_LABEL_WIDTH = 50;
+
+ protected static final int YEAR_HEIGHT = 20;
+ private int deltaY = 10;
+ private int rowHeight = 44;
+
+ private List<List<AllDayItem>> allDayItems = new ArrayList<List<AllDayItem>>();
+ private List<List<ItemPartView>> itemParts = new ArrayList<List<ItemPartView>>();
+
+ private int allDayItemsRowCount;
+ public int allDayItemsRowHeight = 20;
+
+ private Set<ItemPartView> selectedItems = new HashSet<ItemPartView>();
+ // Right click menu
+ private JPopupMenuProvider popupProvider;
+
+ protected List<ItemPartHoverListener> hListeners = new ArrayList<ItemPartHoverListener>();
+ private int startHour = 0;
+ private int endHour = 24;
+
+ public MultipleDayView() {
+
+ this.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
+ if (newSelection != null) {
+ boolean isCurrentlySelected = newSelection.isSelected();
+ // Click on a non selected item
+ boolean ctrlPressed = ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK);
+ if (!ctrlPressed) {
+ deselectAll();
+ }
+ if (e.getButton() == MouseEvent.BUTTON1) {
+ if (isCurrentlySelected) {
+ // Click on a selected item
+ newSelection.setSelected(false);
+ selectedItems.remove(newSelection);
+ } else {
+ newSelection.setSelected(true);
+ selectedItems.add(newSelection);
+ }
+ } else {
+ newSelection.setSelected(true);
+ selectedItems.add(newSelection);
+ }
+ repaint();
+ }
+ // Deselect all if nothing is selected
+ if (newSelection == null && !selectedItems.isEmpty()) {
+ deselectAll();
+ repaint();
+ }
+ // For mac
+ showPopup(e);
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ showPopup(e);
+ }
+
+ private void showPopup(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
+ if (newSelection != null && !newSelection.isSelected()) {
+ newSelection.setSelected(true);
+ selectedItems.add(newSelection);
+ repaint();
+ }
+
+ if (popupProvider != null) {
+ // Selected parts
+ final List<JCalendarItemPart> sParts = new ArrayList<JCalendarItemPart>();
+ for (ItemPartView p : selectedItems) {
+ sParts.add(p.getPart());
+ }
+ // Current column parts
+ final List<JCalendarItemPart> currentColumnParts = new ArrayList<JCalendarItemPart>();
+ int columnIndex = getColumnIndex(e.getX());
+ List<ItemPartView> l = MultipleDayView.this.itemParts.get(columnIndex);
+ for (ItemPartView p : l) {
+ currentColumnParts.add(p.getPart());
+ }
+
+ JPopupMenu popup = popupProvider.getPopup(sParts, currentColumnParts);
+ if (popup != null) {
+ popup.show(MultipleDayView.this, e.getX(), e.getY());
+ }
+ }
+ }
+ }
+ });
+ this.addMouseMotionListener(new MouseAdapter() {
+ ItemPartView previous;
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ if (hListeners.isEmpty()) {
+ return;
+ }
+ ItemPartView newSelection = getItemPartAt(e.getX(), e.getY());
+
+ if (newSelection != previous) {
+
+ for (ItemPartHoverListener l : hListeners) {
+ if (newSelection == null) {
+ l.mouseOn(null);
+ } else {
+ l.mouseOn(newSelection.getPart());
+ }
+ }
+ previous = newSelection;
+ }
+
+ }
+
+ });
+
+ }
+
+ protected int getColumnIndex(int currentX) {
+ int x = HOURS_LABEL_WIDTH;
+ int columnCount = getColumnCount();
+ for (int i = 0; i < columnCount - 1; i++) {
+ x += getColumnWidth(i);
+ if (currentX < x) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ public void setHourRange(int start, int end) {
+ if (start < 0 || start > 24) {
+ throw new IllegalArgumentException("Bad start hour : " + start);
+ }
+ if (end < 0 || end > 24) {
+ throw new IllegalArgumentException("Bad end hour : " + end);
+ }
+ if (end - start < 1) {
+ throw new IllegalArgumentException("Bad end hour must be > (start + 1)");
+ }
+ this.startHour = start;
+ this.endHour = end;
+ repaint();
+ }
+
+ protected void setItems(List<List<JCalendarItem>> list) {
+ assert SwingUtilities.isEventDispatchThread();
+ this.itemParts.clear();
+ this.allDayItems.clear();
+ for (List<JCalendarItem> l : list) {
+ final List<AllDayItem> aDayItems = new ArrayList<AllDayItem>();
+ final List<ItemPartView> aItems = new ArrayList<ItemPartView>();
+ for (JCalendarItem jCalendarItem : l) {
+ if (jCalendarItem.getDtStart().before(jCalendarItem.getDtEnd())) {
+ if (jCalendarItem.isDayOnly()) {
+ aDayItems.add(new AllDayItem(jCalendarItem));
+ } else {
+ aItems.addAll(ItemPartView.split(jCalendarItem));
+ }
+ } else {
+ System.err.println(
+ "MultipleDayView.setItems() " + jCalendarItem.getSummary() + " start :" + jCalendarItem.getDtStart().getTime() + " after " + jCalendarItem.getDtEnd().getTime() + " !");
+ }
+ }
+ this.allDayItems.add(aDayItems);
+ this.itemParts.add(aItems);
+ }
+
+ layoutAllDayItems();
+ layoutItemParts();
+ // Tweak to force header to be relayouted and repainted
+ final Container parent = getParent().getParent();
+ final int w = parent.getSize().width;
+ final int h = parent.getSize().height;
+ parent.setSize(w + 1, h);
+ parent.validate();
+ parent.setSize(w, h);
+ parent.validate();
+ firePropertyChange(CALENDARD_ITEMS_PROPERTY, null, list);
+ }
+
+ private void layoutItemParts() {
+ ItemPartViewLayouter layouter = new ItemPartViewLayouter();
+ for (List<ItemPartView> items : itemParts) {
+ layouter.layout(items);
+ }
+
+ }
+
+ private void layoutAllDayItems() {
+ // final Calendar c = getFirstDayCalendar();
+ // Collections.sort(this.allDayItems, new Comparator<AllDayItem>() {
+ //
+ // @Override
+ // public int compare(AllDayItem o1, AllDayItem o2) {
+ // return o1.getLengthFrom(c) - o2.getLengthFrom(c);
+ // }
+ // });
+ // final int size = this.allDayItems.size();
+ // for (int i = 0; i < size; i++) {
+ // AllDayItem jCalendarItem = this.allDayItems.get(i);
+ // // set X and W
+ // Calendar start = jCalendarItem.getItem().getDtStart();
+ // Calendar end = jCalendarItem.getItem().getDtEnd();
+ // if (start.before(getFirstDayCalendar())) {
+ // start = getFirstDayCalendar();
+ // } else {
+ // jCalendarItem.setLeftBorder(true);
+ // }
+ //
+ // if (end.after(getAfterLastDayCalendar())) {
+ // end = getAfterLastDayCalendar();
+ // end.add(Calendar.MILLISECOND, -1);
+ // } else {
+ // jCalendarItem.setRightBorder(true);
+ // }
+ // int x = (int) (start.getTimeInMillis() - getFirstDayCalendar().getTimeInMillis());
+ // x = x / MILLIS_PER_DAY;
+ // jCalendarItem.setX(x);
+ // int l = ((int) (end.getTimeInMillis() - start.getTimeInMillis())) / MILLIS_PER_DAY + 1;
+ // jCalendarItem.setW(l);
+ //
+ // // Y and H
+ // jCalendarItem.setY(0);
+ // jCalendarItem.setH(1);
+ // for (int j = 0; j < i; j++) {
+ // AllDayItem layoutedItem = this.allDayItems.get(j);
+ // if (layoutedItem.conflictWith(jCalendarItem)) {
+ // jCalendarItem.setY(layoutedItem.getY() + 1);
+ // }
+ // }
+ // }
+ // allDayItemsRowCount = 0;
+ // for (int i = 0; i < size; i++) {
+ // AllDayItem jCalendarItem = this.allDayItems.get(i);
+ // if (jCalendarItem.getY() + jCalendarItem.getH() > allDayItemsRowCount) {
+ // allDayItemsRowCount = jCalendarItem.getY() + jCalendarItem.getH();
+ // }
+ // }
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(800, TITLE_HEIGHT + (this.endHour - this.startHour) * rowHeight);
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ float[] dash4 = { 8f, 4f };
+
+ BasicStroke bs4 = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dash4, 1f);
+
+ final BasicStroke s = new BasicStroke(1f);
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, this.getWidth(), this.getHeight());
+ int columnCount = getColumnCount();
+ if (columnCount < 1)
+ return;
+
+ g2.setStroke(s);
+ // H lines : Hours
+ int y = deltaY;
+ int hourPaintedCount = this.endHour - this.startHour;
+ for (int i = 0; i < hourPaintedCount; i++) {
+ g.setColor(Color.LIGHT_GRAY);
+ g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
+ y += rowHeight;
+ }
+ // H lines : 1/2 Hours
+ y = deltaY + rowHeight / 2;
+ if (rowHeight > 44) {
+ g2.setStroke(s);
+ } else {
+ g2.setStroke(bs4);
+ }
+ g.setColor(LIGHT);
+ for (int i = 0; i < hourPaintedCount; i++) {
+ g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
+ y += rowHeight;
+ }
+
+ if (rowHeight > 44) {
+ g2.setStroke(bs4);
+ y = deltaY + rowHeight / 4;
+ for (int i = 0; i < hourPaintedCount * 2; i++) {
+ g.drawLine(HOURS_LABEL_WIDTH, y, this.getWidth(), y);
+ y += rowHeight / 2;
+ }
+ }
+
+ // Horizontal lines : 5 minutes
+ g.setColor(Color.LIGHT_GRAY);
+ if (rowHeight > 120) {
+ g2.setStroke(s);
+ final float h5 = rowHeight / 12f;
+
+ // int w = this.getWidth();
+ int x = HOURS_LABEL_WIDTH;
+ for (int j = 0; j < columnCount - 1; j++) {
+ x += getColumnWidth(j);
+ y = deltaY + (int) h5;
+ int x2 = x + 10;
+ for (int i = 0; i < 24; i++) {
+ float y1 = y;
+ g.drawLine(x, (int) y1, x2, (int) y1);
+ y1 += h5;
+ g.drawLine(x, (int) y1, x2, (int) y1);
+ y1 += 2 * h5;
+ g.drawLine(x, (int) y1, x2, (int) y1);
+ y1 += h5;
+ g.drawLine(x, (int) y1, x2, (int) y1);
+ y += rowHeight / 2;
+ }
+ }
+ }
+
+ // Hours : text on left
+ g2.setStroke(s);
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setFont(getFont().deriveFont(14f));
+ y = deltaY + 6;
+ g.setColor(Color.GRAY);
+ for (int i = this.startHour; i < this.endHour; i++) {
+ g.drawString(getHourLabel(i), 5, y);
+ y += rowHeight;
+ }
+ // Vertical lines
+ int x = HOURS_LABEL_WIDTH;
+
+ for (int i = 0; i < columnCount - 1; i++) {
+ x += getColumnWidth(i);
+ g.drawLine(x, 0, x, this.getHeight());
+ }
+ int dY = deltaY - this.startHour * rowHeight;
+ for (int i = 0; i < this.itemParts.size(); i++) {
+ List<ItemPartView> items = this.itemParts.get(i);
+ final int columnWidth = getColumnWidth(i);
+ // Draw standard items
+ for (ItemPartView jCalendarItem : items) {
+ final int itemX = getColumnX(i);
+ jCalendarItem.draw(g2, itemX, dY, rowHeight, columnWidth);
+ }
+ }
+
+ }
+
+ String getHourLabel(int i) {
+ if (i < 10) {
+ return "0" + i + ":00";
+ }
+ return String.valueOf(i) + ":00";
+ }
+
+ public int getColumnWidth(int column) {
+ final int c = (this.getWidth() - HOURS_LABEL_WIDTH) / getColumnCount();
+
+ return c;
+ }
+
+ public int getColumnX(int column) {
+ int x = HOURS_LABEL_WIDTH;
+ for (int i = 0; i < column; i++) {
+ x += getColumnWidth(i);
+
+ }
+ return x;
+ }
+
+ public void paintHeader(Graphics g) {
+
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, this.getWidth() + 100, getHeaderHeight());
+ g.setColor(Color.GRAY);
+ // Vertical lines
+ int columnCount = getColumnCount();
+ int x = HOURS_LABEL_WIDTH;
+
+ for (int i = 0; i < columnCount - 1; i++) {
+ x += getColumnWidth(i);
+ g.drawLine(x, YEAR_HEIGHT, x, this.getHeaderHeight());
+ }
+ g.setColor(Color.DARK_GRAY);
+ // Text : month & year
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setFont(getFont().deriveFont(13f));
+
+ String strTitle = getTitle();
+ Rectangle r = g.getFontMetrics().getStringBounds(strTitle, g).getBounds();
+ int w = 0;
+ for (int i = 0; i < getColumnCount(); i++) {
+ w += getColumnWidth(i);
+ }
+ g.drawString(strTitle, (int) (HOURS_LABEL_WIDTH + (w - r.getWidth()) / 2), 15);
+
+ // Text : day
+ final Font font1 = getFont().deriveFont(12f);
+ g.setFont(font1);
+ x = HOURS_LABEL_WIDTH;
+ Rectangle clipRect = g.getClipBounds();
+ for (int i = 0; i < columnCount; i++) {
+ String str = getColumnTitle(i);
+ r = g.getFontMetrics().getStringBounds(str, g).getBounds();
+ int columnWidth = getColumnWidth(i);
+ g.setClip(x, YEAR_HEIGHT, columnWidth - 1, YEAR_HEIGHT + 20);
+ // Centering
+ int x2 = (int) (x + (columnWidth - r.getWidth()) / 2);
+ // If no room, left align
+ if (x2 < x + 2) {
+ x2 = x + 2;
+ }
+ g.drawString(str, x2, YEAR_HEIGHT + 15);
+ x += columnWidth;
+
+ }
+ g.setClip(clipRect);
+ paintHeaderAlldays(g);
+ }
+
+ public String getTitle() {
+ return "Title";
+ }
+
+ public void paintHeaderAlldays(Graphics g) {
+ // Draw alldays
+ // for (AllDayItem jCalendarItem : this.allDayItems) {
+ // int w = 0;
+ // for (int i = jCalendarItem.getX(); i < jCalendarItem.getX() + jCalendarItem.getW(); i++)
+ // {
+ // w += getColumnWidth(i);
+ // }
+ // int x2 = getColumnX(jCalendarItem.getX());
+ // jCalendarItem.draw(g2, x2, YEAR_HEIGHT + TITLE_HEIGHT, allDayItemsRowHeight, w);
+ // }
+ }
+
+ public int getHeaderHeight() {
+ return YEAR_HEIGHT + TITLE_HEIGHT + this.allDayItemsRowCount * this.allDayItemsRowHeight + 4;
+ }
+
+ @Override
+ public Dimension getPreferredScrollableViewportSize() {
+ return new Dimension(1024, 768);
+ }
+
+ @Override
+ public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+ return orientation * this.rowHeight * 2;
+ }
+
+ @Override
+ public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+ return this.rowHeight;
+ }
+
+ @Override
+ public boolean getScrollableTracksViewportWidth() {
+ return true;
+ }
+
+ @Override
+ public boolean getScrollableTracksViewportHeight() {
+ return false;
+ }
+
+ public void mouseWheelMoved(MouseWheelEvent e, MouseWheelListener[] l) {
+
+ if (e.getModifiers() == InputEvent.CTRL_MASK) {
+
+ if (e.getWheelRotation() < 0) {
+ zoom(22);
+ } else {
+ zoom(-22);
+ }
+
+ e.consume();
+ } else {
+ for (int i = 0; i < l.length; i++) {
+ MouseWheelListener mouseWheelListener = l[i];
+ mouseWheelListener.mouseWheelMoved(e);
+ }
+ }
+
+ }
+
+ public void setZoom(int zIndex) {
+ if (zIndex >= 0) {
+ int rh = 22 + zIndex * 22;
+
+ this.rowHeight = rh;
+ // update size
+ final int w = this.getSize().width;
+ final int h = getPreferredSize().height;
+ setSize(new Dimension(w, h));
+ validate();
+ repaint();
+ }
+ }
+
+ private void zoom(int v) {
+ if (rowHeight < 200 && rowHeight > 60) {
+ rowHeight += v;
+ // update size
+ final int w = this.getSize().width;
+ final int h = getPreferredSize().height;
+ setSize(new Dimension(w, h));
+ validate();
+ repaint();
+ }
+ }
+
+ public int getRowHeight() {
+ return this.rowHeight;
+ }
+
+ public void setPopupMenuProvider(JPopupMenuProvider popupProvider) {
+ this.popupProvider = popupProvider;
+ }
+
+ public Set<ItemPartView> getSelectedItems() {
+ return selectedItems;
+ }
+
+ public ItemPartView getItemPartAt(int x, int y) {
+ ItemPartView newSelection = null;
+ for (List<ItemPartView> l : itemParts) {
+ for (ItemPartView p : l) {
+ if (p.contains(x, y)) {
+ newSelection = p;
+ break;
+ }
+ }
+ }
+ return newSelection;
+ }
+
+ public void addItemPartHoverListener(ItemPartHoverListener l) {
+ this.hListeners.add(l);
+ }
+
+ public void removeItemPartHoverListener(ItemPartHoverListener l) {
+ this.hListeners.remove(l);
+ }
+
+ abstract public String getColumnTitle(int index);
+
+ abstract public int getColumnCount();
+
+ abstract public void reload();
+
+ public void deselectAll() {
+ for (ItemPartView p : selectedItems) {
+ p.setSelected(false);
+ }
+ selectedItems.clear();
+
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/AllDayItem.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/AllDayItem.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/AllDayItem.java (revision 137)
@@ -0,0 +1,121 @@
+package org.jopencalendar.ui;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.util.Calendar;
+
+import org.jopencalendar.model.JCalendarItem;
+
+public class AllDayItem {
+ private JCalendarItem item;
+ private int x, y, w, h;
+ private boolean hasLeftBorder;
+ private boolean hasRightBorder;
+
+ public AllDayItem(JCalendarItem item) {
+ this.item = item;
+ }
+
+ public final JCalendarItem getItem() {
+ return item;
+ }
+
+ public final int getX() {
+ return x;
+ }
+
+ public final void setX(int x) {
+ this.x = x;
+ }
+
+ public final int getY() {
+ return y;
+ }
+
+ public final void setY(int y) {
+ this.y = y;
+ }
+
+ public final int getW() {
+ return w;
+ }
+
+ public final void setW(int w) {
+ this.w = w;
+ }
+
+ public final int getH() {
+ return h;
+ }
+
+ public final void setH(int h) {
+ this.h = h;
+ }
+
+ public final boolean hasLeftBorder() {
+ return hasLeftBorder;
+ }
+
+ public final void setLeftBorder(boolean hasLeftBorder) {
+ this.hasLeftBorder = hasLeftBorder;
+ }
+
+ public final boolean hasRightBorder() {
+ return hasRightBorder;
+ }
+
+ public final void setRightBorder(boolean hasRightBorder) {
+ this.hasRightBorder = hasRightBorder;
+ }
+
+ public void draw(Graphics2D g2, int x2, int offsetY, int lineHeight, int width) {
+ final Color c = this.item.getColor();
+ g2.setStroke(new BasicStroke(1f));
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ g2.setColor(WeekView.WHITE_TRANSPARENCY_COLOR);
+ // int x2 = offsetX + x * columnWidth;
+ final int y2 = offsetY + y * (lineHeight) + 2;
+
+ if (hasLeftBorder) {
+ width -= 4;
+ x2 += 4;
+ }
+ if (hasRightBorder) {
+ width -= 4;
+ }
+ g2.fillRect(x2, y2, width, h * lineHeight - 2);
+ g2.setColor(Color.BLACK);
+ g2.drawString(this.item.getSummary(), x2 + 4, y2 + g2.getFont().getSize());
+ // Borders top & bottom
+ g2.setColor(c);
+ g2.drawLine(x2, y2, x2 + width, y2);
+ g2.drawLine(x2, y2 + h * lineHeight - 3, x2 + width, y2 + h * lineHeight - 3);
+
+ g2.setStroke(new BasicStroke(5f));
+ if (hasLeftBorder) {
+ g2.drawLine(x2, y2 + 2, x2, y2 + h * lineHeight - 5);
+ }
+ if (hasRightBorder) {
+ g2.drawLine(x2 + width, y2 + 2, x2 + width, y2 + h * lineHeight - 5);
+ }
+ }
+
+ public int getLengthFrom(Calendar c) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public boolean conflictWith(AllDayItem item) {
+ if (this.getItem().getDtEnd().before(item.getItem().getDtStart())) {
+ return false;
+ }
+ if (item.getItem().getDtEnd().before(this.getItem().getDtStart())) {
+ return false;
+ }
+
+ return true;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/FixedColumnTable.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/FixedColumnTable.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/FixedColumnTable.java (revision 137)
@@ -0,0 +1,216 @@
+package org.jopencalendar.ui;
+
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JViewport;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableModel;
+
+public class FixedColumnTable extends JComponent implements ChangeListener, PropertyChangeListener {
+ private JTable main;
+ private JTable fixed;
+ private JScrollPane scrollPane;
+
+ /*
+ * Specify the number of columns to be fixed and the scroll pane containing the table.
+ */
+ public FixedColumnTable(int fixedColumns, TableModel model) {
+ main = new JTable(model);
+ this.scrollPane = new JScrollPane(main);
+
+ main.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+ main.setAutoCreateColumnsFromModel(false);
+ main.addPropertyChangeListener(this);
+
+ // Use the existing table to create a new table sharing
+ // the DataModel and ListSelectionModel
+ fixed = new JTable();
+ fixed.setAutoCreateColumnsFromModel(false);
+ fixed.setModel(main.getModel());
+ fixed.setSelectionModel(main.getSelectionModel());
+ fixed.setFocusable(false);
+
+ // Remove the fixed columns from the main table
+ // and add them to the fixed table
+ for (int i = 0; i < fixedColumns; i++) {
+ TableColumnModel columnModel = main.getColumnModel();
+ TableColumn column = columnModel.getColumn(0);
+ columnModel.removeColumn(column);
+ fixed.getColumnModel().addColumn(column);
+ }
+
+ // Add the fixed table to the scroll pane
+ fixed.setPreferredScrollableViewportSize(fixed.getPreferredSize());
+ scrollPane.setRowHeaderView(fixed);
+ scrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixed.getTableHeader());
+
+ // Synchronize scrolling of the row header with the main table
+ scrollPane.getRowHeader().addChangeListener(this);
+
+ fixed.getTableHeader().addMouseListener(new MouseAdapter() {
+ TableColumn column;
+ int columnWidth;
+ int pressedX;
+
+ public void mousePressed(MouseEvent e) {
+ JTableHeader header = (JTableHeader) e.getComponent();
+ TableColumnModel tcm = header.getColumnModel();
+ int columnIndex = tcm.getColumnIndexAtX(e.getX());
+ Cursor cursor = header.getCursor();
+ if (columnIndex == tcm.getColumnCount() - 1 && cursor == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)) {
+ column = tcm.getColumn(columnIndex);
+ columnWidth = column.getWidth();
+ pressedX = e.getX();
+ header.addMouseMotionListener(this);
+ }
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ JTableHeader header = (JTableHeader) e.getComponent();
+ header.removeMouseMotionListener(this);
+ }
+
+ public void mouseDragged(MouseEvent e) {
+ int width = columnWidth - pressedX + e.getX();
+ column.setPreferredWidth(width);
+ JTableHeader header = (JTableHeader) e.getComponent();
+ JTable table = header.getTable();
+ table.setPreferredScrollableViewportSize(table.getPreferredSize());
+ JScrollPane scrollPane = (JScrollPane) table.getParent().getParent();
+ scrollPane.revalidate();
+ }
+ });
+ this.setLayout(new GridLayout(1, 1));
+ this.add(scrollPane);
+
+ main.getModel().addTableModelListener(new TableModelListener() {
+
+ @Override
+ public void tableChanged(TableModelEvent e) {
+ // Reload column names
+ final TableColumnModel columnModel = main.getColumnModel();
+ final int size = columnModel.getColumnCount();
+ for (int i = 0; i < size; i++) {
+ columnModel.getColumn(i).setHeaderValue(main.getModel().getColumnName(i + 1));
+ }
+ main.getTableHeader().repaint();
+ }
+ });
+
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ // Sync the scroll pane scrollbar with the row header
+ JViewport viewport = (JViewport) e.getSource();
+ scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y);
+ }
+
+ public void propertyChange(PropertyChangeEvent e) {
+ // Keep the fixed table in sync with the main table
+ if ("selectionModel".equals(e.getPropertyName())) {
+ fixed.setSelectionModel(main.getSelectionModel());
+ }
+ if ("model".equals(e.getPropertyName())) {
+ fixed.setModel(main.getModel());
+ }
+ }
+
+ public void setRowHeight(int height) {
+ this.fixed.setRowHeight(height);
+ this.main.setRowHeight(height);
+ }
+
+ public void setShowHorizontalLines(boolean showGrid) {
+ this.fixed.setShowHorizontalLines(showGrid);
+ this.main.setShowHorizontalLines(showGrid);
+ }
+
+ public void setShowGrid(boolean showGrid) {
+ this.fixed.setShowGrid(showGrid);
+ this.main.setShowGrid(showGrid);
+ }
+
+ public void setColumnWidth(int index, int width) {
+ getColumn(index).setWidth(width);
+ if (index == 0) {
+ final Dimension preferredSize = fixed.getPreferredSize();
+ preferredSize.setSize(width, preferredSize.getHeight());
+ fixed.setPreferredScrollableViewportSize(preferredSize);
+ JScrollPane scrollPane = (JScrollPane) fixed.getParent().getParent();
+ scrollPane.revalidate();
+ }
+ }
+
+ public void setColumnMinWidth(int index, int width) {
+ getColumn(index).setMinWidth(width);
+ }
+
+ public void setColumnMaxWidth(int index, int width) {
+ getColumn(index).setMaxWidth(width);
+ }
+
+ public TableColumn getColumn(int index) {
+ final int columnCount = fixed.getColumnCount();
+ if (index < columnCount) {
+ return this.fixed.getColumnModel().getColumn(index);
+ } else {
+ return this.main.getColumnModel().getColumn(index - columnCount);
+ }
+
+ }
+
+ @Override
+ public synchronized void addMouseListener(MouseListener l) {
+ this.fixed.addMouseListener(l);
+ this.main.addMouseListener(l);
+ }
+
+ @Override
+ public synchronized void addMouseMotionListener(MouseMotionListener l) {
+ this.fixed.addMouseMotionListener(l);
+ this.main.addMouseMotionListener(l);
+ }
+
+ public int getSelectedRow() {
+ return this.main.getSelectedRow();
+ }
+
+ public void ensureVisible(int row, int column) {
+ main.scrollRectToVisible(main.getCellRect(row, column, true));
+ }
+
+ public int rowAtPoint(Point point) {
+ return this.main.rowAtPoint(point);
+ }
+
+ public int columnAtPoint(Point point) {
+ return this.main.columnAtPoint(point);
+ }
+
+ public void setToolTipTextOnHeader(String text) {
+ this.main.setToolTipText(text);
+ }
+
+ public void setReorderingAllowed(boolean b) {
+ main.getTableHeader().setReorderingAllowed(b);
+ }
+
+}
\ No newline at end of file
Index: jOpenCalendar/src/org/jopencalendar/ui/WeekView.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/WeekView.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/WeekView.java (revision 137)
@@ -0,0 +1,264 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.swing.Scrollable;
+import javax.swing.SwingWorker;
+
+import org.jopencalendar.model.JCalendarItem;
+
+public class WeekView extends MultipleDayView implements Scrollable {
+
+ private final JCalendarItemProvider manager;
+
+ // Current week
+ private int week;
+ private int year;
+ // Date of columns
+ private int[] daysOfYear = new int[7];
+ private int[] years = new int[7];
+ private final SimpleDateFormat monthAndYearFormat = new SimpleDateFormat("MMMM yyyy");
+
+ private boolean weekEndMinimised = true;
+
+ public WeekView(JCalendarItemProvider manager) {
+ if (manager == null) {
+ throw new IllegalArgumentException("null manager");
+ }
+ this.manager = manager;
+
+ }
+
+ /**
+ * Load week
+ *
+ * @param week the week number (1 - 52)
+ * */
+ public void loadWeek(final int week, final int year, boolean forceReload) {
+ if (!forceReload) {
+ if (week == this.week && year == this.year) {
+ return;
+ }
+ }
+ this.week = week;
+ this.year = year;
+ Calendar c = getFirstDayCalendar();
+ final int columnCount = this.getColumnCount();
+ for (int i = 0; i < columnCount; i++) {
+ this.daysOfYear[i] = c.get(Calendar.DAY_OF_YEAR);
+ this.years[i] = c.get(Calendar.YEAR);
+ c.add(Calendar.HOUR_OF_DAY, 24);
+ }
+
+ SwingWorker<List<JCalendarItem>, Object> w = new SwingWorker<List<JCalendarItem>, Object>() {
+
+ @Override
+ protected List<JCalendarItem> doInBackground() throws Exception {
+ return manager.getItemInWeek(week, year);
+ }
+
+ protected void done() {
+ try {
+ List<JCalendarItem> l = get();
+ List<List<JCalendarItem>> items = new ArrayList<List<JCalendarItem>>();
+ for (int i = 0; i < columnCount; i++) {
+ List<JCalendarItem> list = new ArrayList<JCalendarItem>();
+ int d = daysOfYear[i];
+ int y = years[i];
+ for (JCalendarItem jCalendarItem : l) {
+ if (jCalendarItem.getDtStart().get(Calendar.DAY_OF_YEAR) == d && jCalendarItem.getDtStart().get(Calendar.YEAR) == y) {
+ list.add(jCalendarItem);
+ }
+ }
+ items.add(list);
+ }
+ setItems(items);
+ } catch (Exception e) {
+ throw new IllegalStateException("error while getting items", e);
+ }
+
+ };
+ };
+ w.execute();
+ }
+
+ public void setWeekEndMinimised(boolean b) {
+ weekEndMinimised = b;
+ repaint();
+ }
+
+ public void paintHeader(Graphics g) {
+
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, this.getWidth() + 100, getHeaderHeight());
+ g.setColor(Color.GRAY);
+ // Vertical lines
+ int columnCount = 7;
+ int x = HOURS_LABEL_WIDTH;
+
+ for (int i = 0; i < columnCount - 1; i++) {
+ x += getColumnWidth(i);
+ g.drawLine(x, YEAR_HEIGHT, x, this.getHeaderHeight());
+ }
+ g.setColor(Color.DARK_GRAY);
+ // Text : month & year
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setFont(getFont().deriveFont(13f));
+ int month = getMonth(this.daysOfYear[0], this.years[0]);
+ int count = 1;
+ for (int i = 1; i < columnCount; i++) {
+ int m = getMonth(this.daysOfYear[i], this.years[i]);
+ if (m == month) {
+ count++;
+ }
+ }
+ if (count == 7) {
+ String str = getMonthName(this.daysOfYear[0], this.years[0]);
+ Rectangle r = g.getFontMetrics().getStringBounds(str, g).getBounds();
+ int w = 0;
+ for (int i = 0; i < count; i++) {
+ w += getColumnWidth(i);
+ }
+ g.drawString(str, (int) (HOURS_LABEL_WIDTH + (w - r.getWidth()) / 2), 15);
+ } else {
+ // draw left month
+ String strLeft = getMonthName(this.daysOfYear[0], this.years[0]);
+ Rectangle r1 = g.getFontMetrics().getStringBounds(strLeft, g).getBounds();
+
+ int wLeft = 0;
+ for (int i = 0; i < count; i++) {
+ wLeft += getColumnWidth(i);
+ }
+ int wRight = 0;
+ for (int i = count; i < columnCount; i++) {
+ wRight += getColumnWidth(i);
+ }
+
+ final int xLeft = (int) (HOURS_LABEL_WIDTH + (wLeft - r1.getWidth()) / 2);
+ g.drawString(strLeft, xLeft, 15);
+
+ // draw right month
+ String strRight = getMonthName(this.daysOfYear[columnCount - 1], this.years[columnCount - 1]);
+ Rectangle r2 = g.getFontMetrics().getStringBounds(strRight, g).getBounds();
+ final int xRight = (int) (HOURS_LABEL_WIDTH + wLeft + (wRight - r2.getWidth()) / 2);
+ g.drawString(strRight, xRight, 15);
+
+ // draw separator
+ g.setColor(Color.GRAY);
+ int xSep = HOURS_LABEL_WIDTH + wLeft;
+ g.drawLine(xSep, 0, xSep, YEAR_HEIGHT);
+ }
+
+ // Text : day
+ final Font font1 = getFont().deriveFont(12f);
+ g.setFont(font1);
+ x = HOURS_LABEL_WIDTH;
+ Calendar today = Calendar.getInstance();
+ int todayYear = today.get(Calendar.YEAR);
+ int todayDay = today.get(Calendar.DAY_OF_YEAR);
+
+ Calendar c = getFirstDayCalendar();
+ final DateFormat df;
+ if (!weekEndMinimised) {
+ df = new SimpleDateFormat("EEEE d");
+ } else {
+ df = new SimpleDateFormat("E d");
+ }
+ for (int i = 0; i < columnCount; i++) {
+ String str = df.format(c.getTime());
+ str = str.substring(0, 1).toUpperCase() + str.substring(1);
+ int columnWidth = getColumnWidth(i);
+ Rectangle r = g.getFontMetrics().getStringBounds(str, g).getBounds();
+ if (c.get(Calendar.YEAR) == todayYear && c.get(Calendar.DAY_OF_YEAR) == todayDay) {
+ g.setColor(new Color(232, 242, 254));
+ g.fillRect(x + 1, YEAR_HEIGHT, columnWidth - 1, (int) r.getHeight() + 4);
+ g.setColor(Color.BLACK);
+ } else {
+ g.setColor(Color.DARK_GRAY);
+ }
+ g.drawString(str, (int) (x + (columnWidth - r.getWidth()) / 2), YEAR_HEIGHT + 15);
+ x += columnWidth;
+ c.add(Calendar.HOUR_OF_DAY, 24);
+ }
+ paintHeaderAlldays(g);
+ }
+
+ private int getMonth(int day, int year) {
+ Calendar c = Calendar.getInstance();
+ c.set(year, 1, 0, 0, 0, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ c.set(Calendar.DAY_OF_YEAR, day);
+ return c.get(Calendar.MONTH);
+ }
+
+ private String getMonthName(int day, int year) {
+ Calendar c = Calendar.getInstance();
+ c.set(year, 1, 0, 0, 0, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ c.set(Calendar.DAY_OF_YEAR, day);
+ return monthAndYearFormat.format(c.getTime()).toUpperCase();
+ }
+
+ private Calendar getFirstDayCalendar() {
+ Calendar c = Calendar.getInstance();
+ c.set(this.year, 1, 0, 0, 0, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ c.set(Calendar.WEEK_OF_YEAR, this.week);
+ c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
+ return c;
+ }
+
+ @Override
+ public String getColumnTitle(int index) {
+ final DateFormat df;
+ if (!weekEndMinimised) {
+ df = new SimpleDateFormat("EEEE d");
+ } else {
+ df = new SimpleDateFormat("E d");
+ }
+ Calendar c = getFirstDayCalendar();
+ c.add(Calendar.DAY_OF_YEAR, index);
+
+ String str = df.format(c.getTime());
+ str = str.substring(0, 1).toUpperCase() + str.substring(1);
+ return str;
+ }
+
+ @Override
+ public void reload() {
+ loadWeek(this.week, this.year, true);
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 7;
+ }
+
+ @Override
+ public int getColumnWidth(int column) {
+ final int c;
+ if (weekEndMinimised) {
+ int minSize = 50;
+ if (column == 5 || column == 6) {
+ return minSize;
+ } else {
+ c = (this.getWidth() - HOURS_LABEL_WIDTH - 2 * minSize) / (getColumnCount() - 2);
+ }
+
+ } else {
+ c = (this.getWidth() - HOURS_LABEL_WIDTH) / getColumnCount();
+ }
+ return c;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStates.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStates.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/MonthActivityStates.java (revision 137)
@@ -0,0 +1,106 @@
+package org.jopencalendar.ui;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import org.jopencalendar.model.JCalendarItem;
+
+public class MonthActivityStates {
+ // ex : null,null,item1,item1,null x 27 for item1 from 3 to 4 january
+ private List<List<JCalendarItem>> l;
+ private final int month;
+ private final int year;
+ private final List<Integer> mIndex = new ArrayList<Integer>(5);
+ private int daysInMonth;
+
+ public MonthActivityStates(int month, int year) {
+ this.month = month;
+ this.year = year;
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, this.month);
+ c.set(Calendar.DAY_OF_MONTH, 1);
+ c.set(Calendar.SECOND, 1);
+ daysInMonth = c.getActualMaximum(Calendar.DAY_OF_MONTH);
+
+ for (int i = 0; i < daysInMonth; i++) {
+ if (c.get(Calendar.DAY_OF_WEEK) == 1) {
+ mIndex.add(i + 1);
+ }
+
+ c.add(Calendar.DAY_OF_MONTH, 1);
+
+ }
+
+ }
+
+ public void set(JCalendarItem jCalendarItem) {
+ if (l == null) {
+ l = new ArrayList<List<JCalendarItem>>(daysInMonth);
+ for (int i = 0; i < daysInMonth; i++) {
+
+ l.add(null);
+ }
+ }
+
+ Calendar cStart = jCalendarItem.getDtStart();
+ cStart.set(Calendar.HOUR_OF_DAY, 0);
+ cStart.set(Calendar.MINUTE, 0);
+ cStart.set(Calendar.SECOND, 0);
+ cStart.set(Calendar.MILLISECOND, 0);
+ Calendar cEnd = jCalendarItem.getDtEnd();
+ cEnd.set(Calendar.HOUR_OF_DAY, 0);
+ cEnd.set(Calendar.MINUTE, 0);
+ cEnd.set(Calendar.SECOND, 0);
+ cEnd.set(Calendar.MILLISECOND, 0);
+ cEnd.add(Calendar.HOUR_OF_DAY, 24);
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, this.month);
+ c.set(Calendar.DAY_OF_MONTH, 1);
+ c.set(Calendar.SECOND, 1);
+
+ final int dayInMonth = l.size();
+ for (int i = 0; i < dayInMonth; i++) {
+ if (c.after(cStart) && c.before(cEnd)) {
+ List<JCalendarItem> list = l.get(i);
+ if (list == null) {
+ list = new ArrayList<JCalendarItem>(2);
+ l.set(i, list);
+ }
+ list.add(jCalendarItem);
+ }
+ c.add(Calendar.DAY_OF_MONTH, 1);
+ }
+
+ }
+
+ public List<List<JCalendarItem>> getList() {
+ return l;
+ }
+
+ public List<Integer> getMondayIndex() {
+ return mIndex;
+ }
+
+ @Override
+ public String toString() {
+ String string = super.toString();
+ if (l != null) {
+ string += " size: " + l.size() + ", items: " + l.toString();
+ }
+ return string;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public int getMonth() {
+ return month;
+ }
+
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/PrintJComponentAction.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/PrintJComponentAction.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/PrintJComponentAction.java (revision 137)
@@ -0,0 +1,76 @@
+package org.jopencalendar.ui;
+
+import java.awt.event.ActionEvent;
+import java.awt.print.PageFormat;
+import java.awt.print.Paper;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.OrientationRequested;
+import javax.print.attribute.standard.PrintQuality;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+
+public class PrintJComponentAction extends AbstractAction {
+ private JComponent component;
+
+ private final int pageFormat;
+ private final String title;
+
+ public PrintJComponentAction(JComponent view) {
+ this(view, PageFormat.PORTRAIT, null);
+ }
+
+ public PrintJComponentAction(JComponent view, int pageFormat, String title) {
+ this.component = view;
+ putValue(Action.NAME, "Print");
+ this.pageFormat = pageFormat;
+ this.title = title;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ PrinterJob pj = PrinterJob.getPrinterJob();
+
+ if (pj.printDialog()) {
+ try {
+
+ if (this.pageFormat == PageFormat.LANDSCAPE) {
+
+ final PageFormat pageFormat = getMinimumMarginPageFormat(pj);
+ pageFormat.setOrientation(PageFormat.LANDSCAPE);
+
+ pj.setPrintable(new JComponentPrintable(component, title), pageFormat);
+ PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
+ printAttributes.add(PrintQuality.HIGH);
+ printAttributes.add(OrientationRequested.LANDSCAPE);
+
+ pj.print(printAttributes);
+ } else {
+ pj.setPrintable(new JComponentPrintable(component, title));
+ PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
+ printAttributes.add(PrintQuality.HIGH);
+ pj.print(printAttributes);
+ }
+ } catch (PrinterException exc) {
+ JOptionPane.showMessageDialog(component, exc.getMessage(), "Printing error", JOptionPane.ERROR_MESSAGE);
+ System.err.println(exc);
+ }
+ }
+
+ }
+
+ private PageFormat getMinimumMarginPageFormat(PrinterJob printJob) {
+ PageFormat pf0 = printJob.defaultPage();
+ PageFormat pf1 = (PageFormat) pf0.clone();
+ Paper p = pf0.getPaper();
+ p.setImageableArea(0, 0, pf0.getWidth(), pf0.getHeight());
+ pf1.setPaper(p);
+ PageFormat pf2 = printJob.validatePage(pf1);
+ return pf2;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/CalendarWithToolBar.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/CalendarWithToolBar.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/CalendarWithToolBar.java (revision 137)
@@ -0,0 +1,245 @@
+package org.jopencalendar.ui;
+
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.print.PageFormat;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Calendar;
+import java.util.Date;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
+import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+public class CalendarWithToolBar extends JPanel {
+ private WeekView weekView;
+ private JSpinner spinWeek;
+ private JSpinner spinYear;
+ private String title;
+ final JScrollPane contentPane = new JScrollPane();
+
+ public CalendarWithToolBar(JCalendarItemProvider manager) {
+ this(manager, false);
+ }
+
+ public CalendarWithToolBar(JCalendarItemProvider manager, boolean showPrintButton) {
+ JPanel toolbar = new JPanel();
+ toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
+
+ Calendar cal = Calendar.getInstance();
+ int week = cal.get(Calendar.WEEK_OF_YEAR);
+ int year = cal.get(Calendar.YEAR);
+ JButton bPrevious = new JButton(new ImageIcon(this.getClass().getResource("left.png")));
+ JButton bNext = new JButton(new ImageIcon(this.getClass().getResource("right.png")));
+ configureButton(bPrevious);
+ configureButton(bNext);
+ toolbar.add(bPrevious);
+ toolbar.add(bNext);
+ bNext.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ addWeek(1);
+
+ }
+ });
+ bPrevious.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ addWeek(-1);
+
+ }
+ });
+
+ toolbar.add(new JLabel("Semaine"));
+ spinWeek = new JSpinner(new SpinnerNumberModel(week, 1, 53, 1));
+ toolbar.add(spinWeek);
+ toolbar.add(new JLabel(" de "));
+ spinYear = new JSpinner(new SpinnerNumberModel(year, 1000, year + 20, 1));
+ toolbar.add(spinYear);
+ //
+ final DatePicker picker = new DatePicker(false);
+ toolbar.add(picker);
+ //
+
+ final JSlider zoomSlider = new JSlider(1, 9, 1);
+ zoomSlider.setSnapToTicks(true);
+ zoomSlider.setMajorTickSpacing(1);
+ zoomSlider.setPaintTicks(true);
+ zoomSlider.addChangeListener(new ChangeListener() {
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ weekView.setZoom(zoomSlider.getValue());
+ }
+ });
+ toolbar.add(new JLabel(" Zoom"));
+ toolbar.add(zoomSlider);
+ if (showPrintButton) {
+ final JButton jButton = new JButton("Imprimer");
+ jButton.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ final PrintJComponentAction a = new PrintJComponentAction(CalendarWithToolBar.this.getContentPane(), PageFormat.LANDSCAPE, CalendarWithToolBar.this.title);
+ a.actionPerformed(arg0);
+ }
+ });
+ toolbar.add(jButton);
+ }
+ JButton reloadButton = new JButton(new ImageIcon(this.getClass().getResource("auto.png")));
+ configureButton(reloadButton);
+ toolbar.add(reloadButton);
+ reloadButton.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reload();
+ }
+ });
+
+ this.setLayout(new GridBagLayout());
+
+ //
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 0;
+ c.weightx = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ this.add(toolbar, c);
+ c.gridy++;
+ this.add(new JSeparator(JSeparator.HORIZONTAL), c);
+ c.gridy++;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty = 1;
+
+ contentPane.setBorder(BorderFactory.createEmptyBorder());
+ contentPane.setOpaque(false);
+ weekView = new WeekView(manager);
+ contentPane.setColumnHeaderView(new WeekViewHeader(weekView));
+ contentPane.setViewportView(weekView);
+ contentPane.getViewport().setBackground(Color.WHITE);
+ final MouseWheelListener[] l = contentPane.getMouseWheelListeners();
+ for (int i = 0; i < l.length; i++) {
+ MouseWheelListener string = l[i];
+ contentPane.removeMouseWheelListener(string);
+ }
+ contentPane.addMouseWheelListener(new MouseWheelListener() {
+
+ @Override
+ public void mouseWheelMoved(MouseWheelEvent e) {
+ weekView.mouseWheelMoved(e, l);
+ }
+ });
+
+ this.add(contentPane, c);
+ final int value = 300;
+ contentPane.getVerticalScrollBar().setValue(value);
+ weekView.loadWeek(week, year, false);
+ final ChangeListener listener = new ChangeListener() {
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ Calendar c = getCurrentDate();
+ picker.setDate(c.getTime());
+ weekView.loadWeek(getWeek(), getYear(), false);
+ }
+ };
+ spinWeek.addChangeListener(listener);
+ spinYear.addChangeListener(listener);
+ picker.addPropertyChangeListener("value", new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (evt.getNewValue() != null) {
+ final Date d = (Date) evt.getNewValue();
+ final Calendar c = Calendar.getInstance();
+ c.setTime(d);
+ final int y = c.get(Calendar.YEAR);
+ final int w = c.get(Calendar.WEEK_OF_YEAR);
+ spinWeek.removeChangeListener(listener);
+ spinYear.removeChangeListener(listener);
+ spinYear.setValue(y);
+ spinWeek.setValue(w);
+ spinWeek.addChangeListener(listener);
+ spinYear.addChangeListener(listener);
+ weekView.loadWeek(getWeek(), getYear(), false);
+ }
+
+ }
+ });
+
+ }
+
+ protected void addWeek(int i) {
+ Calendar c = getCurrentDate();
+ c.add(Calendar.DAY_OF_YEAR, i * 7);
+ final int year = c.get(Calendar.YEAR);
+ final int week = c.get(Calendar.WEEK_OF_YEAR);
+ spinYear.setValue(year);
+ spinWeek.setValue(week);
+
+ }
+
+ public Calendar getCurrentDate() {
+ Calendar c = Calendar.getInstance();
+ c.clear();
+ c.set(Calendar.YEAR, getYear());
+ c.set(Calendar.WEEK_OF_YEAR, getWeek());
+ return c;
+ }
+
+ private void configureButton(JButton b) {
+ b.setOpaque(false);
+ b.setBorderPainted(false);
+ b.setFocusPainted(false);
+ b.setContentAreaFilled(false);
+ b.setMargin(new Insets(1, 5, 1, 5));
+ }
+
+ public void reload() {
+ weekView.reload();
+ }
+
+ public int getWeek() {
+ return ((Number) spinWeek.getValue()).intValue();
+ }
+
+ public int getYear() {
+ return ((Number) spinYear.getValue()).intValue();
+ }
+
+ public WeekView getWeekView() {
+ return weekView;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public void scrollTo(int hour) {
+ contentPane.getVerticalScrollBar().setValue(hour * weekView.getRowHeight());
+ }
+
+ public JScrollPane getContentPane() {
+ return contentPane;
+ }
+}
Index: jOpenCalendar/src/org/jopencalendar/ui/DatePickerPanel.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/ui/DatePickerPanel.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/ui/DatePickerPanel.java (revision 137)
@@ -0,0 +1,358 @@
+package org.jopencalendar.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+public class DatePickerPanel extends JPanel implements ActionListener, MouseListener {
+
+ private static final long serialVersionUID = -2882634897084487051L;
+ public static final String TIME_IN_MILLIS = "timeInMillis";
+ private int rowCount = 7;
+ private int colCount = 7;
+ private int currentYear;
+ private int currentMonth;
+ private List<DateLabel> labels = new ArrayList<DateLabel>();
+ private JLabel title;
+ private JButton bRight;
+ private JButton bLeft;
+ private Date selectedDate;
+
+ public DatePickerPanel() {
+ //
+ Calendar cal = Calendar.getInstance();
+ this.selectedDate = cal.getTime();
+ this.currentYear = cal.get(Calendar.YEAR);
+ this.currentMonth = cal.get(Calendar.MONTH);
+ //
+
+ this.setLayout(new BorderLayout(2, 2));
+ JPanel navigator = new JPanel();
+ navigator.setLayout(new BorderLayout());
+ bLeft = new JButton(new ImageIcon(this.getClass().getResource("left.png")));
+ configureButton(bLeft);
+
+ navigator.add(bLeft, BorderLayout.WEST);
+ title = new JLabel("...", SwingConstants.CENTER);
+ title.setFont(title.getFont().deriveFont(Font.BOLD));
+ navigator.add(title, BorderLayout.CENTER);
+ bRight = new JButton(new ImageIcon(this.getClass().getResource("right.png")));
+ configureButton(bRight);
+ navigator.add(bRight, BorderLayout.EAST);
+ this.add(navigator, BorderLayout.NORTH);
+ final JPanel dayPanel = new JPanel() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ g.setColor(Color.GRAY);
+ g.drawLine(0, 0, getWidth(), 0);
+ }
+ };
+ dayPanel.setBackground(Color.WHITE);
+ dayPanel.setLayout(new GridLayout(rowCount, colCount, 4, 4));
+ dayPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
+ //
+
+ String[] dateFormatSymbols = new DateFormatSymbols().getShortWeekdays();
+ int f = cal.getFirstDayOfWeek();
+
+ for (int i = 0; i < colCount; i++) {
+ int j = i + f;
+ if (j >= 8) {
+ j = 1;
+ }
+ String d = dateFormatSymbols[j];
+ dayPanel.add(new JLabel(d, SwingConstants.RIGHT));
+ }
+
+ //
+ int c = 0;
+ final MouseAdapter mListener = new MouseAdapter() {
+ public long select(MouseEvent e) {
+ if (e.getSource() instanceof DateLabel) {
+ final DateLabel dateLabel = (DateLabel) e.getSource();
+ final Calendar c = Calendar.getInstance();
+ final long timeInMillis = dateLabel.getTimeInMillis();
+ c.setTimeInMillis(timeInMillis);
+ setSelectedDate(c);
+ return timeInMillis;
+ }
+ return -1;
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ e.setSource(dayPanel.getComponentAt(SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), dayPanel)));
+ select(e);
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ // Nothing
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ e.setSource(dayPanel.getComponentAt(SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), dayPanel)));
+ long timeInMillis = select(e);
+ if (timeInMillis >= 0) {
+ firePropertyChange(TIME_IN_MILLIS, Long.valueOf(0), Long.valueOf(timeInMillis));
+ }
+ }
+ };
+
+ for (int i = 0; i < rowCount - 1; i++) {
+ for (int j = 0; j < colCount; j++) {
+ final DateLabel label = new DateLabel(String.valueOf(c), SwingConstants.RIGHT);
+ label.addMouseListener(mListener);
+ label.addMouseMotionListener(mListener);
+ label.setOpaque(true);
+ this.labels.add(label);
+ dayPanel.add(label);
+ c++;
+ }
+
+ }
+
+ this.add(dayPanel, BorderLayout.CENTER);
+ DateFormat df = DateFormat.getDateInstance(DateFormat.FULL);
+ // Today
+ final JLabel date = new JLabel(df.format(new Date()), SwingConstants.CENTER);
+ date.setBorder(BorderFactory.createEmptyBorder(4, 3, 5, 3));
+ this.add(date, BorderLayout.SOUTH);
+ //
+ updateLabels();
+ bRight.addActionListener(this);
+ bLeft.addActionListener(this);
+ date.addMouseListener(this);
+
+ }
+
+ public Date getSelectedDate() {
+ return selectedDate;
+ }
+
+ public void setSelectedDate(Calendar cal) {
+ if (cal == null) {
+ this.selectedDate = null;
+ setDate(Calendar.getInstance());
+ } else if (this.selectedDate == null || !this.selectedDate.equals(cal.getTime())) {
+ this.selectedDate = cal.getTime();
+ setDate(cal);
+ }
+ }
+
+ public void setDate(Calendar cal) {
+ this.currentYear = cal.get(Calendar.YEAR);
+ this.currentMonth = cal.get(Calendar.MONTH);
+ updateLabels();
+ }
+
+ private void configureButton(final JButton button) {
+ int buttonSize = 28;
+ button.setMinimumSize(new Dimension(buttonSize, buttonSize));
+ button.setPreferredSize(new Dimension(buttonSize, buttonSize));
+ button.setFocusPainted(false);
+ button.setBorderPainted(false);
+ button.setBorder(null);
+ button.setContentAreaFilled(false);
+ button.setOpaque(false);
+ }
+
+ private void updateLabels() {
+ int selectedYear = -1;
+ int selectedDay = -1;
+ if (selectedDate != null) {
+ Calendar calSelected = Calendar.getInstance();
+ calSelected.setTime(this.selectedDate);
+ selectedYear = calSelected.get(Calendar.YEAR);
+ selectedDay = calSelected.get(Calendar.DAY_OF_YEAR);
+ }
+
+ Calendar cal = Calendar.getInstance();
+ int todayYear = cal.get(Calendar.YEAR);
+ int todayDay = cal.get(Calendar.DAY_OF_YEAR);
+ cal.clear();
+ cal.set(Calendar.YEAR, this.currentYear);
+ cal.set(Calendar.MONTH, this.currentMonth);
+ cal.set(Calendar.DAY_OF_MONTH, 1);
+ SimpleDateFormat sdf = new SimpleDateFormat("MMMM yyyy");
+ title.setText(sdf.format(cal.getTime()));
+
+ int f = cal.getFirstDayOfWeek();
+ int offset = cal.get(Calendar.DAY_OF_WEEK) - f + 1; // offset du 1er jour du mois par
+ // rapport a
+
+ if (offset < 2) {
+ offset += 7;
+ }
+
+ // grille
+ cal.add(Calendar.DAY_OF_YEAR, -offset);
+
+ int c = 0;
+ for (int i = 0; i < rowCount - 1; i++) {
+ for (int j = 0; j < colCount; j++) {
+ cal.add(Calendar.DAY_OF_YEAR, 1);
+ final DateLabel label = this.labels.get(c);
+ label.setDate(cal);
+ label.setText(cal.get(Calendar.DAY_OF_MONTH) + " ");
+ if (cal.get(Calendar.MONTH) != this.currentMonth) {
+ if (!label.getForeground().equals(Color.GRAY))
+ label.setForeground(Color.GRAY);
+ } else {
+ if (!label.getForeground().equals(Color.BLACK))
+ label.setForeground(Color.BLACK);
+ }
+ if (cal.get(Calendar.YEAR) == todayYear && cal.get(Calendar.DAY_OF_YEAR) == todayDay) {
+ label.setBackground(Color.LIGHT_GRAY);
+ label.setForeground(Color.WHITE);
+ } else {
+ label.setBackground(Color.WHITE);
+ }
+ if (cal.get(Calendar.YEAR) == selectedYear && cal.get(Calendar.DAY_OF_YEAR) == selectedDay) {
+ label.setBackground(new Color(232, 242, 250));
+ label.setForeground(Color.BLACK);
+ }
+ c++;
+ }
+
+ }
+
+ }
+
+ @Override
+ public void setFocusable(boolean focusable) {
+ super.setFocusable(focusable);
+ bRight.setFocusable(focusable);
+ bLeft.setFocusable(focusable);
+ }
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ final JFrame f = new JFrame();
+ final DatePickerPanel picker = new DatePickerPanel();
+ picker.addPropertyChangeListener(TIME_IN_MILLIS, new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ final Long millis = (Long) evt.getNewValue();
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(millis);
+ f.dispose();
+
+ }
+ });
+ f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ f.setContentPane(picker);
+ f.pack();
+ f.setLocationRelativeTo(null);
+ f.setVisible(true);
+
+ final JFrame f1 = new JFrame();
+ final DatePicker p = new DatePicker();
+ Calendar c = Calendar.getInstance();
+ c.set(Calendar.YEAR, 2010);
+ c.set(Calendar.MONTH, 2);
+ c.set(Calendar.DAY_OF_MONTH, 1);
+
+ p.setDate(c.getTime());
+ p.setDate(null);
+ final JPanel pRed = new JPanel();
+ pRed.setBackground(Color.RED);
+ pRed.add(p);
+ pRed.add(new JTextField("Dummy TextField"));
+
+ f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ f1.setContentPane(pRed);
+ f1.pack();
+ f1.setLocation(f.getLocation().x + f.getWidth() + 10, f.getLocation().y);
+ f1.setVisible(true);
+
+ }
+ });
+
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Buttons + / -
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.YEAR, this.currentYear);
+ cal.set(Calendar.MONTH, this.currentMonth);
+ if (e.getSource().equals(this.bLeft)) {
+ cal.add(Calendar.MONTH, -1);
+ } else if (e.getSource().equals(this.bRight)) {
+ cal.add(Calendar.MONTH, 1);
+ }
+ setDate(cal);
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ if (e.getClickCount() > 1) {
+ setSelectedDate(cal);
+ firePropertyChange(TIME_IN_MILLIS, Long.valueOf(0), Long.valueOf(cal.getTimeInMillis()));
+ } else {
+ setDate(cal);
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ }
+
+}
Index: jOpenCalendar/src/org/jopencalendar/LayoutUtils.java
===================================================================
--- jOpenCalendar/src/org/jopencalendar/LayoutUtils.java (revision 0)
+++ jOpenCalendar/src/org/jopencalendar/LayoutUtils.java (revision 137)
@@ -0,0 +1,170 @@
+package org.jopencalendar;
+
+import java.awt.FontMetrics;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class LayoutUtils {
+ public static String firstUp(String s) {
+ if (s.length() == 0) {
+ return s;
+ }
+ if (s.length() == 1) {
+ return s.toUpperCase();
+ }
+ return s.substring(0, 1).toUpperCase() + s.substring(1);
+ }
+
+ /**
+ * Returns an array of strings, one for each line in the string after it has been wrapped to fit
+ * lines of <var>maxWidth</var>. Lines end with any of cr, lf, or cr lf. A line ending at the
+ * end of the string will not output a further, empty string.
+ * <p>
+ * This code assumes <var>str</var> is not <code>null</code>.
+ *
+ * @param str the string to split
+ * @param fm needed for string width calculations
+ * @param maxWidth the max line width, in points
+ * @return a non-empty list of strings
+ */
+ public static List<String> wrap(String str, FontMetrics fm, int maxWidth) {
+ if (str == null) {
+ return new ArrayList<String>(0);
+ }
+ List<String> lines = splitIntoLines(str);
+ if (lines.size() == 0)
+ return lines;
+
+ List<String> strings = new ArrayList<String>();
+ for (Iterator<String> iter = lines.iterator(); iter.hasNext();) {
+ wrapLineInto(iter.next(), strings, fm, maxWidth);
+ }
+ return strings;
+ }
+
+ /**
+ * Given a line of text and font metrics information, wrap the line and add the new line(s) to
+ * <var>list</var>.
+ *
+ * @param line a line of text
+ * @param list an output list of strings
+ * @param fm font metrics
+ * @param maxWidth maximum width of the line(s)
+ */
+ public static void wrapLineInto(String line, List<String> list, FontMetrics fm, int maxWidth) {
+ if (maxWidth <= fm.getHeight() / 3) {
+ return;
+ }
+ int len = line.length();
+ int width;
+ while (len > 0 && (width = fm.stringWidth(line)) > maxWidth) {
+ // Guess where to split the line. Look for the next space before
+ // or after the guess.
+ int guess = len * maxWidth / width;
+
+ String before = line.substring(0, guess).trim();
+
+ width = fm.stringWidth(before);
+ int pos;
+ if (width > maxWidth) // Too long
+ pos = findBreakBefore(line, guess);
+ else { // Too short or possibly just right
+ pos = findBreakAfter(line, guess);
+ if (pos != -1) { // Make sure this doesn't make us too long
+ before = line.substring(0, pos).trim();
+ if (fm.stringWidth(before) > maxWidth)
+ pos = findBreakBefore(line, guess);
+ }
+ }
+ if (pos == -1)
+ pos = guess; // Split in the middle of the word
+
+ if (pos <= 0) {
+ len = 0;
+ break;
+ }
+ list.add(line.substring(0, pos).trim());
+ line = line.substring(pos).trim();
+ len = line.length();
+ }
+ if (len > 0) {
+ list.add(line);
+ }
+ }
+
+ /**
+ * Returns the index of the first whitespace character or '-' in <var>line</var> that is at or
+ * before <var>start</var>. Returns -1 if no such character is found.
+ *
+ * @param line a string
+ * @param start where to star looking
+ */
+ public static int findBreakBefore(String line, int start) {
+ for (int i = start; i >= 0; --i) {
+ char c = line.charAt(i);
+ if (Character.isWhitespace(c) || c == '-')
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index of the first whitespace character or '-' in <var>line</var> that is at or
+ * after <var>start</var>. Returns -1 if no such character is found.
+ *
+ * @param line a string
+ * @param start where to star looking
+ */
+ public static int findBreakAfter(String line, int start) {
+ int len = line.length();
+ for (int i = start; i < len; ++i) {
+ char c = line.charAt(i);
+ if (Character.isWhitespace(c) || c == '-')
+ return i;
+ }
+ return -1;
+ }
+
+ /**
+ * Returns an array of strings, one for each line in the string. Lines end with any of cr, lf,
+ * or cr lf. A line ending at the end of the string will not output a further, empty string.
+ * <p>
+ * This code assumes <var>str</var> is not <code>null</code>.
+ *
+ * @param str the string to split
+ * @return a non-empty list of strings
+ */
+ public static List<String> splitIntoLines(String str) {
+ List<String> strings = new ArrayList<String>();
+
+ int len = str.length();
+ if (len == 0) {
+ strings.add("");
+ return strings;
+ }
+
+ int lineStart = 0;
+
+ for (int i = 0; i < len; ++i) {
+ char c = str.charAt(i);
+ if (c == '\r') {
+ int newlineLength = 1;
+ if ((i + 1) < len && str.charAt(i + 1) == '\n')
+ newlineLength = 2;
+ strings.add(str.substring(lineStart, i));
+ lineStart = i + newlineLength;
+ if (newlineLength == 2) // skip \n next time through loop
+ ++i;
+ } else if (c == '\n') {
+ strings.add(str.substring(lineStart, i));
+ lineStart = i + 1;
+ }
+ }
+ if (lineStart < len)
+ strings.add(str.substring(lineStart));
+
+ return strings;
+ }
+
+}
\ No newline at end of file
Index: jOpenCalendar/.classpath
===================================================================
--- jOpenCalendar/.classpath (revision 0)
+++ jOpenCalendar/.classpath (revision 137)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
Index: jOpenCalendar/sonar-project.properties
===================================================================
--- jOpenCalendar/sonar-project.properties (revision 0)
+++ jOpenCalendar/sonar-project.properties (revision 137)
@@ -0,0 +1,5 @@
+sonar.projectKey=jOpenCalendar
+sonar.projectName=jOpenCalendar
+sonar.projectVersion=1.0
+sonar.sources=src
+sonar.sourceEncoding=UTF-8
\ No newline at end of file