Codejock Calendar Samples?

User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

Hi.

I've been asked by a few people for a short .prg that shows how to use codejock extreme calendar with dbfcdx.

Below is a single short .prg that syncs "events" on the calendar to a dbf/fpt/cdx. I'm trying to keep the sample short. Keep in mind that each event on the calendar may have as many fields as you'd like for things such as "recurring", "reminder", "send email alert", "email address", "medical record", etc... each of these fields would be kept on each event as a custom property. On this short sample I'm implementing only a single custom property "id" to keep the corresponding primary key on file for each event on the calendar.

I hope it helps, but if there are more questions; please feel free to ask, I'm more than willing to help.

Code: Select all

/*----------------------------------------------------------------------------*/
#include "fivewin.ch"
//---------- theme constants
#define xtpCalendarThemeOffice2000  0
#define xtpCalendarThemeOfficeXP        1
#define xtpCalendarThemeOffice2003  2
#define xtpCalendarThemeOffice2007  3

//----------- views
#define xtpCalendarDayView      0
#define xtpCalendarWorkWeekView     1
#define xtpCalendarWeekView     2
#define xtpCalendarMonthView    3

static cAlias 

*--------------------------------------------------------------------------
function Main()

    create_dbf()
    
    MpCal():New()

    (cAlias)->( dbCloseArea() )
    
return nil

//---------------------------------------------------//
static function create_dbf()

    local astruc := { { "id", "C", 12, 0 },;
                        { "starttime"   , "C", 18, 0 },;
                        { "endtime"     , "C", 18, 0 },;
                        { "subject"     , "C", 50, 0 },;
                        { "body"            , "M", 10, 0 } }
                            
    cAlias := "Calendar" 
        
    if !file( "calendar.dbf")
        
        dbcreate( cAlias, aStruc, "DBFCDX", .t., cAlias )
    
        (cAlias)->( OrdCreate( cAlias, "id", "id" ) )
        (cAlias)->( OrdCreate( cAlias, "starttime", "starttime" ) )
    else
    
        dbuseArea( .t., "DBFCDX", cAlias, cAlias, .t. )
    endif

    (cAlias)->( OrdListAdd( cAlias ) )
        
Return Nil
    

//---------------------------------------------------//

CLASS MpCal

   DATA dCurrentDate AS DATE INIT Date()
   
   DATA oCalex, oCalexCapBar
   DATA oDtPick
   DATA oExBar   
   DATA oPanelExplorer
   DATA oPanelCalex
   DATA oWnd
   
   METHOD New()

   METHOD BuildCalex()
   METHOD BuildDatePicker()
   METHOD BuildPanels()
   METHOD SetSize( nType, nWidth, nHeight )
   
    METHOD xTrmCalTriggeredEvents( Event, Parms )   
    METHOD RetrieveDayEvents( aParms )
    METHOD InsertEvent( oEvent )
    METHOD UpdateEvent( oEvent )
    METHOD DeleteEvent( oEvent )

ENDCLASS

//---------------------------------------------------//

METHOD New() CLASS MpCal
   
   local oMenu
   local oSelf := Self
   
   MENU oMenu
   ENDMENU

    DEFINE WINDOW ::oWnd MDI MENU oMenu Title "CodeJock Xtrme Calendar FWH Sample"

   ::BuildPanels()          //two panels -left and right
   ::BuildCalex()               //CodeJock calendar on the right
   ::BuildDatePicker()      //CodeJock DatePicker on the left

   ACTIVATE WINDOW ::oWnd MAXIMIZED;
            ON RESIZE oSelf:SetSize( nSizeType, nWidth, nHeight )
            
RETURN Self

//-----------------------------------------------------------------------------------------------------//
METHOD xTrmCalTriggeredEvents( Event, aParms ) CLASS MpCal

    if valType( Event ) == "C"

        Do Case

        Case Event == "DoRetrieveDayEvents"         
            ::RetrieveDayEvents( aParms )

        case Event == "EventAddedEx"
            ::InsertEvent( aParms[ 1 ] )

        case Event == "EventChangedEx" .and. aParms[ 1 ]:CustomProperties:Property( "id" ) != Nil
            ::UpdateEvent( aParms[ 1 ] )

        case Event == "EventDeletedEx" .and. aParms[ 1 ]:CustomProperties:Property( "id" ) != Nil
            ::DeleteEvent( aParms[ 1 ] )
            
/*      other useful triggered events that may be catched.
        Case Event == "DblClick"
        Case Event == "MouseMove"
        Case Event == "MouseDown" 
        case Event == "KeyDown"
        case Event == "IsEditOperationDisabled"
        case Event == "IsEditOperationDisabledV"
        case Event == "DoUpdateEvent"
        case Event == "BeforeEditOperation"
            Return ::BeforeEditOperation( aParms[ 1 ] )

        otherwise
            Logfile( "trace.log", { EventInfo( event, aParms ) } ) */
            
        End 

    endif
    
Return nil

//-----------------------------------------------------------------------------------------------------//
METHOD InsertEvent( oEvent ) CLASS MpCal

    local cId := GetUniqueId()

    (cAlias)->( dbappend() )
    (cAlias)->( rLock() )
    
    (cAlias)->id            := cId 
    (cAlias)->Subject   := oEvent:Subject()
    (cAlias)->StartTime := Left( TtoS( oEvent:StartTime() ), 14 )
    (cAlias)->EndTime       := Left( TtoS( oEvent:EndTime() ), 14 )
    (cAlias)->body          := oEvent:Body()

    (cAlias)->( dbrUnlock() )

    //load custom property for the newly created event with a unique id that will 
    //match field "id" on calendar.dbf
    oEvent:CustomProperties:Property( "id", cId )

    //every time a new appointment is added on the calendar control
    //you could expand appntmnt details with a custom form where you may pickup 
    //other values.
    //::EventDetails( oEvent )
        
Return oEvent

//-----------------------------------------------------------------------------------------------------//
METHOD UpdateEvent( oEvent ) CLASS MpCal

    local cid := oEvent:CustomProperties:Property( "id" )

    (cAlias)->( OrdSetFocus( "id" ) )
    (cAlias)->( dbseek( cId ) )
   
    if (cAlias)->( found() ) .and. (cAlias)->( rLock() )
    
        (cAlias)->Subject := oEvent:Subject()
        (cAlias)->StartTime := Left( TtoS( oEvent:StartTime() ),14 )
        (cAlias)->EndTime := Left( TtoS( oEvent:EndTime() ), 14 )
        (cAlias)->body := oEvent:body
        
        (cAlias)->( dbrUnlock() )
        
    endif

    //if there is more data that's being pickedup as part of the calendar appointment   
    //then call that screen to allow modification of those values also
    //::EventDetails( oEvent )

return oEvent

//-----------------------------------------------------------------------------------------------------//
METHOD DeleteEvent( oEvent ) CLASS MpCal
                    
    local cid := oEvent:CustomProperties:Property( "id" )

    (cAlias)->( OrdSetFocus( "id" ) )
    (cAlias)->( dbseek( cId ) )

    if (cAlias)->( found() ) .and. (cAlias)->( rLock() )
        (cAlias)->( delete() )
    endif
    
return oEvent

//-----------------------------------------------------------------------------------------------------//
//aParms[ 1 ] contains a datetime value. This function should return all the events found on 
//calendar.dbf for that date.  To extract only the date portion, we convert the datetime 
//value to string and then pullout the first 8 chars asin YYYYMMDD.
//keep in mind that the control calls this function each time the control changes dates,
//or changes views or just about any time the control feels it needs to load data from 
//file.  So it gets called a lot!

METHOD RetrieveDayEvents( aParms ) CLASS MpCal

    local oEvents := aParms[ 2 ] 
    local oEvent
    local cDate     := Left( TtoS( aParms[ 1 ] ), 8 )

    (cAlias)->( OrdSetFocus( "StartTime" ) )
    (cAlias)->( dbSeek( cDate ) )

    While !(cAlias)->( eof() ) .and. left( (cAlias)->StartTime, 8 ) == cDate
    
        oEvent := ::oCalex:DataProvider:CreateEvent()
        
        With Object oEvent
            :Subject := (cAlias)->Subject
            :StartTime := StoT( (cAlias)->StartTime )
            :EndTime := StoT( (cAlias)->EndTime )
            :body := (cAlias)->body

            //custom property "id" will hold the contents of field "id" on calendar.dbf
            //to help us match each event displayed on the calendar to a unique record 
            //on the calendar table. 
            :CustomProperties:Property( "id", (cAlias)->id )

        End
    
        oEvents:add( oEvent )
        (cAlias)->( dbSkip() )

    end
    
Retur Nil
                
//---------------------------------------------------------------------------------------------------//
METHOD BuildCalex() CLASS MpCal
local oErr
local cIni          := "patients.ini"

    TRY     
        ::oCalex := tActiveX():New( ::oPanelCalex, "Codejock.CalendarControl.13.4.2" )
    CATCH oErr
        MsgStop( "Missing installation Components", "Aborting" )
        Quit
    END 
    
    with object ::oCalex
    
        :VisualTheme( xtpCalendarThemeOffice2007 )
        :bOnEvent = { | event, aParms | ::xTrmCalTriggeredEvents( Event, aParms ) }
        
        :SetDataProvider( "Provider=custom" )
        :DataProvider:open()

        :ShowCaptionBar( .t. )
        :ShowCaptionBarSwitchViewButtons( .t. ) //switch from day, week, month view on capbar
    
        :ViewType( xtpCalendarDayView )

        :DayView:TimeScaleMinTime( [8:00:00 AM] )
        :DayView:TimeScaleMaxTime( [6:00:00 PM] )
        :DayView:TimeScale( 15 )
        :DayView:ScrollToWorkDayBegin()     //scroll the view to the work day starting time

        :Options:DayViewTimeScaleShowMinutes( .t. )

    end

   ::oPanelCalex:oClient = ::oCalex

Return Nil

//---------------------------------------------------//
METHOD BuildDatePicker() CLASS MpCal
local nTmp
local oPanel, oErr, oWnd

    TRY
        ::oDtPick := tActiveX():New( ::oPanelExplorer,"Codejock.DatePicker.13.4.2" )
        
        With Object ::oDtPick
            :Enabled( .t. )
            :ShowWeekNumbers( .t. )
            :VisualTheme( xtpCalendarThemeOffice2007 )
            :AttachToCalendar( TOleAuto():New( ActXPdisp( ::oCalex:hActiveX ) ) )
        End 
        
        ::oPanelExplorer:oClient := ::oDtPick

    CATCH oErr
    
    END 
    
RETURN nil

//---------------------------------------------------//

METHOD BuildPanels() CLASS MpCal
local oBrush
local nHeight := ::oWnd:nHeight

   ::oPanelCalex    = TPanel():New( 0, 175, nHeight, ::oWnd:nWidth, ::oWnd:oWndClient )
   ::oPanelExplorer = TPanel():New( 0, 0, nHeight, ::oPanelCalex:nLeft, ::oWnd:oWndClient )
   
RETURN nil

//---------------------------------------------------//

METHOD SetSize( nType, nWidth, nHeight ) CLASS MpCal

   if nWidth != nil 
      ::oPanelExplorer:Move( , , , nHeight )
      ::oPanelCalex:Move( , , nWidth - ::oPanelExplorer:nRight, nHeight )
   endif
   
RETURN nil

*-------------------------------------------------------------------------------------------------------------------------------
procedure RddInit()


    Set Century     On
    Set Deleted     On
    Set SoftSeek    On
    Set Date Format "MM/DD/YYYY"
    set epoch to 1950

    rddsetdefault( "ADS" )
    REQUEST HB_LANG_EN
    REQUEST DBFCDX, DBFFPT
    
return

*-------------------------------------------------------------------------------------------------------------------------------
//I would recommend a better unique value to id each event saved to calendar.dbf
//A better choice of unique Id would be ADS's field defaulting to NewIdString( 'M' )
//but this will do for the this short sample
//
static Function GetUniqueId()
local cJulian   := StrZero( DoY( date() ), 3 )
Local cId       := Right( StrZero( Year( Date() ), 4 ), 2 ) + cJulian + StrTran( StrZero( Seconds(), 7, 1 ), ".", "" )

Return ( cId )
 
Regards;


Reinaldo.
User avatar
Richard Chidiak
Posts: 946
Joined: Thu Oct 06, 2005 7:05 pm
Location: France
Contact:

Re: Codejock Calendar Samples?

Post by Richard Chidiak »

Reinaldo

Thanks for sharing the code, this is very helpful

Can this control be used in a network environment ?

Richard
http://www.cbati.com

Uestudio
Fwh 13.05 Harbour 3.2 MSVC 2013
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

Richard;

In a network environment you'd have to find when a new appointment ("event") has been saved to disk in order update (refresh()) the calendar on alll the other workstations. Many SQLs have configurable services that may broadcast a message to all clients connected. The message could inform that a new appointment has been added/changed or deleted. You'd have to have a loop that processes messages and act accordingly.

ADS has such service so that when something is added/updated/deleted on a table, it broadcasts a message (in ADS nomenclature: "event notification") to all clients connected to the table with information about the event. With out this, you'd have to implement your own messaging system. As you see, it is a little bit tricky -not impossible, but tricky and it has little to do with the calendar control it self.

You could also have a timer to "poll" the table or poll a messages table and force a refresh. But still... I don't see a simpler way of doing it than the centralized notification system on the SQL engine itself -which you find in ADS starting with version 9.

In the absence of ADS, maybe someone has a better idea. I hope this helps.


Reinaldo.
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

Richard;

Another thought; you could periodically call the method :Populate() to force a sync between the data source (dbfs) and the calendar. That should work, but again not as efficient has a notification from the sql engine itself.

Just another idea.


Reinaldo.
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

I highly recommend this control.

Just another screen shot:
Image

Image

Reinaldo.
User avatar
MdaSolution
Posts: 401
Joined: Tue Jan 05, 2010 2:33 pm

Re: Codejock Calendar Samples?

Post by MdaSolution »

ON YOUR CLASS
HOW CREATE EXPLORER CONTROL CAN i SEE THE TEST SOURCE ?
FWH .. BC582.. xharbour
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

MdaSolution;

The source is on this same thread, read 4 or 5 messages above. It is a reduced sample, but it does contain the code that creates the explorer control exactly as you see on the images.

Reinaldo.
User avatar
Massimo Linossi
Posts: 474
Joined: Mon Oct 17, 2005 10:38 am
Location: Italy

Re: Codejock Calendar Samples?

Post by Massimo Linossi »

Hi Reinaldo.
2 little questions.
Is this control available in Italian language ?
If you want to distribute an application that is using this control, how can you make the installation
registering the component ?
Thanks a lot.
Massimo.
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

Massimo;

There is very little fixed text on the control. They call it "Labels". All labels have a property where you can set the text that should be displayed and it can change at any time. I'm not sure if labels are predefined in other languages, I think you should email CodeJock sales people with that question.

Regarding the auto-installation of the OCX, CodeJock has a few sample codes that shows how to automate the OCX registration. I haven't looked into that just yet, since I'm confident that it will not be an issue. At this moment I'm trying to learn how to use their other controls such as the Grid and report control which just looks fantastic!

Reinaldo.
User avatar
Massimo Linossi
Posts: 474
Joined: Mon Oct 17, 2005 10:38 am
Location: Italy

Re: Codejock Calendar Samples?

Post by Massimo Linossi »

Thanks Reinaldo for your answer.
User avatar
richard-service
Posts: 583
Joined: Tue Oct 16, 2007 8:57 am
Location: New Taipei City, Taiwan
Contact:

Re: Codejock Calendar Samples?

Post by richard-service »

Massimo Linossi wrote:Thanks Reinaldo for your answer.
You can use this code below:

Code: Select all

oBF:GlobalSettings:ResourceFile:= "SuitePro.ResourceIt.dll"
 
Regards,

Richard

Harbour 3.2.0dev (r1904111533)/xHarbour 1.2.3 Intl. (SimpLex) (Build 20180818) => Borland C++ v7.4
xHarbour 0.99.71 (SimpLex) => Borland C++ v5.5
MySQL v5.7 /ADS v12
Harbour 3.2.0dev (r1603181642) => Borland C++ v7.4 64bit
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: Codejock Calendar Samples?

Post by hmpaquito »

Reinaldo,

Perdón por el castellano.. pero me interesaba comentarle una cosa.
Én general, fuera del tema del Calendar, el tema del envio de mensajes o eventos sobre la modificacion de datos, a mi modo de ver es intesante pero más allá de la modificación de datos.
Eventos ejemplo que pueden ser enviados a otros usuarios:

- Usuario ingresado (programa abierto)
- Usuario dado de baja
- usuario haciendo proceso exclusivo
- Usuario quiere hace proceso exclusivo
- Documento (ejemplo factura) creada: Un documento puede estar compuesto de mas de una tabla y solamente se notificara la creacion del documento una vez finalizado.

- etc...

No se que le parecerá todo esto que comento... pienso que se puede programar todo esto con codigo .prg..

Saludos
reinaldocrespo wrote:Richard;

In a network environment you'd have to find when a new appointment ("event") has been saved to disk in order update (refresh()) the calendar on alll the other workstations. Many SQLs have configurable services that may broadcast a message to all clients connected. The message could inform that a new appointment has been added/changed or deleted. You'd have to have a loop that processes messages and act accordingly.

ADS has such service so that when something is added/updated/deleted on a table, it broadcasts a message (in ADS nomenclature: "event notification") to all clients connected to the table with information about the event. With out this, you'd have to implement your own messaging system. As you see, it is a little bit tricky -not impossible, but tricky and it has little to do with the calendar control it self.

You could also have a timer to "poll" the table or poll a messages table and force a refresh. But still... I don't see a simpler way of doing it than the centralized notification system on the SQL engine itself -which you find in ADS starting with version 9.

In the absence of ADS, maybe someone has a better idea. I hope this helps.


Reinaldo.
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

hmpaquito;

Realmente aqui hablo de notifiaciones y se trata de notificaciones que el ADS ya envia sin que tengas que programar nada de .prg. O sea, si quieres saber cuando una factura se crea; solo tienes que decir a ADS que genere una notificación cuando la tabla de factura recibe un "Insert". Igual puedes pedir a ADS que envie notificaciones cuando algo cambia en una tabla, cuando se borra algo, cuando se añade algo, cuando un usuario se logea, cuando se des-logea... Cuando cualquiera de estas cosas suceda, entonces ADS (el server) envia la notificacion al respecto a todos los clientes (aplicaciones) conectados al server. Nada que programar. Y funciona muy bien.

Por ejemplo yo tengo un server que envia una notificacion cada vez que una habitacion del hospital es ocupada o desocupada y de esta manera las aplicaciones saben que habitaciones ofrecer a una nueva admision o transferencia de habitacion.

Espero se entienda.


Un saludo,


Reinaldo.
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: Codejock Calendar Samples?

Post by hmpaquito »

Reinaldo,

Solamente planteaba algo ya ya tiempo me ronda la cabeza y que me lo recordó su comentario: un sistema de eventos o notificaciones que una aplicación puede enviar a sus aplicaciones "hermanas" de la red. Las notificaciones pueden ser diversas y no solamente por modificaciones en los datos. En cualquier caso, no se como funciona en ADS las notificaciones, pero si por ejemplo

// Incio de documento
SELECT Factura
APPEND BLANK

Otra codigo

SELECT OtroFichero
APPEND BLANK // ADS aqui ??


// fin de documento

Seria en // fin de documento donde se tendria que realizar la notificacion de nuevo documento. ADS lo haria, segun entiendo, mal.


Saludos
User avatar
reinaldocrespo
Posts: 918
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Codejock Calendar Samples?

Post by reinaldocrespo »

hmpaquito;

Let's move this thread over to the spanish forum. ...y evitamos incomodar a los que no entienden. In the mean while; please excuse me for answering in English.

I will attempt to explain ADS Notifications:

Notifications provide a mechanism for communicating to a client that something has occurred. For example, notifications can be used to inform a client application that data in a critical table has changed. The client application can then use this information to refresh() an xbrowse (or some other control) of that table and thus provide the user with more up to date information (without having to "poll" the table).

A Notification might be used to signal a client that a record has been added to a special table created for purpose of communicating messages from the system administrator to the end users. The client application can then read the latest message and display it within its interface.

A Notification might be used to signal a client that a record has changed. The client app my make a decision based on what changed on that particular record. Perhaps create an entry on a queue to send some information via email. Then a client app listening for such notifications can take care of sending the email.

These are all typical situations where an ADS Notification might be used. No coding. No .prg. ADS provides an API to create a notification, to listen for notifications, to know if a notification has been issued while the app was not listening. etc...

Specifically ADS API provides "sp_SignalEvent()" to create a Notification based on some condition. That part can be stored on the ADS Data Dictionary as a trigger so that you never have to tell the server again to issue a Notification based on that condition. The server always knows because you saved that as a "trigger" info on the Data Dictionary. Then API function "sp_WaitForEvent()" will inform the client application if an event has occurred.

On a single threaded app, you test for notifications by using a repeated periodic call with short timeouts -i.e. "polling". But not polling the table but rather polling for the event notification. Due to its nature, polling will not actually notify the client app when a change has occurred, but rather notifies the client that a change HAS occurred sometime between now and the last check. But that works just fine.

So, In essence, with ADS notifications you take care of "events" on any table without having to write or "invent the wheel". The wheel is already invented and running smoothly. For more information about ADS notifications; please visit http://devzone.advantagedatabase.com.

Hope that helps,



Reinaldo.
Post Reply