diff options
Diffstat (limited to 'svtools/source/control/calendar.cxx')
-rw-r--r-- | svtools/source/control/calendar.cxx | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx new file mode 100644 index 000000000..d1b7f5d11 --- /dev/null +++ b/svtools/source/control/calendar.cxx @@ -0,0 +1,346 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/floatwin.hxx> +#include <vcl/button.hxx> +#include <vcl/fixed.hxx> +#include <vcl/event.hxx> + +#include <svtools/strings.hrc> +#include <svtools/svtresid.hxx> +#include <svtools/calendar.hxx> + +#define CALFIELD_EXTRA_BUTTON_WIDTH 14 +#define CALFIELD_EXTRA_BUTTON_HEIGHT 8 +#define CALFIELD_SEP_X 6 +#define CALFIELD_BORDERLINE_X 5 +#define CALFIELD_BORDER_YTOP 4 +#define CALFIELD_BORDER_Y 5 + +class ImplCFieldFloatWin : public FloatingWindow +{ +private: + VclPtr<Calendar> mpCalendar; + VclPtr<PushButton> mpTodayBtn; + VclPtr<PushButton> mpNoneBtn; + VclPtr<FixedLine> mpFixedLine; + +public: + explicit ImplCFieldFloatWin( vcl::Window* pParent ); + virtual ~ImplCFieldFloatWin() override; + virtual void dispose() override; + + void SetCalendar( Calendar* pCalendar ) + { mpCalendar = pCalendar; } + + PushButton* EnableTodayBtn( bool bEnable ); + PushButton* EnableNoneBtn( bool bEnable ); + void ArrangeButtons(); + + virtual bool EventNotify( NotifyEvent& rNEvt ) override; +}; + +ImplCFieldFloatWin::ImplCFieldFloatWin( vcl::Window* pParent ) : + FloatingWindow( pParent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ), + mpCalendar(nullptr), mpTodayBtn(nullptr), mpNoneBtn(nullptr), mpFixedLine(nullptr) +{ +} + +ImplCFieldFloatWin::~ImplCFieldFloatWin() +{ + disposeOnce(); +} + +void ImplCFieldFloatWin::dispose() +{ + mpTodayBtn.disposeAndClear(); + mpNoneBtn.disposeAndClear(); + mpFixedLine.disposeAndClear(); + mpCalendar.clear(); + FloatingWindow::dispose(); +} + +PushButton* ImplCFieldFloatWin::EnableTodayBtn( bool bEnable ) +{ + if ( bEnable ) + { + if ( !mpTodayBtn ) + { + mpTodayBtn = VclPtr<PushButton>::Create( this, WB_NOPOINTERFOCUS ); + OUString aTodayText(SvtResId(STR_SVT_CALENDAR_TODAY)); + mpTodayBtn->SetText( aTodayText ); + Size aSize; + aSize.setWidth( mpTodayBtn->GetCtrlTextWidth( mpTodayBtn->GetText() ) ); + aSize.setHeight( mpTodayBtn->GetTextHeight() ); + aSize.AdjustWidth(CALFIELD_EXTRA_BUTTON_WIDTH ); + aSize.AdjustHeight(CALFIELD_EXTRA_BUTTON_HEIGHT ); + mpTodayBtn->SetSizePixel( aSize ); + mpTodayBtn->Show(); + } + } + else + { + mpTodayBtn.disposeAndClear(); + } + + return mpTodayBtn; +} + +PushButton* ImplCFieldFloatWin::EnableNoneBtn( bool bEnable ) +{ + if ( bEnable ) + { + if ( !mpNoneBtn ) + { + mpNoneBtn = VclPtr<PushButton>::Create( this, WB_NOPOINTERFOCUS ); + OUString aNoneText(SvtResId(STR_SVT_CALENDAR_NONE)); + mpNoneBtn->SetText( aNoneText ); + Size aSize; + aSize.setWidth( mpNoneBtn->GetCtrlTextWidth( mpNoneBtn->GetText() ) ); + aSize.setHeight( mpNoneBtn->GetTextHeight() ); + aSize.AdjustWidth(CALFIELD_EXTRA_BUTTON_WIDTH ); + aSize.AdjustHeight(CALFIELD_EXTRA_BUTTON_HEIGHT ); + mpNoneBtn->SetSizePixel( aSize ); + mpNoneBtn->Show(); + } + } + else + { + mpNoneBtn.disposeAndClear(); + } + + return mpNoneBtn; +} + +void ImplCFieldFloatWin::ArrangeButtons() +{ + long nBtnHeight = 0; + long nBtnWidth = 0; + Size aOutSize = GetOutputSizePixel(); + if ( mpTodayBtn && mpNoneBtn ) + { + Size aTodayBtnSize = mpTodayBtn->GetSizePixel(); + Size aNoneBtnSize = mpNoneBtn->GetSizePixel(); + if ( aTodayBtnSize.Width() < aNoneBtnSize.Width() ) + aTodayBtnSize.setWidth( aNoneBtnSize.Width() ); + else + aNoneBtnSize.setWidth( aTodayBtnSize.Width() ); + if ( aTodayBtnSize.Height() < aNoneBtnSize.Height() ) + aTodayBtnSize.setHeight( aNoneBtnSize.Height() ); + else + aNoneBtnSize.setHeight( aTodayBtnSize.Height() ); + + nBtnWidth = aTodayBtnSize.Width() + aNoneBtnSize.Width() + CALFIELD_SEP_X; + nBtnHeight = aTodayBtnSize.Height(); + long nX = (aOutSize.Width()-nBtnWidth)/2; + long nY = aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP; + mpTodayBtn->SetPosSizePixel( Point( nX, nY ), aTodayBtnSize ); + nX += aTodayBtnSize.Width() + CALFIELD_SEP_X; + mpNoneBtn->SetPosSizePixel( Point( nX, nY ), aNoneBtnSize ); + } + else if ( mpTodayBtn ) + { + Size aTodayBtnSize = mpTodayBtn->GetSizePixel(); + nBtnWidth = aTodayBtnSize.Width(); + nBtnHeight = aTodayBtnSize.Height(); + mpTodayBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) ); + } + else if ( mpNoneBtn ) + { + Size aNoneBtnSize = mpNoneBtn->GetSizePixel(); + nBtnWidth = aNoneBtnSize.Width(); + nBtnHeight = aNoneBtnSize.Height(); + mpNoneBtn->SetPosPixel( Point( (aOutSize.Width()-nBtnWidth)/2, aOutSize.Height()+CALFIELD_BORDER_Y+CALFIELD_BORDER_YTOP ) ); + } + + if ( nBtnHeight ) + { + if ( !mpFixedLine ) + { + mpFixedLine = VclPtr<FixedLine>::Create( this ); + mpFixedLine->Show(); + } + long nLineWidth = aOutSize.Width()-(CALFIELD_BORDERLINE_X*2); + mpFixedLine->setPosSizePixel( (aOutSize.Width()-nLineWidth)/2, aOutSize.Height()+((CALFIELD_BORDER_YTOP-2)/2), + nLineWidth, 2 ); + aOutSize.AdjustHeight(nBtnHeight + (CALFIELD_BORDER_Y*2) + CALFIELD_BORDER_YTOP ); + SetOutputSizePixel( aOutSize ); + } + else + { + mpFixedLine.disposeAndClear(); + } +} + +bool ImplCFieldFloatWin::EventNotify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT ) + { + const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); + if ( pKEvt->GetKeyCode().GetCode() == KEY_RETURN ) + mpCalendar->Select(); + } + + return FloatingWindow::EventNotify( rNEvt ); +} + +CalendarField::CalendarField(vcl::Window* pParent, WinBits nWinStyle) + : DateField(pParent, nWinStyle) + , mpFloatWin(nullptr) + , mpCalendar(nullptr) + , mpTodayBtn(nullptr) + , mpNoneBtn(nullptr) + , mbToday(false) + , mbNone(false) +{ +} + +CalendarField::~CalendarField() +{ + disposeOnce(); +} + +void CalendarField::dispose() +{ + mpCalendar.disposeAndClear(); + mpFloatWin.disposeAndClear(); + mpTodayBtn.clear(); + mpNoneBtn.clear(); + DateField::dispose(); +} + +IMPL_LINK( CalendarField, ImplSelectHdl, Calendar*, pCalendar, void ) +{ + if ( pCalendar->IsTravelSelect() ) + return; + + mpFloatWin->EndPopupMode(); + EndDropDown(); + GrabFocus(); + Date aNewDate = mpCalendar->GetFirstSelectedDate(); + if ( IsEmptyDate() || ( aNewDate != GetDate() ) ) + { + SetDate( aNewDate ); + SetModifyFlag(); + Modify(); + } +} + +IMPL_LINK( CalendarField, ImplClickHdl, Button*, pButton, void ) +{ + PushButton* pBtn = static_cast<PushButton*>(pButton); + mpFloatWin->EndPopupMode(); + EndDropDown(); + GrabFocus(); + + if ( pBtn == mpTodayBtn ) + { + Date aToday( Date::SYSTEM ); + if ( (aToday != GetDate()) || IsEmptyDate() ) + { + SetDate( aToday ); + SetModifyFlag(); + Modify(); + } + } + else if ( pBtn == mpNoneBtn ) + { + if ( !IsEmptyDate() ) + { + SetEmptyDate(); + SetModifyFlag(); + Modify(); + } + } +} + +IMPL_LINK_NOARG(CalendarField, ImplPopupModeEndHdl, FloatingWindow*, void) +{ + EndDropDown(); + GrabFocus(); + mpCalendar->EndSelection(); +} + +bool CalendarField::ShowDropDown( bool bShow ) +{ + if ( bShow ) + { + Calendar* pCalendar = GetCalendar(); + + Date aDate = GetDate(); + if ( IsEmptyDate() || !aDate.IsValidAndGregorian() ) + { + aDate = Date( Date::SYSTEM ); + } + pCalendar->SetCurDate( aDate ); + Point aPos( GetParent()->OutputToScreenPixel( GetPosPixel() ) ); + tools::Rectangle aRect( aPos, GetSizePixel() ); + aRect.AdjustBottom( -1 ); + mpCalendar->SetOutputSizePixel( mpCalendar->CalcWindowSizePixel() ); + mpFloatWin->SetOutputSizePixel( mpCalendar->GetSizePixel() ); + mpFloatWin->SetCalendar( mpCalendar ); + mpTodayBtn = mpFloatWin->EnableTodayBtn( mbToday ); + mpNoneBtn = mpFloatWin->EnableNoneBtn( mbNone ); + if ( mpTodayBtn ) + mpTodayBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) ); + if ( mpNoneBtn ) + mpNoneBtn->SetClickHdl( LINK( this, CalendarField, ImplClickHdl ) ); + mpFloatWin->ArrangeButtons(); + mpCalendar->EnableCallEverySelect(); + mpCalendar->StartSelection(); + mpCalendar->GrabFocus(); + mpCalendar->Show(); + mpFloatWin->StartPopupMode( aRect, FloatWinPopupFlags::Down ); + } + else + { + mpFloatWin->EndPopupMode( FloatWinPopupEndFlags::Cancel ); + mpCalendar->EndSelection(); + EndDropDown(); + } + return true; +} + +Calendar* CalendarField::GetCalendar() +{ + if ( !mpFloatWin ) + { + mpFloatWin = VclPtr<ImplCFieldFloatWin>::Create( this ); + mpFloatWin->SetPopupModeEndHdl( LINK( this, CalendarField, ImplPopupModeEndHdl ) ); + mpCalendar = VclPtr<Calendar>::Create( mpFloatWin, WB_TABSTOP ); + mpCalendar->SetPosPixel( Point() ); + mpCalendar->SetSelectHdl( LINK( this, CalendarField, ImplSelectHdl ) ); + } + + return mpCalendar; +} + +void CalendarField::StateChanged( StateChangedType nStateChange ) +{ + DateField::StateChanged( nStateChange ); + + if ( ( nStateChange == StateChangedType::Style ) && GetSubEdit() ) + { + WinBits nAllAlignmentBits = ( WB_LEFT | WB_CENTER | WB_RIGHT | WB_TOP | WB_VCENTER | WB_BOTTOM ); + WinBits nMyAlignment = GetStyle() & nAllAlignmentBits; + GetSubEdit()->SetStyle( ( GetSubEdit()->GetStyle() & ~nAllAlignmentBits ) | nMyAlignment ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |