home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / powergui / listctls / spinbut / datectrl.cpp next >
Encoding:
C/C++ Source or Header  |  1996-10-31  |  6.4 KB  |  250 lines

  1. /************************************************************
  2. / List Controls - Spin Button Date Control
  3. /
  4. / Copyright (C) 1994, Law, Leong, Love, Olson, Tsuji.
  5. / Copyright (c) 1997 John Wiley & Sons, Inc.
  6. / All Rights Reserved.
  7. ************************************************************/
  8. #include <istring.hpp>
  9. #include <ispintxt.hpp>
  10. #include <ispinnum.hpp>
  11. #include <ispinhdr.hpp>
  12. #include "datectrl.hpp"
  13.  
  14. class DateSpinHandler : public ISpinHandler
  15. {
  16. public:
  17.   DateSpinHandler ( ITextSpinButton& month,
  18.                     INumericSpinButton& day,
  19.                     INumericSpinButton& year )
  20.        : _month(&month), _day(&day), _year(&year) {}
  21.  
  22. ITextSpinButton
  23.  &month  (  )   { return *_month;}
  24. INumericSpinButton
  25.  &day    (  )   { return *_day;}
  26. INumericSpinButton
  27.  &year    (  )  { return *_year;}
  28.  
  29. protected:
  30. virtual Boolean
  31.   arrowUp              ( IControlEvent& event ),
  32.   arrowDown            ( IControlEvent& event ),
  33.   dayChanged           ( Boolean        forward ),
  34.   monthChanged         ( Boolean        forward );
  35.  
  36. DateSpinHandler
  37.  &updateMonth          ( Boolean forward );
  38.  
  39. unsigned long
  40.   daysInMonth          ( ) const;
  41.  
  42. private:
  43. ITextSpinButton
  44.  *_month;
  45. INumericSpinButton
  46.  *_day,
  47.  *_year;
  48. };
  49.  
  50. ITextSpinButton& DateControl::month(  )
  51. { return *_month;}
  52.  
  53. INumericSpinButton& DateControl::day(  )
  54. { return *_day;}
  55.  
  56. INumericSpinButton& DateControl::year(  )
  57. { return *_year;}
  58.  
  59.  
  60. DateControl::DateControl ( unsigned long id,
  61.                            IWindow*      parent,
  62.                            IWindow*      owner,
  63.                            const IDate& aDate,
  64.                            const IRange& aYearRange)
  65.       : IMultiCellCanvas(id, parent, owner),
  66.         _month     ( new ITextSpinButton(id + 4, this, this,
  67.                        IRectangle(),
  68.                        IBaseSpinButton::servant |
  69.                        IBaseSpinButton::rightAlign |
  70.                        IWindow::visible)),
  71.         _day       ( new INumericSpinButton(id + 5, this, this,
  72.                        IRectangle(),
  73.                        IBaseSpinButton::servant |
  74.                        IBaseSpinButton::rightAlign |
  75.                        IWindow::visible)),
  76.         _year      ( new INumericSpinButton(id + 6, this, this,
  77.                        IRectangle(),
  78.                        IBaseSpinButton::master |
  79.                        IBaseSpinButton::rightAlign |
  80.                        IWindow::visible)),
  81.         _spinHandler(new DateSpinHandler(*_month, *_day, *_year))
  82. {
  83.  
  84.  
  85. (*this)
  86.   .addToCell( _month,      2, 2)
  87.   .addToCell( _day,        4, 2)
  88.   .addToCell( _year,       6, 2)
  89.   .setColumnWidth(1, 1, true)
  90.   .setColumnWidth(3, 2, false)
  91.   .setColumnWidth(5, 2, false)
  92.   .setColumnWidth(7, 1, true)
  93.   .setRowHeight  (1, 1, true)
  94.   .setRowHeight  (3, 1, true);
  95.  
  96. year()
  97.   .setRange(aYearRange)
  98.   .setLimit(4);
  99. year()
  100.   .spinTo(aDate.year());
  101.  
  102. // Load the Month spin button
  103. for (int i=1;
  104.      i < 13;
  105.      i++)
  106. {
  107.    month().addAsLast(IDate::monthName((IDate::Month)i));
  108. }
  109.  
  110. month()
  111.   .setMaster(year());
  112. #ifdef IC_PM
  113. // Disabled until setLimit fixed.
  114. month()
  115.   .setLimit(12);
  116. #else
  117. #if IC_MAJOR_VERSION > 320 || IC_MINOR_VERSION >= 3
  118. month()
  119.   .setLimit(12);
  120. #endif
  121. #endif
  122. month()
  123.   .setText(aDate.monthName());
  124.  
  125. day()
  126.   .setRange(IRange(1,32))
  127.   .setMaster(year())
  128.   .setLimit(2);
  129. day()
  130.   .spinTo(aDate.dayOfMonth());
  131.  
  132. // Start the spin handler on the canvas
  133. (*_spinHandler)
  134.   .handleEventsFor(this);
  135. }
  136.  
  137. IString DateControl::dateAsString ( ) const
  138. {
  139.   IString str= _month->text()+" "+IString(_day->value())+", "+
  140.                IString(_year->value());
  141.   return str;
  142. }
  143.  
  144.  
  145. IBase::Boolean DateSpinHandler::arrowUp( IControlEvent& event )
  146. {
  147.    IBaseSpinButton* spin = (IBaseSpinButton*)(event.controlWindow());
  148.    if (spin)
  149.    {
  150.       if  (spin->handle()==day().handle())
  151.          return dayChanged(true);
  152.       else if  (spin->handle()==month().handle())
  153.          return monthChanged(true);
  154.    }
  155.    return false;
  156. }
  157.  
  158. IBase::Boolean DateSpinHandler::arrowDown( IControlEvent& event )
  159. {
  160.    IBaseSpinButton* spin = (IBaseSpinButton*)(event.controlWindow());
  161.    if (spin)
  162.    {
  163.       if  (spin->handle()==day().handle())
  164.          return dayChanged(false);
  165.       else if  (spin->handle()==month().handle())
  166.          return monthChanged(false);
  167.    }
  168.   return false;
  169. }
  170.  
  171. // Handle a Month change - update the year if necessary
  172. IBase::Boolean DateSpinHandler::monthChanged( Boolean forward)
  173. {
  174.   IString contents = month().text();
  175.   if (forward  &&
  176.       contents == IDate::monthName(IDate::January))
  177.   {
  178.      year().setValue(year().value() + 1);
  179.   }
  180.   else if (!forward)
  181.   {
  182.      if(day().value() > daysInMonth())
  183.        day().setValue(daysInMonth());
  184.      if(contents == IDate::monthName(IDate::December))
  185.        year().setValue(year().value() - 1);
  186.   }
  187.   return true;
  188.  
  189. }
  190.  
  191. // Handle a day change - update the month if necessary
  192. IBase::Boolean DateSpinHandler::dayChanged( Boolean forward)
  193. {
  194.   unsigned long contents = day().value();
  195.   if ( forward  && contents > daysInMonth())
  196.   {
  197.      updateMonth(true);
  198.      day().setValue(1);
  199.      return true;
  200.   }
  201.   else if ( !forward &&
  202.             contents == day().range().upperBound())
  203.   {
  204.     updateMonth(false);
  205.     day().setValue(daysInMonth());
  206.     return true;
  207.   }
  208.   return false;
  209. }
  210.  
  211. // Roll the spin buttons month forward one month or
  212. // backward one month
  213. DateSpinHandler& DateSpinHandler::updateMonth ( Boolean forward)
  214. {
  215.   unsigned newMonth;
  216.   for (unsigned i=1; i<13; i++)
  217.   {
  218.     if (month().text() == IDate::monthName((IDate::Month)i))
  219.     {
  220.       if(forward)
  221.          newMonth = (i<12)? i+1 : 1;
  222.       else
  223.          newMonth = (i>1)? i-1 : 12;
  224.       month().setText(IDate::monthName(IDate::Month(newMonth)));
  225.       if(forward && newMonth == 1)
  226.         year().setValue(year().value() + 1);
  227.       if(!forward && newMonth == 12)
  228.         year().setValue(year().value() - 1);
  229.  
  230.       break;
  231.     }
  232.   }
  233.   return *this;
  234. }
  235.  
  236. // Compute the days in the Spin Buttons month
  237. unsigned long DateSpinHandler::daysInMonth ( ) const
  238. {
  239.   for (int i=1; i<13; i++)
  240.   {
  241.     if (((DateSpinHandler*)this)->month().text() ==
  242.                    IDate::monthName((IDate::Month)i))
  243.     {
  244.        return IDate::daysInMonth((IDate::Month)i,
  245.                    ((DateSpinHandler*)this)->year().value());
  246.     }
  247.   }
  248.   return 0;
  249. }
  250.