1#!/usr/bin/env python
2
3#----------------------------------------------------------------------------
4# Name:         Calendar.py
5# Purpose:      Calendar control display testing on panel for wxPython demo
6#
7# Author:       Lorne White (email: lwhite1@planet.eon.net)
8#
9# Version       0.9
10# Date:         Feb 26, 2001
11# Licence:      wxWindows license
12#----------------------------------------------------------------------------
13# 11/15/2003 - Jeff Grimmett (grimmtooth@softhome.net)
14#
15# o Updated for wx namespace
16#
17# 11/26/2003 - Jeff Grimmett (grimmtooth@softhome.net)
18#
19# o Ugh. AFter updating to the Bind() method, things lock up
20#   on various control clicks. Will have to debug. Only seems
21#   to happen on windows with calendar controls, though.
22#
23# 11/30/2003 - Jeff Grimmett (grimmtooth@softhome.net)
24#
25# o Lockup issue clarification: it appears that the spinner is
26#   the culprit.
27#
28
29import os
30
31import wx
32import wx.lib.calendar
33
34import images
35
36
37# highlighted days in month
38
39test_days ={ 0: [],
40            1: [3, 7, 9, 21],
41            2: [2, 10, 4, 9],
42            3: [4, 20, 29],
43            4: [1, 12, 22],
44            5: [2, 10, 15],
45            6: [4, 8, 17],
46            7: [6, 7, 8],
47            8: [5, 10, 20],
48            9: [1, 2, 5, 29],
49           10: [2, 4, 6, 22],
50           11: [6, 9, 12, 28, 29],
51           12: [8, 9, 10, 11, 20] }
52
53# test of full window calendar control functions
54
55def GetMonthList():
56
57    monthlist = []
58
59    for i in range(13):
60        name = wx.lib.calendar.Month[i]
61
62        if name != None:
63            monthlist.append(name)
64
65    return monthlist
66
67class TestPanel(wx.Panel):
68    def __init__(self, parent, log, frame):
69        wx.Panel.__init__(self, parent, -1)
70
71        self.log = log
72        self.frame = frame
73
74        self.calend = wx.lib.calendar.Calendar(self, -1, (100, 50), (200, 180))
75
76#        start_month = 2        # preselect the date for calendar
77#        start_year = 2001
78
79        start_month = self.calend.GetMonth()        # get the current month & year
80        start_year = self.calend.GetYear()
81
82        # month list from DateTime module
83
84        monthlist = GetMonthList()
85
86        self.date = wx.ComboBox(self, -1, "",
87                               (100, 20), (90, -1),
88                               monthlist, wx.CB_DROPDOWN)
89
90        self.date.SetSelection(start_month-1)
91        self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.date)
92
93        # set start month and year
94
95        self.calend.SetMonth(start_month)
96        self.calend.SetYear(start_year)
97
98        # set attributes of calendar
99
100        self.calend.hide_title = True
101        self.calend.HideGrid()
102        self.calend.SetWeekColor('WHITE', 'BLACK')
103
104        # display routine
105
106        self.ResetDisplay()
107
108        # mouse click event
109        self.Bind(wx.lib.calendar.EVT_CALENDAR, self.MouseClick, self.calend)
110
111        # scroll bar for month selection
112        self.scroll = wx.ScrollBar(self, -1, (100, 240), (200, 20), wx.SB_HORIZONTAL)
113        self.scroll.SetScrollbar(start_month-1, 1, 12, 1, True)
114        self.Bind(wx.EVT_COMMAND_SCROLL, self.Scroll, self.scroll)
115
116        # spin control for year selection
117
118        self.dtext = wx.TextCtrl(self, -1, str(start_year), (200, 20), (60, -1))
119        h = self.dtext.GetSize().height
120
121        self.spin = wx.SpinButton(self, -1, (270, 20), (h*2, h))
122        self.spin.SetRange(1980, 2010)
123        self.spin.SetValue(start_year)
124        self.Bind(wx.EVT_SPIN, self.OnSpin, self.spin)
125
126        # button for calendar dialog test
127        self.but1 = wx.Button(self, -1, "Test Calendar Dialog", (380, 80))
128        self.Bind(wx.EVT_BUTTON, self.TestDlg, self.but1)
129
130        # button for calendar window test
131        self.but2 = wx.Button(self, -1, "Test Calendar Window", (380, 180))
132        self.Bind(wx.EVT_BUTTON, self.TestFrame, self.but2)
133
134        self.but3 = wx.Button(self, -1, "Test Calendar Print", (380, 280))
135        self.Bind(wx.EVT_BUTTON, self.OnPreview, self.but3)
136
137        # calendar dialog
138
139    def TestDlg(self, event):       # test the date dialog
140        dlg = wx.lib.calendar.CalenDlg(self)
141        dlg.Centre()
142
143        if dlg.ShowModal() == wx.ID_OK:
144            result = dlg.result
145            day = result[1]
146            month = result[2]
147            year = result[3]
148            new_date = str(month) + '/'+ str(day) + '/'+ str(year)
149            self.log.WriteText('Date Selected: %s\n' % new_date)
150        else:
151            self.log.WriteText('No Date Selected')
152
153        # calendar window test
154
155    def TestFrame(self, event):
156        frame = CalendFrame(self, -1, "Test Calendar", self.log)
157        frame.Show(True)
158        return True
159
160    # calendar print preview
161
162    def OnPreview(self, event):
163        month = self.calend.GetMonth()
164        year = self.calend.GetYear()
165
166        prt = PrintCalend(self.frame, month, year)
167        prt.Preview()
168
169    # month and year control events
170
171    def OnSpin(self, event):
172        year = event.GetPosition()
173        self.dtext.SetValue(str(year))
174        self.calend.SetYear(year)
175        self.calend.Refresh()
176
177    def EvtComboBox(self, event):
178        name = event.GetString()
179        self.log.WriteText('EvtComboBox: %s\n' % name)
180        monthval = self.date.FindString(name)
181        self.scroll.SetScrollbar(monthval, 1, 12, 1, True)
182
183        self.calend.SetMonth(monthval+1)
184        self.ResetDisplay()
185
186    def Scroll(self, event):
187        value = self.scroll.GetThumbPosition()
188        monthval = int(value)+1
189        self.calend.SetMonth(monthval)
190        self.ResetDisplay()
191        self.log.WriteText('Month: %s\n' % value)
192
193        name = wx.lib.calendar.Month[monthval]
194        self.date.SetValue(name)
195
196    # log mouse events
197
198    def MouseClick(self, evt):
199        text = '%s CLICK   %02d/%02d/%d' % (evt.click, evt.day, evt.month, evt.year)  # format date
200        self.log.WriteText('Date Selected: ' + text + '\n')
201
202
203    # set the highlighted days for the calendar
204
205    def ResetDisplay(self):
206        month = self.calend.GetMonth()
207
208        try:
209            set_days = test_days[month]
210        except:
211            set_days = [1, 5, 12]
212
213        self.calend.AddSelect([4, 11], 'BLUE', 'WHITE')
214        self.calend.SetSelDay(set_days)
215        self.calend.Refresh()
216
217    # increment and decrement toolbar controls
218
219    def OnIncYear(self, event):
220        self.calend.IncYear()
221        self.ResetDisplay()
222
223    def OnDecYear(self, event):
224        self.calend.DecYear()
225        self.ResetDisplay()
226
227    def OnIncMonth(self, event):
228        self.calend.IncMonth()
229        self.ResetDisplay()
230
231    def OnDecMonth(self, event):
232        self.calend.DecMonth()
233        self.ResetDisplay()
234
235    def OnCurrent(self, event):
236        self.calend.SetCurrentDay()
237        self.ResetDisplay()
238
239# test of full window calendar control functions
240
241class CalendFrame(wx.Frame):
242    def __init__(self, parent, id, title, log):
243        wx.Frame.__init__(self, parent, id, title, size=(400, 400),
244                         style=wx.DEFAULT_FRAME_STYLE|wx.NO_FULL_REPAINT_ON_RESIZE)
245
246        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
247
248        self.log = log
249        self.CreateStatusBar()
250        self.mainmenu = wx.MenuBar()
251        menu = wx.Menu()
252
253        menu = self.MakeFileMenu()
254        self.mainmenu.Append(menu, '&File')
255
256        self.MakeToolMenu()             # toolbar
257
258        self.SetMenuBar(self.mainmenu)
259        self.calend = wx.lib.calendar.Calendar(self, -1)
260        self.calend.SetCurrentDay()
261        self.calend.grid_color = 'BLUE'
262        self.calend.SetBusType()
263#        self.calend.ShowWeekEnd()
264
265        self.ResetDisplay()
266
267        self.Bind(wx.lib.calendar.EVT_CALENDAR, self.MouseClick, self.calend)
268
269    def MouseClick(self, evt):
270        text = '%s CLICK   %02d/%02d/%d' % (evt.click, evt.day, evt.month, evt.year)  # format date
271        self.log.WriteText('Date Selected: ' + text + '\n')
272
273    def OnCloseWindow(self, event):
274        self.Destroy()
275
276    def ResetDisplay(self):
277        month = self.calend.GetMonth()
278
279        try:
280            set_days = test_days[month]
281        except:
282            set_days = [1, 5, 12]
283
284        self.calend.AddSelect([2, 16], 'GREEN', 'WHITE')
285
286        self.calend.SetSelDay(set_days)
287        self.calend.Refresh()
288
289    def OnIncYear(self, event):
290        self.calend.IncYear()
291        self.ResetDisplay()
292
293    def OnDecYear(self, event):
294        self.calend.DecYear()
295        self.ResetDisplay()
296
297    def OnIncMonth(self, event):
298        self.calend.IncMonth()
299        self.ResetDisplay()
300
301    def OnDecMonth(self, event):
302        self.calend.DecMonth()
303        self.ResetDisplay()
304
305    def OnCurrent(self, event):
306        self.calend.SetCurrentDay()
307        self.ResetDisplay()
308
309    def MakeFileMenu(self):
310        menu = wx.Menu()
311
312        mID = wx.NewIdRef()
313        menu.Append(mID, 'Decrement', 'Next')
314        self.Bind(wx.EVT_MENU, self.OnDecMonth, id=mID)
315
316        mID = wx.NewIdRef()
317        menu.Append(mID, 'Increment', 'Dec')
318        self.Bind(wx.EVT_MENU, self.OnIncMonth, id=mID)
319
320        menu.AppendSeparator()
321
322        mID = wx.NewIdRef()
323        menu.Append(mID, 'E&xit', 'Exit')
324        self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=mID)
325
326        return menu
327
328    def MakeToolMenu(self):
329        tb = self.CreateToolBar(wx.TB_HORIZONTAL|wx.NO_BORDER)
330
331        mID = wx.NewIdRef()
332        SetToolPath(self, tb, mID, images.DbDec.GetBitmap(), 'Dec Year')
333        self.Bind(wx.EVT_TOOL, self.OnDecYear, id=mID)
334
335        mID = wx.NewIdRef()
336        SetToolPath(self, tb, mID, images.Dec.GetBitmap(), 'Dec Month')
337        self.Bind(wx.EVT_TOOL, self.OnDecMonth, id=mID)
338
339        mID = wx.NewIdRef()
340        SetToolPath(self, tb, mID, images.Pt.GetBitmap(), 'Current Month')
341        self.Bind(wx.EVT_TOOL, self.OnCurrent, id=mID)
342
343        mID = wx.NewIdRef()
344        SetToolPath(self, tb, mID, images.Inc.GetBitmap(), 'Inc Month')
345        self.Bind(wx.EVT_TOOL, self.OnIncMonth, id=mID)
346
347        mID = wx.NewIdRef()
348        SetToolPath(self, tb, mID, images.DbInc.GetBitmap(), 'Inc Year')
349        self.Bind(wx.EVT_TOOL, self.OnIncYear, id=mID)
350
351        tb.Realize()
352
353#---------------------------------------------------------------------------
354
355# example class for printing/previewing calendars
356
357class PrintCalend:
358    def __init__(self, parent, month, year):
359        self.frame = parent
360        self.month = month
361        self.year = year
362
363        self.SetParms()
364        self.SetCal()
365        self.printData = wx.PrintData()
366
367    def SetCal(self):
368        self.grid_color = 'BLUE'
369        self.back_color = 'WHITE'
370        self.sel_color = 'RED'
371        self.high_color = 'LIGHT BLUE'
372        self.font = wx.FONTFAMILY_SWISS
373        self.bold = wx.FONTWEIGHT_NORMAL
374
375        self.sel_key = None      # last used by
376        self.sel_lst = []        # highlighted selected days
377
378        self.size = None
379        self.hide_title = False
380        self.hide_grid = False
381        self.set_day = None
382
383    def SetParms(self):
384        self.ymax = 1
385        self.xmax = 1
386        self.page = 1
387        self.total_pg = 1
388
389        self.preview = None
390        self.scale = 1.0
391
392        self.pagew = 8.5
393        self.pageh = 11.0
394
395        self.txt_marg = 0.1
396        self.lf_marg = 0
397        self.top_marg = 0
398
399        self.page = 0
400
401    def SetDates(self, month, year):
402        self.month = month
403        self.year = year
404
405    def SetStyleDef(self, desc):
406        self.style = desc
407
408    def SetCopies(self, copies):        # number of copies of label
409        self.copies = copies
410
411    def SetStart(self, start):          # start position of label
412        self.start = start
413
414    def Preview(self):
415        printout = SetPrintout(self)
416        printout2 = SetPrintout(self)
417        self.preview = wx.PrintPreview(printout, printout2, self.printData)
418
419        if not self.preview.IsOk():
420            wx.MessageBox("There was a problem printing!", "Printing", wx.OK)
421            return
422
423        self.preview.SetZoom(60)        # initial zoom value
424
425        frame = wx.PreviewFrame(self.preview, self.frame, "Print preview")
426
427        frame.Initialize()
428        frame.SetPosition(self.frame.GetPosition())
429        frame.SetSize(self.frame.GetSize())
430        frame.Show(True)
431
432    def Print(self):
433        pdd = wx.PrintDialogData()
434        pdd.SetPrintData(self.printData)
435        printer = wx.Printer(pdd)
436        printout = SetPrintout(self)
437        frame = wx.Frame(None, -1, "Test")
438
439        if not printer.Print(frame, printout):
440            wx.MessageBox("There was a problem printing.\nPerhaps your current printer is not set correctly?", "Printing", wx.OK)
441        else:
442            self.printData = printer.GetPrintDialogData().GetPrintData()
443
444        printout.Destroy()
445
446    def DoDrawing(self, DC):
447        size = DC.GetSize()
448
449        cal = wx.lib.calendar.PrtCalDraw(self)
450
451        if self.preview is None:
452            cal.SetPSize(size[0]/self.pagew, size[1]/self.pageh)
453            cal.SetPreview(False)
454
455        else:
456            if self.preview == 1:
457                cal.SetPSize(size[0]/self.pagew, size[1]/self.pageh)
458            else:
459                cal.SetPSize(self.pwidth, self.pheight)
460
461            cal.SetPreview(self.preview)
462
463        cal.hide_title = self.hide_title        # set the calendar parameters
464        cal.hide_grid = self.hide_grid
465
466        cal.grid_color = self.grid_color
467        cal.high_color = self.high_color
468        cal.back_color = self.back_color
469        cal.outer_border = False
470        cal.font = self.font
471        cal.bold = self.bold
472
473        cal_size = (3.0, 3.0)
474        cal.SetSize(cal_size)
475
476        year, month = self.year, self.month
477
478        x = 0.5
479        for i in range(2):
480            y = 0.5
481
482            for j in range(3):
483                cal.SetCal(year, month)       # current month
484                cal.SetPos(x, y)
485
486                try:
487                    set_days = test_days[month]
488                except:
489                    set_days = [1, 5, 12]
490
491                cal.AddSelect([2, 16], 'GREEN', 'WHITE')
492
493                cal.DrawCal(DC, set_days)
494
495                year, month = self.IncMonth(year, month)
496                y = y + 3.5
497
498            x = x + 4.0     # next column
499
500        self.ymax = DC.MaxY()
501        self.xmax = DC.MaxX()
502
503    def IncMonth(self, year, month):     # next month
504        month = month + 1
505
506        if month > 12:
507            month = 1
508            year = year + 1
509
510        return year, month
511
512    def GetTotalPages(self):
513        self.pg_cnt = 1
514        return self.pg_cnt
515
516    def SetPage(self, page):
517        self.page = page
518
519    def SetPageSize(self, width, height):
520        self.pwidth, self.pheight = width, height
521
522    def SetTotalSize(self, width, height):
523        self.ptwidth, self.ptheight = width, height
524
525    def SetPreview(self, preview, scale):
526        self.preview = preview
527        self.scale = scale
528
529    def SetTotalSize(self, width, height):
530        self.ptwidth = width
531        self.ptheight = height
532
533def SetToolPath(self, tb, id, bmp, title):
534    tb.AddSimpleTool(id, bmp, title, title)
535
536class SetPrintout(wx.Printout):
537    def __init__(self, canvas):
538        wx.Printout.__init__(self)
539        self.canvas = canvas
540        self.end_pg = 1
541
542    def OnBeginDocument(self, start, end):
543        return super(SetPrintout, self).OnBeginDocument(start, end)
544
545    def OnEndDocument(self):
546        super(SetPrintout, self).OnEndDocument()
547
548    def HasPage(self, page):
549        if page <= self.end_pg:
550            return True
551        else:
552            return False
553
554    def GetPageInfo(self):
555        self.end_pg = self.canvas.GetTotalPages()
556        str_pg = 1
557
558        try:
559            end_pg = self.end_pg
560        except:
561            end_pg = 1
562
563        return (str_pg, end_pg, str_pg, end_pg)
564
565    def OnPreparePrinting(self):
566        super(SetPrintout, self).OnPreparePrinting()
567
568    def OnBeginPrinting(self):
569        dc = self.GetDC()
570
571        self.preview = self.IsPreview()
572
573        if (self.preview):
574            self.pixelsPerInch = self.GetPPIScreen()
575        else:
576            self.pixelsPerInch = self.GetPPIPrinter()
577
578        (w, h) = dc.GetSize()
579        scaleX = float(w) / 1000
580        scaleY = float(h) / 1000
581        self.printUserScale = min(scaleX, scaleY)
582
583        super(SetPrintout, self).OnBeginPrinting()
584
585    def GetSize(self):
586        self.psizew, self.psizeh = self.GetPPIPrinter()
587        return self.psizew, self.psizeh
588
589    def GetTotalSize(self):
590        self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
591        return self.ptsizew, self.ptsizeh
592
593    def OnPrintPage(self, page):
594        dc = self.GetDC()
595        (w, h) = dc.GetSize()
596        scaleX = float(w) / 1000
597        scaleY = float(h) / 1000
598        self.printUserScale = min(scaleX, scaleY)
599        dc.SetUserScale(self.printUserScale, self.printUserScale)
600
601        self.preview = self.IsPreview()
602
603        self.canvas.SetPreview(self.preview, self.printUserScale)
604        self.canvas.SetPage(page)
605
606        self.ptsizew, self.ptsizeh = self.GetPageSizePixels()
607        self.canvas.SetTotalSize(self.ptsizew, self.ptsizeh)
608
609        self.psizew, self.psizeh = self.GetPPIPrinter()
610        self.canvas.SetPageSize(self.psizew, self.psizeh)
611
612        self.canvas.DoDrawing(dc)
613        return True
614
615class MyApp(wx.App):
616    def OnInit(self):
617        frame = CalendFrame(None, -1, "Test Calendar", log)
618        frame.Show(True)
619        self.SetTopWindow(frame)
620        return True
621
622#---------------------------------------------------------------------------
623
624def MessageDlg(self, message, type = 'Message'):
625    dlg = wx.MessageDialog(self, message, type, wx.OK | wx.ICON_INFORMATION)
626    dlg.ShowModal()
627    dlg.Destroy()
628
629#---------------------------------------------------------------------------
630
631def runTest(frame, nb, log):
632    win = TestPanel(nb, log, frame)
633    return win
634
635#---------------------------------------------------------------------------
636
637
638overview = """\
639This control provides a Calendar control class for displaying and selecting dates.
640In addition, the class is extended and can be used for printing/previewing.
641
642Additional features include weekend highlighting and business type Monday-Sunday
643format.
644
645See example for various methods used to set display month, year, and highlighted
646dates (different font and background colours).
647
648by Lorne White
649
650"""
651
652
653
654
655if __name__ == '__main__':
656    import sys,os
657    import run
658    run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
659
660