blob: 279a070214c90a88e589eec41902805052c338eb [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
// include ---------------------------------------------------------------
#include <limits.h>
#include <tools/shl.hxx>
#include <vcl/status.hxx>
#include <vcl/menu.hxx>
#include <vcl/image.hxx>
#include <svl/stritem.hxx>
#include <svl/ptitem.hxx>
#include <svl/itempool.hxx>
#include <sfx2/app.hxx>
#include <sfx2/module.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/objsh.hxx>
#include <svl/intitem.hxx>
#define _SVX_PSZCTRL_CXX
#include "svx/pszctrl.hxx"
#define PAINT_OFFSET 5
#include <editeng/sizeitem.hxx>
#include <svx/dialmgr.hxx>
#include "svx/dlgutil.hxx"
#include "stbctrls.h"
#include "sfx2/module.hxx"
#include <svx/dialogs.hrc>
#include <unotools/localedatawrapper.hxx>
#ifndef _UNOTOOLS_PROCESSFACTORY_HXX
#include <comphelper/processfactory.hxx>
#endif
// -----------------------------------------------------------------------
/* [Beschreibung]
Funktion, mit der ein metrischer Wert in textueller Darstellung
umgewandelt wird.
nVal ist hier der metrische Wert in der Einheit eUnit.
[Querverweise]
<SvxPosSizeStatusBarControl::Paint(const UserDrawEvent&)>
*/
String SvxPosSizeStatusBarControl::GetMetricStr_Impl( long nVal )
{
// Applikations-Metrik besorgen und setzen
FieldUnit eOutUnit = SfxModule::GetModuleFieldUnit( getFrameInterface() );
FieldUnit eInUnit = FUNIT_100TH_MM;
String sMetric;
const sal_Unicode cSep = Application::GetSettings().GetLocaleDataWrapper().getNumDecimalSep().GetChar(0);
sal_Int64 nConvVal = MetricField::ConvertValue( nVal * 100, 0L, 0, eInUnit, eOutUnit );
if ( nConvVal < 0 && ( nConvVal / 100 == 0 ) )
sMetric += '-';
sMetric += String::CreateFromInt64( nConvVal / 100 );
if( FUNIT_NONE != eOutUnit )
{
sMetric += cSep;
sal_Int64 nFract = nConvVal % 100;
if ( nFract < 0 )
nFract *= -1;
if ( nFract < 10 )
sMetric += '0';
sMetric += String::CreateFromInt64( nFract );
}
return sMetric;
}
// -----------------------------------------------------------------------
SFX_IMPL_STATUSBAR_CONTROL(SvxPosSizeStatusBarControl, SvxSizeItem);
// class FunctionPopup_Impl ----------------------------------------------
class FunctionPopup_Impl : public PopupMenu
{
public:
FunctionPopup_Impl( sal_uInt16 nCheck );
sal_uInt16 GetSelected() const { return nSelected; }
private:
sal_uInt16 nSelected;
virtual void Select();
};
// -----------------------------------------------------------------------
FunctionPopup_Impl::FunctionPopup_Impl( sal_uInt16 nCheck ) :
PopupMenu( ResId( RID_SVXMNU_PSZ_FUNC, DIALOG_MGR() ) ),
nSelected( 0 )
{
if (nCheck)
CheckItem( nCheck );
}
// -----------------------------------------------------------------------
void FunctionPopup_Impl::Select()
{
nSelected = GetCurItemId();
}
// struct SvxPosSizeStatusBarControl_Impl --------------------------------
struct SvxPosSizeStatusBarControl_Impl
/* [Beschreibung]
Diese Implementations-Struktur der Klasse SvxPosSizeStatusBarControl
dient der Entkopplung von "Anderungen vom exportierten Interface sowie
der Verringerung von extern sichtbaren Symbolen.
Eine Instanz exisitiert pro SvxPosSizeStatusBarControl-Instanz
f"ur deren Laufzeit.
*/
{
Point aPos; // g"ultig, wenn eine Position angezeigt wird
Size aSize; // g"ultig, wenn eine Gr"o/se angezeigt wird
String aStr; // g"ultig, wenn ein Text angezeigt wird
sal_Bool bPos; // show position
sal_Bool bSize; // Gr"o/se anzeigen?
sal_Bool bTable; // Tabellenindex anzeigen?
sal_Bool bHasMenu; // StarCalc Popup-Menue anzeigen?
sal_uInt16 nFunction; // selektierte StarCalc Funktion
Image aPosImage; // Image f"ur die Positionsanzeige
Image aSizeImage; // Image f"ur die Gr"o/senanzeige
};
// class SvxPosSizeStatusBarControl ------------------------------------------
/* [Beschreibung]
Ctor():
Anlegen einer Impl-Klassen-Instanz, Default die Zeitanzeige enablen,
Images fu"r die Position und Gro"sse laden.
*/
#define STR_POSITION ".uno:Position"
#define STR_TABLECELL ".uno:StateTableCell"
#define STR_FUNC ".uno:StatusBarFunc"
SvxPosSizeStatusBarControl::SvxPosSizeStatusBarControl( sal_uInt16 _nSlotId,
sal_uInt16 _nId,
StatusBar& rStb ) :
SfxStatusBarControl( _nSlotId, _nId, rStb ),
pImp( new SvxPosSizeStatusBarControl_Impl )
{
pImp->bPos = sal_False;
pImp->bSize = sal_False;
pImp->bTable = sal_False;
pImp->bHasMenu = sal_False;
pImp->nFunction = 0;
pImp->aPosImage = Image( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) );
pImp->aSizeImage = Image( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) );
addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_POSITION ))); // SID_ATTR_POSITION
addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_TABLECELL ))); // SID_TABLE_CELL
addStatusListener( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( STR_FUNC ))); // SID_PSZ_FUNCTION
}
// -----------------------------------------------------------------------
/* [Beschreibung]
Dtor():
Pointer auf die Impl-Klasse lo"schen, damit der Timer gestoppt wird.
*/
SvxPosSizeStatusBarControl::~SvxPosSizeStatusBarControl()
{
delete pImp;
}
// -----------------------------------------------------------------------
/* [Beschreibung]
SID_PSZ_FUNCTION aktiviert das Popup-Menue fuer Calc, ansonsten:
Statusbenachrichtigung;
Je nach Item-Typ wird eine bestimmte Anzeige enabled, die anderen disabled.
NULL/Void SfxPointItem SvxSizeItem SfxStringItem
------------------------------------------------------------------------
Zeit sal_True sal_False sal_False FALSE
Position sal_False FALSE
Gro"sse FALSE TRUE FALSE
Text sal_False sal_False TRUE
Ein anderes Item bewirkt einen Assert, die Zeitanzeige wird enabled.
*/
void SvxPosSizeStatusBarControl::StateChanged( sal_uInt16 nSID, SfxItemState eState,
const SfxPoolItem* pState )
{
// da Kombi-Controller, immer die aktuelle Id als HelpId setzen
// gecachten HelpText vorher l"oschen
GetStatusBar().SetHelpText( GetId(), String() );
switch ( nSID )
{
case SID_ATTR_POSITION : GetStatusBar().SetHelpId( GetId(), STR_POSITION ); break;
case SID_TABLE_CELL: GetStatusBar().SetHelpId( GetId(), STR_TABLECELL ); break;
case SID_PSZ_FUNCTION: GetStatusBar().SetHelpId( GetId(), STR_FUNC ); break;
default: break;
}
if ( nSID == SID_PSZ_FUNCTION )
{
if ( eState == SFX_ITEM_AVAILABLE )
{
pImp->bHasMenu = sal_True;
if ( pState && pState->ISA(SfxUInt16Item) )
pImp->nFunction = ((const SfxUInt16Item*)pState)->GetValue();
}
else
pImp->bHasMenu = sal_False;
}
else if ( SFX_ITEM_AVAILABLE != eState )
{
// #i34458# don't switch to empty display before an empty state was
// notified for all display types
if ( nSID == SID_TABLE_CELL )
pImp->bTable = sal_False;
else if ( nSID == SID_ATTR_POSITION )
pImp->bPos = sal_False;
else if ( nSID == GetSlotId() ) // controller is registered for SID_ATTR_SIZE
pImp->bSize = sal_False;
else
{
DBG_ERRORFILE("unknown slot id");
}
}
else if ( pState->ISA( SfxPointItem ) )
{
// Position anzeigen
pImp->aPos = ( (SfxPointItem*)pState )->GetValue();
pImp->bPos = sal_True;
pImp->bTable = sal_False;
}
else if ( pState->ISA( SvxSizeItem ) )
{
// Groesse anzeigen
pImp->aSize = ( (SvxSizeItem*)pState )->GetSize();
pImp->bSize = sal_True;
pImp->bTable = sal_False;
}
else if ( pState->ISA( SfxStringItem ) )
{
// String anzeigen (Tabellen-Zelle oder anderes)
pImp->aStr = ( (SfxStringItem*)pState )->GetValue();
pImp->bTable = sal_True;
pImp->bPos = sal_False;
pImp->bSize = sal_False;
}
else
{
DBG_ERRORFILE( "invalid item type" );
// trotzdem Datum und Zeit anzeigen
pImp->bPos = sal_False;
pImp->bSize = sal_False;
pImp->bTable = sal_False;
}
if ( GetStatusBar().AreItemsVisible() )
GetStatusBar().SetItemData( GetId(), 0 );
// nur Strings auch als Text an der StatusBar setzen, damit Tip-Hilfe
// funktioniert, wenn der Text zu lang ist.
String aText;
if ( pImp->bTable )
aText = pImp->aStr;
GetStatusBar().SetItemText( GetId(), aText );
}
// -----------------------------------------------------------------------
/* [Beschreibung]
Popup-Menue ausfuehren, wenn per Status enabled
*/
void SvxPosSizeStatusBarControl::Command( const CommandEvent& rCEvt )
{
if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU && pImp->bHasMenu )
{
sal_uInt16 nSelect = pImp->nFunction;
if (!nSelect)
nSelect = PSZ_FUNC_NONE;
FunctionPopup_Impl aMenu( nSelect );
if ( aMenu.Execute( &GetStatusBar(), rCEvt.GetMousePosPixel() ) )
{
nSelect = aMenu.GetSelected();
if (nSelect)
{
if (nSelect == PSZ_FUNC_NONE)
nSelect = 0;
::com::sun::star::uno::Any a;
SfxUInt16Item aItem( SID_PSZ_FUNCTION, nSelect );
::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aArgs( 1 );
aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StatusBarFunc" ));
aItem.QueryValue( a );
aArgs[0].Value = a;
execute( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:StatusBarFunc" )), aArgs );
// GetBindings().GetDispatcher()->Execute( SID_PSZ_FUNCTION, SFX_CALLMODE_RECORD, &aItem, 0L );
}
}
}
else
SfxStatusBarControl::Command( rCEvt );
}
// -----------------------------------------------------------------------
/* [Beschreibung]
Je nach enableden Anzeigentyp, wird der Wert angezeigt. Vorher wird
das Rectangle u"bermalt (gelo"scht).
*/
void SvxPosSizeStatusBarControl::Paint( const UserDrawEvent& rUsrEvt )
{
OutputDevice* pDev = rUsrEvt.GetDevice();
DBG_ASSERT( pDev, "no OutputDevice on UserDrawEvent" );
const Rectangle& rRect = rUsrEvt.GetRect();
StatusBar& rBar = GetStatusBar();
Point aItemPos = rBar.GetItemTextPos( GetId() );
Color aOldLineColor = pDev->GetLineColor();
Color aOldFillColor = pDev->GetFillColor();
pDev->SetLineColor();
pDev->SetFillColor( pDev->GetBackground().GetColor() );
if ( pImp->bPos || pImp->bSize )
{
// Position fuer Size-Anzeige berechnen
long nSizePosX =
rRect.Left() + rRect.GetWidth() / 2 + PAINT_OFFSET;
// Position zeichnen
Point aPnt = rRect.TopLeft();
aPnt.Y() = aItemPos.Y();
aPnt.X() += PAINT_OFFSET;
pDev->DrawImage( aPnt, pImp->aPosImage );
aPnt.X() += pImp->aPosImage.GetSizePixel().Width();
aPnt.X() += PAINT_OFFSET;
String aStr = GetMetricStr_Impl( pImp->aPos.X());
aStr.AppendAscii(" / ");
aStr += GetMetricStr_Impl( pImp->aPos.Y());
pDev->DrawRect(
Rectangle( aPnt, Point( nSizePosX, rRect.Bottom() ) ) );
pDev->DrawText( aPnt, aStr );
// falls verf"ugbar, Gr"osse zeichnen
aPnt.X() = nSizePosX;
if ( pImp->bSize )
{
pDev->DrawImage( aPnt, pImp->aSizeImage );
aPnt.X() += pImp->aSizeImage.GetSizePixel().Width();
Point aDrwPnt = aPnt;
aPnt.X() += PAINT_OFFSET;
aStr = GetMetricStr_Impl( pImp->aSize.Width() );
aStr.AppendAscii(" x ");
aStr += GetMetricStr_Impl( pImp->aSize.Height() );
pDev->DrawRect( Rectangle( aDrwPnt, rRect.BottomRight() ) );
pDev->DrawText( aPnt, aStr );
}
else
pDev->DrawRect( Rectangle( aPnt, rRect.BottomRight() ) );
}
else if ( pImp->bTable )
{
pDev->DrawRect( rRect );
pDev->DrawText( Point(
rRect.Left() + rRect.GetWidth() / 2 - pDev->GetTextWidth( pImp->aStr ) / 2,
aItemPos.Y() ), pImp->aStr );
}
else
{
// Empty display if neither size nor table position are available.
// Date/Time are no longer used (#65302#).
pDev->DrawRect( rRect );
}
pDev->SetLineColor( aOldLineColor );
pDev->SetFillColor( aOldFillColor );
}
// -----------------------------------------------------------------------
sal_uIntPtr SvxPosSizeStatusBarControl::GetDefItemWidth(const StatusBar& rStb)
{
Image aTmpPosImage( ResId( RID_SVXBMP_POSITION, DIALOG_MGR() ) );
Image aTmpSizeImage( ResId( RID_SVXBMP_SIZE, DIALOG_MGR() ) );
sal_uIntPtr nWidth=PAINT_OFFSET+aTmpPosImage.GetSizePixel().Width();
nWidth+=PAINT_OFFSET+aTmpSizeImage.GetSizePixel().Width();
nWidth+=2*(PAINT_OFFSET+rStb.GetTextWidth(String::CreateFromAscii("XXXX,XX / XXXX,XX")));
return nWidth;
}