View previous topic :: View next topic |
Author |
Message |
kbogert
Joined: 18 May 2006 Posts: 5
|
Posted: Thu May 18, 2006 11:12 am Post subject: Primitive Calendar and Date Picker Controls |
|
|
Hello all, after some work I've managed to come up with a no frills calendar and date picker controls. They can be made much better, but they work for me.
Code: |
// Written By Kenneth Bogert
private import dfl.all;
private import dfl.winapi;
private import std.date;
class Calendar : Panel {
static char [][] monstrs = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December" ];
protected void onHandleCreated(EventArgs ea){
super.onHandleCreated(ea);
selectedDay(UTCtoLocalTime(getUTCtime()));
backButton = new Button();
backButton.parent = this;
backButton.text = "<";
backButton.bounds = dfl.base.Rect(3, 3, 15, 15);
backButton.click ~= &this.backMonth;
forwardButton = new Button();
forwardButton.parent = this;
forwardButton.text = ">";
forwardButton.click ~= &this.forwardMonth;
forwardButton.bounds = dfl.base.Rect(183, 3, 15, 15);
monthYear = new Label();
monthYear.bounds = dfl.base.Rect(15, 3, 168, 15);
monthYear.textAlign = dfl.base.ContentAlignment.MIDDLE_CENTER;
monthYear.parent = this;
foreach (int i, Label l; weekDays) {
weekDays[i] = new Label();
with (weekDays[i]) {
bounds = dfl.base.Rect(i * 28 + 3, 20, 28, 15);
textAlign = dfl.base.ContentAlignment.MIDDLE_CENTER;
parent = this;
text = daystr[(i * 3) .. (i * 3 + 3)];
}
}
foreach (int i, Label b; days) {
with (days[i] = new Label()) {
bounds = dfl.base.Rect((i * 28) ? 196 + 3, 15 * (i / 7) + 38, 28, 15);
parent = this;
click ~= &daySelect;
textAlign = dfl.base.ContentAlignment.MIDDLE_CENTER;
}
}
_selectedDayBackColor = Color(128, 128, 128);
_unselectedDayForeColor = Color(0, 0, 128);
_otherMonthDayForeColor = Color(128, 128, 128);
updateDisplay();
}
public:
d_time selectedDay() {
return startingDay + (cast(long)_selectedDay * msPerDay);
}
void selectedDay(d_time d) {
month = MonthFromTime(d);
year = YearFromTime(d);
calcStartingDay();
calcSelectedDay(d);
updateDisplay();
}
void selectedDayMod(int amount) {
if (_selectedDay + amount < 0) {
d_time oldDay = selectedDay();
backMonth(null, EventArgs.empty);
oldDay += amount * msPerDay;
calcSelectedDay(oldDay);
daySelect(days[_selectedDay], EventArgs.empty);
} else if (_selectedDay + amount >= days.length) {
d_time oldDay = selectedDay();
forwardMonth(null, EventArgs.empty);
oldDay += amount * msPerDay;
calcSelectedDay(oldDay);
daySelect(days[_selectedDay], EventArgs.empty);
} else
daySelect(days[_selectedDay + amount], EventArgs.empty);
}
Color selectedDayBackColor() {
return _selectedDayBackColor;
}
void selectedDayBackColor(Color c) {
_selectedDayBackColor = c;
updateDisplay();
}
Color unselectedDayForeColor() {
return _unselectedDayForeColor;
}
void unselectedDayForeColor(Color c) {
_unselectedDayForeColor = c;
updateDisplay();
}
Color otherMonthDayForeColor() {
return _otherMonthDayForeColor;
}
void otherMonthDayForeColor(Color c) {
_otherMonthDayForeColor = c;
updateDisplay();
}
bool selectedDay3D() {
return _selectedDay3D;
}
void selectedDay3D(bool b) {
_selectedDay3D = b;
}
EventHandler daySelected;
private:
bool _selectedDay3D;
Button backButton;
Button forwardButton;
Label monthYear;
Label [7] weekDays;
Label [42] days;
int _selectedDay;
d_time startingDay;
d_time firstOfMonth;
d_time endOfMonth;
int month;
int year;
Color _selectedDayBackColor;
Color _unselectedDayForeColor;
Color _otherMonthDayForeColor;
void updateDisplay() {
// calculate the starting day;
calcStartingDay();
if (backButton) {
monthYear.text = monstrs[month] ~ " " ~ std.string.toString(year);
d_time startDate = startingDay;
foreach (int i, Label b; days) {
with (days[i]) {
int dft = DateFromTime(startDate);
text = (dft < 10 ? " " : "") ~ std.string.toString(dft);
if (_selectedDay3D) {
if (i == _selectedDay) {
borderStyle = dfl.base.BorderStyle.FIXED_3D;
} else {
borderStyle = dfl.base.BorderStyle.NONE;
}
} else {
if (i == _selectedDay) {
backColor = _selectedDayBackColor;
} else {
backColor = SystemColors.control;
}
}
if (startDate < firstOfMonth || startDate >= endOfMonth) {
foreColor = _otherMonthDayForeColor;
} else {
foreColor = _unselectedDayForeColor;
}
}
startDate += msPerDay;
}
}
}
void daySelect(Object sender, EventArgs ea) {
foreach (int i, Label b; days) {
if (sender == b) {
_selectedDay = i;
break;
}
}
d_time theDay = startingDay + (cast(long)_selectedDay * msPerDay);
int newMonth = MonthFromTime(theDay);
if (newMonth != month) {
if (newMonth > month + 2) //went back a year
year --;
if (newMonth < month - 2) //went forward a year
year ++;
month = newMonth;
calcStartingDay();
calcSelectedDay(theDay);
}
updateDisplay();
daySelected(this, EventArgs.empty);
}
void forwardMonth(Object sender, EventArgs ea) {
month ++;
if (month > 11) {
month = 0;
year ++;
}
updateDisplay();
}
void backMonth(Object sender, EventArgs ea) {
month --;
if (month < 0) {
month = 11;
year --;
}
updateDisplay();
}
void calcSelectedDay(d_time d) {
// from a month, year, and absolute date, figure out which square is selected
_selectedDay = (d - startingDay) / msPerDay;
}
void calcStartingDay() {
// from a month and year calc the absolute date of the first day to display in the array
firstOfMonth = TimeFromYear(year) + (cast(d_time)mdays[month] + (month >= 1 ? LeapYear(year) : 0 )) * msPerDay;
endOfMonth = TimeFromYear(month == 11 ? year + 1 : year) + (cast(d_time)mdays[(month+1) ? 12] + ((month + 1) ? 12 >= 1 ? LeapYear(year) : 0) ) * msPerDay;
startingDay = firstOfMonth - (cast(long)WeekDay(firstOfMonth) * msPerDay);
}
protected override void dispose() {
backButton.dispose();
forwardButton.dispose();
monthYear.dispose();
foreach (int i, Label l; weekDays) {
weekDays[i].dispose();
}
foreach (int i, Label b; days) {
days[i].dispose();
}
}
}
class DatePicker : Panel {
public:
protected void onHandleCreated(EventArgs ea){
super.onHandleCreated(ea);
t = new TextBox();
t.bounds = dfl.base.Rect(0, 0, this.bounds.width - 27, 24);
t.parent = this;
t.click ~= &toggleCalendar;
t.keyPress ~= &textBoxKeyPress;
t.keyUp ~= &textBoxKeyUp;
t.textChanged ~= &textBoxChange;
b = new Button();
b.bounds = dfl.base.Rect(this.bounds.width - 26, 0, 22, 24);
b.parent = this;
b.click ~= &toggleCalendar;
b.text = "Ȇ";
b.font = new dfl.drawing.Font("WingDings", 9f, dfl.drawing.FontStyle.REGULAR);
b.tabStop = false;
myCal = new Calendar();
myCal.visible = false;
myCal.bounds = dfl.base.Rect(0, 25, 203, 130);
myCal.daySelected ~= &closeDropDown;
myCal.parent = this;
myCal.borderStyle = dfl.base.BorderStyle.FIXED_SINGLE;
myCal.backColor = SystemColors.control;
date = UTCtoLocalTime(getUTCtime());
writeDate();
}
d_time date() {
return _date;
}
void date(d_time d) {
_date = d;
myCal.selectedDay = d;
}
bool isValid() {
return _isValid;
}
private:
Calendar myCal;
d_time _date;
TextBox t;
Button b;
Rect origSize;
bool _isValid;
bool _textBoxParseFlag = false;
bool _closeOnSelect = true;
void isValid(bool v) {
_isValid = v;
if (v) {
t.backColor = dfl.drawing.SystemColors.window;
} else {
t.backColor = Color(200, 0, 0);
}
}
void writeDate() {
_textBoxParseFlag = false;
t.text = std.string.toString(MonthFromTime(_date) + 1) ~ "/" ~ std.string.toString(DateFromTime(_date)) ~ "/" ~ std.string.toString(YearFromTime(_date));
isValid = true;
_textBoxParseFlag = true;
}
void closeDropDown(Object sender, EventArgs ea) {
_date = myCal.selectedDay;
writeDate();
if (_closeOnSelect) toggleCalendar(sender, ea);
}
void toggleCalendar(Object sender, EventArgs ea) {
myCal.visible = ! myCal.visible;
if (myCal.visible) {
origSize = this.bounds;
Rect newSize = this.bounds;
if (this.bounds.width < myCal.bounds.width) newSize.width = myCal.bounds.width;
if (this.bounds.height + 25 < myCal.bounds.height) newSize.height = myCal.bounds.height + 25;
this.bounds = newSize;
} else {
this.bounds = origSize;
}
}
void textBoxKeyUp(Object sender, KeyEventArgs ea) {
if (ea.keyCode == Keys.ESCAPE) {
if (myCal.visible)
toggleCalendar(sender, EventArgs.empty);
ea.handled = true;
} else if ( ea.keyCode == Keys.ENTER) {
toggleCalendar(sender, EventArgs.empty);
}
}
void textBoxChange(Object sender, EventArgs ea) {
if (_textBoxParseFlag) {
d_time d = std.date.parse(t.text);
if (d != d_time_nan) {
date = d;
isValid = true;
} else {
isValid = false;
}
// if (myCal.visible) toggleCalendar(sender, ea); // remove when ctrl-space is controlled ?
}
}
void textBoxKeyPress(Object sender, KeyEventArgs ea) {
if (ea.control && ea.keyCode == Keys.SPACEBAR) {
writeDate();
toggleCalendar(sender, EventArgs.empty);
ea.handled = true; // ??? Not working?
} else if (myCal.visible) {
if (ea.keyCode == Keys.LEFT) {
_closeOnSelect = false;
myCal.selectedDayMod = -1;
_closeOnSelect = true;
ea.handled = true;
} else if (ea.keyCode == Keys.RIGHT) {
_closeOnSelect = false;
myCal.selectedDayMod = 1;
_closeOnSelect = true;
ea.handled = true;
} else if (ea.keyCode == Keys.UP) {
_closeOnSelect = false;
myCal.selectedDayMod = -7;
_closeOnSelect = true;
ea.handled = true;
} else if (ea.keyCode == Keys.DOWN) {
_closeOnSelect = false;
myCal.selectedDayMod = 7;
_closeOnSelect = true;
ea.handled = true;
}
}
}
protected override void dispose() {
myCal.dispose();
t.dispose();
b.dispose();
}
}
|
Thanks for all the hard work everyone has put into DFL,
- kdb
Last edited by kbogert on Thu May 18, 2006 12:46 pm; edited 1 time in total |
|
Back to top |
|
|
Chris Miller
Joined: 27 Mar 2004 Posts: 514 Location: The Internet
|
Posted: Thu May 18, 2006 11:49 am Post subject: Re: Primitive Calendar and Date Picker Controls |
|
|
Cool! I tested it and it looks better than I expected. I can't figure out what is on the date picker button, though.
What license is this code? May I suggest the zlib/libpng license - and if you want, I'll put the code with the DFL addons, and perhaps in with DFL itself at some point.
- Chris |
|
Back to top |
|
|
kbogert
Joined: 18 May 2006 Posts: 5
|
Posted: Thu May 18, 2006 12:09 pm Post subject: Re: Primitive Calendar and Date Picker Controls |
|
|
ZLib license sounds good, Add-ons sounds good and I'd be very happy if you did decide to include it with DFL one day.
As for the button, I was at a loss as to what to put on there. What should be displayed now is a wingdings curving down arrow. Looks like it got screwed up in the upload.
Replace:
with:
I was thinking about putting an image on it but that would have been a slight pain to distribute. Also was thinking about programatically drawing a little calendar on it, maybe in the future.
- kdb |
|
Back to top |
|
|
Chris Miller
Joined: 27 Mar 2004 Posts: 514 Location: The Internet
|
Posted: Sat May 20, 2006 12:09 pm Post subject: Re: Primitive Calendar and Date Picker Controls |
|
|
Add-on posted: http://wiki.dprogramming.com/Dfl/CalDate
The new button symbol you gave me didn't work either, but I figured out what you wanted to do and used "\u00CA" |
|
Back to top |
|
|
rocex
Joined: 23 Apr 2009 Posts: 4
|
Posted: Mon Sep 21, 2009 11:16 pm Post subject: Re: Primitive Calendar and Date Picker Controls |
|
|
this is a great tool, thinks.
is there a caldate base on tango version?
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|