Calendar component


#1

Hi all.

Here is a calendar component I’ve created in a rush for my needs.
It was successfully compiled using GCC for MinGW v.4.2.1 (WindowsXP) and Code::Blocks as the IDE. But I didn’t supply a project file, just source codes.

I have several notes for it. Please, read them carefully.

  1. I use STL containers instead of JUCE ones for several reasons. The main reason is STL containers are more effective and convenient to use in the context of the component’s design.

  2. I use time related classes from the Poco library instead of JUCE’s ones for several reasons. First, JUCE’s Time and RelativeTime classes have bugs that prevent me from using those JUCE’s classes. Second, Poco’s time related classes have a wider minimum and maximum range for a year value (from 0 to 9999 against JUCE’s 1970 - 2037). Third, Poco’s classes are faster and more reliable then that of JUCE’s (no offence meant, Julian :)).

  3. A note to build: monolyticDateTime.cxx and monolyticDateTime.hxx files MUST be in the same directory as CalendarComponent source files. I’ve created that files from several Poco’s separate source files by merging them into the monolithic independent files that can be easily included in any C++ source code to bring a powerful date-time manipulations into your application. See monolyticDateTime.hxx header file to find out classes that it contains. See Poco’s library documentation on how to use them. [color=red]DO NOT INCLUDE[/color] monolyticDateTime.cxx source file into your project to build beacause it is already included in the CalendarComponent.cpp source file for you. Just include CalendarComponent.cpp into your project and you’re done. If you are going to use monolyticDateTime.hxx separately, please note, it is advisable to include it before any other header files to prevent unexpected compiler errors when compiling a GUI application (under Windows).


Please note, this is the first draft version of the component I present to those who needs a simple, powerful and elegant calendar component in JUCE. My code is not perfect and clean but it’s functional. Please, post here any comments and questions concerning the component. Your advice, remarks and criticism are welcome.

See the demo application (for Windows) to experience the calendar component.

CalendarComponent.7z

Here are a few screen shots of the demo application to tease you :slight_smile:




#2

Looks very nice!

You say you found bugs in the juce time classes? Let me know what they are and I’ll fix them!


#3

This is truely impressive and intuitive to use.

What’s the reason to include a 117KB header ?
What is inside Poco’s time that would require some much code ?

What is the license, and can we use it as-is, or it’s required to change some part in the code ?


#4

yeah very cool indeed. something i had in mind to do for months: clean and simple to use.
anyway i’ll try to clean up the code and convert it to be pure 100% juce code compliant (with comments also :P) without any other include needed, if is not a problem…


#5

Oh, just one thing… it says “Marry Christmas” on it, which might not mean exactly what you intended…


#6

[quote=“jules”]Looks very nice!

You say you found bugs in the juce time classes? Let me know what they are and I’ll fix them![/quote]

Sometimes, when you walk through the month days by adding a day to the current date then RelativeTime class may return a wrong date - it may repeat the current date twice (01 02 03 … 25 26 27 [color=red]28 28[/color] 29). I encountered it in October while testing but I’m not sure in which year.


#7

:smiley: That’s OK. The component is highly customizable. “Marry Christmas” is just the custom description for the special date. It might be whatever you set it. “Marry Christmas” was just for testing purposes to make sure this day displays its description.


#8

Dear Ptomaine,

This is also what I always wanted to do: Christmas vocation.

Your faithfully,
Santa claus.


#9

[quote=“kraken”]yeah very cool indeed. something i had in mind to do for months: clean and simple to use.
anyway i’ll try to clean up the code and convert it to be pure 100% juce code compliant (with comments also :P) without any other include needed, if is not a problem…[/quote]

I’m sure you’ll do it right.
Just for you to note:

The juce::Time class has limits for the year value the class is able to work with (against Poco’s from 0 to 9999). The limits are from 1970 to 2037. In my component, the year of value 0 has a special meaning for special dates and date periods. It indicates that the special date or period just last forever (for every single year). Please, keep it in your mind. Also, the reason for having CalendarComponentSettings class is you can create different localized settings and share them between different components (reuse them) instead of resetting the same settings for each component each time they are created. Just supply settings for components and they tunes itself for it, even runtime. The component refers to a settings instance. About runtime, component is not aware when you change its settings. Then do not forget to call redrawCalendar member function to make all components that refer your settings instance reflect your new settings.

Good luck! I believe in you, kraken :wink:


#10

[quote=“X-Ryl669”]This is truely impressive and intuitive to use.

What’s the reason to include a 117KB header ?
What is inside Poco’s time that would require some much code ?

What is the license, and can we use it as-is, or it’s required to change some part in the code ?[/quote]

Dear Santa Claus :wink:

Everything you want to know is here


#11

That’s very interesting too.

I’ll keep an eye on this Poco project for all those 2 days projects I might have.
Thanks for the link.


#12

[quote=“Ptomaine”][quote=“jules”]Looks very nice!

You say you found bugs in the juce time classes? Let me know what they are and I’ll fix them![/quote]

Sometimes, when you walk through the month days by adding a day to the current date then RelativeTime class may return a wrong date - it may repeat the current date twice (01 02 03 … 25 26 27 [color=red]28 28[/color] 29). I encountered it in October while testing but I’m not sure in which year.[/quote]

How odd - it’s all done in milliseconds, so not much scope for maths errors, and it’s the normal c library routines that convert from millisecs to days, so can’t think why that’d happen. I guess the poco classes store it as separate fields for the days, month, year, etc.


#13

Yes, they do. And that’s very important for the calendar component because it needs to know the current month or day or year very often. The Poco classes just returns that values without any evaluations instead of evaluating their values each time I call functions in JUCE.

Besides, Poco files also contains very useful extra classes you can use:

Timestamp - the monolithic datetime representation;

Timespan - aka JUCE RelativeTime;

LocalDateTime - aka JUCE LocalTime;

Timezone - info of a time zone :slight_smile:

DateTimeFormat - various standard string datetime formats;

DateTimeFormatter - to format your datetime to any of the standard datetime formats (e.g. to store in XML);

DateTimeParser - very powerful datetime parser to convert standard formated datetime string back to the DateTime instance (e.g. to restore from XML);

I wish JUCE has the same functionality for dates and time.


#14

[quote=“jules”]

How odd - it’s all done in milliseconds, so not much scope for maths errors, and it’s the normal c library routines that convert from millisecs to days, so can’t think why that’d happen. I guess the poco classes store it as separate fields for the days, month, year, etc.[/quote]

I’ve seen similar math bugs. I think I mentioned them ages back. I’ve never been able to get to the bottom of what causes them though.


#15

[color=red]I’ve updated the Calendar component a bit.[/color]
It is advisable to download the latest version.


#16

What’s new in last version ?


#17
  1. Some minor fixes (listeners are now called also when changing to some date from locateDate member function)

  2. Some listener functions’ signature has changed to let you get more info on changes. Thus letting you change more bits of the component than before.

  3. Added some functions to customize your component instance even more.

  4. Fixed .withAlpha to .withMultipliedAlpha to display colours properly.

  5. From now on, special day colours and date period colours are now overlaid.

  6. Some other minor fixes.


#18

[quote=“jules”][quote=“Ptomaine”][quote=“jules”]Looks very nice!

You say you found bugs in the juce time classes? Let me know what they are and I’ll fix them![/quote]

Sometimes, when you walk through the month days by adding a day to the current date then RelativeTime class may return a wrong date - it may repeat the current date twice (01 02 03 … 25 26 27 [color=red]28 28[/color] 29). I encountered it in October while testing but I’m not sure in which year.[/quote]

How odd - it’s all done in milliseconds, so not much scope for maths errors, and it’s the normal c library routines that convert from millisecs to days, so can’t think why that’d happen. I guess the poco classes store it as separate fields for the days, month, year, etc.[/quote]

Well, actually it is not that odd and not really wrong. :slight_smile: The reason is, that juce has (as far as I’ve seen) no way of adding calendar days, a RelativeTime with 1 day is exactly 606024 seconds long, it is, as the name says a relative time, so when you start in a month where the daylight saving time ends with creating a Time with the 1st of that month and the time of 0:00 (like Ptomaines beautiful component does) then adding 24h ReliativeTime instances will repeat a day, one day after end of DST because that day is 25 hours long, so you are at 23:00 the same day after adding 24h.

The right way to implement that for only iterating over the days of a month with only 24h steps would be to use a save time like 12:00.

It might become handy to be able to add calendar days in JUCE too, but that handling still is not a bug, in my opinion.

The other thing is, that on one hand JUCE is a bit limited for a calendar component to be useful for e.g. birthdays (at least mine is not allowed), so the range is indeed a problem. Poco, on the other hand, is far beyond a reasonable range, claiming to support years from 0 up to 9999 but failing to do it right. Years before 1528 are handled simply wrong (the leap year rules where different before that year, so the calendar component would show wrong entries anyway) and it might be even questionable to support them anyway.


#19

Shouldn’t converting the time_t to tm structure (with C library: localtime) and doing the computation on the tm structure, then and only then, convert back to time_t (with mktime) would give correct result ?

Aren’t C library functions supposed to handle DST and leap year and so forth correctly ?

That would still limit the calendar to 2038, but I guess that, by that time, all computer will be 64bits, so will be time_t, and a simple recompile would extend this limit.

Under linux, time_t is already 64bit, so no 2038 limit there.

BTW, Gulrak is true that there was no 5 to 14 october 1582, while Poco does still allow this.


#20

[quote=“X-Ryl669”]Shouldn’t converting the time_t to tm structure (with C library: localtime) and doing the computation on the tm structure, then and only then, convert back to time_t (with mktime) would give correct result ?

Aren’t C library functions supposed to handle DST and leap year and so forth correctly ?[/quote]

Well, there’s no single allways right way.

As far as I understood, RelativeTime is some kind of time span, so adding a constant time span to a Time should always advance the same amount of time. If we change operator+(RelativeTime&) to do work on a mix of seconds and days, it would definately break old code, and if you code some progress info where the ETA is days ahead, then the resulting time would be simply wrong, as in that case one would expect it to add an amount of time. So there are calendar expressions and time expressions, and there is no way the OS or JUCE can do it right without the developer showing his intentions (e.g. selecting different functions).

It would be nice to be able to do calendar expressions, but not when losing the time based way. Both are useful. Something like a RelativeDate might be a way to go.