Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_SVTOOLS_CALENDAR_HXX
21 : #define INCLUDED_SVTOOLS_CALENDAR_HXX
22 :
23 : #include <svtools/svtdllapi.h>
24 : #include <unotools/calendarwrapper.hxx>
25 : #include <com/sun/star/i18n/Weekdays.hpp>
26 :
27 : #include <vcl/ctrl.hxx>
28 : #include <vcl/timer.hxx>
29 : #include <vcl/field.hxx>
30 : #include <set>
31 :
32 : class MouseEvent;
33 : class TrackingEvent;
34 : class KeyEvent;
35 : class HelpEvent;
36 : class DataChangedEvent;
37 : class FloatingWindow;
38 : class PushButton;
39 : class ImplCFieldFloatWin;
40 :
41 : /*************************************************************************
42 :
43 : Description
44 : ============
45 :
46 : class Calendar
47 :
48 : This class allows for the selection of a date. The displayed date range is
49 : the one specified by the Date class. We display as many months as we have
50 : space in the control. The user can switch between months using a ContextMenu
51 : (clicking on the month's name) or via two ScrollButtons in-between the months.
52 :
53 : --------------------------------------------------------------------------
54 :
55 : WinBits
56 :
57 : WB_BORDER We draw a border around the window.
58 : WB_TABSTOP Keyboard control is possible. We get the focus, when
59 : the user clicks in the Control.
60 : WB_QUICKHELPSHOWSDATEINFO Show DateInfo as BallonHelp even if QuickInfo is enabled
61 : WB_BOLDTEXT We format by bold texts and DIB_BOLD is evaluated by
62 : AddDateInfo()
63 : WB_FRAMEINFO We format in a way, so that FrameInfo can be displayed
64 : and the FrameColor is evaluated by AddDateInfo()
65 : WB_RANGESELECT The user can select multiple days, which need to be
66 : consecutive
67 : WB_MULTISELECT The user can select multiple days
68 : WB_WEEKNUMBER We also display the weekdays
69 :
70 : --------------------------------------------------------------------------
71 :
72 : We set and get the selected date by SetCurDate()/GetCurDate().
73 : If the user selects a date Select() is called. If the user double clicks
74 : DoubleClick() is called.
75 :
76 : --------------------------------------------------------------------------
77 :
78 : CalcWindowSizePixel() calculates the window size in pixel that is needed
79 : to display a certain number of months.
80 :
81 : --------------------------------------------------------------------------
82 :
83 : SetSaturdayColor() and SetSundayColor() set a special color for Saturdays
84 : and Sundays.
85 : AddDateInfo() marks special days. With that we can set e.g. public holidays
86 : to another color or encircle them (for e.g. appointments).
87 : If we do not supply a year in the date, the day is used in EVERY year.
88 :
89 : AddDateInfo() can also add text for every date, which is displayed if the
90 : BalloonHelp is enabled.
91 : In order to not have to supply all years with the relevant data, we call
92 : the RequestDateInfo() handler if a new year is displayed. We can then query
93 : the year in the handler with GetRequestYear().
94 :
95 : --------------------------------------------------------------------------
96 :
97 : In order to display a ContextMenu for a date, we need to override the
98 : Command handler. GetDate() can infer the date from the mouse's position.
99 : If we use the keyboard, the current date should be use.
100 :
101 : If a ContextMenu is displayed, the baseclass' handler must not be called.
102 :
103 : --------------------------------------------------------------------------
104 :
105 : For multiple selection (WB_RANGESELECT or WB_MULTISELECT) SelectDate(),
106 : SelectDateRange() can select date ranges. SelectDateRange() selects
107 : including the end date.
108 : SetNoSelection() deselects everything.
109 : SetCurDate() does not select the current date, but only defines the focus
110 : rectangle.
111 : GetSelectDateCount()/GetSelectDate() query the selected range.
112 : IsDateSelected() queries for the status of a date.
113 :
114 : The SelectionChanging() handler is being called while a user selects a
115 : date. In it, we can change the selected range. E.g. if we want to limit
116 : or extend the selected range. The selected range is realised via SelectDate()
117 : and SelectDateRange() and queried with GetSelectDateCount()/GetSelectDate().
118 :
119 : IsSelectLeft() returns the direction of the selection:
120 : sal_True is a selection to the left or up
121 : sal_False is a selection to the right or down
122 :
123 : --------------------------------------------------------------------------
124 :
125 : If the DateRange area changes and we want to take over the selection, we
126 : should only do this is if IsScrollDateRangeChanged() retruns sal_True.
127 : This method returns sal_True if the area change was triggered by using the
128 : ScrollButtons and sal_False if it was triggered by Resize(), other method
129 : calls or by ending a selection.
130 :
131 : *************************************************************************/
132 :
133 :
134 : // - Calendar types -
135 :
136 :
137 : #define WB_QUICKHELPSHOWSDATEINFO ((WinBits)0x00004000)
138 : #define WB_BOLDTEXT ((WinBits)0x00008000)
139 : #define WB_FRAMEINFO ((WinBits)0x00010000)
140 : #define WB_WEEKNUMBER ((WinBits)0x00020000)
141 : // Needs to in agreement with the WinBits in the TabBar or
142 : // we move it to \vcl\inc\wintypes.hxx
143 : #ifndef WB_RANGESELECT
144 : #define WB_RANGESELECT ((WinBits)0x00200000)
145 : #endif
146 : #ifndef WB_MULTISELECT
147 : #define WB_MULTISELECT ((WinBits)0x00400000)
148 : #endif
149 :
150 : #define DIB_BOLD ((sal_uInt16)0x0001)
151 :
152 :
153 : // - Calendar -
154 :
155 :
156 : typedef std::set<sal_uInt32> IntDateSet;
157 :
158 :
159 : class SVT_DLLPUBLIC Calendar : public Control
160 : {
161 : private:
162 : IntDateSet* mpSelectTable;
163 : IntDateSet* mpOldSelectTable;
164 : IntDateSet* mpRestoreSelectTable;
165 : OUString maDayTexts[31];
166 : OUString maDayText;
167 : OUString maWeekText;
168 : CalendarWrapper maCalendarWrapper;
169 : Rectangle maPrevRect;
170 : Rectangle maNextRect;
171 : OUString maDayOfWeekText;
172 : long mnDayOfWeekAry[7];
173 : Date maOldFormatFirstDate;
174 : Date maOldFormatLastDate;
175 : Date maFirstDate;
176 : Date maOldFirstDate;
177 : Date maCurDate;
178 : Date maOldCurDate;
179 : Date maAnchorDate;
180 : Date maDropDate;
181 : Color maSelColor;
182 : Color maOtherColor;
183 : Color* mpStandardColor;
184 : Color* mpSaturdayColor;
185 : Color* mpSundayColor;
186 : sal_uLong mnDayCount;
187 : long mnDaysOffX;
188 : long mnWeekDayOffY;
189 : long mnDaysOffY;
190 : long mnMonthHeight;
191 : long mnMonthWidth;
192 : long mnMonthPerLine;
193 : long mnLines;
194 : long mnDayWidth;
195 : long mnDayHeight;
196 : long mnWeekWidth;
197 : WinBits mnWinStyle;
198 : sal_uInt16 mnFirstYear;
199 : sal_uInt16 mnLastYear;
200 : sal_uInt16 mnRequestYear;
201 : bool mbCalc:1,
202 : mbFormat:1,
203 : mbDrag:1,
204 : mbSelection:1,
205 : mbMultiSelection:1,
206 : mbWeekSel:1,
207 : mbUnSel:1,
208 : mbMenuDown:1,
209 : mbSpinDown:1,
210 : mbPrevIn:1,
211 : mbNextIn:1,
212 : mbDirect:1,
213 : mbInSelChange:1,
214 : mbTravelSelect:1,
215 : mbScrollDateRange:1,
216 : mbSelLeft:1,
217 : mbAllSel:1,
218 : mbDropPos:1;
219 : Link<> maSelectionChangingHdl;
220 : Link<> maDateRangeChangedHdl;
221 : Link<> maRequestDateInfoHdl;
222 : Link<> maDoubleClickHdl;
223 : Link<> maSelectHdl;
224 : Timer maDragScrollTimer;
225 : sal_uInt16 mnDragScrollHitTest;
226 :
227 : using Control::ImplInitSettings;
228 : using Window::ImplInit;
229 : SVT_DLLPRIVATE void ImplInit( WinBits nWinStyle );
230 : SVT_DLLPRIVATE void ImplInitSettings();
231 :
232 : virtual void ApplySettings(vcl::RenderContext& rRenderContext) SAL_OVERRIDE;
233 :
234 : SVT_DLLPRIVATE void ImplGetWeekFont( vcl::Font& rFont ) const;
235 : SVT_DLLPRIVATE void ImplFormat();
236 : using Window::ImplHitTest;
237 : SVT_DLLPRIVATE sal_uInt16 ImplHitTest( const Point& rPos, Date& rDate ) const;
238 : SVT_DLLPRIVATE void ImplDrawSpin(vcl::RenderContext& rRenderContext, bool bDrawPrev = true, bool bDrawNext = true);
239 : SVT_DLLPRIVATE void ImplDrawDate(vcl::RenderContext& rRenderContext, long nX, long nY,
240 : sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear,
241 : DayOfWeek eDayOfWeek, bool bBack = true,
242 : bool bOther = false, sal_uLong nToday = 0);
243 : SVT_DLLPRIVATE void ImplDraw(vcl::RenderContext& rRenderContext, bool bPaint = false);
244 : SVT_DLLPRIVATE void ImplUpdateDate( const Date& rDate );
245 : SVT_DLLPRIVATE void ImplUpdateSelection( IntDateSet* pOld );
246 : SVT_DLLPRIVATE void ImplMouseSelect( const Date& rDate, sal_uInt16 nHitTest,
247 : bool bMove, bool bExpand, bool bExtended );
248 : SVT_DLLPRIVATE void ImplUpdate( bool bCalcNew = false );
249 : using Window::ImplScroll;
250 : SVT_DLLPRIVATE void ImplScroll( bool bPrev );
251 : SVT_DLLPRIVATE void ImplInvertDropPos();
252 : SVT_DLLPRIVATE void ImplShowMenu( const Point& rPos, const Date& rDate );
253 : SVT_DLLPRIVATE void ImplTracking( const Point& rPos, bool bRepeat );
254 : SVT_DLLPRIVATE void ImplEndTracking( bool bCancel );
255 : SVT_DLLPRIVATE DayOfWeek ImplGetWeekStart() const;
256 :
257 : protected:
258 :
259 : DECL_LINK_TYPED( ScrollHdl, Timer *, void );
260 :
261 : public:
262 : Calendar( vcl::Window* pParent, WinBits nWinStyle = 0 );
263 : virtual ~Calendar();
264 : virtual void dispose() SAL_OVERRIDE;
265 :
266 : virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE;
267 : virtual void MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;
268 : virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE;
269 : virtual void Tracking( const TrackingEvent& rMEvt ) SAL_OVERRIDE;
270 : virtual void KeyInput( const KeyEvent& rKEvt ) SAL_OVERRIDE;
271 : virtual void Paint( vcl::RenderContext& rRenderContext, const Rectangle& rRect ) SAL_OVERRIDE;
272 : virtual void Resize() SAL_OVERRIDE;
273 : virtual void GetFocus() SAL_OVERRIDE;
274 : virtual void LoseFocus() SAL_OVERRIDE;
275 : virtual void RequestHelp( const HelpEvent& rHEvt ) SAL_OVERRIDE;
276 : virtual void Command( const CommandEvent& rCEvt ) SAL_OVERRIDE;
277 : virtual void StateChanged( StateChangedType nStateChange ) SAL_OVERRIDE;
278 : virtual void DataChanged( const DataChangedEvent& rDCEvt ) SAL_OVERRIDE;
279 :
280 : void SelectionChanging();
281 : void DateRangeChanged();
282 : void RequestDateInfo();
283 : void DoubleClick();
284 : void Select();
285 :
286 : const CalendarWrapper& GetCalendarWrapper() const { return maCalendarWrapper; }
287 :
288 : void SelectDate( const Date& rDate, bool bSelect = true );
289 : void SetNoSelection();
290 : bool IsDateSelected( const Date& rDate ) const;
291 : Date GetFirstSelectedDate() const;
292 0 : void EnableCallEverySelect( bool bEvery = true ) { mbAllSel = bEvery; }
293 : bool IsCallEverySelectEnabled() const { return mbAllSel; }
294 :
295 : sal_uInt16 GetRequestYear() const { return mnRequestYear; }
296 : void SetCurDate( const Date& rNewDate );
297 : Date GetCurDate() const { return maCurDate; }
298 : void SetFirstDate( const Date& rNewFirstDate );
299 0 : Date GetFirstDate() const { return maFirstDate; }
300 0 : Date GetLastDate() const { return GetFirstDate() + mnDayCount; }
301 : sal_uLong GetDayCount() const { return mnDayCount; }
302 : Date GetFirstMonth() const;
303 : Date GetLastMonth() const;
304 : sal_uInt16 GetMonthCount() const;
305 : bool GetDate( const Point& rPos, Date& rDate ) const;
306 : Rectangle GetDateRect( const Date& rDate ) const;
307 :
308 : long GetCurMonthPerLine() const { return mnMonthPerLine; }
309 : long GetCurLines() const { return mnLines; }
310 :
311 : const Color& GetStandardColor() const;
312 : const Color& GetSaturdayColor() const;
313 : const Color& GetSundayColor() const;
314 :
315 : void StartSelection();
316 : void EndSelection();
317 :
318 0 : bool IsTravelSelect() const { return mbTravelSelect; }
319 : bool IsScrollDateRangeChanged() const { return mbScrollDateRange; }
320 : bool IsSelectLeft() const { return mbSelLeft; }
321 :
322 : Size CalcWindowSizePixel( long nCalcMonthPerLine = 1,
323 : long nCalcLines = 1 ) const;
324 :
325 : void SetSelectionChangingHdl( const Link<>& rLink ) { maSelectionChangingHdl = rLink; }
326 : const Link<>& GetSelectionChangingHdl() const { return maSelectionChangingHdl; }
327 : void SetDateRangeChangedHdl( const Link<>& rLink ) { maDateRangeChangedHdl = rLink; }
328 : const Link<>& GetDateRangeChangedHdl() const { return maDateRangeChangedHdl; }
329 : void SetRequestDateInfoHdl( const Link<>& rLink ) { maRequestDateInfoHdl = rLink; }
330 : const Link<>& GetRequestDateInfoHdl() const { return maRequestDateInfoHdl; }
331 : void SetDoubleClickHdl( const Link<>& rLink ) { maDoubleClickHdl = rLink; }
332 : const Link<>& GetDoubleClickHdl() const { return maDoubleClickHdl; }
333 0 : void SetSelectHdl( const Link<>& rLink ) { maSelectHdl = rLink; }
334 : const Link<>& GetSelectHdl() const { return maSelectHdl; }
335 : };
336 :
337 : inline const Color& Calendar::GetStandardColor() const
338 : {
339 : if ( mpStandardColor )
340 : return *mpStandardColor;
341 : else
342 : return GetFont().GetColor();
343 : }
344 :
345 : inline const Color& Calendar::GetSaturdayColor() const
346 : {
347 : if ( mpSaturdayColor )
348 : return *mpSaturdayColor;
349 : else
350 : return GetFont().GetColor();
351 : }
352 :
353 : inline const Color& Calendar::GetSundayColor() const
354 : {
355 : if ( mpSundayColor )
356 : return *mpSundayColor;
357 : else
358 : return GetFont().GetColor();
359 : }
360 :
361 : /*************************************************************************
362 :
363 : Description
364 : ============
365 :
366 : class CalendarField
367 :
368 : This class is a DateField with which one can select a date via a DropDownButton
369 : and the CalendarControl.
370 :
371 : --------------------------------------------------------------------------
372 :
373 : WinBits
374 :
375 : See DateField
376 :
377 : The preferences for the CalendarControl can be set via SetCalendarStyle().
378 :
379 : --------------------------------------------------------------------------
380 :
381 : With EnableToday()/EnableNone() we can enable a TodayButton and a NoneButton.
382 :
383 : --------------------------------------------------------------------------
384 :
385 : If we set WB_RANGESELECT with SetCalendarStyle(), we can select multiple days
386 : in the Calendar.
387 :
388 : Because we only take over the start date into the field, we should query
389 : with GetCalendar() in the SelectHandler and with GetSelectDateCount()/GetSelectDate()
390 : the selected range. We then can e.g. take over that value to another field.
391 :
392 : --------------------------------------------------------------------------
393 :
394 : If a derived Calendar should be used, we can override the CreateCalendar()
395 : method in CalendarField and create an own calendar there ourselves.
396 :
397 : *************************************************************************/
398 :
399 :
400 : // - CalendarField -
401 :
402 :
403 : class SVT_DLLPUBLIC CalendarField : public DateField
404 : {
405 : private:
406 : VclPtr<ImplCFieldFloatWin> mpFloatWin;
407 : VclPtr<Calendar> mpCalendar;
408 : WinBits mnCalendarStyle;
409 : VclPtr<PushButton> mpTodayBtn;
410 : VclPtr<PushButton> mpNoneBtn;
411 : Date maDefaultDate;
412 : bool mbToday;
413 : bool mbNone;
414 : Link<> maSelectHdl;
415 :
416 : DECL_DLLPRIVATE_LINK( ImplSelectHdl, Calendar* );
417 : DECL_DLLPRIVATE_LINK( ImplClickHdl, PushButton* );
418 : DECL_DLLPRIVATE_LINK( ImplPopupModeEndHdl, void* );
419 :
420 : public:
421 : CalendarField( vcl::Window* pParent, WinBits nWinStyle );
422 : virtual ~CalendarField();
423 : virtual void dispose() SAL_OVERRIDE;
424 :
425 : void Select();
426 :
427 : virtual bool ShowDropDown( bool bShow ) SAL_OVERRIDE;
428 : VclPtr<Calendar> CreateCalendar( vcl::Window* pParent );
429 : Calendar* GetCalendar();
430 :
431 : void SetDefaultDate( const Date& rDate ) { maDefaultDate = rDate; }
432 : Date GetDefaultDate() const { return maDefaultDate; }
433 :
434 34 : void EnableToday( bool bToday = true ) { mbToday = bToday; }
435 : bool IsTodayEnabled() const { return mbToday; }
436 34 : void EnableNone( bool bNone = true ) { mbNone = bNone; }
437 : bool IsNoneEnabled() const { return mbNone; }
438 :
439 : void SetCalendarStyle( WinBits nStyle ) { mnCalendarStyle = nStyle; }
440 : WinBits GetCalendarStyle() const { return mnCalendarStyle; }
441 :
442 : void SetSelectHdl( const Link<>& rLink ) { maSelectHdl = rLink; }
443 : const Link<>& GetSelectHdl() const { return maSelectHdl; }
444 :
445 : protected:
446 : virtual void StateChanged( StateChangedType nStateChange ) SAL_OVERRIDE;
447 : };
448 :
449 : #endif // INCLUDED_SVTOOLS_CALENDAR_HXX
450 :
451 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|