A simple month calendar

A simple month calendar

Postby xProgrammer » Tue Jul 29, 2008 12:56 am

Image

work in progress but now has slightly neater code and code to increment by any number of months (forward or backwards) and the same for years. That code looks slightly complicated but its to allow for leap years.

MoveYears( iIncrement), it has just occurred to me, could be implemented as:

Code: Select all  Expand view
METHOD MoveYears( iIncrement ) CLASS CALENDAR

   ::MoveNonths( iIncrement * 12 )

RETURN nil


MoveMonths() could be implemented in a simpler manner if you don't want to allow maintining a highlight on a certain day of the month as a possibility.

Here is the code (dirty) as it stands:

Code: Select all  Expand view
// Calendar.prg

#include "FiveLinuxDF.ch"
#include "hbclass.ch"

#define GTK_NORMAL 0
#define GTK_ACTIVE   1
#define GTK_PRELIGHT 2
#define GTK_SELECTED 3
#define GTK_INSENSITIVE 4

CLASS CALENDAR

DATA aDATEBUTTONS
DATA aDOW
DATA dAnchorDate
DATA iStartOfMonth
DATA iEndOfMonth
DATA grp_CALENDAR

METHOD New() CONSTRUCTOR
METHOD Show()
METHOD SetButtons()
METHOD SetAnchorDate( dDate )
METHOD MoveMonths( iIncrement )
METHOD MoveYears( iIncrement )

ENDCLASS

METHOD New() CLASS CALENDAR

::SetAnchorDate( DATE() )
::aDATEBUTTONS := ARRAY( 37 )
::aDOW := { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }

Return self


METHOD Show() CLASS CALENDAR

LOCAL dlg_CALENDAR
LOCAL sTitle
LOCAL ii
LOCAL oBtn

sTitle := "Calendar"
DEFINE DIALOG dlg_CALENDAR TITLE sTitle SIZE 400, 500

@ 90, 10 GROUP ::grp_CALENDAR LABEL "Calendar" OF dlg_CALENDAR SIZE 370, 250 PIXEL
iRow := 120
iCol = 20
FOR ii = -6 TO 37
   IF ii > 0
      @ iRow, iCol BUTTON ::aDATEBUTTONS[ii] PROMPT "Test" OF dlg_CALENDAR PIXEL SIZE 40, 25 NORMAL "aquamarine" PRELIGHT "medium aquamarine"
     ELSE
      @ iRow, iCol BUTTON oBtn PROMPT ::aDOW[ii + 7] OF dlg_CALENDAR PIXEL SIZE 40, 25 WHEN .F.
      oBtn:SetBackgroundColor( "yellow", GTK_INSENSITIVE )   
   ENDIF
   iCol += 50
   IF iCol > 330
      iRow += 30
      iCol := 20
   ENDIF
NEXT

@360, 10 BUTTON "Previous Month" OF dlg_CALENDAR PIXEL SIZE 120, 27 ACTION ::MoveMonths( -1 )
@360,250 BUTTON "Following Month" OF dlg_CALENDAR PIXEL SIZE 120, 27 ACTION ::MoveMonths( 1 )
@400, 10 BUTTON "Previous Year"  OF dlg_CALENDAR PIXEL SIZE 120, 27 ACTION ::MoveYears( -1 )
@400,250 BUTTON "Following Year"  OF dlg_CALENDAR PIXEL SIZE 120, 27 ACTION ::MoveYears( 1 )

ACTIVATE DIALOG dlg_CALENDAR ON INIT ::SetButtons()

RETURN nil


METHOD SetButtons() CLASS CALENDAR

FOR ii = 1 TO 37
   DO CASE
      CASE ii < ::iStartOfMonth
         ::aDATEBUTTONS[ii]:Hide()
      CASE ii > ::iEndOfMonth
         ::aDATEBUTTONS[ii]:Hide()
      OTHERWISE
         ::aDATEBUTTONS[ii]:SetText( ALLTRIM( STR( ii - ::iStartOfMonth + 1 ) ) )
         ::aDATEBUTTONS[ii]:Show()
   ENDCASE
NEXT
::grp_CALENDAR:SetText( CMONTH( ::dAnchorDate ) + " " + STR( YEAR( ::dAnchorDate ) ) )

RETURN nil


METHOD SetAnchorDate( dDate ) CLASS CALENDAR

::dAnchorDate   := dDate
::iStartOfMonth := DOW( BOM( dDate ) )
::iEndOfMonth   := DaysInMonth( MONTH( dDate ), IsLeap( dDate ) ) + ::iStartOfMonth -1


RETURN nil


METHOD MoveMonths( iIncrement ) CLASS CALENDAR

iTemp := MONTH( ::dAnchorDate ) + iIncrement
iNewMonth := iTemp % 12
IF iNewMonth == 0
   iNewMonth := 12
ENDIF
iNewYear  := YEAR( ::dAnchorDate ) + ( ( iTemp - iNewMonth ) / 12 )
dTestDate := CTOD( "01/01/" + STR( iNewYear, 4, 0 ) )
iNewDay   := MIN( DAY( ::dAnchorDate ), DaysInMonth( iNewMonth, IsLeap( dTestDate ) ) )
::SetAnchorDate( CTOD( PADL( ALLTRIM( STR( iNewDay, 2, 0 ) ), 2 ) + "/" + PADL( ALLTRIM( STR( iNewMonth, 2, 0 ) ), 2 ) + "/" + STR( iNewYear, 4, 0 ) ) )
::SetButtons()

RETURN nil


METHOD MoveYears( iIncrement ) CLASS CALENDAR

iNewYear  := YEAR( ::dAnchorDate ) + iIncrement
dTestDate := CTOD( "01/01/" + STR( iNewYear, 4, 0 ) )
iNewDay   := MIN( DAY( ::dAnchorDate ), DaysInMonth( MONTH( ::dAnchorDate ), IsLeap( dTestDate ) ) )
::SetAnchorDate( CTOD( PADL( ALLTRIM( STR( iNewDay, 2, 0 ) ), 2 ) + "/" + PADL( ALLTRIM( STR( MONTH( ::dAnchorDate ), 2, 0 ) ), 2 ) + "/" + STR( iNewYear, 4, 0 ) ) )
::SetButtons()

RETURN nil


Regards
xProgrammer
User avatar
xProgrammer
 
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia

Postby Antonio Linares » Tue Jul 29, 2008 7:19 am

Doug,

Thanks for sharing it! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41206
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Postby xProgrammer » Tue Jul 29, 2008 10:35 pm

Hi all

I discovered a small glitch in my code. It occurred when MoveMonths() was used to move backwards enough for iTemp to go negative. This of course only happened when the move was back more than 1 month (which couldn't happen in the version given above).

The problem is with the % operator.

-5 % 12 is giving -5 whereas I would have expected +7.

So the code can be corrected as follows. Replace:

Code: Select all  Expand view
iNewMonth := iTemp % 12


With:

Code: Select all  Expand view
IF iTemp >= 0
   iNewMonth := iTemp % 12
  ELSE
   iNewMonth := 12 + (iTemp % 12 )
ENDIF


Regards
Doug
(xProgrammer)
User avatar
xProgrammer
 
Posts: 464
Joined: Tue May 16, 2006 7:47 am
Location: Australia


Return to FiveLinux / FiveDroid (Android)

Who is online

Users browsing this forum: No registered users and 7 guests