FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Primitive Calendar and Date Picker Controls

 
Post new topic   Reply to topic     Forum Index -> DFL
View previous topic :: View next topic  
Author Message
kbogert



Joined: 18 May 2006
Posts: 5

PostPosted: Thu May 18, 2006 11:12 am    Post subject: Primitive Calendar and Date Picker Controls Reply with quote

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
View user's profile Send private message
Chris Miller



Joined: 27 Mar 2004
Posts: 514
Location: The Internet

PostPosted: Thu May 18, 2006 11:49 am    Post subject: Re: Primitive Calendar and Date Picker Controls Reply with quote

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
View user's profile Send private message
kbogert



Joined: 18 May 2006
Posts: 5

PostPosted: Thu May 18, 2006 12:09 pm    Post subject: Re: Primitive Calendar and Date Picker Controls Reply with quote

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:

Code:

b.text = "Ê";


with:

Code:

b.text = "Ȇ";




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
View user's profile Send private message
Chris Miller



Joined: 27 Mar 2004
Posts: 514
Location: The Internet

PostPosted: Sat May 20, 2006 12:09 pm    Post subject: Re: Primitive Calendar and Date Picker Controls Reply with quote

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
View user's profile Send private message
rocex



Joined: 23 Apr 2009
Posts: 4

PostPosted: Mon Sep 21, 2009 11:16 pm    Post subject: Re: Primitive Calendar and Date Picker Controls Reply with quote

this is a great tool, thinks.

is there a caldate base on tango version?

Chris Miller wrote:
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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> DFL All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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