diff options
Diffstat (limited to 'svtools/source')
110 files changed, 10655 insertions, 349 deletions
diff --git a/svtools/source/brwbox/brwbox1.cxx b/svtools/source/brwbox/brwbox1.cxx index 9a4903b1e093..3a29c4ae63fa 100644 --- a/svtools/source/brwbox/brwbox1.cxx +++ b/svtools/source/brwbox/brwbox1.cxx @@ -2446,8 +2446,6 @@ void BrowseBox::SetMode( BrowserMode nMode ) BROWSER_AUTO_HSCROLL | BROWSER_TRACKING_TIPS | // BROWSER_HIGHLIGHT_NONE | - BROWSER_HIGHLIGHT_AUTO | -// BROWSER_HIGHLIGHT_MANU | BROWSER_HEADERBAR_NEW | // BROWSER_AUTOSIZE_LASTCOL | 0; @@ -2517,9 +2515,6 @@ void BrowseBox::SetMode( BrowserMode nMode ) pVScroll->SetScrollHdl( LINK( this, BrowseBox, ScrollHdl ) ); pVScroll->SetEndScrollHdl( LINK( this, BrowseBox, EndScrollHdl ) ); - getDataWindow()->bHighlightAuto = - BROWSER_HIGHLIGHT_AUTO == ( nMode & BROWSER_HIGHLIGHT_AUTO ) || - BROWSER_HIGHLIGHT_MANU != ( nMode & BROWSER_HIGHLIGHT_MANU ); getDataWindow()->bAutoSizeLastCol = BROWSER_AUTOSIZE_LASTCOL == ( nMode & BROWSER_AUTOSIZE_LASTCOL ); getDataWindow()->bOwnDataChangedHdl = diff --git a/svtools/source/brwbox/brwbox2.cxx b/svtools/source/brwbox/brwbox2.cxx index da07415dfee8..68cf316e813b 100644 --- a/svtools/source/brwbox/brwbox2.cxx +++ b/svtools/source/brwbox/brwbox2.cxx @@ -340,10 +340,6 @@ void BrowseBox::ToggleSelection( BOOL bForce ) if ( !bForce && ( bNotToggleSel || !IsUpdateMode() || !bSelectionIsVisible ) ) return; -//MI, 28.01.98 -// if ( !getDataWindow()->bHighlightToggle && -// !getDataWindow()->bHighlightAuto ) -// return; // only highlight painted areas! bNotToggleSel = TRUE; @@ -984,11 +980,10 @@ void BrowseBox::ImplPaintData(OutputDevice& _rOut, const Rectangle& _rRect, BOOL Size( _rRect.GetSize().Width(), nDataRowHeigt ) ); PaintRow( _rOut, aRowRect ); - BOOL bRowAutoHighlight = _bDrawSelections - && !bHideSelect - && ((BrowserDataWin&)GetDataWindow()).bHighlightAuto - && IsRowSelected( nRow ); - if ( bRowAutoHighlight ) + BOOL bRowSelected = _bDrawSelections + && !bHideSelect + && IsRowSelected( nRow ); + if ( bRowSelected ) { _rOut.SetTextColor( rHighlightTextColor ); _rOut.SetFillColor( rHighlightFillColor ); @@ -1082,7 +1077,7 @@ void BrowseBox::ImplPaintData(OutputDevice& _rOut, const Rectangle& _rRect, BOOL bRetouching = TRUE; // reset auto-highlight - if ( bRowAutoHighlight ) + if ( bRowSelected ) { _rOut.SetTextColor( aOldTextColor ); _rOut.SetFillColor( aOldFillColor ); diff --git a/svtools/source/brwbox/brwbox3.cxx b/svtools/source/brwbox/brwbox3.cxx index 449d5642e034..102af1b6e1a1 100644 --- a/svtools/source/brwbox/brwbox3.cxx +++ b/svtools/source/brwbox/brwbox3.cxx @@ -542,7 +542,7 @@ BOOL BrowseBox::GetGlyphBoundRects( const Point& rOrigin, const String& rStr, in return Control::GetGlyphBoundRects( rOrigin, rStr, nIndex, nLen, nBase, rVector ); } // ----------------------------------------------------------------------------- -Rectangle BrowseBox::GetWindowExtentsRelative( Window *pRelativeWindow ) +Rectangle BrowseBox::GetWindowExtentsRelative( Window *pRelativeWindow ) const { return Control::GetWindowExtentsRelative( pRelativeWindow ); } diff --git a/svtools/source/brwbox/datwin.hxx b/svtools/source/brwbox/datwin.hxx index e068f669e46e..1deb8aeb5b56 100644 --- a/svtools/source/brwbox/datwin.hxx +++ b/svtools/source/brwbox/datwin.hxx @@ -142,7 +142,6 @@ public: FASTBOOL bAutoVScroll; // autohide horizontaler Scrollbar FASTBOOL bUpdateMode; // nicht SV-UpdateMode wegen Invalidate() FASTBOOL bAutoSizeLastCol;// last column always fills up window - FASTBOOL bHighlightAuto; // new auto-highlight by SetFont() etc. FASTBOOL bResizeOnPaint; // outstanding resize-event FASTBOOL bUpdateOnUnlock; // Update() while locked FASTBOOL bInUpdateScrollbars; // Rekursionsschutz diff --git a/svtools/source/brwbox/editbrowsebox.cxx b/svtools/source/brwbox/editbrowsebox.cxx index 817ab743140a..4f0afbaf5d2d 100644 --- a/svtools/source/brwbox/editbrowsebox.cxx +++ b/svtools/source/brwbox/editbrowsebox.cxx @@ -47,7 +47,7 @@ #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #include <algorithm> diff --git a/svtools/source/brwbox/editbrowsebox.src b/svtools/source/brwbox/editbrowsebox.src index 8c00c673c32b..6511d97ea86a 100644 --- a/svtools/source/brwbox/editbrowsebox.src +++ b/svtools/source/brwbox/editbrowsebox.src @@ -30,7 +30,7 @@ #endif #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif ImageList RID_SVTOOLS_IMAGELIST_EDITBROWSEBOX diff --git a/svtools/source/contnr/fileview.cxx b/svtools/source/contnr/fileview.cxx index 8538e344bdc1..843de83f7710 100644 --- a/svtools/source/contnr/fileview.cxx +++ b/svtools/source/contnr/fileview.cxx @@ -34,7 +34,7 @@ #include <svtools/headbar.hxx> #include <svtools/svtabbx.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "fileview.hrc" #include "contentenumeration.hxx" #include <svtools/AccessibleBrowseBoxObjType.hxx> diff --git a/svtools/source/contnr/fileview.src b/svtools/source/contnr/fileview.src index e45f35fc1927..f40530c10347 100644 --- a/svtools/source/contnr/fileview.src +++ b/svtools/source/contnr/fileview.src @@ -27,7 +27,7 @@ // includes ------------------------------------------------------------------ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "fileview.hrc" #include <svtools/helpid.hrc> diff --git a/svtools/source/contnr/svcontnr.src b/svtools/source/contnr/svcontnr.src index c296cc686c1d..bcd1e060664f 100644 --- a/svtools/source/contnr/svcontnr.src +++ b/svtools/source/contnr/svcontnr.src @@ -25,7 +25,7 @@ * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> Image RID_IMG_TREENODE_COLLAPSED { diff --git a/svtools/source/contnr/svimpbox.cxx b/svtools/source/contnr/svimpbox.cxx index 426f55be5b93..7111a29a6a8a 100644 --- a/svtools/source/contnr/svimpbox.cxx +++ b/svtools/source/contnr/svimpbox.cxx @@ -47,7 +47,7 @@ #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif // #102891# -------------------- @@ -3115,7 +3115,7 @@ void lcl_DeleteSubPopups(PopupMenu* pPopup) } } -void SvImpLBox::Command( const CommandEvent& rCEvt ) +bool SvImpLBox::Command( const CommandEvent& rCEvt ) { USHORT nCommand = rCEvt.GetCommand(); @@ -3123,9 +3123,22 @@ void SvImpLBox::Command( const CommandEvent& rCEvt ) aEditTimer.Stop(); // Rollmaus-Event? - if( ( ( nCommand == COMMAND_WHEEL ) || ( nCommand == COMMAND_STARTAUTOSCROLL ) || ( nCommand == COMMAND_AUTOSCROLL ) ) - && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) ) - return; + if ( ( ( nCommand == COMMAND_WHEEL ) + || ( nCommand == COMMAND_STARTAUTOSCROLL ) + || ( nCommand == COMMAND_AUTOSCROLL ) + ) + && pView->HandleScrollCommand( rCEvt, &aHorSBar, &aVerSBar ) + ) + { + return true; + } + + if ( ( nCommand == COMMAND_CONTEXTMENU ) + && !bContextMenuHandling + ) + { + return false; + } if( bContextMenuHandling && nCommand == COMMAND_CONTEXTMENU ) { @@ -3174,8 +3187,6 @@ void SvImpLBox::Command( const CommandEvent& rCEvt ) { // deselect all pView->SelectAll( FALSE ); } - - } else { // key event (or at least no mouse event) @@ -3235,15 +3246,18 @@ void SvImpLBox::Command( const CommandEvent& rCEvt ) aSelRestore.pop(); } } + return true; } -#ifndef NOCOMMAND - else - { - const Point& rPos = rCEvt.GetMousePosPixel(); - if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() ) - aSelEng.Command( rCEvt ); - } -#endif + + const Point& rPos = rCEvt.GetMousePosPixel(); + if( rPos.X() < aOutputSize.Width() && rPos.Y() < aOutputSize.Height() ) + aSelEng.Command( rCEvt ); + + // strictly, this is not correct. However, it leads to a behavior compatible to the one at the time + // when this method did have a void return value ... + // A proper solution would be to give the EditEngine::Command also a boolean return value, and forward + // this (or false) to our caller + return true; } void SvImpLBox::BeginScroll() diff --git a/svtools/source/contnr/svlbox.cxx b/svtools/source/contnr/svlbox.cxx index 2752e813052e..fb71f64772ad 100644 --- a/svtools/source/contnr/svlbox.cxx +++ b/svtools/source/contnr/svlbox.cxx @@ -1515,9 +1515,10 @@ void SvLBox::MakeVisible( SvLBoxEntry* ) DBG_CHKTHIS(SvLBox,0); } -void SvLBox::Command( const CommandEvent& ) +void SvLBox::Command( const CommandEvent& i_rCommandEvent ) { DBG_CHKTHIS(SvLBox,0); + Control::Command( i_rCommandEvent ); } void SvLBox::KeyInput( const KeyEvent& rKEvt ) @@ -1774,10 +1775,14 @@ void SvLBox::StartDrag( sal_Int8, const Point& rPosPixel ) { DBG_CHKTHIS(SvLBox,0); + nOldDragMode = GetDragDropMode(); + if ( !nOldDragMode ) + return; + ReleaseMouse(); + SvLBoxEntry* pEntry = GetEntry( rPosPixel ); // GetDropTarget( rPos ); - nOldDragMode = GetDragDropMode(); - if( !pEntry || !nOldDragMode ) + if( !pEntry ) { DragFinished( DND_ACTION_NONE ); return; diff --git a/svtools/source/contnr/svtabbx.cxx b/svtools/source/contnr/svtabbx.cxx index 9d4ad1ba15b5..53fbded59f11 100644 --- a/svtools/source/contnr/svtabbx.cxx +++ b/svtools/source/contnr/svtabbx.cxx @@ -31,7 +31,7 @@ #include <svtools/headbar.hxx> #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/AccessibleEventId.hpp> @@ -1232,7 +1232,7 @@ BOOL SvHeaderTabListBox::GetGlyphBoundRects( const Point& rOrigin, const String& return Control::GetGlyphBoundRects( rOrigin, rStr, nIndex, nLen, nBase, rVector ); } // ----------------------------------------------------------------------- -Rectangle SvHeaderTabListBox::GetWindowExtentsRelative( Window *pRelativeWindow ) +Rectangle SvHeaderTabListBox::GetWindowExtentsRelative( Window *pRelativeWindow ) const { return Control::GetWindowExtentsRelative( pRelativeWindow ); } diff --git a/svtools/source/contnr/svtreebx.cxx b/svtools/source/contnr/svtreebx.cxx index 143ac922eebc..bf6e41f93f36 100644 --- a/svtools/source/contnr/svtreebx.cxx +++ b/svtools/source/contnr/svtreebx.cxx @@ -40,6 +40,7 @@ class TabBar; #include <svtools/svlbox.hxx> #include <svtools/svlbitm.hxx> #include <svtools/svtreebx.hxx> +#include <tools/diagnose_ex.h> #include <svimpbox.hxx> #include <unotools/accessiblestatesethelper.hxx> #include <com/sun/star/accessibility/AccessibleStateType.hpp> @@ -427,17 +428,6 @@ SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText,SvLBoxEntry* pPa else SvLBox::Insert( pEntry, pParent, nPos ); - short nExpWidth = (short)rDefExpBmp.GetSizePixel().Width(); - short nColWidth = (short)rDefColBmp.GetSizePixel().Width(); - short nMax = Max(nExpWidth, nColWidth); - // #97680# ---------------- - nMax = pImp->UpdateContextBmpWidthVector( pEntry, nMax ); - if( nMax > nContextBmpWidthMax ) - { - nContextBmpWidthMax = nMax; - SetTabs(); - } - aPrevInsertedExpBmp = rDefExpBmp; aPrevInsertedColBmp = rDefColBmp; @@ -468,17 +458,6 @@ SvLBoxEntry* SvTreeListBox::InsertEntry( const XubString& aText, else SvLBox::Insert( pEntry, pParent, nPos ); - short nExpWidth = (short)aExpEntryBmp.GetSizePixel().Width(); - short nColWidth = (short)aCollEntryBmp.GetSizePixel().Width(); - short nMax = Max(nExpWidth, nColWidth); - // #97680# ---------------- - nMax = pImp->UpdateContextBmpWidthVector( pEntry, nMax ); - if( nMax > nContextBmpWidthMax ) - { - nContextBmpWidthMax = nMax; - SetTabs(); - } - aPrevInsertedExpBmp = aExpEntryBmp; aPrevInsertedColBmp = aCollEntryBmp; @@ -1041,7 +1020,7 @@ BOOL SvTreeListBox::Expand( SvLBoxEntry* pParent ) // --> OD 2009-04-01 #i92103# if ( bExpanded ) { - pImp->CallEventListeners( VCLEVENT_LISTBOX_ENTRY_EXPANDED, pParent ); + pImp->CallEventListeners( VCLEVENT_ITEM_EXPANDED, pParent ); } // <-- @@ -1068,7 +1047,7 @@ BOOL SvTreeListBox::Collapse( SvLBoxEntry* pParent ) // --> OD 2009-04-01 #i92103# if ( bCollapsed ) { - pImp->CallEventListeners( VCLEVENT_LISTBOX_ENTRY_COLLAPSED, pParent ); + pImp->CallEventListeners( VCLEVENT_ITEM_COLLAPSED, pParent ); } // <-- @@ -2250,7 +2229,8 @@ Region SvTreeListBox::GetDragRegion() const void SvTreeListBox::Command( const CommandEvent& rCEvt ) { DBG_CHKTHIS(SvTreeListBox,0); - pImp->Command( rCEvt ); + if ( !pImp->Command( rCEvt ) ) + SvLBox::Command( rCEvt ); } @@ -2346,6 +2326,25 @@ void SvTreeListBox::ModelNotification( USHORT nActionId, SvListEntry* pEntry1, SvLBox::ModelNotification( nActionId, pEntry1, pEntry2, nPos ); switch( nActionId ) { + case LISTACTION_INSERTED: + { + SvLBoxEntry* pEntry( dynamic_cast< SvLBoxEntry* >( pEntry1 ) ); + ENSURE_OR_BREAK( pEntry, "SvTreeListBox::ModelNotification: invalid entry!" ); + SvLBoxContextBmp* pBmpItem = static_cast< SvLBoxContextBmp* >( pEntry->GetFirstItem( SV_ITEM_ID_LBOXCONTEXTBMP ) ); + if ( !pBmpItem ) + break; + const Image& rBitmap1( pBmpItem->GetBitmap1() ); + const Image& rBitmap2( pBmpItem->GetBitmap2() ); + short nMaxWidth = short( Max( rBitmap1.GetSizePixel().Width(), rBitmap2.GetSizePixel().Width() ) ); + nMaxWidth = pImp->UpdateContextBmpWidthVector( pEntry, nMaxWidth ); + if( nMaxWidth > nContextBmpWidthMax ) + { + nContextBmpWidthMax = nMaxWidth; + SetTabs(); + } + } + break; + case LISTACTION_RESORTING: SetUpdateMode( FALSE ); break; diff --git a/svtools/source/contnr/templwin.cxx b/svtools/source/contnr/templwin.cxx index 47b5ab9aa4b9..61112f6669ca 100644 --- a/svtools/source/contnr/templwin.cxx +++ b/svtools/source/contnr/templwin.cxx @@ -41,7 +41,7 @@ #include "imgdef.hxx" #include "txtattr.hxx" #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #ifndef _SVTOOLS_TEMPLWIN_HRC #include "templwin.hrc" diff --git a/svtools/source/contnr/templwin.src b/svtools/source/contnr/templwin.src index 636c54ef6632..048d052c18d8 100644 --- a/svtools/source/contnr/templwin.src +++ b/svtools/source/contnr/templwin.src @@ -30,7 +30,7 @@ #include "templwin.hrc" #include "controldims.hrc" #include <svtools/helpid.hrc> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> // Magenta and Grey as mask colors #define MASK_COL_MAGENTA Color { Red = 0xFFFF ; Green = 0x0000 ; Blue = 0xFFFF ; }; diff --git a/svtools/source/control/calendar.cxx b/svtools/source/control/calendar.cxx index c83ffa3ed70f..f7b49ac57eeb 100644..100755 --- a/svtools/source/control/calendar.cxx +++ b/svtools/source/control/calendar.cxx @@ -59,7 +59,7 @@ #include <com/sun/star/i18n/CalendarFieldIndex.hpp> #define _SV_CALENDAR_CXX -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <svtools/svtdata.hxx> #include <calendar.hxx> diff --git a/svtools/source/control/calendar.src b/svtools/source/control/calendar.src index 15c82cfdd184..4dd31765a5c1 100644..100755 --- a/svtools/source/control/calendar.src +++ b/svtools/source/control/calendar.src @@ -25,7 +25,7 @@ * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> String STR_SVT_CALENDAR_DAY { Text [ en-US ] = "Day" ; diff --git a/svtools/source/control/collatorres.cxx b/svtools/source/control/collatorres.cxx index 23a84e757ebe..9988bfdadbb9 100644..100755 --- a/svtools/source/control/collatorres.cxx +++ b/svtools/source/control/collatorres.cxx @@ -29,7 +29,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include <svtools/svtdata.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <collatorres.hxx> diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx index 2f692944d3c7..d44b18a29ae1 100644..100755 --- a/svtools/source/control/ctrlbox.cxx +++ b/svtools/source/control/ctrlbox.cxx @@ -40,7 +40,7 @@ #include <unotools/charclass.hxx> #include <svtools/svtdata.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <ctrlbox.hxx> #include <ctrltool.hxx> diff --git a/svtools/source/control/ctrlbox.src b/svtools/source/control/ctrlbox.src index 0c63aef259b3..95440c905d89 100644..100755 --- a/svtools/source/control/ctrlbox.src +++ b/svtools/source/control/ctrlbox.src @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #ifndef IMAGE_STDBTN_COLOR #define IMAGE_STDBTN_COLOR Color { Red = 0xFFFF; Green = 0x0000; Blue = 0xFFFF; } diff --git a/svtools/source/control/ctrltool.cxx b/svtools/source/control/ctrltool.cxx index 9abd14331fe4..bd965aca66a6 100644..100755 --- a/svtools/source/control/ctrltool.cxx +++ b/svtools/source/control/ctrltool.cxx @@ -42,7 +42,7 @@ #include <vcl/svapp.hxx> #include <vcl/wrkwin.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <svtools/svtdata.hxx> #include <ctrltool.hxx> diff --git a/svtools/source/control/ctrltool.src b/svtools/source/control/ctrltool.src index 3e1c1ba884f8..72420af4908e 100644..100755 --- a/svtools/source/control/ctrltool.src +++ b/svtools/source/control/ctrltool.src @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> String STR_SVT_STYLE_LIGHT { diff --git a/svtools/source/control/indexentryres.cxx b/svtools/source/control/indexentryres.cxx index 32e3aa14c0dc..5a79edab5b77 100644..100755 --- a/svtools/source/control/indexentryres.cxx +++ b/svtools/source/control/indexentryres.cxx @@ -29,7 +29,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svtools.hxx" #include <svtools/svtdata.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <indexentryres.hxx> diff --git a/svtools/source/control/makefile.mk b/svtools/source/control/makefile.mk index a40a81163eb3..a2e622730635 100644..100755 --- a/svtools/source/control/makefile.mk +++ b/svtools/source/control/makefile.mk @@ -51,7 +51,9 @@ EXCEPTIONSFILES=\ $(SLO)$/scriptedtext.obj\ $(SLO)$/fmtfield.obj \ $(SLO)$/inettbc.obj \ - $(SLO)$/valueacc.obj + $(SLO)$/valueacc.obj \ + $(SLO)$/toolbarmenu.obj \ + $(SLO)$/toolbarmenuacc.obj SLOFILES=\ $(EXCEPTIONSFILES) \ diff --git a/svtools/source/control/toolbarmenu.cxx b/svtools/source/control/toolbarmenu.cxx new file mode 100644 index 000000000000..f07ebd7fe8cd --- /dev/null +++ b/svtools/source/control/toolbarmenu.cxx @@ -0,0 +1,1805 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <comphelper/processfactory.hxx> + +#include <vcl/dockwin.hxx> +#include <vcl/decoview.hxx> +#include <vcl/image.hxx> +#include <vcl/taskpanelist.hxx> +#include <vcl/toolbox.hxx> + +#include "svtools/valueset.hxx" +#include "svtools/toolbarmenu.hxx" +#include "toolbarmenuimp.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::accessibility; + +namespace svtools { + +// -------------------------------------------------------------------- + +static Window* GetTopMostParentSystemWindow( Window* pWindow ) +{ + OSL_ASSERT( pWindow ); + if ( pWindow ) + { + // ->manually search topmost system window + // required because their might be another system window between this and the top window + pWindow = pWindow->GetParent(); + SystemWindow* pTopMostSysWin = NULL; + while ( pWindow ) + { + if ( pWindow->IsSystemWindow() ) + pTopMostSysWin = (SystemWindow*)pWindow; + pWindow = pWindow->GetParent(); + } + pWindow = pTopMostSysWin; + OSL_ASSERT( pWindow ); + return pWindow; + } + + return NULL; +} + +// -------------------------------------------------------------------- + +void ToolbarMenuEntry::init( int nEntryId, MenuItemBits nBits ) +{ + mnEntryId = nEntryId; + mnBits = nBits; + + mbHasText = false; + mbHasImage = false; + mbChecked = false; + mbEnabled = true; + + mpControl = NULL; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits ) +: mrMenu( rMenu ) +{ + init( nEntryId, nBits ); + + maText = rText; + mbHasText = true; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits ) +: mrMenu( rMenu ) +{ + init( nEntryId, nBits ); + + maImage = rImage; + mbHasImage = true; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits ) +: mrMenu( rMenu ) +{ + init( nEntryId, nBits ); + + maText = rText; + mbHasText = true; + + maImage = rImage; + mbHasImage = true; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry::ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits ) +: mrMenu( rMenu ) +{ + init( nEntryId, nBits ); + + if( pControl ) + { + mpControl = pControl; + mpControl->Show(); + } +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry::~ToolbarMenuEntry() +{ + if( mxAccContext.is() ) + { + Reference< XComponent > xComponent( mxAccContext, UNO_QUERY ); + if( xComponent.is() ) + xComponent->dispose(); + mxAccContext.clear(); + } + delete mpControl; +} + +// -------------------------------------------------------------------- + +const Reference< XAccessibleContext >& ToolbarMenuEntry::GetAccessible( bool bCreate /* = false */ ) +{ + if( !mxAccContext.is() && bCreate ) + { + if( mpControl ) + { + mxAccContext = Reference< XAccessibleContext >( mpControl->GetAccessible( TRUE ), UNO_QUERY ); + } + else + { + mxAccContext = Reference< XAccessibleContext >( new ToolbarMenuEntryAcc( this ) ); + } + } + + return mxAccContext; +} + +// -------------------------------------------------------------------- + +sal_Int32 ToolbarMenuEntry::getAccessibleChildCount() throw (RuntimeException) +{ + if( mpControl ) + { + const Reference< XAccessibleContext >& xContext = GetAccessible( true ); + if( xContext.is() ) + { + return xContext->getAccessibleChildCount(); + } + } + return 1; +} + +// -------------------------------------------------------------------- + +Reference< XAccessible > ToolbarMenuEntry::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const Reference< XAccessibleContext >& xContext = GetAccessible( true ); + if( mpControl ) + { + if( xContext.is() ) + { + return xContext->getAccessibleChild(index); + } + } + else if( index == 0 ) + { + Reference< XAccessible > xRet( xContext, UNO_QUERY ); + if( xRet.is() ) + return xRet; + } + + throw IndexOutOfBoundsException(); +} + +// -------------------------------------------------------------------- + +ToolbarMenu_Impl::ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame ) +: mrMenu( rMenu ) +, mxFrame( xFrame ) +, mxServiceManager( ::comphelper::getProcessServiceFactory() ) +, mnCheckPos(0) +, mnImagePos(0) +, mnTextPos(0) +, mnHighlightedEntry(-1) +, mnSelectedEntry(-1) +, mnLastColumn(0) +{ +} + +// -------------------------------------------------------------------- + +ToolbarMenu_Impl::~ToolbarMenu_Impl() +{ + setAccessible( 0 ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu_Impl::setAccessible( ToolbarMenuAcc* pAccessible ) +{ + if( mxAccessible.get() != pAccessible ) + { + if( mxAccessible.is() ) + mxAccessible->dispose(); + + mxAccessible.set( pAccessible ); + } +} + +// ----------------------------------------------------------------------- + +void ToolbarMenu_Impl::fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ) +{ + if( mxAccessible.is() ) + mxAccessible->FireAccessibleEvent( nEventId, rOldValue, rNewValue ); +} + +// ----------------------------------------------------------------------- + +bool ToolbarMenu_Impl::hasAccessibleListeners() +{ + return( mxAccessible.is() && mxAccessible->HasAccessibleListeners() ); +} + +// -------------------------------------------------------------------- + +sal_Int32 ToolbarMenu_Impl::getAccessibleChildCount() throw (RuntimeException) +{ + sal_Int32 nCount = 0; + const int nEntryCount = maEntryVector.size(); + for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; + if( pEntry ) + { + if( pEntry->mpControl ) + { + nCount += pEntry->getAccessibleChildCount(); + } + else + { + nCount += 1; + } + } + } + + return nCount; +} + +// -------------------------------------------------------------------- + +Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( sal_Int32 index ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const int nEntryCount = maEntryVector.size(); + for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; + if( pEntry ) + { + const sal_Int32 nCount = pEntry->getAccessibleChildCount(); + if( index < nCount ) + { + return pEntry->getAccessibleChild( index ); + } + index -= nCount; + } + } + + throw IndexOutOfBoundsException(); +} + +// -------------------------------------------------------------------- + +Reference< XAccessible > ToolbarMenu_Impl::getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const int nEntryCount = maEntryVector.size(); + for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; + if( pEntry && (pEntry->mpControl == pControl) ) + { + return pEntry->getAccessibleChild( childIndex ); + } + } + + throw IndexOutOfBoundsException(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu_Impl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const int nEntryCount = maEntryVector.size(); + for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; + if( pEntry ) + { + const sal_Int32 nCount = pEntry->getAccessibleChildCount(); + if( nChildIndex < nCount ) + { + if( pEntry->mpControl ) + { + Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + xSel->selectAccessibleChild(nChildIndex); + } + else if( pEntry->mnEntryId != TITLE_ID ) + { + mrMenu.implSelectEntry( nEntry ); + } + return; + } + nChildIndex -= nCount; + } + } + + throw IndexOutOfBoundsException(); +} + +// -------------------------------------------------------------------- + +sal_Bool ToolbarMenu_Impl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const int nEntryCount = maEntryVector.size(); + for( int nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = maEntryVector[nEntry]; + if( pEntry ) + { + const sal_Int32 nCount = pEntry->getAccessibleChildCount(); + if( nChildIndex < nCount ) + { + if( mnHighlightedEntry == nEntry ) + { + if( pEntry->mpControl ) + { + Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + xSel->isAccessibleChildSelected(nChildIndex); + } + return true; + } + else + { + return false; + } + } + nChildIndex -= nCount; + } + } + + throw IndexOutOfBoundsException(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu_Impl::clearAccessibleSelection() +{ + if( mnHighlightedEntry != -1 ) + { + mrMenu.implHighlightEntry( mnHighlightedEntry, false ); + mnHighlightedEntry = -1; + } +} + + +// -------------------------------------------------------------------- + +void ToolbarMenu_Impl::notifyHighlightedEntry() +{ + if( hasAccessibleListeners() ) + { + ToolbarMenuEntry* pEntry = implGetEntry( mnHighlightedEntry ); + if( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) + { + Any aNew; + Any aOld( mxOldSelection ); + if( pEntry->mpControl ) + { + sal_Int32 nChildIndex = 0; + // todo: if other controls than ValueSet are allowed, addapt this code + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); + if( pValueSet ) + nChildIndex = static_cast< sal_Int32 >( pValueSet->GetItemPos( pValueSet->GetSelectItemId() ) ); + + if( nChildIndex >= pEntry->getAccessibleChildCount() ) + return; + + aNew <<= getAccessibleChild( pEntry->mpControl, nChildIndex ); + } + else + { + aNew <<= pEntry->GetAccessible(true); + } + + fireAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOld, aNew ); + fireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, aOld, aNew ); + fireAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), Any( AccessibleStateType::FOCUSED ) ); + aNew >>= mxOldSelection; + } + } +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry* ToolbarMenu_Impl::implGetEntry( int nEntry ) const +{ + if( (nEntry < 0) || (nEntry >= (int)maEntryVector.size() ) ) + return NULL; + + return maEntryVector[nEntry]; +} + + +// -------------------------------------------------------------------- + +IMPL_LINK( ToolbarMenu, HighlightHdl, Control *, pControl ) +{ + (void)pControl; + mpImpl->notifyHighlightedEntry(); + return 0; +} + +// ==================================================================== + +ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, WinBits nBits ) +: DockingWindow(pParentWindow, nBits) +{ + implInit(rFrame); +} + +// -------------------------------------------------------------------- + +ToolbarMenu::ToolbarMenu( const Reference< XFrame >& rFrame, Window* pParentWindow, const ResId& rResId ) +: DockingWindow(pParentWindow, rResId) +{ + implInit(rFrame); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implInit(const Reference< XFrame >& rFrame) +{ + mpImpl = new ToolbarMenu_Impl( *this, rFrame ); + + initWindow(); + + Window* pWindow = GetTopMostParentSystemWindow( this ); + if ( pWindow ) + ((SystemWindow *)pWindow)->GetTaskPaneList()->AddWindow( this ); +} + +// -------------------------------------------------------------------- + +ToolbarMenu::~ToolbarMenu() +{ + Window* pWindow = GetTopMostParentSystemWindow( this ); + if ( pWindow ) + ((SystemWindow *)pWindow)->GetTaskPaneList()->RemoveWindow( this ); + + if ( mpImpl->mxStatusListener.is() ) + { + mpImpl->mxStatusListener->dispose(); + mpImpl->mxStatusListener.clear(); + } + + // delete all menu entries + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + delete mpImpl->maEntryVector[nEntry]; + } + + delete mpImpl; +} + +// -------------------------------------------------------------------- + +int ToolbarMenu::getSelectedEntryId() const +{ + ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnSelectedEntry ); + return pEntry ? pEntry->mnEntryId : -1; +} + +// -------------------------------------------------------------------- + +int ToolbarMenu::getHighlightedEntryId() const +{ + ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); + return pEntry ? pEntry->mnEntryId : -1; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::checkEntry( int nEntryId, bool bChecked ) +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry && pEntry->mbChecked != bChecked ) + { + pEntry->mbChecked = bChecked; + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +bool ToolbarMenu::isEntryChecked( int nEntryId ) const +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + return pEntry && pEntry->mbChecked; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::enableEntry( int nEntryId, bool bEnable ) +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry && pEntry->mbEnabled != bEnable ) + { + pEntry->mbEnabled = bEnable; + if( pEntry->mpControl ) + { + pEntry->mpControl->Enable( bEnable ); + + // hack for the valueset to make it paint itself anew + pEntry->mpControl->Resize(); + } + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +bool ToolbarMenu::isEntryEnabled( int nEntryId ) const +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + return pEntry && pEntry->mbEnabled; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::setEntryText( int nEntryId, const String& rStr ) +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry && pEntry->maText != rStr ) + { + pEntry->maText = rStr; + mpImpl->maSize = implCalcSize(); + if( IsVisible() ) + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +const String& ToolbarMenu::getEntryText( int nEntryId ) const +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry ) + return pEntry->maText; + else + { + static String aEmptyStr; + return aEmptyStr; + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::setEntryImage( int nEntryId, const Image& rImage ) +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry && pEntry->maImage != rImage ) + { + pEntry->maImage = rImage; + mpImpl->maSize = implCalcSize(); + if( IsVisible() ) + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +const Image& ToolbarMenu::getEntryImage( int nEntryId ) const +{ + ToolbarMenuEntry* pEntry = implSearchEntry( nEntryId ); + if( pEntry ) + return pEntry->maImage; + else + { + static Image aEmptyImage; + return aEmptyImage; + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::initWindow() +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + SetControlBackground( GetSettings().GetStyleSettings().GetFaceGradientColor() ); + + SetPointFont( rStyleSettings.GetMenuFont() ); + SetBackground( Wallpaper( GetControlBackground() ) ); + SetTextColor( rStyleSettings.GetMenuTextColor() ); + SetTextFillColor(); + SetLineColor(); + + mpImpl->maSize = implCalcSize(); +} + +// -------------------------------------------------------------------- + +Size ToolbarMenu::implCalcSize() +{ + const long nFontHeight = GetTextHeight(); + long nExtra = nFontHeight/4; + + Size aSz; + Size aMaxImgSz; + long nMaxTextWidth = 0; + long nMinMenuItemHeight = nFontHeight+2; + sal_Bool bCheckable = sal_False; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + + const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + const bool bUseImages = rSettings.GetUseImagesInMenus(); + + // get maximum image size + if( bUseImages ) + { + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + if( pEntry && pEntry->mbHasImage ) + { + Size aImgSz( pEntry->maImage.GetSizePixel() ); + nMinMenuItemHeight = std::max( nMinMenuItemHeight, aImgSz.Height() + 6 ); + aMaxImgSz.Width() = std::max( aMaxImgSz.Width(), aImgSz.Width() ); + } + } + } + + mpImpl->mnCheckPos = nExtra; + mpImpl->mnImagePos = nExtra; + mpImpl->mnTextPos = mpImpl->mnImagePos + aMaxImgSz.Width(); + + if ( aMaxImgSz.Width() ) + mpImpl->mnTextPos += std::max( nExtra, 7L ); + if ( bCheckable ) + mpImpl->mnTextPos += 16; + + // set heights, calc maximum width + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + if( pEntry ) + { + if ( ( pEntry->mnBits ) & ( MIB_RADIOCHECK | MIB_CHECKABLE ) ) + bCheckable = sal_True; + + // Text: + if( pEntry->mbHasText || pEntry->mbHasImage ) + { + pEntry->maSize.Height() = nMinMenuItemHeight; + + if( pEntry->mbHasText ) + { + long nTextWidth = GetCtrlTextWidth( pEntry->maText ) + mpImpl->mnTextPos + nExtra; + nMaxTextWidth = std::max( nTextWidth, nMaxTextWidth ); + } + } + // Control: + else if( pEntry->mpControl ) + { + Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); + + nMaxTextWidth = std::max( aControlSize.Width(), nMaxTextWidth ); + pEntry->maSize.Height() = aControlSize.Height() + 1; + } + + } + } + + aSz.Width() = nMaxTextWidth + (BORDER_X<<1); + + // positionate controls + int nY = BORDER_Y; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + if( pEntry ) + { + pEntry->maSize.Width() = nMaxTextWidth; + + if( pEntry->mpControl ) + { + Size aControlSize( pEntry->mpControl->GetOutputSizePixel() ); + Point aControlPos( (aSz.Width() - aControlSize.Width())>>1, nY); + + pEntry->mpControl->SetPosPixel( aControlPos ); + + pEntry->maRect = Rectangle( aControlPos, aControlSize ); + } + else + { + pEntry->maRect = Rectangle( Point( 0, nY ), pEntry->maSize ); + } + + nY += pEntry->maSize.Height(); + } + else + { + nY += SEPARATOR_HEIGHT; + } + } + + aSz.Height() += nY + BORDER_Y; + + return aSz; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::highlightFirstEntry() +{ + implChangeHighlightEntry( 0 ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::GetFocus() +{ + if( mpImpl->mnHighlightedEntry == -1 ) + implChangeHighlightEntry( 0 ); + + DockingWindow::GetFocus(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::LoseFocus() +{ + if( mpImpl->mnHighlightedEntry != -1 ) + implChangeHighlightEntry( -1 ); + + DockingWindow::LoseFocus(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, MenuItemBits nItemBits ) +{ + appendEntry( new ToolbarMenuEntry( *this, nEntryId, rStr, nItemBits ) ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( int nEntryId, const Image& rImage, MenuItemBits nItemBits ) +{ + appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, nItemBits ) ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( int nEntryId, const String& rStr, const Image& rImage, MenuItemBits nItemBits ) +{ + appendEntry( new ToolbarMenuEntry( *this, nEntryId, rImage, rStr, nItemBits ) ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( int nEntryId, Control* pControl, MenuItemBits nItemBits ) +{ + appendEntry( new ToolbarMenuEntry( *this, nEntryId, pControl, nItemBits ) ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendEntry( ToolbarMenuEntry* pEntry ) +{ + mpImpl->maEntryVector.push_back( pEntry ); + mpImpl->maSize = implCalcSize(); + if( IsVisible() ) + Invalidate(); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::appendSeparator() +{ + appendEntry( 0 ); +} + +// -------------------------------------------------------------------- + +/** creates an empty ValueSet that is initialized and can be inserted with appendEntry. */ +ValueSet* ToolbarMenu::createEmptyValueSetControl() +{ + ValueSet* pSet = new ValueSet( this, WB_TABSTOP | WB_MENUSTYLEVALUESET | WB_FLATVALUESET | WB_NOBORDER | WB_NO_DIRECTSELECT ); + pSet->EnableFullItemMode( FALSE ); + pSet->SetColor( GetControlBackground() ); + pSet->SetHighlightHdl( LINK( this, ToolbarMenu, HighlightHdl ) ); + return pSet; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry* ToolbarMenu::implGetEntry( int nEntry ) const +{ + return mpImpl->implGetEntry( nEntry ); +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry* ToolbarMenu::implSearchEntry( int nEntryId ) const +{ + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* p = mpImpl->maEntryVector[nEntry]; + if( p && p->mnEntryId == nEntryId ) + { + return p; + } + } + + return NULL; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implHighlightEntry( int nHighlightEntry, bool bHighlight ) +{ + Size aSz( GetOutputSizePixel() ); + long nX = 0, nY = 0; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + if( pEntry && (nEntry == nHighlightEntry) ) + { + // no highlights for controls only items + if( pEntry->mpControl ) + { + if( !bHighlight ) + { + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pEntry->mpControl ); + if( pValueSet ) + { + pValueSet->SetNoSelection(); + } + } + break; + } + + bool bRestoreLineColor = false; + Color oldLineColor; + bool bDrawItemRect = true; + + Rectangle aItemRect( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ); + if ( pEntry->mnBits & MIB_POPUPSELECT ) + { + long nFontHeight = GetTextHeight(); + aItemRect.Right() -= nFontHeight + nFontHeight/4; + } + + if( IsNativeControlSupported( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL ) ) + { + Size aPxSize( GetOutputSizePixel() ); + Push( PUSH_CLIPREGION ); + IntersectClipRegion( Rectangle( Point( nX, nY ), Size( aSz.Width(), pEntry->maSize.Height() ) ) ); + Rectangle aCtrlRect( Point( nX, 0 ), Size( aPxSize.Width()-nX, aPxSize.Height() ) ); + DrawNativeControl( CTRL_MENU_POPUP, PART_ENTIRE_CONTROL, + Region( aCtrlRect ), + CTRL_STATE_ENABLED, + ImplControlValue(), + OUString() ); + if( bHighlight && IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM ) ) + { + bDrawItemRect = false; + if( FALSE == DrawNativeControl( CTRL_MENU_POPUP, PART_MENU_ITEM, + Region( aItemRect ), + CTRL_STATE_SELECTED | ( pEntry->mbEnabled? CTRL_STATE_ENABLED: 0 ), + ImplControlValue(), + OUString() ) ) + { + bDrawItemRect = bHighlight; + } + } + else + bDrawItemRect = bHighlight; + Pop(); + } + if( bDrawItemRect ) + { + if ( bHighlight ) + { + if( pEntry->mbEnabled ) + SetFillColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); + else + { + SetFillColor(); + oldLineColor = GetLineColor(); + SetLineColor( GetSettings().GetStyleSettings().GetMenuHighlightColor() ); + bRestoreLineColor = true; + } + } + else + SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); + + DrawRect( aItemRect ); + } + implPaint( pEntry, bHighlight ); + if( bRestoreLineColor ) + SetLineColor( oldLineColor ); + break; + } + + nY += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implSelectEntry( int nSelectedEntry ) +{ + mpImpl->mnSelectedEntry = nSelectedEntry; + + ToolbarMenuEntry* pEntry = NULL; + if( nSelectedEntry != -1 ) + pEntry = mpImpl->maEntryVector[ nSelectedEntry ]; + + if( pEntry ) + mpImpl->maSelectHdl.Call( this ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::MouseButtonDown( const MouseEvent& rMEvt ) +{ + implHighlightEntry( rMEvt, true ); + + implSelectEntry( mpImpl->mnHighlightedEntry ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::MouseButtonUp( const MouseEvent& ) +{ +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::MouseMove( const MouseEvent& rMEvt ) +{ + if ( !IsVisible() ) + return; + + implHighlightEntry( rMEvt, false ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implHighlightEntry( const MouseEvent& rMEvt, bool bMBDown ) +{ + long nY = 0; + long nMouseY = rMEvt.GetPosPixel().Y(); + Size aOutSz = GetOutputSizePixel(); + if ( ( nMouseY >= 0 ) && ( nMouseY < aOutSz.Height() ) ) + { + bool bHighlighted = FALSE; + + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + if( pEntry ) + { + long nOldY = nY; + nY += pEntry->maSize.Height(); + + if( pEntry->mnEntryId != TITLE_ID ) + { + if ( ( nOldY <= nMouseY ) && ( nY > nMouseY ) ) + { + if( bMBDown ) + { + if( nEntry != mpImpl->mnHighlightedEntry ) + { + implChangeHighlightEntry( nEntry ); + } + } + else + { + if ( nEntry != mpImpl->mnHighlightedEntry ) + { + implChangeHighlightEntry( nEntry ); + } + } + bHighlighted = true; + } + } + } + else + { + nY += SEPARATOR_HEIGHT; + } + } + if ( !bHighlighted ) + implChangeHighlightEntry( -1 ); + } + else + { + implChangeHighlightEntry( -1 ); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::implChangeHighlightEntry( int nEntry ) +{ + if( mpImpl->mnHighlightedEntry != -1 ) + { + implHighlightEntry( mpImpl->mnHighlightedEntry, false ); + } + + mpImpl->mnHighlightedEntry = nEntry; + Invalidate(); + + if( mpImpl->mnHighlightedEntry != -1 ) + { + implHighlightEntry( mpImpl->mnHighlightedEntry, true ); + } + + mpImpl->notifyHighlightedEntry(); +} + +// -------------------------------------------------------------------- + +static bool implCheckSubControlCursorMove( Control* pControl, bool bUp, int& nLastColumn ) +{ + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); + if( pValueSet ) + { + USHORT nItemPos = pValueSet->GetItemPos( pValueSet->GetSelectItemId() ); + if( nItemPos != VALUESET_ITEM_NOTFOUND ) + { + const USHORT nColCount = pValueSet->GetColCount(); + const USHORT nLine = nItemPos / nColCount; + + nLastColumn = nItemPos - (nLine * nColCount); + + if( bUp ) + { + return nLine > 0; + } + else + { + const USHORT nLineCount = (pValueSet->GetItemCount() + nColCount - 1) / nColCount; + return (nLine+1) < nLineCount; + } + } + } + + return false; +} + +// -------------------------------------------------------------------- + +ToolbarMenuEntry* ToolbarMenu::implCursorUpDown( bool bUp, bool bHomeEnd ) +{ + int n = 0, nLoop = 0; + if( !bHomeEnd ) + { + n = mpImpl->mnHighlightedEntry; + if( n == -1 ) + { + if( bUp ) + n = 0; + else + n = mpImpl->maEntryVector.size()-1; + } + else + { + // if we have a currently selected entry and + // cursor keys are used than check if this entry + // has a control that can use those cursor keys + ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; + if( pData && pData->mpControl && !pData->mbHasText ) + { + if( implCheckSubControlCursorMove( pData->mpControl, bUp, mpImpl->mnLastColumn ) ) + return pData; + } + } + nLoop = n; + } + else + { + // absolute positioning + if( bUp ) + { + n = mpImpl->maEntryVector.size(); + nLoop = n-1; + } + else + { + n = -1; + nLoop = mpImpl->maEntryVector.size()-1; + } + } + + do + { + if( bUp ) + { + if ( n ) + n--; + else + if( mpImpl->mnHighlightedEntry == -1 ) + n = mpImpl->maEntryVector.size()-1; + else + break; + } + else + { + if( n < ((int)mpImpl->maEntryVector.size()-1) ) + n++; + else + if( mpImpl->mnHighlightedEntry == -1 ) + n = 0; + else + break; + } + + ToolbarMenuEntry* pData = mpImpl->maEntryVector[n]; + if( pData && (pData->mnEntryId != TITLE_ID) ) + { + implChangeHighlightEntry( n ); + return pData; + } + } while ( n != nLoop ); + + return 0; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu_Impl::implHighlightControl( USHORT nCode, Control* pControl ) +{ + ValueSet* pValueSet = dynamic_cast< ValueSet* >( pControl ); + if( pValueSet ) + { + const USHORT nItemCount = pValueSet->GetItemCount(); + USHORT nItemPos = VALUESET_ITEM_NOTFOUND; + switch( nCode ) + { + case KEY_UP: + { + const USHORT nColCount = pValueSet->GetColCount(); + const USHORT nLastLine = nItemCount / nColCount; + nItemPos = std::min( ((nLastLine-1) * nColCount) + mnLastColumn, nItemCount-1 ); + break; + } + case KEY_DOWN: + nItemPos = std::min( mnLastColumn, nItemCount-1 ); + break; + case KEY_END: + nItemPos = nItemCount -1; + break; + case KEY_HOME: + nItemPos = 0; + break; + } + pValueSet->SelectItem( pValueSet->GetItemId( nItemPos ) ); + notifyHighlightedEntry(); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::KeyInput( const KeyEvent& rKEvent ) +{ + Control* pForwardControl = 0; + USHORT nCode = rKEvent.GetKeyCode().GetCode(); + switch ( nCode ) + { + case KEY_UP: + case KEY_DOWN: + { + int nOldEntry = mpImpl->mnHighlightedEntry; + ToolbarMenuEntry*p = implCursorUpDown( nCode == KEY_UP, false ); + if( p && p->mpControl ) + { + if( nOldEntry != mpImpl->mnHighlightedEntry ) + { + mpImpl->implHighlightControl( nCode, p->mpControl ); + } + else + { + // in case we are in a system floating window, GrabFocus does not work :-/ + pForwardControl = p->mpControl; + } + } + } + break; + case KEY_END: + case KEY_HOME: + { + ToolbarMenuEntry* p = implCursorUpDown( nCode == KEY_END, true ); + if( p && p->mpControl ) + { + mpImpl->implHighlightControl( nCode, p->mpControl ); + } + } + break; + case KEY_F6: + case KEY_ESCAPE: + { + // Ctrl-F6 acts like ESC here, the menu bar however will then put the focus in the document + if( nCode == KEY_F6 && !rKEvent.GetKeyCode().IsMod1() ) + break; + + implSelectEntry( -1 ); + } + break; + + case KEY_RETURN: + { + ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); + if ( pEntry && pEntry->mbEnabled && (pEntry->mnEntryId != TITLE_ID) ) + { + if( pEntry->mpControl ) + { + pForwardControl = pEntry->mpControl; + } + else + { + implSelectEntry( mpImpl->mnHighlightedEntry ); + } + } + } + break; + default: + { + ToolbarMenuEntry* pEntry = implGetEntry( mpImpl->mnHighlightedEntry ); + if ( pEntry && pEntry->mbEnabled && pEntry->mpControl && !pEntry->mbHasText ) + { + pForwardControl = pEntry->mpControl; + } + } + + } + if( pForwardControl ) + pForwardControl->KeyInput( rKEvent ); + +} + +// -------------------------------------------------------------------- +static void ImplPaintCheckBackground( Window* i_pWindow, const Rectangle& i_rRect, bool i_bHighlight ) +{ + BOOL bNativeOk = FALSE; + if( i_pWindow->IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) + { + ImplControlValue aControlValue; + Region aCtrlRegion( i_rRect ); + ControlState nState = CTRL_STATE_PRESSED | CTRL_STATE_ENABLED; + + aControlValue.setTristateVal( BUTTONVALUE_ON ); + + bNativeOk = i_pWindow->DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, + aCtrlRegion, nState, aControlValue, + rtl::OUString() ); + } + + if( ! bNativeOk ) + { + const StyleSettings& rSettings = i_pWindow->GetSettings().GetStyleSettings(); + Color aColor( i_bHighlight ? rSettings.GetMenuHighlightTextColor() : rSettings.GetHighlightColor() ); + i_pWindow->DrawSelectionBackground( i_rRect, 0, i_bHighlight, TRUE, FALSE, 2, NULL, &aColor ); + } +} + +static long ImplGetNativeCheckAndRadioSize( Window* pWin, long& rCheckHeight, long& rRadioHeight, long &rMaxWidth ) +{ + rMaxWidth = rCheckHeight = rRadioHeight = 0; + + ImplControlValue aVal; + Region aNativeBounds; + Region aNativeContent; + Point tmp( 0, 0 ); + Region aCtrlRegion( Rectangle( tmp, Size( 100, 15 ) ) ); + if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_CHECK_MARK ) ) + { + if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), + ControlPart(PART_MENU_ITEM_CHECK_MARK), + aCtrlRegion, + ControlState(CTRL_STATE_ENABLED), + aVal, + OUString(), + aNativeBounds, + aNativeContent ) + ) + { + rCheckHeight = aNativeBounds.GetBoundRect().GetHeight(); + rMaxWidth = aNativeContent.GetBoundRect().GetWidth(); + } + } + if( pWin->IsNativeControlSupported( CTRL_MENU_POPUP, PART_MENU_ITEM_RADIO_MARK ) ) + { + if( pWin->GetNativeControlRegion( ControlType(CTRL_MENU_POPUP), + ControlPart(PART_MENU_ITEM_RADIO_MARK), + aCtrlRegion, + ControlState(CTRL_STATE_ENABLED), + aVal, + OUString(), + aNativeBounds, + aNativeContent ) + ) + { + rRadioHeight = aNativeBounds.GetBoundRect().GetHeight(); + rMaxWidth = Max (rMaxWidth, aNativeContent.GetBoundRect().GetWidth()); + } + } + return (rCheckHeight > rRadioHeight) ? rCheckHeight : rRadioHeight; +} + +void ToolbarMenu::implPaint( ToolbarMenuEntry* pThisOnly, bool bHighlighted ) +{ + USHORT nBorder = 0; long nStartY = 0; // from Menu implementations, needed when we support native menu background & scrollable menu + + long nFontHeight = GetTextHeight(); +// long nExtra = nFontHeight/4; + + long nCheckHeight = 0, nRadioHeight = 0, nMaxCheckWidth = 0; + ImplGetNativeCheckAndRadioSize( this, nCheckHeight, nRadioHeight, nMaxCheckWidth ); + + DecorationView aDecoView( this ); + const StyleSettings& rSettings = GetSettings().GetStyleSettings(); + const bool bUseImages = rSettings.GetUseImagesInMenus(); + + int nOuterSpace = 0; // ImplGetSVData()->maNWFData.mnMenuFormatExtraBorder; + Point aTopLeft( nOuterSpace, nOuterSpace ), aTmpPos; + + Size aOutSz( GetOutputSizePixel() ); + const int nEntryCount = mpImpl->maEntryVector.size(); + int nEntry; + for( nEntry = 0; nEntry < nEntryCount; nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpImpl->maEntryVector[nEntry]; + + Point aPos( aTopLeft ); + aPos.Y() += nBorder; + aPos.Y() += nStartY; + + + if( (pEntry == 0) && !pThisOnly ) + { + // Separator + aTmpPos.Y() = aPos.Y() + ((SEPARATOR_HEIGHT-2)/2); + aTmpPos.X() = aPos.X() + 2 + nOuterSpace; + SetLineColor( rSettings.GetShadowColor() ); + DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); + aTmpPos.Y()++; + SetLineColor( rSettings.GetLightColor() ); + DrawLine( aTmpPos, Point( aOutSz.Width() - 3 - 2*nOuterSpace, aTmpPos.Y() ) ); + SetLineColor(); + } + else if( !pThisOnly || ( pEntry == pThisOnly ) ) + { + const bool bTitle = pEntry->mnEntryId == TITLE_ID; + + if ( pThisOnly && bHighlighted ) + SetTextColor( rSettings.GetMenuHighlightTextColor() ); + + if( aPos.Y() >= 0 ) + { + long nTextOffsetY = ((pEntry->maSize.Height()-nFontHeight)/2); + + USHORT nTextStyle = 0; + USHORT nSymbolStyle = 0; + USHORT nImageStyle = 0; + + if( !pEntry->mbEnabled ) + { + nTextStyle |= TEXT_DRAW_DISABLE; + nSymbolStyle |= SYMBOL_DRAW_DISABLE; + nImageStyle |= IMAGE_DRAW_DISABLE; + } + + Rectangle aOuterCheckRect( Point( aPos.X()+mpImpl->mnCheckPos, aPos.Y() ), Size( pEntry->maSize.Height(), pEntry->maSize.Height() ) ); + aOuterCheckRect.Left() += 1; + aOuterCheckRect.Right() -= 1; + aOuterCheckRect.Top() += 1; + aOuterCheckRect.Bottom() -= 1; + + if( bTitle ) + { + // fill the background + Rectangle aRect( aTopLeft, Size( aOutSz.Width(), pEntry->maSize.Height() ) ); + SetFillColor(rSettings.GetDialogColor()); + SetLineColor(); + DrawRect(aRect); + SetLineColor( rSettings.GetLightColor() ); + DrawLine( aRect.TopLeft(), aRect.TopRight() ); + SetLineColor( rSettings.GetShadowColor() ); + DrawLine( aRect.BottomLeft(), aRect.BottomRight() ); + } + + // CheckMark + if ( pEntry->HasCheck() ) + { + // draw selection transparent marker if checked + // onto that either a checkmark or the item image + // will be painted + // however do not do this if native checks will be painted since + // the selection color too often does not fit the theme's check and/or radio + + if( !pEntry->mbHasImage ) + { + if( this->IsNativeControlSupported( CTRL_MENU_POPUP, + (pEntry->mnBits & MIB_RADIOCHECK) + ? PART_MENU_ITEM_CHECK_MARK + : PART_MENU_ITEM_RADIO_MARK ) ) + { + ControlPart nPart = ((pEntry->mnBits & MIB_RADIOCHECK) + ? PART_MENU_ITEM_RADIO_MARK + : PART_MENU_ITEM_CHECK_MARK); + + ControlState nState = 0; + + if ( pEntry->mbChecked ) + nState |= CTRL_STATE_PRESSED; + + if ( pEntry->mbEnabled ) + nState |= CTRL_STATE_ENABLED; + + if ( bHighlighted ) + nState |= CTRL_STATE_SELECTED; + + long nCtrlHeight = (pEntry->mnBits & MIB_RADIOCHECK) ? nCheckHeight : nRadioHeight; + aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - nCtrlHeight)/2; + aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - nCtrlHeight)/2; + + Rectangle aCheckRect( aTmpPos, Size( nCtrlHeight, nCtrlHeight ) ); + DrawNativeControl( CTRL_MENU_POPUP, nPart, Region( aCheckRect ), nState, ImplControlValue(), OUString() ); + } + else if ( pEntry->mbChecked ) // by default do nothing for unchecked items + { + ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); + + SymbolType eSymbol; + Size aSymbolSize; + if ( pEntry->mnBits & MIB_RADIOCHECK ) + { + eSymbol = SYMBOL_RADIOCHECKMARK; + aSymbolSize = Size( nFontHeight/2, nFontHeight/2 ); + } + else + { + eSymbol = SYMBOL_CHECKMARK; + aSymbolSize = Size( (nFontHeight*25)/40, nFontHeight/2 ); + } + aTmpPos.X() = aOuterCheckRect.Left() + (aOuterCheckRect.GetWidth() - aSymbolSize.Width())/2; + aTmpPos.Y() = aOuterCheckRect.Top() + (aOuterCheckRect.GetHeight() - aSymbolSize.Height())/2; + Rectangle aRect( aTmpPos, aSymbolSize ); + aDecoView.DrawSymbol( aRect, eSymbol, GetTextColor(), nSymbolStyle ); + } + } + } + + // Image: + if( pEntry->mbHasImage && bUseImages ) + { + // Don't render an image for a check thing + /* if((nMenuFlags & MENU_FLAG_SHOWCHECKIMAGES) || !pEntry->HasCheck() )*/ + { + if( pEntry->mbChecked ) + ImplPaintCheckBackground( this, aOuterCheckRect, pThisOnly && bHighlighted ); + aTmpPos = aOuterCheckRect.TopLeft(); + aTmpPos.X() += (aOuterCheckRect.GetWidth()-pEntry->maImage.GetSizePixel().Width())/2; + aTmpPos.Y() += (aOuterCheckRect.GetHeight()-pEntry->maImage.GetSizePixel().Height())/2; + DrawImage( aTmpPos, pEntry->maImage, nImageStyle ); + } + } + + // Text: + if( pEntry->mbHasText ) + { + aTmpPos.X() = aPos.X() + (bTitle ? 4 : mpImpl->mnTextPos); + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nTextOffsetY; + USHORT nStyle = nTextStyle|TEXT_DRAW_MNEMONIC; + + DrawCtrlText( aTmpPos, pEntry->maText, 0, pEntry->maText.Len(), nStyle, NULL, NULL ); // pVector, pDisplayText ); + } + +/* + // Accel + if ( !bLayout && !bIsMenuBar && pData->aAccelKey.GetCode() && !ImplAccelDisabled() ) + { + XubString aAccText = pData->aAccelKey.GetName(); + aTmpPos.X() = aOutSz.Width() - this->GetTextWidth( aAccText ); + aTmpPos.X() -= 4*nExtra; + + aTmpPos.X() -= nOuterSpace; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nTextOffsetY; + this->DrawCtrlText( aTmpPos, aAccText, 0, aAccText.Len(), nTextStyle ); + } +*/ + +/* + // SubMenu? + if ( !bLayout && !bIsMenuBar && pData->pSubMenu ) + { + aTmpPos.X() = aOutSz.Width() - nFontHeight + nExtra - nOuterSpace; + aTmpPos.Y() = aPos.Y(); + aTmpPos.Y() += nExtra/2; + aTmpPos.Y() += ( pEntry->maSize.Height() / 2 ) - ( nFontHeight/4 ); + if ( pEntry->mnBits & MIB_POPUPSELECT ) + { + this->SetTextColor( rSettings.GetMenuTextColor() ); + Point aTmpPos2( aPos ); + aTmpPos2.X() = aOutSz.Width() - nFontHeight - nFontHeight/4; + aDecoView.DrawFrame( + Rectangle( aTmpPos2, Size( nFontHeight+nFontHeight/4, pEntry->maSize.Height() ) ), FRAME_DRAW_GROUP ); + } + aDecoView.DrawSymbol( + Rectangle( aTmpPos, Size( nFontHeight/2, nFontHeight/2 ) ), + SYMBOL_SPIN_RIGHT, this->GetTextColor(), nSymbolStyle ); +// if ( pEntry->mnBits & MIB_POPUPSELECT ) +// { +// aTmpPos.Y() += nFontHeight/2 ; +// this->SetLineColor( rSettings.GetShadowColor() ); +// this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); +// this->SetLineColor( rSettings.GetLightColor() ); +// aTmpPos.Y()++; +// this->DrawLine( aTmpPos, Point( aTmpPos.X() + nFontHeight/3, aTmpPos.Y() ) ); +// this->SetLineColor(); +// } + } +*/ + + if ( pThisOnly && bHighlighted ) + { + // This restores the normal menu or menu bar text + // color for when it is no longer highlighted. + SetTextColor( rSettings.GetMenuTextColor() ); + } + } + } + + aTopLeft.Y() += pEntry ? pEntry->maSize.Height() : SEPARATOR_HEIGHT; + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::Paint( const Rectangle& ) +{ + SetFillColor( GetSettings().GetStyleSettings().GetMenuColor() ); + + implPaint(); + + if( mpImpl->mnHighlightedEntry != -1 ) + implHighlightEntry( mpImpl->mnHighlightedEntry, true ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::RequestHelp( const HelpEvent& rHEvt ) +{ + DockingWindow::RequestHelp( rHEvt ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::StateChanged( StateChangedType nType ) +{ + DockingWindow::StateChanged( nType ); + + if ( ( nType == STATE_CHANGE_CONTROLFOREGROUND ) || ( nType == STATE_CHANGE_CONTROLBACKGROUND ) ) + { + initWindow(); + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::DataChanged( const DataChangedEvent& rDCEvt ) +{ + DockingWindow::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + initWindow(); + Invalidate(); + } +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == COMMAND_WHEEL ) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if( !pData->GetModifier() && ( pData->GetMode() == COMMAND_WHEEL_SCROLL ) ) + { + implCursorUpDown( pData->GetDelta() > 0L, false ); + } + } +} + +// -------------------------------------------------------------------- + +Reference< ::com::sun::star::accessibility::XAccessible > ToolbarMenu::CreateAccessible() +{ + mpImpl->setAccessible( new ToolbarMenuAcc( *mpImpl ) ); + return Reference< XAccessible >( mpImpl->mxAccessible.get() ); +} + +// -------------------------------------------------------------------- + +// todo: move to new base class that will replace SfxPopupWindo +void ToolbarMenu::AddStatusListener( const rtl::OUString& rCommandURL ) +{ + initStatusListener(); + mpImpl->mxStatusListener->addStatusListener( rCommandURL ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::RemoveStatusListener( const rtl::OUString& rCommandURL ) +{ + mpImpl->mxStatusListener->removeStatusListener( rCommandURL ); +} +// -------------------------------------------------------------------- + + +void ToolbarMenu::UpdateStatus( const rtl::OUString& rCommandURL ) +{ + mpImpl->mxStatusListener->updateStatus( rCommandURL ); +} + +// -------------------------------------------------------------------- + +// XStatusListener (subclasses must override this one to get the status updates +void SAL_CALL ToolbarMenu::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& /*Event*/ ) throw ( ::com::sun::star::uno::RuntimeException ) +{ +} + +// -------------------------------------------------------------------- + +class ToolbarMenuStatusListener : public svt::FrameStatusListener +{ +public: + ToolbarMenuStatusListener( const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, + ToolbarMenu& rToolbarMenu ); + + virtual void SAL_CALL dispose() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ); + + ToolbarMenu* mpMenu; +}; + +// -------------------------------------------------------------------- + +ToolbarMenuStatusListener::ToolbarMenuStatusListener( + const com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory >& xServiceManager, + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame, + ToolbarMenu& rToolbarMenu ) +: svt::FrameStatusListener( xServiceManager, xFrame ) +, mpMenu( &rToolbarMenu ) +{ +} + +// -------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuStatusListener::dispose() throw (::com::sun::star::uno::RuntimeException) +{ + mpMenu = 0; + svt::FrameStatusListener::dispose(); +} + +// -------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuStatusListener::statusChanged( const ::com::sun::star::frame::FeatureStateEvent& Event ) throw ( ::com::sun::star::uno::RuntimeException ) +{ + if( mpMenu ) + mpMenu->statusChanged( Event ); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::initStatusListener() +{ + if( !mpImpl->mxStatusListener.is() ) + mpImpl->mxStatusListener.set( new ToolbarMenuStatusListener( mpImpl->mxServiceManager, mpImpl->mxFrame, *this ) ); +} + +// -------------------------------------------------------------------- + +bool ToolbarMenu::IsInPopupMode() +{ + return GetDockingManager()->IsInPopupMode(this); +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::EndPopupMode() +{ + GetDockingManager()->EndPopupMode(this); +} + +// -------------------------------------------------------------------- + +const Size& ToolbarMenu::getMenuSize() const +{ + return mpImpl->maSize; +} + +// -------------------------------------------------------------------- + +void ToolbarMenu::SetSelectHdl( const Link& rLink ) +{ + mpImpl->maSelectHdl = rLink; +} + +// -------------------------------------------------------------------- + +const Link& ToolbarMenu::GetSelectHdl() const +{ + return mpImpl->maSelectHdl; +} + +// -------------------------------------------------------------------- + +Reference< XFrame > ToolbarMenu::GetFrame() const +{ + return mpImpl->mxFrame; +} + +// -------------------------------------------------------------------- + + +// -------------------------------------------------------------------- + +} + + diff --git a/svtools/source/control/toolbarmenuacc.cxx b/svtools/source/control/toolbarmenuacc.cxx new file mode 100644 index 000000000000..020467084748 --- /dev/null +++ b/svtools/source/control/toolbarmenuacc.cxx @@ -0,0 +1,1003 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +#include <unotools/accessiblestatesethelper.hxx> + +#include <vcl/svapp.hxx> + +#include "svtools/toolbarmenu.hxx" + +#include "toolbarmenuimp.hxx" + +using ::rtl::OUString; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::accessibility; + +namespace svtools { + +// ------------------ +// - ToolbarMenuAcc - +// ------------------ + +ToolbarMenuAcc::ToolbarMenuAcc( ToolbarMenu_Impl& rParent ) +: ToolbarMenuAccComponentBase(m_aMutex) +, mpParent( &rParent ) +, mbIsFocused(false) +{ + mpParent->mrMenu.AddEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); +} + +// ----------------------------------------------------------------------------- + +ToolbarMenuAcc::~ToolbarMenuAcc() +{ + if( mpParent ) + mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); +} + +// ----------------------------------------------------------------------- + +IMPL_LINK( ToolbarMenuAcc, WindowEventListener, VclSimpleEvent*, pEvent ) +{ + DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); + + /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper + * might have been destroyed by the previous VCLEventListener (if no AT tool + * is running), e.g. sub-toolbars in impress. + */ + if ( mpParent && pEvent && pEvent->ISA( VclWindowEvent ) && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) ) + { + DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" ); + if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) ) + { + ProcessWindowEvent( *(VclWindowEvent*)pEvent ); + } + } + return 0; +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuAcc::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) +{ + Any aOldValue, aNewValue; + + switch ( rVclWindowEvent.GetId() ) + { + case VCLEVENT_OBJECT_DYING: + { + mpParent->mrMenu.RemoveEventListener( LINK( this, ToolbarMenuAcc, WindowEventListener ) ); + mpParent = 0; + } + break; + + case VCLEVENT_WINDOW_GETFOCUS: + { + if( !mbIsFocused ) + { + mpParent->notifyHighlightedEntry(); + mbIsFocused = true; + } + } + break; + case VCLEVENT_WINDOW_LOSEFOCUS: + { + if( mbIsFocused ) + { + mbIsFocused = false; + } + } + break; + default: + { + } + break; + } +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue ) +{ + if( nEventId ) + { + EventListenerVector aTmpListeners( mxEventListeners ); + EventListenerVector::const_iterator aIter( aTmpListeners.begin() ); + AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + try + { + (*aIter)->notifyEvent( aEvtObject ); + } + catch( Exception& ) + { + } + + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleContext > SAL_CALL ToolbarMenuAcc::getAccessibleContext() throw (RuntimeException) +{ + ThrowIfDisposed(); + return this; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleChildCount() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->getAccessibleChildCount(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->getAccessibleChild(i); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleParent() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + Reference< XAccessible > xRet; + + Window* pParent = mpParent->mrMenu.GetParent(); + if( pParent ) + xRet = pParent->GetAccessible(); + + return xRet; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getAccessibleIndexInParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + Window* pParent = mpParent->mrMenu.GetParent(); + if( pParent ) + { + for( USHORT i = 0, nCount = pParent->GetChildCount(); i < nCount ; i++ ) + { + if( pParent->GetChild( i ) == &mpParent->mrMenu ) + return i; + } + } + + return 0; +} + +// ----------------------------------------------------------------------------- + +sal_Int16 SAL_CALL ToolbarMenuAcc::getAccessibleRole() throw (RuntimeException) +{ + ThrowIfDisposed(); + return AccessibleRole::LIST; +} + +// ----------------------------------------------------------------------------- + +OUString SAL_CALL ToolbarMenuAcc::getAccessibleDescription() throw (RuntimeException) +{ + ThrowIfDisposed(); + return OUString( RTL_CONSTASCII_USTRINGPARAM( "ToolbarMenu" ) ); +} + +// ----------------------------------------------------------------------------- + +OUString SAL_CALL ToolbarMenuAcc::getAccessibleName() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + OUString aRet; + + if( mpParent ) + aRet = mpParent->mrMenu.GetAccessibleName(); + + if( !aRet.getLength() ) + { + Window* pLabel = mpParent->mrMenu.GetLabeledBy(); + if( pLabel && pLabel != &mpParent->mrMenu ) + aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() ); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuAcc::getAccessibleRelationSet() throw (RuntimeException) +{ + ThrowIfDisposed(); + return Reference< XAccessibleRelationSet >(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuAcc::getAccessibleStateSet() throw (RuntimeException) +{ + ThrowIfDisposed(); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper(); + + // Set some states. + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::MANAGES_DESCENDANTS); + pStateSet->AddState (AccessibleStateType::FOCUSABLE); + if (mbIsFocused) + pStateSet->AddState (AccessibleStateType::FOCUSED); + + return pStateSet; +} + +// ----------------------------------------------------------------------------- + +Locale SAL_CALL ToolbarMenuAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const ::rtl::OUString aEmptyStr; + Reference< XAccessible > xParent( getAccessibleParent() ); + Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + if( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale (); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard(m_aMutex); + + if( rxListener.is() ) + { + EventListenerVector::const_iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = true; + else + aIter++; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard(m_aMutex); + + if( rxListener.is() ) + { + EventListenerVector::iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = true; + } + else + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getAccessibleAtPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + Reference< XAccessible > xRet; + + const Point aVclPoint( aPoint.X, aPoint.Y ); + + const int nEntryCount = mpParent->maEntryVector.size(); + for( int nEntry = 0; (nEntry < nEntryCount) && !xRet.is(); nEntry++ ) + { + ToolbarMenuEntry* pEntry = mpParent->maEntryVector[nEntry]; + if( pEntry && pEntry->maRect.IsInside( aVclPoint ) ) + { + if( pEntry->mpControl ) + { + awt::Point aChildPoint( aPoint.X - pEntry->maRect.Left(), aPoint.Y - pEntry->maRect.Top() ); + Reference< XAccessibleComponent > xComp( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + xRet = xComp->getAccessibleAtPoint(aChildPoint); + } + else + { + xRet = Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY ); + } + } + } + return xRet; +} + +// ----------------------------------------------------------------------------- + +awt::Rectangle SAL_CALL ToolbarMenuAcc::getBounds() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aOutPos( mpParent->mrMenu.GetPosPixel() ); + const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() ); + awt::Rectangle aRet; + + aRet.X = aOutPos.X(); + aRet.Y = aOutPos.Y(); + aRet.Width = aOutSize.Width(); + aRet.Height = aOutSize.Height(); + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuAcc::getLocation() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aOutPos( mpParent->mrMenu.GetPosPixel() ); + return awt::Point( aOutPos.X(), aOutPos.Y() ); +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuAcc::getLocationOnScreen() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( Point() ) ); + return awt::Point( aScreenPos.X(), aScreenPos.Y() ); +} + +// ----------------------------------------------------------------------------- + +awt::Size SAL_CALL ToolbarMenuAcc::getSize() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + const Size aOutSize( mpParent->mrMenu.GetOutputSizePixel() ); + return awt::Size( aOutSize.Width(), aOutSize.Height() ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::grabFocus() throw (RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + mpParent->mrMenu.GrabFocus(); +} + +// ----------------------------------------------------------------------------- + +Any SAL_CALL ToolbarMenuAcc::getAccessibleKeyBinding() throw (RuntimeException) +{ + ThrowIfDisposed(); + return Any(); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getForeground() throw (RuntimeException) +{ + ThrowIfDisposed(); + UINT32 nColor = Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor(); + return static_cast<sal_Int32>(nColor); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getBackground() throw (RuntimeException) +{ + ThrowIfDisposed(); + UINT32 nColor = Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor(); + return static_cast<sal_Int32>(nColor); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + mpParent->selectAccessibleChild( nChildIndex ); +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuAcc::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + return mpParent->isAccessibleChildSelected( nChildIndex ); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::clearAccessibleSelection() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + mpParent->clearAccessibleSelection(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::selectAllAccessibleChildren() throw (RuntimeException) +{ + ThrowIfDisposed(); + // unsupported due to single selection only +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChildCount() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ThrowIfDisposed(); + + return mpParent->mnHighlightedEntry != -1 ? 1 : 0; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + if( (mpParent->mnHighlightedEntry != -1) && (nSelectedChildIndex == 0) ) + { + ToolbarMenuEntry* pEntry = mpParent->maEntryVector[ mpParent->mnHighlightedEntry ]; + if( pEntry ) + { + if( pEntry->mpControl ) + { + Reference< XAccessibleSelection > xSel( pEntry->GetAccessible(true), UNO_QUERY_THROW ); + return xSel->getSelectedAccessibleChild(0); + } + else + return Reference< XAccessible >( pEntry->GetAccessible(true), UNO_QUERY ); + } + } + + throw IndexOutOfBoundsException(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) +{ + ThrowIfDisposed(); + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + // Because of the single selection we can reset the whole selection when + // the specified child is currently selected. + if (isAccessibleChildSelected(nChildIndex)) + mpParent->clearAccessibleSelection(); +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuAcc::disposing (void) +{ + EventListenerVector aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = NULL; + } + + // Inform all listeners that this objects is disposing. + EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin()); + EventObject aEvent (static_cast<XAccessible*>(this)); + while(aListenerIterator != aListenerListCopy.end()) + { + try + { + (*aListenerIterator)->disposing (aEvent); + } + catch( Exception& ) + { + // Ignore exceptions. + } + + ++aListenerIterator; + } +} + +void ToolbarMenuAcc::ThrowIfDisposed (void) throw (DisposedException) +{ + if(rBHelper.bDisposed || rBHelper.bInDispose || !mpParent) + { + throw DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), static_cast<XWeak*>(this)); + } +} + +// ----------------------- +// - ToolbarMenuEntryAcc - +// ----------------------- + +ToolbarMenuEntryAcc::ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent ) +: ToolbarMenuEntryAccBase( m_aMutex ) +, mpParent( pParent ) +{ +} + +// ----------------------------------------------------------------------------- + +ToolbarMenuEntryAcc::~ToolbarMenuEntryAcc() +{ +} + +// ----------------------------------------------------------------------- + +void ToolbarMenuEntryAcc::FireAccessibleEvent( short nEventId, const Any& rOldValue, const Any& rNewValue ) +{ + if( nEventId ) + { + EventListenerVector aTmpListeners( mxEventListeners ); + ::std::vector< Reference< XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() ); + AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + (*aIter)->notifyEvent( aEvtObject ); + aIter++; + } + } +} + + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::disposing (void) +{ + EventListenerVector aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = NULL; + } + + // Inform all listeners that this objects is disposing. + EventListenerVector::const_iterator aListenerIterator (aListenerListCopy.begin()); + EventObject aEvent (static_cast<XAccessible*>(this)); + while(aListenerIterator != aListenerListCopy.end()) + { + try + { + (*aListenerIterator)->disposing (aEvent); + } + catch( Exception& ) + { + // Ignore exceptions. + } + + ++aListenerIterator; + } +} +// ----------------------------------------------------------------------------- + +Reference< XAccessibleContext > SAL_CALL ToolbarMenuEntryAcc::getAccessibleContext() throw (RuntimeException) +{ + return this; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleChildCount() throw (RuntimeException) +{ + return 0; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleChild( sal_Int32 ) throw (IndexOutOfBoundsException, RuntimeException) +{ + throw IndexOutOfBoundsException(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + Reference< XAccessible > xRet; + + if( mpParent ) + xRet = mpParent->mrMenu.GetAccessible(); + + return xRet; +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getAccessibleIndexInParent() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + // The index defaults to -1 to indicate the child does not belong to its + // parent. + sal_Int32 nIndexInParent = -1; + + if( mpParent ) + { + Reference< XAccessibleContext > xParent( mpParent->mrMenu.GetAccessible(), UNO_QUERY ); + + if( xParent.is() ) + { + Reference< XAccessible > xThis( this ); + + const sal_Int32 nCount = xParent->getAccessibleChildCount(); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + if( xParent->getAccessibleChild(nIndex) == xThis ) + { + nIndexInParent = nIndex; + break; + } + } + } + } + + return nIndexInParent; +} + +// ----------------------------------------------------------------------------- + +sal_Int16 SAL_CALL ToolbarMenuEntryAcc::getAccessibleRole() throw (RuntimeException) +{ + return AccessibleRole::LIST_ITEM; +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleDescription() throw (RuntimeException) +{ + return ::rtl::OUString(); +} + +// ----------------------------------------------------------------------------- + +::rtl::OUString SAL_CALL ToolbarMenuEntryAcc::getAccessibleName() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + String aRet; + + if( mpParent ) + { + aRet = mpParent->maText; + + if( !aRet.Len() ) + { + aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) ); + aRet += String::CreateFromInt32( mpParent->mnEntryId ); + } + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleRelationSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleRelationSet() throw (RuntimeException) +{ + return Reference< XAccessibleRelationSet >(); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessibleStateSet > SAL_CALL ToolbarMenuEntryAcc::getAccessibleStateSet() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper; + + if( mpParent ) + { + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::TRANSIENT); + if( mpParent->mnEntryId != TITLE_ID ) + { + pStateSet->AddState( AccessibleStateType::SELECTABLE ); + + // SELECTED + if( mpParent->mrMenu.getHighlightedEntryId() == mpParent->mnEntryId ) + pStateSet->AddState( AccessibleStateType::SELECTED ); + } + } + + return pStateSet; +} + +// ----------------------------------------------------------------------------- + +Locale SAL_CALL ToolbarMenuEntryAcc::getLocale() throw (IllegalAccessibleComponentStateException, RuntimeException) +{ + const ::rtl::OUString aEmptyStr; + Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + Reference< XAccessible > xParent( getAccessibleParent() ); + if( xParent.is() ) + { + Reference< XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::addEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + const ::vos::OGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + EventListenerVector::const_iterator aIter( mxEventListeners.begin() ); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = true; + else + aIter++; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::removeEventListener( const Reference< XAccessibleEventListener >& rxListener ) throw (RuntimeException) +{ + const ::vos::OGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + EventListenerVector::iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = true; + } + else + aIter++; + } + } +} + +// ----------------------------------------------------------------------------- + +sal_Bool SAL_CALL ToolbarMenuEntryAcc::containsPoint( const awt::Point& aPoint ) throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +// ----------------------------------------------------------------------------- + +Reference< XAccessible > SAL_CALL ToolbarMenuEntryAcc::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException) +{ + Reference< XAccessible > xRet; + return xRet; +} + +// ----------------------------------------------------------------------------- + +awt::Rectangle SAL_CALL ToolbarMenuEntryAcc::getBounds() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + awt::Rectangle aRet; + + if( mpParent ) + { + Rectangle aRect( mpParent->maRect ); + Point aOrigin; + Rectangle aParentRect( aOrigin, mpParent->mrMenu.GetOutputSizePixel() ); + + aRect.Intersection( aParentRect ); + + aRet.X = aRect.Left(); + aRet.Y = aRect.Top(); + aRet.Width = aRect.GetWidth(); + aRet.Height = aRect.GetHeight(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocation() throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + return awt::Point( aRect.X, aRect.Y ); +} + +// ----------------------------------------------------------------------------- + +awt::Point SAL_CALL ToolbarMenuEntryAcc::getLocationOnScreen() throw (RuntimeException) +{ + const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + awt::Point aRet; + + if( mpParent ) + { + const Point aScreenPos( mpParent->mrMenu.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) ); + + aRet.X = aScreenPos.X(); + aRet.Y = aScreenPos.Y(); + } + + return aRet; +} + +// ----------------------------------------------------------------------------- + +awt::Size SAL_CALL ToolbarMenuEntryAcc::getSize() throw (RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +// ----------------------------------------------------------------------------- + +void SAL_CALL ToolbarMenuEntryAcc::grabFocus() throw (RuntimeException) +{ + // nothing to do +} + +// ----------------------------------------------------------------------------- + +Any SAL_CALL ToolbarMenuEntryAcc::getAccessibleKeyBinding() throw (RuntimeException) +{ + return Any(); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getForeground( ) throw (RuntimeException) +{ + return static_cast<sal_Int32>(Application::GetSettings().GetStyleSettings().GetMenuTextColor().GetColor()); +} + +// ----------------------------------------------------------------------------- + +sal_Int32 SAL_CALL ToolbarMenuEntryAcc::getBackground( ) throw (RuntimeException) +{ + return static_cast<sal_Int32>(Application::GetSettings().GetStyleSettings().GetMenuColor().GetColor()); +} + +} diff --git a/svtools/source/control/toolbarmenuimp.hxx b/svtools/source/control/toolbarmenuimp.hxx new file mode 100644 index 000000000000..d1de4f704b76 --- /dev/null +++ b/svtools/source/control/toolbarmenuimp.hxx @@ -0,0 +1,314 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <vos/mutex.hxx> +#include <vcl/image.hxx> +#include <vcl/menu.hxx> + +#include <cppuhelper/compbase4.hxx> +#include <cppuhelper/compbase5.hxx> +#include <comphelper/broadcasthelper.hxx> + +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleSelection.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +#include <rtl/ref.hxx> + +#include <vector> + +#include "framestatuslistener.hxx" + +#include "svtools/valueset.hxx" + +namespace svtools { + +struct ToolbarMenu_Impl; +class ToolbarMenu; +class ToolbarMenuEntry; + +typedef ::std::vector< ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener > > EventListenerVector; +typedef std::vector< ToolbarMenuEntry * > ToolbarMenuEntryVector; + +const int EXTRAITEMHEIGHT = 0; // 4; +const int SEPARATOR_HEIGHT = 4; +const int TITLE_ID = -1; +const int BORDER_X = 0; +const int BORDER_Y = 0; + +// -------------------- +// - ToolbarMenuEntry - +// -------------------- + +class ToolbarMenuEntry +{ +public: + ToolbarMenu& mrMenu; + + int mnEntryId; + MenuItemBits mnBits; + Size maSize; + + bool mbHasText; + bool mbHasImage; + bool mbChecked; + bool mbEnabled; + + String maText; + Image maImage; + Control* mpControl; + Rectangle maRect; + + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > mxAccContext; + +public: + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const String& rText, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, const Image& rImage, const String& rText, MenuItemBits nBits ); + ToolbarMenuEntry( ToolbarMenu& rMenu, int nEntryId, Control* pControl, MenuItemBits nBits ); + ~ToolbarMenuEntry(); + + void init( int nEntryId, MenuItemBits nBits ); + + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& GetAccessible( bool bCreate = false ); + + sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + bool HasCheck() const + { + return mbChecked || ( mnBits & ( MIB_RADIOCHECK | MIB_CHECKABLE | MIB_AUTOCHECK ) ); + } +}; + +// --------------- +// - ToolbarMenuAcc - +// --------------- + +typedef ::cppu::WeakComponentImplHelper5< + ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleSelection > + ToolbarMenuAccComponentBase; + +class ToolbarMenuAcc : + public ::comphelper::OBaseMutex, + public ToolbarMenuAccComponentBase +{ +public: + + ToolbarMenuAcc( ToolbarMenu_Impl& rParent ); + ~ToolbarMenuAcc(); + + void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + +public: + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::addEventListener; + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + using cppu::WeakComponentImplHelper5<com::sun::star::accessibility::XAccessible, com::sun::star::accessibility::XAccessibleEventBroadcaster, com::sun::star::accessibility::XAccessibleContext, com::sun::star::accessibility::XAccessibleComponent, com::sun::star::accessibility::XAccessibleSelection>::removeEventListener; + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleSelection + virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearAccessibleSelection( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectAllAccessibleChildren( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + DECL_LINK( WindowEventListener, VclSimpleEvent* ); + +private: + EventListenerVector mxEventListeners; + ToolbarMenu_Impl* mpParent; + /// The current FOCUSED state. + bool mbIsFocused; + + void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ); + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing (void); + + /** Check whether or not the object has been disposed (or is in the + state of beeing disposed). If that is the case then + DisposedException is thrown to inform the (indirect) caller of the + foul deed. + */ + void ThrowIfDisposed (void) throw (::com::sun::star::lang::DisposedException); +}; + +// ----------------------- +// - ToolbarMenuEntryAcc - +// ----------------------- + +typedef ::cppu::WeakComponentImplHelper4< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent > ToolbarMenuEntryAccBase; + +class ToolbarMenuEntryAcc : public ::comphelper::OBaseMutex, + public ToolbarMenuEntryAccBase +{ +public: + ToolbarMenuEntryAcc( ToolbarMenuEntry* pParent ); + ~ToolbarMenuEntryAcc(); + + void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + using ToolbarMenuEntryAccBase::addEventListener; + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + using ToolbarMenuEntryAccBase::removeEventListener; + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + +private: + EventListenerVector mxEventListeners; + ::vos::OMutex maMutex; + ToolbarMenuEntry* mpParent; + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing (void); +}; + +// ----------------------------------------------------------------------------- + +struct ToolbarMenu_Impl +{ + ToolbarMenu& mrMenu; + + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > mxFrame; + rtl::Reference< svt::FrameStatusListener > mxStatusListener; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxServiceManager; + rtl::Reference< ToolbarMenuAcc > mxAccessible; + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxOldSelection; + + ToolbarMenuEntryVector maEntryVector; + + int mnCheckPos; + int mnImagePos; + int mnTextPos; + + int mnHighlightedEntry; + int mnSelectedEntry; + int mnLastColumn; + + Size maSize; + + Link maSelectHdl; + + ToolbarMenu_Impl( ToolbarMenu& rMenu, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& xFrame ); + ~ToolbarMenu_Impl(); + + void setAccessible( ToolbarMenuAcc* pAccessible ); + + void fireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + bool hasAccessibleListeners(); + + sal_Int32 getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > getAccessibleChild( Control* pControl, sal_Int32 childIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + void selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + sal_Bool isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + void clearAccessibleSelection(); + + ToolbarMenuEntry* implGetEntry( int nEntry ) const; + void notifyHighlightedEntry(); + + void implHighlightControl( USHORT nCode, Control* pControl ); +}; + +} diff --git a/svtools/source/control/valueacc.cxx b/svtools/source/control/valueacc.cxx index 6712e75aa9b4..66da5636d89c 100644 --- a/svtools/source/control/valueacc.cxx +++ b/svtools/source/control/valueacc.cxx @@ -976,10 +976,7 @@ sal_Int16 SAL_CALL ValueItemAcc::getAccessibleRole() ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleDescription() throw (uno::RuntimeException) { - const vos::OGuard aSolarGuard( Application::GetSolarMutex() ); - String aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet item" ) ); - - return aRet; + return ::rtl::OUString(); } // ----------------------------------------------------------------------------- @@ -1239,7 +1236,7 @@ sal_Int32 SAL_CALL ValueItemAcc::getBackground( ) throw (uno::RuntimeException) { UINT32 nColor; - if (mpParent->meType == VALUESETITEM_COLOR) + if (mpParent && mpParent->meType == VALUESETITEM_COLOR) nColor = mpParent->maColor.GetColor(); else nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor(); diff --git a/svtools/source/control/valueimp.hxx b/svtools/source/control/valueimp.hxx index f74cdf00a4db..abde4a015ab8 100644..100755 --- a/svtools/source/control/valueimp.hxx +++ b/svtools/source/control/valueimp.hxx @@ -111,6 +111,7 @@ struct ValueSet_Impl { ::std::auto_ptr< ValueItemList > mpItemList; bool mbIsTransientChildrenDisabled; + Link maHighlightHdl; ValueSet_Impl() : mpItemList( ::std::auto_ptr< ValueItemList >( new ValueItemList() ) ), mbIsTransientChildrenDisabled( false ) diff --git a/svtools/source/control/valueset.cxx b/svtools/source/control/valueset.cxx index bb48c11c7c0b..62193eadf735 100644 --- a/svtools/source/control/valueset.cxx +++ b/svtools/source/control/valueset.cxx @@ -1418,7 +1418,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) { USHORT nLastItem = (USHORT)mpImpl->mpItemList->Count(); USHORT nItemPos = VALUESET_ITEM_NOTFOUND; - USHORT nCurPos; + USHORT nCurPos = VALUESET_ITEM_NONEITEM; USHORT nCalcPos; if ( !nLastItem || !ImplGetFirstItem() ) @@ -1431,8 +1431,6 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) if ( mnSelItemId ) nCurPos = GetItemPos( mnSelItemId ); - else - nCurPos = VALUESET_ITEM_NONEITEM; nCalcPos = nCurPos; //switch off selection mode if key travelling is used @@ -1528,30 +1526,20 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nCalcPos - ( nLineCount * mnCols )); else { - if( (KEY_UP == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) ) + if ( mpNoneItem ) { - Window* pParent = GetParent(); - pParent->GrabFocus(); - pParent->KeyInput( rKEvt ); - break; + mnCurCol = nCalcPos%mnCols; + nItemPos = VALUESET_ITEM_NONEITEM; } else { - if ( mpNoneItem ) - { - mnCurCol = nCalcPos%mnCols; - nItemPos = VALUESET_ITEM_NONEITEM; - } + if ( nLastItem+1 <= mnCols ) + nItemPos = nCalcPos; else { - if ( nLastItem+1 <= mnCols ) - nItemPos = nCalcPos; - else - { - nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(nCalcPos%mnCols); - if ( nItemPos+mnCols <= nLastItem ) - nItemPos = nItemPos + mnCols; - } + nItemPos = ((((nLastItem+1)/mnCols)-1)*mnCols)+(nCalcPos%mnCols); + if ( nItemPos+mnCols <= nLastItem ) + nItemPos = nItemPos + mnCols; } } } @@ -1580,6 +1568,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nCalcPos + ( nLineCount * mnCols )); else { +#if 0 if( (KEY_DOWN == rKEvt.GetKeyCode().GetCode() ) && (GetStyle() & WB_MENUSTYLEVALUESET) ) { Window* pParent = GetParent(); @@ -1588,6 +1577,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) break; } else +#endif { if ( mpNoneItem ) { @@ -1620,7 +1610,6 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) bDefault = TRUE; break; } - if(!bDefault) EndSelection(); if ( nItemPos != VALUESET_ITEM_NOTFOUND ) @@ -1630,6 +1619,7 @@ void ValueSet::KeyInput( const KeyEvent& rKEvt ) nItemId = GetItemId( nItemPos ); else nItemId = 0; + if ( nItemId != mnSelItemId ) { SelectItem( nItemId ); @@ -2278,6 +2268,7 @@ void ValueSet::SelectItem( USHORT nItemId ) ::com::sun::star::uno::Any aOldAny, aNewAny; ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); } + mpImpl->maHighlightHdl.Call(this); } } @@ -2749,3 +2740,19 @@ bool ValueSet::IsRTLActive (void) return Application::GetSettings().GetLayoutRTL() && IsRTLEnabled(); } +// ----------------------------------------------------------------------- + +void ValueSet::SetHighlightHdl( const Link& rLink ) +{ + mpImpl->maHighlightHdl = rLink; +} + +// ----------------------------------------------------------------------- + +const Link& ValueSet::GetHighlightHdl() const +{ + return mpImpl->maHighlightHdl; +} + +// ----------------------------------------------------------------------- + diff --git a/svtools/source/dialogs/addresstemplate.cxx b/svtools/source/dialogs/addresstemplate.cxx index 2849ddb71d10..9a66230f012c 100644 --- a/svtools/source/dialogs/addresstemplate.cxx +++ b/svtools/source/dialogs/addresstemplate.cxx @@ -36,7 +36,7 @@ #include "addresstemplate.hrc" #endif #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #ifndef _SVT_HELPID_HRC #include <svtools/helpid.hrc> diff --git a/svtools/source/dialogs/addresstemplate.src b/svtools/source/dialogs/addresstemplate.src index f4812f8b7566..0652dfb9d0f5 100644 --- a/svtools/source/dialogs/addresstemplate.src +++ b/svtools/source/dialogs/addresstemplate.src @@ -26,7 +26,7 @@ ************************************************************************/ #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #ifndef _SVT_ADDRESSTEMPLATE_HRC_ #include "addresstemplate.hrc" diff --git a/svtools/source/dialogs/printdlg.hrc b/svtools/source/dialogs/printdlg.hrc index ef780acbb47c..83b7b0b28c82 100644 --- a/svtools/source/dialogs/printdlg.hrc +++ b/svtools/source/dialogs/printdlg.hrc @@ -25,7 +25,7 @@ * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define FL_PRINTER 1 #define LB_NAMES 2 diff --git a/svtools/source/dialogs/prnsetup.hrc b/svtools/source/dialogs/prnsetup.hrc index 7d10c4652d45..4a06c3cf0e63 100644 --- a/svtools/source/dialogs/prnsetup.hrc +++ b/svtools/source/dialogs/prnsetup.hrc @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define FL_PRINTER 1 #define LB_NAMES 2 diff --git a/svtools/source/dialogs/roadmapwizard.cxx b/svtools/source/dialogs/roadmapwizard.cxx index 2c71e60e8101..c28cfe1d4b18 100644 --- a/svtools/source/dialogs/roadmapwizard.cxx +++ b/svtools/source/dialogs/roadmapwizard.cxx @@ -29,7 +29,7 @@ #include "precompiled_svtools.hxx" #include <svtools/roadmapwizard.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <svtools/svtdata.hxx> #include "roadmap.hxx" #include <tools/debug.hxx> @@ -182,7 +182,21 @@ namespace svt ,m_pImpl( new RoadmapWizardImpl ) { DBG_CTOR( RoadmapWizard, CheckInvariants ); + impl_construct(); + } + + //-------------------------------------------------------------------- + RoadmapWizard::RoadmapWizard( Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags ) + :OWizardMachine( _pParent, i_nStyle, _nButtonFlags ) + ,m_pImpl( new RoadmapWizardImpl ) + { + DBG_CTOR( RoadmapWizard, CheckInvariants ); + impl_construct(); + } + //-------------------------------------------------------------------- + void RoadmapWizard::impl_construct() + { SetLeftAlignedButtonCount( 1 ); SetEmptyViewMargin(); @@ -328,15 +342,16 @@ namespace svt if ( (sal_Int32)aNewPathPos->second.size() <= nCurrentStatePathIndex ) return; -#if OSL_DEBUG_LEVEL > 0 // assert that the current and the new path are equal, up to nCurrentStatePathIndex Paths::const_iterator aActivePathPos = m_pImpl->aPaths.find( m_pImpl->nActivePath ); if ( aActivePathPos != m_pImpl->aPaths.end() ) { - DBG_ASSERT( m_pImpl->getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) > nCurrentStatePathIndex, - "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" ); + if ( m_pImpl->getFirstDifferentIndex( aActivePathPos->second, aNewPathPos->second ) <= nCurrentStatePathIndex ) + { + OSL_ENSURE( false, "RoadmapWizard::activate: you cannot activate a path which conflicts with the current one *before* the current state!" ); + return; + } } -#endif m_pImpl->nActivePath = _nPathId; m_pImpl->bActivePathIsDefinite = _bDecideForIt; @@ -383,8 +398,14 @@ namespace svt } // can we advance from the current page? - const OWizardPage* pCurrentPage = dynamic_cast< const OWizardPage* >( GetPage( getCurrentState() ) ); - const bool bCurrentPageCanAdvance = !pCurrentPage || pCurrentPage->canAdvance(); + bool bCurrentPageCanAdvance = true; + TabPage* pCurrentPage = GetPage( getCurrentState() ); + if ( pCurrentPage ) + { + const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); + OSL_ENSURE( pController != NULL, "RoadmapWizard::implUpdateRoadmap: no controller for the current page!" ); + bCurrentPageCanAdvance = !pController || pController->canAdvance(); + } // now, we have to remove all items after nCurrentStatePathIndex, and insert the items from the active // path, up to (excluding) nUpperStepBoundary @@ -641,11 +662,33 @@ namespace svt // if the state is currently in the roadmap, reflect it's new status m_pImpl->pRoadmap->EnableRoadmapItem( (RoadmapTypes::ItemId)_nState, _bEnable ); } + + //-------------------------------------------------------------------- + bool RoadmapWizard::knowsState( WizardState i_nState ) const + { + for ( Paths::const_iterator path = m_pImpl->aPaths.begin(); + path != m_pImpl->aPaths.end(); + ++path + ) + { + for ( WizardPath::const_iterator state = path->second.begin(); + state != path->second.end(); + ++state + ) + { + if ( *state == i_nState ) + return true; + } + } + return false; + } + //-------------------------------------------------------------------- bool RoadmapWizard::isStateEnabled( WizardState _nState ) const { return m_pImpl->aDisabledStates.find( _nState ) == m_pImpl->aDisabledStates.end(); } + //-------------------------------------------------------------------- void RoadmapWizard::Resize() { diff --git a/svtools/source/dialogs/wizardmachine.cxx b/svtools/source/dialogs/wizardmachine.cxx index 6a09f85036fd..2053da80019d 100644 --- a/svtools/source/dialogs/wizardmachine.cxx +++ b/svtools/source/dialogs/wizardmachine.cxx @@ -30,10 +30,11 @@ #include <svtools/wizardmachine.hxx> #include <svtools/helpid.hrc> #include <tools/debug.hxx> +#include <tools/diagnose_ex.h> #include <vcl/msgbox.hxx> #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif //......................................................................... @@ -101,7 +102,7 @@ namespace svt } //--------------------------------------------------------------------- - sal_Bool OWizardPage::commitPage( CommitPageReason ) + sal_Bool OWizardPage::commitPage( WizardTypes::CommitPageReason ) { return sal_True; } @@ -161,6 +162,25 @@ namespace svt ,m_pHelp(NULL) ,m_pImpl( new WizardMachineImplData ) { + implConstruct( _nButtonFlags ); + } + + //--------------------------------------------------------------------- + OWizardMachine::OWizardMachine(Window* _pParent, const WinBits i_nStyle, sal_uInt32 _nButtonFlags ) + :WizardDialog( _pParent, i_nStyle ) + ,m_pFinish(NULL) + ,m_pCancel(NULL) + ,m_pNextPage(NULL) + ,m_pPrevPage(NULL) + ,m_pHelp(NULL) + ,m_pImpl( new WizardMachineImplData ) + { + implConstruct( _nButtonFlags ); + } + + //--------------------------------------------------------------------- + void OWizardMachine::implConstruct( const sal_uInt32 _nButtonFlags ) + { m_pImpl->sTitleBase = GetText(); // create the buttons according to the wizard button flags @@ -225,8 +245,6 @@ namespace svt AddButton( m_pCancel, WIZARDDIALOG_BUTTON_STDOFFSET_X ); } - - } //--------------------------------------------------------------------- @@ -274,35 +292,42 @@ namespace svt } //--------------------------------------------------------------------- - void OWizardMachine::ActivatePage() + TabPage* OWizardMachine::GetOrCreatePage( const WizardState i_nState ) { - WizardDialog::ActivatePage(); - - WizardState nCurrentLevel = GetCurLevel(); - if (NULL == GetPage(nCurrentLevel)) + if ( NULL == GetPage( i_nState ) ) { - TabPage* pNewPage = createPage(nCurrentLevel); - DBG_ASSERT(pNewPage, "OWizardMachine::ActivatePage: invalid new page (NULL)!"); + TabPage* pNewPage = createPage( i_nState ); + DBG_ASSERT( pNewPage, "OWizardMachine::GetOrCreatePage: invalid new page (NULL)!" ); // fill up the page sequence of our base class (with dummies) - while (m_pImpl->nFirstUnknownPage < nCurrentLevel) + while ( m_pImpl->nFirstUnknownPage < i_nState ) { - AddPage(NULL); + AddPage( NULL ); ++m_pImpl->nFirstUnknownPage; } - if (m_pImpl->nFirstUnknownPage == nCurrentLevel) + if ( m_pImpl->nFirstUnknownPage == i_nState ) { // encountered this page number the first time - AddPage(pNewPage); + AddPage( pNewPage ); ++m_pImpl->nFirstUnknownPage; } else // already had this page - just change it - SetPage(nCurrentLevel, pNewPage); + SetPage( i_nState, pNewPage ); } + return GetPage( i_nState ); + } - enterState(nCurrentLevel); + //--------------------------------------------------------------------- + void OWizardMachine::ActivatePage() + { + WizardDialog::ActivatePage(); + + WizardState nCurrentLevel = GetCurLevel(); + GetOrCreatePage( nCurrentLevel ); + + enterState( nCurrentLevel ); } //--------------------------------------------------------------------- @@ -330,8 +355,10 @@ namespace svt if (m_pCancel && (_nWizardButtonFlags & WZB_CANCEL)) pNewDefButton = m_pCancel; - if (pNewDefButton) - defaultButton(pNewDefButton); + if ( pNewDefButton ) + defaultButton( pNewDefButton ); + else + implResetDefault( this ); } //--------------------------------------------------------------------- @@ -395,9 +422,10 @@ namespace svt void OWizardMachine::enterState(WizardState _nState) { // tell the page - IWizardPage* pCurrentPage = getWizardPage(GetPage(_nState)); - if ( pCurrentPage ) - pCurrentPage->initializePage(); + IWizardPageController* pController = getPageController( GetPage( _nState ) ); + OSL_ENSURE( pController, "OWizardMachine::enterState: no controller for the given page!" ); + if ( pController ) + pController->initializePage(); if ( isAutomaticNextButtonStateEnabled() ) enableButtons( WZB_NEXT, canAdvance() ); @@ -419,9 +447,9 @@ namespace svt } //--------------------------------------------------------------------- - sal_Bool OWizardMachine::onFinish(sal_Int32 _nResult) + sal_Bool OWizardMachine::onFinish() { - return Finnish(_nResult); + return Finnish( RET_OK ); } //--------------------------------------------------------------------- @@ -434,8 +462,7 @@ namespace svt { return 0L; } - long nRet = onFinish( RET_OK ); - return nRet; + return onFinish() ? 1L : 0L; } //--------------------------------------------------------------------- @@ -447,10 +474,9 @@ namespace svt //--------------------------------------------------------------------- sal_Bool OWizardMachine::prepareLeaveCurrentState( CommitPageReason _eReason ) { - IWizardPage* pCurrentPage = getWizardPage(GetPage(getCurrentState())); - if ( pCurrentPage ) - return pCurrentPage->commitPage( _eReason ); - return sal_True; + IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); + ENSURE_OR_RETURN( pController != NULL, "OWizardMachine::prepareLeaveCurrentState: no controller for the current page!", sal_True ); + return pController->commitPage( _eReason ); } //--------------------------------------------------------------------- @@ -664,10 +690,10 @@ namespace svt } //--------------------------------------------------------------------- - IWizardPage* OWizardMachine::getWizardPage(TabPage* _pCurrentPage) const + IWizardPageController* OWizardMachine::getPageController( TabPage* _pCurrentPage ) const { - OWizardPage* pPage = dynamic_cast< OWizardPage* >( _pCurrentPage ); - return pPage; + IWizardPageController* pController = dynamic_cast< IWizardPageController* >( _pCurrentPage ); + return pController; } //--------------------------------------------------------------------- @@ -690,11 +716,12 @@ namespace svt //--------------------------------------------------------------------- void OWizardMachine::updateTravelUI() { - OWizardPage* pPage = dynamic_cast< OWizardPage* >( GetPage( getCurrentState() ) ); + const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) ); + OSL_ENSURE( pController != NULL, "RoadmapWizard::updateTravelUI: no controller for the current page!" ); bool bCanAdvance = - ( !pPage || pPage->canAdvance() ) // the current page allows to advance - && canAdvance(); // the dialog as a whole allows to advance + ( !pController || pController->canAdvance() ) // the current page allows to advance + && canAdvance(); // the dialog as a whole allows to advance enableButtons( WZB_NEXT, bCanAdvance ); } diff --git a/svtools/source/dialogs/wizardmachine.src b/svtools/source/dialogs/wizardmachine.src index c3570335773f..9c82ea30071f 100644 --- a/svtools/source/dialogs/wizardmachine.src +++ b/svtools/source/dialogs/wizardmachine.src @@ -26,7 +26,7 @@ ************************************************************************/ #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif String STR_WIZDLG_FINISH diff --git a/svtools/source/filter.vcl/filter/dlgejpg.hrc b/svtools/source/filter.vcl/filter/dlgejpg.hrc index 523a1d9553f1..90a3c1d162be 100644 --- a/svtools/source/filter.vcl/filter/dlgejpg.hrc +++ b/svtools/source/filter.vcl/filter/dlgejpg.hrc @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define BTN_OK 1 #define BTN_CANCEL 1 diff --git a/svtools/source/filter.vcl/filter/dlgepng.hrc b/svtools/source/filter.vcl/filter/dlgepng.hrc index 4a05771534ab..b3ffaab3ab1e 100644 --- a/svtools/source/filter.vcl/filter/dlgepng.hrc +++ b/svtools/source/filter.vcl/filter/dlgepng.hrc @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define BTN_OK 1 #define BTN_CANCEL 1 diff --git a/svtools/source/filter.vcl/filter/dlgexpor.hrc b/svtools/source/filter.vcl/filter/dlgexpor.hrc index 2e5377ce4fcb..69870c9b00b0 100644 --- a/svtools/source/filter.vcl/filter/dlgexpor.hrc +++ b/svtools/source/filter.vcl/filter/dlgexpor.hrc @@ -24,7 +24,7 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define BTN_OK_PIX 1 #define BTN_CANCEL_PIX 1 diff --git a/svtools/source/filter.vcl/filter/filter.cxx b/svtools/source/filter.vcl/filter/filter.cxx index e8121f1d7e94..c8a79d3a35cd 100644 --- a/svtools/source/filter.vcl/filter/filter.cxx +++ b/svtools/source/filter.vcl/filter/filter.cxx @@ -992,7 +992,8 @@ namespace { struct Cache : public rtl::Static<ImpFilterLibCache, Cache> {}; } // ----------------- GraphicFilter::GraphicFilter( sal_Bool bConfig ) : - bUseConfig ( bConfig ) + bUseConfig ( bConfig ), + nExpGraphHint ( 0 ) { ImplInit(); } @@ -1678,6 +1679,7 @@ USHORT GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& rPat USHORT nFormatCount = GetExportFormatCount(); ResetLastError(); + nExpGraphHint = 0; if( nFormat == GRFILTER_FORMAT_DONTKNOW ) { @@ -1850,8 +1852,10 @@ USHORT GraphicFilter::ExportGraphic( const Graphic& rGraphic, const String& rPat } else if( aFilterName.EqualsIgnoreCaseAscii( EXP_JPEG ) ) { - if( !ExportJPEG( rOStm, aGraphic, pFilterData ) ) + bool bExportedGrayJPEG = false; + if( !ExportJPEG( rOStm, aGraphic, pFilterData, &bExportedGrayJPEG ) ) nStatus = GRFILTER_FORMATERROR; + nExpGraphHint = bExportedGrayJPEG ? GRFILTER_OUTHINT_GREY : 0; if( rOStm.GetError() ) nStatus = GRFILTER_IOERROR; diff --git a/svtools/source/filter.vcl/filter/strings.hrc b/svtools/source/filter.vcl/filter/strings.hrc index ac162bff09f4..0eea67fb2338 100644 --- a/svtools/source/filter.vcl/filter/strings.hrc +++ b/svtools/source/filter.vcl/filter/strings.hrc @@ -24,4 +24,4 @@ * for a copy of the LGPLv3 License. * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> diff --git a/svtools/source/filter.vcl/jpeg/jpeg.cxx b/svtools/source/filter.vcl/jpeg/jpeg.cxx index 7fd2e09a82dd..a2de92171af3 100644 --- a/svtools/source/filter.vcl/jpeg/jpeg.cxx +++ b/svtools/source/filter.vcl/jpeg/jpeg.cxx @@ -590,10 +590,11 @@ ReadState JPEGReader::Read( Graphic& rGraphic ) // - JPEGWriter - // -------------- -JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData ) : +JPEGWriter::JPEGWriter( SvStream& rStm, const uno::Sequence< beans::PropertyValue >* pFilterData, bool* pExportWasGrey ) : rOStm ( rStm ), pAcc ( NULL ), - pBuffer ( NULL ) + pBuffer ( NULL ), + pExpWasGrey ( pExportWasGrey ) { FilterConfigItem aConfigItem( (uno::Sequence< beans::PropertyValue >*)pFilterData ); bGreys = aConfigItem.ReadInt32( String( RTL_CONSTASCII_USTRINGPARAM( "ColorMode" ) ), 0 ) != 0; @@ -704,6 +705,9 @@ BOOL JPEGWriter::Write( const Graphic& rGraphic ) bGreys = sal_True; } + if( pExpWasGrey ) + *pExpWasGrey = bGreys; + if( pAcc ) { bNative = ( pAcc->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ); @@ -765,8 +769,11 @@ BOOL ImportJPEG( SvStream& rStm, Graphic& rGraphic, void* pCallerData, sal_Int32 // - ExportJPEG - // -------------- -BOOL ExportJPEG( SvStream& rOStm, const Graphic& rGraphic, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ) +BOOL ExportJPEG( SvStream& rOStm, const Graphic& rGraphic, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData, + bool* pExportWasGrey + ) { - JPEGWriter aJPEGWriter( rOStm, pFilterData ); + JPEGWriter aJPEGWriter( rOStm, pFilterData, pExportWasGrey ); return aJPEGWriter.Write( rGraphic ); } diff --git a/svtools/source/inc/iodlg.hrc b/svtools/source/inc/iodlg.hrc index 918e47f849b4..e78e3fb687fe 100644 --- a/svtools/source/inc/iodlg.hrc +++ b/svtools/source/inc/iodlg.hrc @@ -29,7 +29,7 @@ #define _SVTOOLS_IODLGIMPL_HRC #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif // ModalDialog DLG_SVT_EXPLORERFILE diff --git a/svtools/source/inc/jpeg.hxx b/svtools/source/inc/jpeg.hxx index 906bcd9ea2de..9923190c5e21 100644 --- a/svtools/source/inc/jpeg.hxx +++ b/svtools/source/inc/jpeg.hxx @@ -99,13 +99,16 @@ class JPEGWriter sal_Bool bGreys; sal_Int32 nQuality; + bool* pExpWasGrey; + com::sun::star::uno::Reference< com::sun::star::task::XStatusIndicator > xStatusIndicator; public: void* GetScanline( long nY ); - JPEGWriter( SvStream& rOStm, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ); + JPEGWriter( SvStream& rOStm, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData, + bool* pExportWasGrey = NULL ); ~JPEGWriter() {}; BOOL Write( const Graphic& rGraphic ); @@ -119,6 +122,10 @@ public: BOOL ImportJPEG( SvStream& rStream, Graphic& rGraphic, void* pCallerData, sal_Int32 nImportFlags ); -BOOL ExportJPEG( SvStream& rStream, const Graphic& rGraphic, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData ); +BOOL ExportJPEG( SvStream& rStream, + const Graphic& rGraphic, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >* pFilterData, + bool* pExportWasGrey = NULL + ); #endif // _JPEG_HXX diff --git a/svtools/source/inc/svimpbox.hxx b/svtools/source/inc/svimpbox.hxx index cde986b3cb7d..92b9f960b65c 100644 --- a/svtools/source/inc/svimpbox.hxx +++ b/svtools/source/inc/svimpbox.hxx @@ -340,7 +340,7 @@ public: const Size& GetOutputSize() const { return aOutputSize;} void KeyUp( BOOL bPageUp, BOOL bNotifyScroll = TRUE ); void KeyDown( BOOL bPageDown, BOOL bNotifyScroll = TRUE ); - void Command( const CommandEvent& rCEvt ); + bool Command( const CommandEvent& rCEvt ); void Invalidate(); void DestroyAnchor() { pAnchor=0; aSelEng.Reset(); } diff --git a/svtools/source/java/javaerror.src b/svtools/source/java/javaerror.src index e16992a3473d..d5990c05a663 100644 --- a/svtools/source/java/javaerror.src +++ b/svtools/source/java/javaerror.src @@ -25,7 +25,7 @@ * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> WarningBox WARNINGBOX_JAVANOTFOUND { diff --git a/svtools/source/java/javainteractionhandler.cxx b/svtools/source/java/javainteractionhandler.cxx index 3dde9c33cd48..ec34ed07f25d 100644 --- a/svtools/source/java/javainteractionhandler.cxx +++ b/svtools/source/java/javainteractionhandler.cxx @@ -30,7 +30,7 @@ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <tools/resid.hxx> #include <com/sun/star/task/XInteractionContinuation.hpp> #include <com/sun/star/task/XInteractionAbort.hpp> diff --git a/svtools/source/java/patchjavaerror.src b/svtools/source/java/patchjavaerror.src index e16992a3473d..d5990c05a663 100644 --- a/svtools/source/java/patchjavaerror.src +++ b/svtools/source/java/patchjavaerror.src @@ -25,7 +25,7 @@ * ************************************************************************/ -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> WarningBox WARNINGBOX_JAVANOTFOUND { diff --git a/svtools/source/misc/ehdl.cxx b/svtools/source/misc/ehdl.cxx index cf476098056b..bf9e87d33a74 100644 --- a/svtools/source/misc/ehdl.cxx +++ b/svtools/source/misc/ehdl.cxx @@ -42,7 +42,7 @@ #include <svtools/ehdl.hxx> #include <svtools/svtdata.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "sfxecode.hxx" //========================================================================= diff --git a/svtools/source/misc/ehdl.src b/svtools/source/misc/ehdl.src index 55ab99b93bdf..436e06b7f3c5 100644 --- a/svtools/source/misc/ehdl.src +++ b/svtools/source/misc/ehdl.src @@ -26,7 +26,7 @@ ************************************************************************/ #define __RSC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "sfxecode.hxx" // pragma ---------------------------------------------------------------- diff --git a/svtools/source/misc/embedhlp.cxx b/svtools/source/misc/embedhlp.cxx index f606e1e2e4b1..3aa0016c225e 100644 --- a/svtools/source/misc/embedhlp.cxx +++ b/svtools/source/misc/embedhlp.cxx @@ -30,7 +30,7 @@ #include <svtools/embedhlp.hxx> #include <svtools/filter.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <svtools/svtdata.hxx> #include <comphelper/embeddedobjectcontainer.hxx> diff --git a/svtools/source/misc/errtxt.src b/svtools/source/misc/errtxt.src index 4e9a316308e0..6c1a90ae6412 100644 --- a/svtools/source/misc/errtxt.src +++ b/svtools/source/misc/errtxt.src @@ -26,7 +26,7 @@ ************************************************************************/ #define __RSC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "sfxecode.hxx" // pragma ---------------------------------------------------------------- Resource RID_ERRCTX diff --git a/svtools/source/misc/helpagent.src b/svtools/source/misc/helpagent.src index c649c1f17a40..1f2eaaa291a3 100644 --- a/svtools/source/misc/helpagent.src +++ b/svtools/source/misc/helpagent.src @@ -26,7 +26,7 @@ ************************************************************************/ #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif Bitmap BMP_HELP_AGENT_IMAGE diff --git a/svtools/source/misc/helpagentwindow.cxx b/svtools/source/misc/helpagentwindow.cxx index 55800a213a2e..1d407bbdb611 100644 --- a/svtools/source/misc/helpagentwindow.cxx +++ b/svtools/source/misc/helpagentwindow.cxx @@ -36,7 +36,7 @@ #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #ifndef _SVT_HELPID_HRC #include <svtools/helpid.hrc> diff --git a/svtools/source/misc/imagemgr.cxx b/svtools/source/misc/imagemgr.cxx index 391ad02e6aa1..c02ebc4477c6 100644 --- a/svtools/source/misc/imagemgr.cxx +++ b/svtools/source/misc/imagemgr.cxx @@ -52,7 +52,7 @@ #include <rtl/logfile.hxx> #include <unotools/configmgr.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "imagemgr.hrc" #include <svtools/svtdata.hxx> #include <vos/mutex.hxx> diff --git a/svtools/source/misc/imagemgr.src b/svtools/source/misc/imagemgr.src index 0664cdc6bc87..cdc9f8da1c87 100644 --- a/svtools/source/misc/imagemgr.src +++ b/svtools/source/misc/imagemgr.src @@ -26,7 +26,7 @@ ************************************************************************/ // includes ****************************************************************** -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include "imagemgr.hrc" // images ******************************************************************** diff --git a/svtools/source/misc/imageresourceaccess.cxx b/svtools/source/misc/imageresourceaccess.cxx index a4f19d9e004a..436c3f721833 100644 --- a/svtools/source/misc/imageresourceaccess.cxx +++ b/svtools/source/misc/imageresourceaccess.cxx @@ -48,8 +48,6 @@ namespace svt { //........................................................................ -#define GRAPHOBJ_URLPREFIX "vnd.sun.star.GraphicObject:" - using namespace ::utl; using namespace ::comphelper; using namespace ::com::sun::star::io; @@ -141,8 +139,14 @@ namespace svt //-------------------------------------------------------------------- bool GraphicAccess::isSupportedURL( const ::rtl::OUString& _rURL ) { - ::rtl::OUString sIndicator( RTL_CONSTASCII_USTRINGPARAM( "private:resource/" ) ); - return ( ( _rURL.indexOf( sIndicator ) == 0 ) || ( _rURL.compareToAscii( GRAPHOBJ_URLPREFIX, RTL_CONSTASCII_LENGTH( GRAPHOBJ_URLPREFIX ) ) == 0 ) ); + if ( ( _rURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:resource/" ) ) == 0 ) + || ( _rURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:graphicrepository/" ) ) == 0 ) + || ( _rURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "private:standardimage/" ) ) == 0 ) + || ( _rURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.GraphicObject:" ) ) == 0 ) + || ( _rURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "vnd.sun.star.extension://" ) ) == 0 ) + ) + return true; + return false; } //-------------------------------------------------------------------- diff --git a/svtools/source/misc/langtab.cxx b/svtools/source/misc/langtab.cxx index b656dbf501c4..d1ff94572a99 100755..100644 --- a/svtools/source/misc/langtab.cxx +++ b/svtools/source/misc/langtab.cxx @@ -39,7 +39,7 @@ #include <i18npool/lang.h> #include <i18npool/mslangid.hxx> -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #include <svtools/svtdata.hxx> #include <svtools/langtab.hxx> #include <unotools/syslocale.hxx> diff --git a/svtools/source/misc/langtab.src b/svtools/source/misc/langtab.src index 39f9362e3940..1cb20d27fc12 100644 --- a/svtools/source/misc/langtab.src +++ b/svtools/source/misc/langtab.src @@ -26,7 +26,7 @@ ************************************************************************/ // include --------------------------------------------------------------- -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #define RSC_RESOURCE_USAGE 1 #include <i18npool/lang.h> @@ -138,7 +138,7 @@ StringArray STR_ARR_SVT_LANGUAGE_TABLE < "Lithuanian" ; LANGUAGE_LITHUANIAN ; > ; < "Macedonian" ; LANGUAGE_MACEDONIAN ; > ; < "Malay (Malaysia)" ; LANGUAGE_MALAY_MALAYSIA ; > ; - < "Malay (Brunei Darusalam)" ; LANGUAGE_MALAY_BRUNEI_DARUSSALAM ; > ; + < "Malay (Brunei Darussalam)" ; LANGUAGE_MALAY_BRUNEI_DARUSSALAM ; > ; < "Malayalam" ; LANGUAGE_MALAYALAM ; > ; < "Manipuri" ; LANGUAGE_MANIPURI ; > ; < "Marathi" ; LANGUAGE_MARATHI ; > ; diff --git a/svtools/source/misc/svtaccessiblefactory.cxx b/svtools/source/misc/svtaccessiblefactory.cxx index 1a8284642698..b20863db3208 100644..100755 --- a/svtools/source/misc/svtaccessiblefactory.cxx +++ b/svtools/source/misc/svtaccessiblefactory.cxx @@ -209,6 +209,24 @@ namespace svt { return NULL; } + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > + createAccessibleToolPanelDeck( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*i_rAccessibleParent*/, + ::svt::ToolPanelDeck& /*i_rPanelDeck*/ + ) + { + return NULL; + } + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > + createAccessibleToolPanelTabBar( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& /*i_rAccessibleParent*/, + ::svt::IToolPanelDeck& /*i_rPanelDeck*/, + ::svt::PanelTabBar& /*i_rTabBar*/ + ) + { + return NULL; + } }; //---------------------------------------------------------------- diff --git a/svtools/source/productregistration/productregistration.cxx b/svtools/source/productregistration/productregistration.cxx index 4a5db9cf47c4..39629f5c3f77 100644 --- a/svtools/source/productregistration/productregistration.cxx +++ b/svtools/source/productregistration/productregistration.cxx @@ -32,7 +32,7 @@ #include "unotools/regoptions.hxx" #include "registrationdlg.hxx" #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #include "cppuhelper/factory.hxx" #include <cppuhelper/implbase1.hxx> diff --git a/svtools/source/productregistration/registrationdlg.cxx b/svtools/source/productregistration/registrationdlg.cxx index 93b7e5c88462..460cedb060d1 100644 --- a/svtools/source/productregistration/registrationdlg.cxx +++ b/svtools/source/productregistration/registrationdlg.cxx @@ -32,7 +32,7 @@ #if 0 /* @@@ */ #include <svtools/svtdata.hxx> #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #endif /* @@@ */ diff --git a/svtools/source/productregistration/registrationdlg.src b/svtools/source/productregistration/registrationdlg.src index e0598ab05e60..c4cdcbcbe3ec 100644 --- a/svtools/source/productregistration/registrationdlg.src +++ b/svtools/source/productregistration/registrationdlg.src @@ -29,7 +29,7 @@ #include "registrationdlg.hrc" #endif #ifndef _SVTOOLS_HRC -#include <svl/svtools.hrc> +#include <svtools/svtools.hrc> #endif #ifndef _SVT_HELPID_HRC #include <svtools/helpid.hrc> diff --git a/svtools/source/table/tablecontrol.cxx b/svtools/source/table/tablecontrol.cxx index 418348c81b7d..1770bfd7dd02 100644 --- a/svtools/source/table/tablecontrol.cxx +++ b/svtools/source/table/tablecontrol.cxx @@ -76,6 +76,11 @@ namespace svt { namespace table aTableData->SetMouseButtonUpHdl( LINK( this, TableControl, ImplMouseButtonUpHdl ) ); aTableData->SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) ); m_pAccessTable.reset(new ::svt::table::AccessibleTableControl_Impl()); + + // by default, use the background as determined by the style settings + const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() ); + SetBackground( Wallpaper( aWindowColor ) ); + SetFillColor( aWindowColor ); } //-------------------------------------------------------------------- @@ -120,6 +125,39 @@ namespace svt { namespace table } } } + + + //-------------------------------------------------------------------- + void TableControl::StateChanged( StateChangedType i_nStateChange ) + { + Control::StateChanged( i_nStateChange ); + + // forward certain settings to the data window + switch ( i_nStateChange ) + { + case STATE_CHANGE_CONTROLBACKGROUND: + if ( IsControlBackground() ) + getDataWindow()->SetControlBackground( GetControlBackground() ); + else + getDataWindow()->SetControlBackground(); + break; + + case STATE_CHANGE_CONTROLFOREGROUND: + if ( IsControlForeground() ) + getDataWindow()->SetControlForeground( GetControlForeground() ); + else + getDataWindow()->SetControlForeground(); + break; + + case STATE_CHANGE_CONTROLFONT: + if ( IsControlFont() ) + getDataWindow()->SetControlFont( GetControlFont() ); + else + getDataWindow()->SetControlFont(); + break; + } + } + //-------------------------------------------------------------------- void TableControl::Resize() { @@ -175,6 +213,11 @@ namespace svt { namespace table return m_pImpl->goTo( _nColPos, _nRowPos ); } //-------------------------------------------------------------------- + void TableControl::clearSelection() + { + m_pImpl->clearSelection(); + } + //-------------------------------------------------------------------- void TableControl::InvalidateDataWindow(RowPos _nRowStart, RowPos _nRowEnd, bool _bRemoved) { Rectangle _rRect; @@ -401,7 +444,7 @@ void TableControl::FillAccessibleStateSet( } } -Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) +Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) const { return Control::GetWindowExtentsRelative( pRelativeWindow ); } diff --git a/svtools/source/table/tablecontrol_impl.cxx b/svtools/source/table/tablecontrol_impl.cxx index 1526dbdb778d..3288ab6a4284 100644 --- a/svtools/source/table/tablecontrol_impl.cxx +++ b/svtools/source/table/tablecontrol_impl.cxx @@ -1647,6 +1647,12 @@ namespace svt { namespace table { return m_nRowSelected; } + //-------------------------------------------------------------------- + void TableControl_Impl::clearSelection() + { + m_nRowSelected.clear(); + } + //-------------------------------------------------------------------- //------------------------------------------------------------------------------- void TableControl_Impl::removeSelectedRow(RowPos _nRowPos) { diff --git a/svtools/source/table/tablecontrol_impl.hxx b/svtools/source/table/tablecontrol_impl.hxx index 0a487c77c76c..12b518aa3578 100644 --- a/svtools/source/table/tablecontrol_impl.hxx +++ b/svtools/source/table/tablecontrol_impl.hxx @@ -204,6 +204,7 @@ namespace svt { namespace table /** updates the vector, which contains the selected rows after removing the row nRowPos*/ void removeSelectedRow(RowPos _nRowPos); void invalidateRows(); + void clearSelection(); // IAbstractTableControl virtual void hideCursor(); virtual void showCursor(); diff --git a/svtools/source/table/tabledatawindow.cxx b/svtools/source/table/tabledatawindow.cxx index e307071e2699..3245b7e84aac 100644 --- a/svtools/source/table/tabledatawindow.cxx +++ b/svtools/source/table/tabledatawindow.cxx @@ -47,6 +47,10 @@ namespace svt { namespace table ,m_rTableControl ( _rTableControl ) ,m_nRowAlreadySelected( -1 ) { + // by default, use the background as determined by the style settings + const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() ); + SetBackground( Wallpaper( aWindowColor ) ); + SetFillColor( aWindowColor ); } //-------------------------------------------------------------------- @@ -54,6 +58,7 @@ namespace svt { namespace table { m_rTableControl.doPaintContent( rUpdateRect ); } + //-------------------------------------------------------------------- void TableDataWindow::MouseMove( const MouseEvent& rMEvt ) { diff --git a/svtools/source/toolpanel/drawerlayouter.cxx b/svtools/source/toolpanel/drawerlayouter.cxx new file mode 100644 index 000000000000..040f33045fff --- /dev/null +++ b/svtools/source/toolpanel/drawerlayouter.cxx @@ -0,0 +1,305 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/drawerlayouter.hxx" +#include "toolpaneldrawer.hxx" + +#include <com/sun/star/accessibility/XAccessible.hpp> + +#include <comphelper/accimplaccess.hxx> +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::accessibility::XAccessible; + /** === end UNO using === **/ + + //================================================================================================================== + //= DrawerDeckLayouter + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + DrawerDeckLayouter::DrawerDeckLayouter( ::Window& i_rParentWindow, IToolPanelDeck& i_rPanels ) + :m_rParentWindow( i_rParentWindow ) + ,m_rPanelDeck( i_rPanels ) + ,m_aDrawers() + ,m_aLastKnownActivePanel() + { + m_rPanelDeck.AddListener( *this ); + + // simulate PanelInserted events for the panels which are already there + for ( size_t i=0; i<m_rPanelDeck.GetPanelCount(); ++i ) + PanelInserted( m_rPanelDeck.GetPanel( i ), i ); + } + + //------------------------------------------------------------------------------------------------------------------ + DrawerDeckLayouter::~DrawerDeckLayouter() + { + } + + //------------------------------------------------------------------------------------------------------------------ + IMPLEMENT_IREFERENCE( DrawerDeckLayouter ) + + //------------------------------------------------------------------------------------------------------------------ + Rectangle DrawerDeckLayouter::Layout( const Rectangle& i_rDeckPlayground ) + { + const size_t nPanelCount( m_rPanelDeck.GetPanelCount() ); + if ( nPanelCount == 0 ) + return i_rDeckPlayground; + + const int nWidth( i_rDeckPlayground.GetWidth() ); + ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() ); + if ( !aActivePanel ) + aActivePanel = m_aLastKnownActivePanel; + + // arrange the title bars which are *above* the active panel (or *all* if there is no active panel), plus + // the title bar of the active panel itself + Point aUpperDrawerPos( i_rDeckPlayground.TopLeft() ); + const size_t nUpperBound = !!aActivePanel ? *aActivePanel : nPanelCount - 1; + for ( size_t i=0; i<=nUpperBound; ++i ) + { + sal_uInt32 nDrawerHeight = m_aDrawers[i]->GetPreferredHeightPixel(); + m_aDrawers[i]->SetPosSizePixel( + aUpperDrawerPos, Size( nWidth, nDrawerHeight ) ); + aUpperDrawerPos.Move( 0, nDrawerHeight ); + } + + // arrange title bars which are below the active panel (or *none* if there is no active panel) + Point aLowerDrawerPos( i_rDeckPlayground.BottomLeft() ); + for ( size_t j = nPanelCount - 1; j > nUpperBound; --j ) + { + sal_uInt32 nDrawerHeight = m_aDrawers[j]->GetPreferredHeightPixel(); + m_aDrawers[j]->SetPosSizePixel( + Point( aLowerDrawerPos.X(), aLowerDrawerPos.Y() - nDrawerHeight + 1 ), + Size( nWidth, nDrawerHeight ) + ); + aLowerDrawerPos.Move( 0, -nDrawerHeight ); + } + + // fincally calculate the rectangle for the active panel + return Rectangle( + aUpperDrawerPos, + Size( nWidth, aLowerDrawerPos.Y() - aUpperDrawerPos.Y() + 1 ) + ); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::Destroy() + { + while ( !m_aDrawers.empty() ) + impl_removeDrawer( 0 ); + m_rPanelDeck.RemoveListener( *this ); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::SetFocusToPanelSelector() + { + const size_t nPanelCount( m_rPanelDeck.GetPanelCount() ); + if ( !nPanelCount ) + // nothing to focus + return; + ::boost::optional< size_t > aActivePanel( m_rPanelDeck.GetActivePanel() ); + if ( !aActivePanel ) + aActivePanel = 0; + ENSURE_OR_RETURN_VOID( *aActivePanel < m_aDrawers.size(), "DrawerDeckLayouter::SetFocusToPanelSelector: invalid active panel, or inconsistent drawers!" ); + m_aDrawers[ *aActivePanel ]->GrabFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + size_t DrawerDeckLayouter::GetAccessibleChildCount() const + { + return m_aDrawers.size(); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessible > DrawerDeckLayouter::GetAccessibleChild( const size_t i_nChildIndex, const Reference< XAccessible >& i_rParentAccessible ) + { + ENSURE_OR_RETURN( i_nChildIndex < m_aDrawers.size(), "illegal index", NULL ); + + const PToolPanelDrawer pDrawer( m_aDrawers[ i_nChildIndex ] ); + + Reference< XAccessible > xItemAccessible = pDrawer->GetAccessible( FALSE ); + if ( !xItemAccessible.is() ) + { + xItemAccessible = pDrawer->GetAccessible( TRUE ); + ENSURE_OR_RETURN( xItemAccessible.is(), "illegal accessible provided by the drawer implementation!", NULL ); + OSL_VERIFY( ::comphelper::OAccessibleImplementationAccess::setAccessibleParent( xItemAccessible->getAccessibleContext(), + i_rParentAccessible ) ); + } + + return xItemAccessible; + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + OSL_PRECOND( i_nPosition <= m_aDrawers.size(), "DrawerDeckLayouter::PanelInserted: inconsistency!" ); + + PToolPanelDrawer pDrawer( new ToolPanelDrawer( m_rParentWindow, i_pPanel->GetDisplayName() ) ); + pDrawer->SetSmartHelpId( i_pPanel->GetHelpID() ); + // proper Z-Order + if ( i_nPosition == 0 ) + { + pDrawer->SetZOrder( NULL, WINDOW_ZORDER_FIRST ); + } + else + { + const PToolPanelDrawer pFirstDrawer( m_aDrawers[ i_nPosition - 1 ] ); + pDrawer->SetZOrder( pFirstDrawer.get(), WINDOW_ZORDER_BEHIND ); + } + + pDrawer->Show(); + pDrawer->AddEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) ); + m_aDrawers.insert( m_aDrawers.begin() + i_nPosition, pDrawer ); + impl_triggerRearrange(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::PanelRemoved( const size_t i_nPosition ) + { + impl_removeDrawer( i_nPosition ); + impl_triggerRearrange(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::impl_triggerRearrange() const + { + // this is somewhat hacky, it assumes that the parent of our panels is a tool panel deck, which, in its + // Resize implementation, rearrances all elements. + m_rParentWindow.Resize(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) + { + if ( !!i_rOldActive ) + { + OSL_ENSURE( *i_rOldActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal old index!" ); + m_aDrawers[ *i_rOldActive ]->SetExpanded( false ); + } + + if ( !!i_rNewActive ) + { + OSL_ENSURE( *i_rNewActive < m_aDrawers.size(), "DrawerDeckLayouter::ActivePanelChanged: illegal new index!" ); + m_aDrawers[ *i_rNewActive ]->SetExpanded( true ); + } + + impl_triggerRearrange(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::LayouterChanged( const PDeckLayouter& i_rNewLayouter ) + { + // not interested in + (void)i_rNewLayouter; + } + + //------------------------------------------------------------------------------------------------------------------ + size_t DrawerDeckLayouter::impl_getPanelPositionFromWindow( const Window* i_pDrawerWindow ) const + { + for ( ::std::vector< PToolPanelDrawer >::const_iterator drawerPos = m_aDrawers.begin(); + drawerPos != m_aDrawers.end(); + ++drawerPos + ) + { + if ( drawerPos->get() == i_pDrawerWindow ) + return drawerPos - m_aDrawers.begin(); + } + return m_aDrawers.size(); + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::impl_removeDrawer( const size_t i_nPosition ) + { + OSL_PRECOND( i_nPosition < m_aDrawers.size(), "DrawerDeckLayouter::impl_removeDrawer: invalid panel position!" ); + m_aDrawers[ i_nPosition ]->RemoveEventListener( LINK( this, DrawerDeckLayouter, OnWindowEvent ) ); + OSL_ENSURE( m_aDrawers[ i_nPosition ].unique(), "DrawerDeckLayouter::impl_removeDrawer: somebody else is still holding a reference!" ); + m_aDrawers.erase( m_aDrawers.begin() + i_nPosition ); + } + + //------------------------------------------------------------------------------------------------------------------ + IMPL_LINK( DrawerDeckLayouter, OnWindowEvent, VclSimpleEvent*, i_pEvent ) + { + const VclWindowEvent* pWindowEvent = PTR_CAST( VclWindowEvent, i_pEvent ); + ENSURE_OR_RETURN( pWindowEvent, "no WindowEvent", 0L ); + + bool bActivatePanel = false; + switch ( pWindowEvent->GetId() ) + { + case VCLEVENT_WINDOW_MOUSEBUTTONUP: + { + const MouseEvent* pMouseEvent = static_cast< const MouseEvent* >( pWindowEvent->GetData() ); + ENSURE_OR_RETURN( pMouseEvent, "no mouse event with MouseButtonUp", 0L ); + if ( pMouseEvent->GetButtons() == MOUSE_LEFT ) + { + bActivatePanel = true; + } + } + break; + case VCLEVENT_WINDOW_KEYINPUT: + { + const KeyEvent* pKeyEvent = static_cast< const KeyEvent* >( pWindowEvent->GetData() ); + ENSURE_OR_RETURN( pKeyEvent, "no key event with KeyInput", 0L ); + const KeyCode& rKeyCode( pKeyEvent->GetKeyCode() ); + if ( ( rKeyCode.GetModifier() == 0 ) && ( rKeyCode.GetCode() == KEY_RETURN ) ) + { + bActivatePanel = true; + } + } + break; + } + if ( bActivatePanel ) + { + const size_t nPanelPos = impl_getPanelPositionFromWindow( pWindowEvent->GetWindow() ); + if ( nPanelPos != m_rPanelDeck.GetActivePanel() ) + { + m_rPanelDeck.ActivatePanel( nPanelPos ); + } + else + { + PToolPanel pPanel( m_rPanelDeck.GetPanel( nPanelPos ) ); + pPanel->GrabFocus(); + } + return 1L; + } + return 0L; + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerDeckLayouter::Dying() + { + Destroy(); + } + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/dummypanel.cxx b/svtools/source/toolpanel/dummypanel.cxx new file mode 100644 index 000000000000..20f140a6e610 --- /dev/null +++ b/svtools/source/toolpanel/dummypanel.cxx @@ -0,0 +1,107 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "dummypanel.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::accessibility::XAccessible; + + //==================================================================== + //= DummyPanel + //==================================================================== + //-------------------------------------------------------------------- + DummyPanel::DummyPanel() + { + } + + //-------------------------------------------------------------------- + DummyPanel::~DummyPanel() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( DummyPanel ) + + //-------------------------------------------------------------------- + void DummyPanel::Activate( Window& ) + { + } + + //-------------------------------------------------------------------- + void DummyPanel::Deactivate() + { + } + + //-------------------------------------------------------------------- + void DummyPanel::SetSizePixel( const Size& ) + { + } + + //-------------------------------------------------------------------- + ::rtl::OUString DummyPanel::GetDisplayName() const + { + return ::rtl::OUString(); + } + + //-------------------------------------------------------------------- + Image DummyPanel::GetImage() const + { + return Image(); + } + + //-------------------------------------------------------------------- + SmartId DummyPanel::GetHelpID() const + { + return SmartId(); + } + + //-------------------------------------------------------------------- + void DummyPanel::GrabFocus() + { + } + + //-------------------------------------------------------------------- + void DummyPanel::Dispose() + { + } + + //-------------------------------------------------------------------- + Reference< XAccessible > DummyPanel::CreatePanelAccessible( const Reference< XAccessible >& i_rParentAccessible ) + { + (void)i_rParentAccessible; + return NULL; + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/dummypanel.hxx b/svtools/source/toolpanel/dummypanel.hxx new file mode 100644 index 000000000000..adb98e52077e --- /dev/null +++ b/svtools/source/toolpanel/dummypanel.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef DUMMYPANEL_HXX +#define DUMMYPANEL_HXX + +#include "svtools/toolpanel/toolpanel.hxx" +#include "svtools/toolpanel/refbase.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= DummyPanel + //==================================================================== + /// is a dummy implementation of the IToolPanel interface + class DummyPanel :public RefBase + ,public IToolPanel + { + public: + DummyPanel(); + ~DummyPanel(); + + // IToolPanel + virtual ::rtl::OUString GetDisplayName() const; + virtual Image GetImage() const; + virtual SmartId GetHelpID() const; + virtual void Activate( Window& i_rParentWindow ); + virtual void Deactivate(); + virtual void SetSizePixel( const Size& i_rPanelWindowSize ); + virtual void GrabFocus(); + virtual void Dispose(); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > + CreatePanelAccessible( + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& i_rParentAccessible + ); + + DECLARE_IREFERENCE() + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // DUMMYPANEL_HXX diff --git a/svtools/source/toolpanel/makefile.mk b/svtools/source/toolpanel/makefile.mk new file mode 100755 index 000000000000..58282056f529 --- /dev/null +++ b/svtools/source/toolpanel/makefile.mk @@ -0,0 +1,68 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.16 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=svtools +TARGET=toolpanel + +# --- Settings ----------------------------------------------------- + +ENABLE_EXCEPTIONS=TRUE + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/svt.pmk + +# --- Files -------------------------------------------------------- + +SRS1NAME=$(TARGET) +SRC1FILES=\ + toolpanel.src + +SLOFILES=\ + $(SLO)$/drawerlayouter.obj \ + $(SLO)$/dummypanel.obj \ + $(SLO)$/paneldecklisteners.obj \ + $(SLO)$/paneltabbar.obj \ + $(SLO)$/paneltabbarpeer.obj \ + $(SLO)$/refbase.obj \ + $(SLO)$/tabbargeometry.obj \ + $(SLO)$/tablayouter.obj \ + $(SLO)$/toolpanel.obj \ + $(SLO)$/toolpanelcollection.obj \ + $(SLO)$/toolpaneldrawer.obj \ + $(SLO)$/toolpaneldrawerpeer.obj \ + $(SLO)$/toolpaneldeck.obj \ + $(SLO)$/toolpaneldeckpeer.obj \ + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/svtools/source/toolpanel/paneldecklisteners.cxx b/svtools/source/toolpanel/paneldecklisteners.cxx new file mode 100755 index 000000000000..32ba9b5c6a24 --- /dev/null +++ b/svtools/source/toolpanel/paneldecklisteners.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "paneldecklisteners.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= PanelDeckListeners + //==================================================================== + //-------------------------------------------------------------------- + PanelDeckListeners::PanelDeckListeners() + { + } + + //-------------------------------------------------------------------- + PanelDeckListeners::~PanelDeckListeners() + { + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + ::std::vector< IToolPanelDeckListener* > aListeners( m_aListeners ); + for ( ::std::vector< IToolPanelDeckListener* >::const_iterator loop = aListeners.begin(); + loop != aListeners.end(); + ++loop + ) + { + (*loop)->PanelInserted( i_pPanel, i_nPosition ); + } + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::PanelRemoved( const size_t i_nPosition ) + { + ::std::vector< IToolPanelDeckListener* > aListeners( m_aListeners ); + for ( ::std::vector< IToolPanelDeckListener* >::const_iterator loop = aListeners.begin(); + loop != aListeners.end(); + ++loop + ) + { + (*loop)->PanelRemoved( i_nPosition ); + } + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) + { + ::std::vector< IToolPanelDeckListener* > aListeners( m_aListeners ); + for ( ::std::vector< IToolPanelDeckListener* >::const_iterator loop = aListeners.begin(); + loop != aListeners.end(); + ++loop + ) + { + (*loop)->ActivePanelChanged( i_rOldActive, i_rNewActive ); + } + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::LayouterChanged( const PDeckLayouter& i_rNewLayouter ) + { + ::std::vector< IToolPanelDeckListener* > aListeners( m_aListeners ); + for ( ::std::vector< IToolPanelDeckListener* >::const_iterator loop = aListeners.begin(); + loop != aListeners.end(); + ++loop + ) + { + (*loop)->LayouterChanged( i_rNewLayouter ); + } + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::Dying() + { + while ( !m_aListeners.empty() ) + { + IToolPanelDeckListener* pListener( *m_aListeners.begin() ); + m_aListeners.erase( m_aListeners.begin() ); + pListener->Dying(); + } + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::AddListener( IToolPanelDeckListener& i_rListener ) + { + m_aListeners.push_back( &i_rListener ); + } + + //-------------------------------------------------------------------- + void PanelDeckListeners::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + for ( ::std::vector< IToolPanelDeckListener* >::iterator lookup = m_aListeners.begin(); + lookup != m_aListeners.end(); + ++lookup + ) + { + if ( *lookup == &i_rListener ) + { + m_aListeners.erase( lookup ); + return; + } + } + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/paneldecklisteners.hxx b/svtools/source/toolpanel/paneldecklisteners.hxx new file mode 100755 index 000000000000..bc7e2ae7db88 --- /dev/null +++ b/svtools/source/toolpanel/paneldecklisteners.hxx @@ -0,0 +1,72 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef PANELDECKLISTENERS_HXX +#define PANELDECKLISTENERS_HXX + +#include "svtools/toolpanel/toolpaneldeck.hxx" + +#include <boost/optional.hpp> +#include <vector> + +//........................................................................ +namespace svt +{ +//........................................................................ + + class IToolPanelDeckListener; + + //==================================================================== + //= PanelDeckListeners + //==================================================================== + /** implements a container for IToolPanelDeckListeners + */ + class PanelDeckListeners + { + public: + PanelDeckListeners(); + ~PanelDeckListeners(); + + // IToolPanelDeckListener equivalents, forward the events to all registered listeners + void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ); + void PanelRemoved( const size_t i_nPosition ); + void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ); + void LayouterChanged( const PDeckLayouter& i_rNewLayouter ); + void Dying(); + + // listener maintainance + void AddListener( IToolPanelDeckListener& i_rListener ); + void RemoveListener( IToolPanelDeckListener& i_rListener ); + + private: + ::std::vector< IToolPanelDeckListener* > m_aListeners; + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // PANELDECKLISTENERS_HXX diff --git a/svtools/source/toolpanel/paneltabbar.cxx b/svtools/source/toolpanel/paneltabbar.cxx new file mode 100755 index 000000000000..38aee00c8f55 --- /dev/null +++ b/svtools/source/toolpanel/paneltabbar.cxx @@ -0,0 +1,1356 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/paneltabbar.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" +#include "svtools/svtdata.hxx" +#include "svtools/svtools.hrc" + +#include "tabitemdescriptor.hxx" +#include "paneltabbarpeer.hxx" +#include "tabbargeometry.hxx" + +#include <vcl/button.hxx> +#include <vcl/help.hxx> +#include <vcl/virdev.hxx> +#include <tools/diagnose_ex.h> + +#include <boost/optional.hpp> +#include <vector> + +// space around an item +#define ITEM_OUTER_SPACE 2 * 3 +// spacing before and after an item's text +#define ITEM_TEXT_FLOW_SPACE 5 +// space between item icon and icon text +#define ITEM_ICON_TEXT_DISTANCE 4 + +//........................................................................ +namespace svt +{ +//........................................................................ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::awt::XWindowPeer; + + typedef sal_uInt16 ItemFlags; + + #define ITEM_STATE_NORMAL 0x00 + #define ITEM_STATE_ACTIVE 0x01 + #define ITEM_STATE_HOVERED 0x02 + #define ITEM_STATE_FOCUSED 0x04 + #define ITEM_POSITION_FIRST 0x08 + #define ITEM_POSITION_LAST 0x10 + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + ControlState lcl_ItemToControlState( const ItemFlags i_nItemFlags ) + { + ControlState nState = CTRL_STATE_ENABLED; + if ( i_nItemFlags & ITEM_STATE_FOCUSED ) nState |= CTRL_STATE_FOCUSED | CTRL_STATE_PRESSED; + if ( i_nItemFlags & ITEM_STATE_HOVERED ) nState |= CTRL_STATE_ROLLOVER; + if ( i_nItemFlags & ITEM_STATE_ACTIVE ) nState |= CTRL_STATE_SELECTED; + return nState; + } + } + + //================================================================================================================== + //= ITabBarRenderer + //================================================================================================================== + class SAL_NO_VTABLE ITabBarRenderer + { + public: + /** fills the background of our target device + */ + virtual void renderBackground() const = 0; + virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const = 0; + virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const = 0; + virtual void postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const = 0; + + // TODO: postRenderItem takes the "real" window, i.e. effectively the tab bar. This is because + // DrawSelectionBackground needs to be applied after everything else is painted, and is available at the Window + // class, but not at the OutputDevice. This makes the API somewhat weird, as we're now mixing operations on the + // target device, done in a normalized geometry, with operations on the window, done in a transformed geometry. + // So, we should get rid of postRenderItem completely. + }; + typedef ::boost::shared_ptr< ITabBarRenderer > PTabBarRenderer; + + //================================================================================================================== + //= VCLItemRenderer - declaration + //================================================================================================================== + class VCLItemRenderer : public ITabBarRenderer + { + public: + VCLItemRenderer( OutputDevice& i_rTargetDevice ) + :m_rTargetDevice( i_rTargetDevice ) + { + } + + // ITabBarRenderer + virtual void renderBackground() const; + virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const; + virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const; + virtual void postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const; + + protected: + OutputDevice& getTargetDevice() const { return m_rTargetDevice; } + + private: + OutputDevice& m_rTargetDevice; + }; + + //================================================================================================================== + //= VCLItemRenderer - implementation + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + void VCLItemRenderer::renderBackground() const + { + getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle VCLItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const + { + (void)i_nItemFlags; + // no decorations at all + return i_rContentArea; + } + + //------------------------------------------------------------------------------------------------------------------ + void VCLItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const + { + (void)i_rContentRect; + (void)i_nItemFlags; + } + + //------------------------------------------------------------------------------------------------------------------ + void VCLItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const + { + const bool bActive = ( ( i_nItemFlags & ITEM_STATE_ACTIVE ) != 0 ); + const bool bHovered = ( ( i_nItemFlags & ITEM_STATE_HOVERED ) != 0 ); + const bool bFocused = ( ( i_nItemFlags & ITEM_STATE_FOCUSED ) != 0 ); + if ( bActive || bHovered || bFocused ) + { + Rectangle aSelectionRect( i_rItemRect ); + aSelectionRect.Left() += ITEM_OUTER_SPACE / 2; + aSelectionRect.Top() += ITEM_OUTER_SPACE / 2; + aSelectionRect.Right() -= ITEM_OUTER_SPACE / 2; + aSelectionRect.Bottom() -= ITEM_OUTER_SPACE / 2; + i_rActualWindow.DrawSelectionBackground( + aSelectionRect, + ( bHovered || bFocused ) ? ( bActive ? 1 : 2 ) : 0 /* hilight */, + bActive /* check */, + TRUE /* border */, + FALSE /* ext border only */, + 0 /* corner radius */, + NULL, + NULL + ); + } + } + + //================================================================================================================== + //= NWFToolboxItemRenderer - declaration + //================================================================================================================== + class NWFToolboxItemRenderer : public ITabBarRenderer + { + public: + NWFToolboxItemRenderer( OutputDevice& i_rTargetDevice ) + :m_rTargetDevice( i_rTargetDevice ) + { + } + + // ITabBarRenderer + virtual void renderBackground() const; + virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const; + virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const; + virtual void postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const; + + protected: + OutputDevice& getTargetDevice() const { return m_rTargetDevice; } + + private: + OutputDevice& m_rTargetDevice; + }; + + //================================================================================================================== + //= NWFToolboxItemRenderer - implementation + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + void NWFToolboxItemRenderer::renderBackground() const + { + getTargetDevice().DrawRect( Rectangle( Point(), getTargetDevice().GetOutputSizePixel() ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle NWFToolboxItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const + { + // don't ask GetNativeControlRegion, this will not deliver proper results in all cases. + // Instead, simply assume that both the content and the bounding region are the same. +// const ControlState nState( lcl_ItemToControlState( i_nItemFlags ); +// const ImplControlValue aControlValue; +// bool bNativeOK = m_rTargetWindow.GetNativeControlRegion( +// CTRL_TOOLBAR, PART_BUTTON, +// i_rContentArea, nState, +// aControlValue, ::rtl::OUString(), +// aBoundingRegion, aContentRegion +// ); + (void)i_nItemFlags; + return Rectangle( + Point( i_rContentArea.Left() - 1, i_rContentArea.Top() - 1 ), + Size( i_rContentArea.GetWidth() + 2, i_rContentArea.GetHeight() + 2 ) + ); + } + + //------------------------------------------------------------------------------------------------------------------ + void NWFToolboxItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const + { + const ControlState nState = lcl_ItemToControlState( i_nItemFlags ); + + ImplControlValue aControlValue; + aControlValue.setTristateVal( ( i_nItemFlags & ITEM_STATE_ACTIVE ) ? BUTTONVALUE_ON : BUTTONVALUE_OFF ); + + bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TOOLBAR, PART_BUTTON, i_rContentRect, nState, aControlValue, rtl::OUString() ); + (void)bNativeOK; + OSL_ENSURE( bNativeOK, "NWFToolboxItemRenderer::preRenderItem: inconsistent NWF implementation!" ); + // IsNativeControlSupported returned true, previously, otherwise we would not be here ... + } + + //------------------------------------------------------------------------------------------------------------------ + void NWFToolboxItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const + { + (void)i_rActualWindow; + (void)i_rItemRect; + (void)i_nItemFlags; + } + + //================================================================================================================== + //= NWFTabItemRenderer - declaration + //================================================================================================================== + class NWFTabItemRenderer : public ITabBarRenderer + { + public: + NWFTabItemRenderer( OutputDevice& i_rTargetDevice ) + :m_rTargetDevice( i_rTargetDevice ) + { + } + + // ITabBarRenderer + virtual void renderBackground() const; + virtual Rectangle calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const; + virtual void preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const; + virtual void postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const; + + protected: + OutputDevice& getTargetDevice() const { return m_rTargetDevice; } + + private: + OutputDevice& m_rTargetDevice; + }; + + //================================================================================================================== + //= NWFTabItemRenderer - implementation + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + void NWFTabItemRenderer::renderBackground() const + { + Rectangle aBackground( Point(), getTargetDevice().GetOutputSizePixel() ); + getTargetDevice().DrawRect( aBackground ); + + aBackground.Top() = aBackground.Bottom(); + getTargetDevice().DrawNativeControl( CTRL_TAB_PANE, PART_ENTIRE_CONTROL, aBackground, + CTRL_STATE_ENABLED, ImplControlValue(), ::rtl::OUString() ); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle NWFTabItemRenderer::calculateDecorations( const Rectangle& i_rContentArea, const ItemFlags i_nItemFlags ) const + { + const ControlState nState( lcl_ItemToControlState( i_nItemFlags ) ); + + TabitemValue tiValue; + ImplControlValue aControlValue( (void*)(&tiValue) ); + + Region aBoundingRegion, aContentRegion; + bool bNativeOK = getTargetDevice().GetNativeControlRegion( + CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, + i_rContentArea, nState, + aControlValue, ::rtl::OUString(), + aBoundingRegion, aContentRegion + ); + (void)bNativeOK; + OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::calculateDecorations: GetNativeControlRegion not implemented for CTRL_TAB_ITEM?!" ); + + return aBoundingRegion.GetBoundRect(); + } + + //------------------------------------------------------------------------------------------------------------------ + void NWFTabItemRenderer::preRenderItem( const Rectangle& i_rContentRect, const ItemFlags i_nItemFlags ) const + { + const ControlState nState = lcl_ItemToControlState( i_nItemFlags ); + + TabitemValue tiValue; + if ( i_nItemFlags & ITEM_POSITION_FIRST ) + tiValue.mnAlignment |= TABITEM_FIRST_IN_GROUP; + if ( i_nItemFlags & ITEM_POSITION_LAST ) + tiValue.mnAlignment |= TABITEM_LAST_IN_GROUP; + + ImplControlValue aControlValue( (void *)(&tiValue) ); + + bool bNativeOK = getTargetDevice().DrawNativeControl( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL, i_rContentRect, nState, aControlValue, rtl::OUString() ); + (void)bNativeOK; + OSL_ENSURE( bNativeOK, "NWFTabItemRenderer::preRenderItem: inconsistent NWF implementation!" ); + // IsNativeControlSupported returned true, previously, otherwise we would not be here ... + } + + //------------------------------------------------------------------------------------------------------------------ + void NWFTabItemRenderer::postRenderItem( Window& i_rActualWindow, const Rectangle& i_rItemRect, const ItemFlags i_nItemFlags ) const + { + (void)i_rActualWindow; + (void)i_rItemRect; + (void)i_nItemFlags; + } + + //================================================================================================================== + //= PanelTabBar_Impl + //================================================================================================================== + class PanelTabBar_Impl : public IToolPanelDeckListener + { + public: + PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent ); + + ~PanelTabBar_Impl() + { + m_rPanelDeck.RemoveListener( *this ); + } + + // IToolPanelDeckListener + virtual void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + (void)i_pPanel; + (void)i_nPosition; + m_bItemsDirty = true; + m_rTabBar.Invalidate(); + + Relayout(); + } + + virtual void PanelRemoved( const size_t i_nPosition ) + { + m_bItemsDirty = true; + m_rTabBar.Invalidate(); + + if ( i_nPosition < m_nScrollPosition ) + --m_nScrollPosition; + + Relayout(); + } + + virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ); + virtual void LayouterChanged( const PDeckLayouter& i_rNewLayouter ); + virtual void Dying(); + + void UpdateScrollButtons() + { + m_aScrollBack.Enable( m_nScrollPosition > 0 ); + m_aScrollForward.Enable( m_nScrollPosition < m_aItems.size() - 1 ); + } + + void Relayout(); + void EnsureItemsCache(); + ::boost::optional< size_t > FindItemForPoint( const Point& i_rPoint ) const; + void DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const; + void InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags = 0 ) const; + void CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const; + Rectangle GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const; + Rectangle GetItemScreenRect( const size_t i_nItemPos ) const; + + void FocusItem( const ::boost::optional< size_t >& i_rItemPos ); + + inline bool IsVertical() const + { + return ( ( m_eTabAlignment == TABS_LEFT ) + || ( m_eTabAlignment == TABS_RIGHT ) + ); + } + + protected: + DECL_LINK( OnScroll, const PushButton* ); + + void impl_calcItemRects(); + Size impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const; + void impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const; + ItemFlags impl_getItemFlags( const size_t i_nItemIndex ) const; + + public: + PanelTabBar& m_rTabBar; + TabBarGeometry m_aGeometry; + NormalizedArea m_aNormalizer; + TabAlignment m_eTabAlignment; + IToolPanelDeck& m_rPanelDeck; + + VirtualDevice m_aRenderDevice; + PTabBarRenderer m_pRenderer; + + ::boost::optional< size_t > m_aHoveredItem; + ::boost::optional< size_t > m_aFocusedItem; + bool m_bMouseButtonDown; + + ItemDescriptors m_aItems; + bool m_bItemsDirty; + + PushButton m_aScrollBack; + PushButton m_aScrollForward; + + size_t m_nScrollPosition; + }; + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + #if OSL_DEBUG_LEVEL > 0 + static void lcl_checkConsistency( const PanelTabBar_Impl& i_rImpl ) + { + if ( !i_rImpl.m_bItemsDirty ) + { + if ( i_rImpl.m_rPanelDeck.GetPanelCount() != i_rImpl.m_aItems.size() ) + { + OSL_ENSURE( false, "lcl_checkConsistency: inconsistent array sizes!" ); + return; + } + for ( size_t i = 0; i < i_rImpl.m_rPanelDeck.GetPanelCount(); ++i ) + { + if ( i_rImpl.m_rPanelDeck.GetPanel( i ).get() != i_rImpl.m_aItems[i].pPanel.get() ) + { + OSL_ENSURE( false, "lcl_checkConsistency: array elements are inconsistent!" ); + return; + } + } + } + } + + #define DBG_CHECK( data ) \ + lcl_checkConsistency( data ); + #else + #define DBG_CHECK( data ) \ + (void)data; + #endif + + //-------------------------------------------------------------------------------------------------------------- + class ClipItemRegion + { + public: + ClipItemRegion( const PanelTabBar_Impl& i_rImpl ) + :m_rDevice( i_rImpl.m_rTabBar ) + { + m_rDevice.Push( PUSH_CLIPREGION ); + m_rDevice.SetClipRegion( i_rImpl.m_aNormalizer.getTransformed( i_rImpl.m_aGeometry.getItemsRect(), i_rImpl.m_eTabAlignment ) ); + } + + ~ClipItemRegion() + { + m_rDevice.Pop(); + } + + private: + OutputDevice& m_rDevice; + }; + } + + //================================================================================================================== + //= PanelTabBar_Impl - implementation + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + PanelTabBar_Impl::PanelTabBar_Impl( PanelTabBar& i_rTabBar, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent ) + :m_rTabBar( i_rTabBar ) + ,m_aGeometry( i_eItemContent ) + ,m_aNormalizer() + ,m_eTabAlignment( i_eAlignment ) + ,m_rPanelDeck( i_rPanelDeck ) + ,m_aRenderDevice( i_rTabBar ) + ,m_pRenderer() + ,m_aHoveredItem() + ,m_aFocusedItem() + ,m_bMouseButtonDown( false ) + ,m_aItems() + ,m_bItemsDirty( true ) + ,m_aScrollBack( &i_rTabBar, WB_BEVELBUTTON ) + ,m_aScrollForward( &i_rTabBar, WB_BEVELBUTTON ) + ,m_nScrollPosition( 0 ) + { +#ifdef WNT + if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TAB_ITEM, PART_ENTIRE_CONTROL ) ) + // this mode requires the NWF framework to be able to render those items onto a virtual + // device. For some frameworks (some GTK themes, in particular), this is known to fail. + // So, be on the safe side for the moment. + m_pRenderer.reset( new NWFTabItemRenderer( m_aRenderDevice ) ); + else +#endif + if ( m_aRenderDevice.IsNativeControlSupported( CTRL_TOOLBAR, PART_BUTTON ) ) + m_pRenderer.reset( new NWFToolboxItemRenderer( m_aRenderDevice ) ); + else + m_pRenderer.reset( new VCLItemRenderer( m_aRenderDevice ) ); + + m_aRenderDevice.SetLineColor(); + + m_rPanelDeck.AddListener( *this ); + + m_aScrollBack.SetSymbol( IsVertical() ? SYMBOL_ARROW_UP : SYMBOL_ARROW_LEFT ); + m_aScrollBack.Show(); + m_aScrollBack.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) ); + m_aScrollBack.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_FWD ) ) ); + m_aScrollBack.SetAccessibleName( m_aScrollBack.GetAccessibleDescription() ); + + m_aScrollForward.SetSymbol( IsVertical() ? SYMBOL_ARROW_DOWN : SYMBOL_ARROW_RIGHT ); + m_aScrollForward.Show(); + m_aScrollForward.SetClickHdl( LINK( this, PanelTabBar_Impl, OnScroll ) ); + m_aScrollForward.SetAccessibleDescription( String( SvtResId( STR_SVT_TOOL_PANEL_BUTTON_BACK ) ) ); + m_aScrollForward.SetAccessibleName( m_aScrollForward.GetAccessibleDescription() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::impl_calcItemRects() + { + m_aItems.resize(0); + + Point aCompletePos( m_aGeometry.getFirstItemPosition() ); + Point aIconOnlyPos( aCompletePos ); + Point aTextOnlyPos( aCompletePos ); + + for ( size_t i = 0; + i < m_rPanelDeck.GetPanelCount(); + ++i + ) + { + PToolPanel pPanel( m_rPanelDeck.GetPanel( i ) ); + + ItemDescriptor aItem; + aItem.pPanel = pPanel; + + Rectangle aContentArea; + + const Size aCompleteSize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_AND_TEXT ) ); + const Size aIconOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_IMAGE_ONLY ) ); + const Size aTextOnlySize( impl_calculateItemContentSize( pPanel, TABITEM_TEXT_ONLY ) ); + + // TODO: have one method calculating all sizes? + + // remember the three areas + aItem.aCompleteArea = Rectangle( aCompletePos, aCompleteSize ); + aItem.aIconOnlyArea = Rectangle( aIconOnlyPos, aIconOnlySize ); + aItem.aTextOnlyArea = Rectangle( aTextOnlyPos, aTextOnlySize ); + + m_aItems.push_back( aItem ); + + aCompletePos = aItem.aCompleteArea.TopRight(); + aIconOnlyPos = aItem.aIconOnlyArea.TopRight(); + aTextOnlyPos = aItem.aTextOnlyArea.TopRight(); + } + + m_bItemsDirty = false; + } + + //------------------------------------------------------------------------------------------------------------------ + Size PanelTabBar_Impl::impl_calculateItemContentSize( const PToolPanel& i_pPanel, const TabItemContent i_eItemContent ) const + { + // calculate the size needed for the content + OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_calculateItemContentSize: illegal TabItemContent value!" ); + + const Image aImage( i_pPanel->GetImage() ); + const bool bUseImage = !!aImage && ( i_eItemContent != TABITEM_TEXT_ONLY ); + + const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() ); + const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY ); + + Size aItemContentSize; + if ( bUseImage ) + { + aItemContentSize = aImage.GetSizePixel(); + } + + if ( bUseText ) + { + if ( bUseImage ) + aItemContentSize.Width() += ITEM_ICON_TEXT_DISTANCE; + + // add space for text + const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() ); + aItemContentSize.Width() += aTextSize.Width(); + aItemContentSize.Height() = ::std::max( aItemContentSize.Height(), aTextSize.Height() ); + + aItemContentSize.Width() += 2 * ITEM_TEXT_FLOW_SPACE; + } + + if ( !bUseImage && !bUseText ) + { + // have a minimal size - this is pure heuristics, but if it doesn't suit your needs, then give your panels + // a name and or image! :) + aItemContentSize = Size( 16, 16 ); + } + + aItemContentSize.Width() += 2 * ITEM_OUTER_SPACE; + aItemContentSize.Height() += 2 * ITEM_OUTER_SPACE; + + return aItemContentSize; + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::impl_renderItemContent( const PToolPanel& i_pPanel, const Rectangle& i_rContentArea, const TabItemContent i_eItemContent ) const + { + OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "PanelTabBar_Impl::impl_renderItemContent: illegal TabItemContent value!" ); + + Rectangle aRenderArea( i_rContentArea ); + if ( IsVertical() ) + { + aRenderArea.Top() += ITEM_OUTER_SPACE; + } + else + { + aRenderArea.Left() += ITEM_OUTER_SPACE; + } + + // draw the image + const Image aItemImage( i_pPanel->GetImage() ); + const Size aImageSize( aItemImage.GetSizePixel() ); + const bool bUseImage = !!aItemImage && ( i_eItemContent != TABITEM_TEXT_ONLY ); + + if ( bUseImage ) + { + Point aImagePos; + if ( IsVertical() ) + { + aImagePos.X() = aRenderArea.Left() + ( aRenderArea.GetWidth() - aImageSize.Width() ) / 2; + aImagePos.Y() = aRenderArea.Top(); + } + else + { + aImagePos.X() = aRenderArea.Left(); + aImagePos.Y() = aRenderArea.Top() + ( aRenderArea.GetHeight() - aImageSize.Height() ) / 2; + } + m_rTabBar.DrawImage( aImagePos, aItemImage ); + } + + const ::rtl::OUString sItemText( i_pPanel->GetDisplayName() ); + const bool bUseText = ( sItemText.getLength() != 0 ) && ( i_eItemContent != TABITEM_IMAGE_ONLY ); + + if ( bUseText ) + { + if ( IsVertical() ) + { + if ( bUseImage ) + aRenderArea.Top() += aImageSize.Height() + ITEM_ICON_TEXT_DISTANCE; + aRenderArea.Top() += ITEM_TEXT_FLOW_SPACE; + } + else + { + if ( bUseImage ) + aRenderArea.Left() += aImageSize.Width() + ITEM_ICON_TEXT_DISTANCE; + aRenderArea.Left() += ITEM_TEXT_FLOW_SPACE; + } + + // draw the text + const Size aTextSize( m_rTabBar.GetCtrlTextWidth( sItemText ), m_rTabBar.GetTextHeight() ); + Point aTextPos( aRenderArea.TopLeft() ); + if ( IsVertical() ) + { + m_rTabBar.Push( PUSH_FONT ); + + Font aFont( m_rTabBar.GetFont() ); + aFont.SetOrientation( 2700 ); + aFont.SetVertical( TRUE ); + m_rTabBar.SetFont( aFont ); + + aTextPos.X() += aTextSize.Height(); + aTextPos.X() += ( aRenderArea.GetWidth() - aTextSize.Height() ) / 2; + } + else + { + aTextPos.Y() += ( aRenderArea.GetHeight() - aTextSize.Height() ) / 2; + } + + m_rTabBar.DrawText( aTextPos, sItemText ); + + if ( IsVertical() ) + { + m_rTabBar.Pop(); + } + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::CopyFromRenderDevice( const Rectangle& i_rLogicalRect ) const + { + BitmapEx aBitmap( m_aRenderDevice.GetBitmapEx( + i_rLogicalRect.TopLeft(), + Size( + i_rLogicalRect.GetSize().Width(), + i_rLogicalRect.GetSize().Height() + ) + ) ); + if ( IsVertical() ) + { + aBitmap.Rotate( 2700, COL_BLACK ); + if ( m_eTabAlignment == TABS_LEFT ) + aBitmap.Mirror( BMP_MIRROR_HORZ ); + } + else if ( m_eTabAlignment == TABS_BOTTOM ) + { + aBitmap.Mirror( BMP_MIRROR_VERT ); + } + + const Rectangle aActualRect( m_aNormalizer.getTransformed( i_rLogicalRect, m_eTabAlignment ) ); + m_rTabBar.DrawBitmapEx( aActualRect.TopLeft(), aBitmap ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::InvalidateItem( const size_t i_nItemIndex, const ItemFlags i_nAdditionalItemFlags ) const + { + const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] ); + const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) | i_nAdditionalItemFlags ); + + const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) ); + const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) ); + + const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment ); + m_rTabBar.Invalidate( aActualBounds ); + } + + //------------------------------------------------------------------------------------------------------------------ + ItemFlags PanelTabBar_Impl::impl_getItemFlags( const size_t i_nItemIndex ) const + { + ItemFlags nItemFlags( ITEM_STATE_NORMAL ); + if ( m_aHoveredItem == i_nItemIndex ) + { + nItemFlags |= ITEM_STATE_HOVERED; + if ( m_bMouseButtonDown ) + nItemFlags |= ITEM_STATE_ACTIVE; + } + + if ( m_rPanelDeck.GetActivePanel() == i_nItemIndex ) + nItemFlags |= ITEM_STATE_ACTIVE; + + if ( m_aFocusedItem == i_nItemIndex ) + nItemFlags |= ITEM_STATE_FOCUSED; + + if ( 0 == i_nItemIndex ) + nItemFlags |= ITEM_POSITION_FIRST; + + if ( m_rPanelDeck.GetPanelCount() - 1 == i_nItemIndex ) + nItemFlags |= ITEM_POSITION_LAST; + + return nItemFlags; + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::DrawItem( const size_t i_nItemIndex, const Rectangle& i_rBoundaries ) const + { + const ItemDescriptor& rItem( m_aItems[ i_nItemIndex ] ); + const ItemFlags nItemFlags( impl_getItemFlags( i_nItemIndex ) ); + + // the normalized bounding and content rect + const Rectangle aNormalizedContent( GetActualLogicalItemRect( rItem.GetCurrentRect() ) ); + const Rectangle aNormalizedBounds( m_pRenderer->calculateDecorations( aNormalizedContent, nItemFlags ) ); + + // check whether the item actually overlaps with the painting area + if ( !i_rBoundaries.IsEmpty() ) + { + const Rectangle aItemRect( GetActualLogicalItemRect( rItem.GetCurrentRect() ) ); + if ( !aItemRect.IsOver( i_rBoundaries ) ) + return; + } + + m_rTabBar.SetUpdateMode( FALSE ); + + // the aligned bounding and content rect + const Rectangle aActualBounds = m_aNormalizer.getTransformed( aNormalizedBounds, m_eTabAlignment ); + const Rectangle aActualContent = m_aNormalizer.getTransformed( aNormalizedContent, m_eTabAlignment ); + + // render item "background" layer + m_pRenderer->preRenderItem( aNormalizedContent, nItemFlags ); + + // copy from the virtual device to ourself + CopyFromRenderDevice( aNormalizedBounds ); + + // render the actual item content + impl_renderItemContent( rItem.pPanel, aActualContent, rItem.eContent ); + + // render item "foreground" layer + m_pRenderer->postRenderItem( m_rTabBar, aActualBounds, nItemFlags ); + + m_rTabBar.SetUpdateMode( TRUE ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::EnsureItemsCache() + { + if ( m_bItemsDirty == false ) + { + DBG_CHECK( *this ); + return; + } + impl_calcItemRects(); + OSL_POSTCOND( m_bItemsDirty == false, "PanelTabBar_Impl::EnsureItemsCache: cache still dirty!" ); + DBG_CHECK( *this ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::Relayout() + { + EnsureItemsCache(); + + const Size aOutputSize( m_rTabBar.GetOutputSizePixel() ); + m_aNormalizer = NormalizedArea( Rectangle( Point(), aOutputSize ), IsVertical() ); + const Size aLogicalOutputSize( m_aNormalizer.getReferenceSize() ); + + // forward actual output size to our render device + m_aRenderDevice.SetOutputSizePixel( aLogicalOutputSize ); + + // re-calculate the size of the scroll buttons and of the items + m_aGeometry.relayout( aLogicalOutputSize, m_aItems ); + + if ( m_aGeometry.getButtonBackRect().IsEmpty() ) + { + m_aScrollBack.Hide(); + } + else + { + const Rectangle aButtonBack( m_aNormalizer.getTransformed( m_aGeometry.getButtonBackRect(), m_eTabAlignment ) ); + m_aScrollBack.SetPosSizePixel( aButtonBack.TopLeft(), aButtonBack.GetSize() ); + m_aScrollBack.Show(); + } + + if ( m_aGeometry.getButtonForwardRect().IsEmpty() ) + { + m_aScrollForward.Hide(); + } + else + { + const Rectangle aButtonForward( m_aNormalizer.getTransformed( m_aGeometry.getButtonForwardRect(), m_eTabAlignment ) ); + m_aScrollForward.SetPosSizePixel( aButtonForward.TopLeft(), aButtonForward.GetSize() ); + m_aScrollForward.Show(); + } + + UpdateScrollButtons(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::boost::optional< size_t > PanelTabBar_Impl::FindItemForPoint( const Point& i_rPoint ) const + { + Point aPoint( IsVertical() ? i_rPoint.Y() : i_rPoint.X(), IsVertical() ? i_rPoint.X() : i_rPoint.Y() ); + + if ( !m_aGeometry.getItemsRect().IsInside( aPoint ) ) + return ::boost::optional< size_t >(); + + size_t i=0; + for ( ItemDescriptors::const_iterator item = m_aItems.begin(); + item != m_aItems.end(); + ++item, ++i + ) + { + Rectangle aItemRect( GetActualLogicalItemRect( item->GetCurrentRect() ) ); + if ( aItemRect.IsInside( aPoint ) ) + { + return ::boost::optional< size_t >( i ); + } + } + return ::boost::optional< size_t >(); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle PanelTabBar_Impl::GetItemScreenRect( const size_t i_nItemPos ) const + { + ENSURE_OR_RETURN( i_nItemPos < m_aItems.size(), "PanelTabBar_Impl::GetItemScreenRect: invalid item pos!", Rectangle() ); + const ItemDescriptor& rItem( m_aItems[ i_nItemPos ] ); + const Rectangle aItemRect( m_aNormalizer.getTransformed( + GetActualLogicalItemRect( rItem.GetCurrentRect() ), + m_eTabAlignment ) ); + + const Rectangle aTabBarRect( m_rTabBar.GetWindowExtentsRelative( NULL ) ); + return Rectangle( + Point( aTabBarRect.Left() + aItemRect.Left(), aTabBarRect.Top() + aItemRect.Top() ), + aItemRect.GetSize() + ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::FocusItem( const ::boost::optional< size_t >& i_rItemPos ) + { + // reset old focus item + if ( !!m_aFocusedItem ) + InvalidateItem( *m_aFocusedItem ); + m_aFocusedItem.reset(); + + // mark the active icon as focused + if ( !!i_rItemPos ) + { + m_aFocusedItem = i_rItemPos; + InvalidateItem( *m_aFocusedItem ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + IMPL_LINK( PanelTabBar_Impl, OnScroll, const PushButton*, i_pButton ) + { + if ( i_pButton == &m_aScrollBack ) + { + OSL_ENSURE( m_nScrollPosition > 0, "PanelTabBar_Impl::OnScroll: inconsistency!" ); + --m_nScrollPosition; + m_rTabBar.Invalidate(); + } + else if ( i_pButton == &m_aScrollForward ) + { + OSL_ENSURE( m_nScrollPosition < m_aItems.size() - 1, "PanelTabBar_Impl::OnScroll: inconsistency!" ); + ++m_nScrollPosition; + m_rTabBar.Invalidate(); + } + + UpdateScrollButtons(); + + return 0L; + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle PanelTabBar_Impl::GetActualLogicalItemRect( const Rectangle& i_rLogicalItemRect ) const + { + // care for the offset imposed by our geometry, i.e. whether or not we have scroll buttons + Rectangle aItemRect( i_rLogicalItemRect ); + aItemRect.Move( m_aGeometry.getItemsRect().Left() - m_aGeometry.getButtonBackRect().Left(), 0 ); + + // care for the current scroll position + OSL_ENSURE( m_nScrollPosition < m_aItems.size(), "GetActualLogicalItemRect: invalid scroll position!" ); + if ( ( m_nScrollPosition > 0 ) && ( m_nScrollPosition < m_aItems.size() ) ) + { + long nOffsetX = m_aItems[ m_nScrollPosition ].GetCurrentRect().Left() - m_aItems[ 0 ].GetCurrentRect().Left(); + long nOffsetY = m_aItems[ m_nScrollPosition ].GetCurrentRect().Top() - m_aItems[ 0 ].GetCurrentRect().Top(); + aItemRect.Move( -nOffsetX, -nOffsetY ); + } + + return aItemRect; + } + + //================================================================================================================== + //= PanelTabBar_Impl + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) + { + EnsureItemsCache(); + + if ( !!i_rOldActive ) + InvalidateItem( *i_rOldActive, ITEM_STATE_ACTIVE ); + if ( !!i_rNewActive ) + InvalidateItem( *i_rNewActive ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::LayouterChanged( const PDeckLayouter& i_rNewLayouter ) + { + // not interested in + (void)i_rNewLayouter; + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar_Impl::Dying() + { + // not interested in - the notifier is a member of this instance here, so we're dying ourself at the moment + } + + //================================================================================================================== + //= PanelTabBar + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + PanelTabBar::PanelTabBar( Window& i_rParentWindow, IToolPanelDeck& i_rPanelDeck, const TabAlignment i_eAlignment, const TabItemContent i_eItemContent ) + :Control( &i_rParentWindow, 0 ) + ,m_pImpl( new PanelTabBar_Impl( *this, i_rPanelDeck, i_eAlignment, i_eItemContent ) ) + { + DBG_CHECK( *m_pImpl ); + } + + //------------------------------------------------------------------------------------------------------------------ + PanelTabBar::~PanelTabBar() + { + } + + //------------------------------------------------------------------------------------------------------------------ + TabItemContent PanelTabBar::GetTabItemContent() const + { + return m_pImpl->m_aGeometry.getItemContent(); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::SetTabItemContent( const TabItemContent& i_eItemContent ) + { + m_pImpl->m_aGeometry.setItemContent( i_eItemContent ); + m_pImpl->Relayout(); + Invalidate(); + } + + //------------------------------------------------------------------------------------------------------------------ + IToolPanelDeck& PanelTabBar::GetPanelDeck() const + { + DBG_CHECK( *m_pImpl ); + return m_pImpl->m_rPanelDeck; + } + + //------------------------------------------------------------------------------------------------------------------ + Size PanelTabBar::GetOptimalSize( WindowSizeType i_eType ) const + { + m_pImpl->EnsureItemsCache(); + Size aOptimalSize( m_pImpl->m_aGeometry.getOptimalSize( m_pImpl->m_aItems, i_eType == WINDOWSIZE_MINIMUM ) ); + if ( m_pImpl->IsVertical() ) + ::std::swap( aOptimalSize.Width(), aOptimalSize.Height() ); + return aOptimalSize; + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::Resize() + { + Control::Resize(); + m_pImpl->Relayout(); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::Paint( const Rectangle& i_rRect ) + { + m_pImpl->EnsureItemsCache(); + + // background + const Rectangle aNormalizedPaintArea( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) ); + m_pImpl->m_aRenderDevice.Push( PUSH_CLIPREGION ); + m_pImpl->m_aRenderDevice.SetClipRegion( aNormalizedPaintArea ); + m_pImpl->m_pRenderer->renderBackground(); + m_pImpl->m_aRenderDevice.Pop(); + m_pImpl->CopyFromRenderDevice( aNormalizedPaintArea ); + + // ensure the items really paint into their own playground only + ClipItemRegion aClipItems( *m_pImpl ); + + const Rectangle aLogicalPaintRect( m_pImpl->m_aNormalizer.getNormalized( i_rRect, m_pImpl->m_eTabAlignment ) ); + + const ::boost::optional< size_t > aActivePanel( m_pImpl->m_rPanelDeck.GetActivePanel() ); + const ::boost::optional< size_t > aHoveredPanel( m_pImpl->m_aHoveredItem ); + + // items: + // 1. paint all non-active, non-hovered items + size_t i=0; + for ( ItemDescriptors::const_iterator item = m_pImpl->m_aItems.begin(); + item != m_pImpl->m_aItems.end(); + ++item, ++i + ) + { + if ( i == aActivePanel ) + continue; + + if ( aHoveredPanel == i ) + continue; + + m_pImpl->DrawItem( i, aLogicalPaintRect ); + } + + // 2. paint the item which is hovered, /without/ the mouse button pressed down + if ( !!aHoveredPanel && !m_pImpl->m_bMouseButtonDown ) + m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect ); + + // 3. paint the active item + if ( !!aActivePanel ) + m_pImpl->DrawItem( *aActivePanel, aLogicalPaintRect ); + + // 4. paint the item which is hovered, /with/ the mouse button pressed down + if ( !!aHoveredPanel && m_pImpl->m_bMouseButtonDown ) + m_pImpl->DrawItem( *aHoveredPanel, aLogicalPaintRect ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseMove( const MouseEvent& i_rMouseEvent ) + { + m_pImpl->EnsureItemsCache(); + + ::boost::optional< size_t > aOldItem( m_pImpl->m_aHoveredItem ); + ::boost::optional< size_t > aNewItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) ); + + if ( i_rMouseEvent.IsLeaveWindow() ) + aNewItem.reset(); + + if ( aOldItem != aNewItem ) + { + if ( !!aOldItem ) + m_pImpl->InvalidateItem( *aOldItem ); + + m_pImpl->m_aHoveredItem = aNewItem; + + if ( !!aNewItem ) + m_pImpl->InvalidateItem( *aNewItem ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseButtonDown( const MouseEvent& i_rMouseEvent ) + { + Control::MouseButtonDown( i_rMouseEvent ); + + if ( !i_rMouseEvent.IsLeft() ) + return; + + m_pImpl->EnsureItemsCache(); + + ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) ); + if ( !aHitItem ) + return; + + CaptureMouse(); + m_pImpl->m_bMouseButtonDown = true; + + m_pImpl->InvalidateItem( *aHitItem ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::MouseButtonUp( const MouseEvent& i_rMouseEvent ) + { + Control::MouseButtonUp( i_rMouseEvent ); + + if ( m_pImpl->m_bMouseButtonDown ) + { + ::boost::optional< size_t > aHitItem( m_pImpl->FindItemForPoint( i_rMouseEvent.GetPosPixel() ) ); + if ( !!aHitItem ) + { + // re-draw that item now that we're not in mouse-down mode anymore + m_pImpl->InvalidateItem( *aHitItem ); + // activate the respective panel + m_pImpl->m_rPanelDeck.ActivatePanel( *aHitItem ); + } + + OSL_ENSURE( IsMouseCaptured(), "PanelTabBar::MouseButtonUp: inconsistency!" ); + if ( IsMouseCaptured() ) + ReleaseMouse(); + m_pImpl->m_bMouseButtonDown = false; + } + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::RequestHelp( const HelpEvent& i_rHelpEvent ) + { + m_pImpl->EnsureItemsCache(); + + ::boost::optional< size_t > aHelpItem( m_pImpl->FindItemForPoint( ScreenToOutputPixel( i_rHelpEvent.GetMousePosPixel() ) ) ); + if ( !aHelpItem ) + return; + + const ItemDescriptor& rItem( m_pImpl->m_aItems[ *aHelpItem ] ); + if ( rItem.eContent != TABITEM_IMAGE_ONLY ) + // if the text is displayed for the item, we do not need to show it as tooltip + return; + + const ::rtl::OUString sItemText( rItem.pPanel->GetDisplayName() ); + if ( i_rHelpEvent.GetMode() == HELPMODE_BALLOON ) + Help::ShowBalloon( this, OutputToScreenPixel( rItem.GetCurrentRect().Center() ), rItem.GetCurrentRect(), sItemText ); + else + Help::ShowQuickHelp( this, rItem.GetCurrentRect(), sItemText ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::GetFocus() + { + Control::GetFocus(); + if ( !m_pImpl->m_aFocusedItem ) + m_pImpl->FocusItem( m_pImpl->m_rPanelDeck.GetActivePanel() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::LoseFocus() + { + Control::LoseFocus(); + + if ( !!m_pImpl->m_aFocusedItem ) + { + m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem ); + } + + m_pImpl->m_aFocusedItem.reset(); + } + + //------------------------------------------------------------------------------------------------------------------ + class KeyInputHandler + { + public: + KeyInputHandler( Control& i_rControl, const KeyEvent& i_rKeyEvent ) + :m_rControl( i_rControl ) + ,m_rKeyEvent( i_rKeyEvent ) + ,m_bHandled( false ) + { + } + + ~KeyInputHandler() + { + if ( !m_bHandled ) + m_rControl.Control::KeyInput( m_rKeyEvent ); + } + + void setHandled() + { + m_bHandled = true; + } + + private: + Control& m_rControl; + const KeyEvent& m_rKeyEvent; + bool m_bHandled; + }; + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::KeyInput( const KeyEvent& i_rKeyEvent ) + { + KeyInputHandler aKeyInputHandler( *this, i_rKeyEvent ); + + const KeyCode& rKeyCode( i_rKeyEvent.GetKeyCode() ); + if ( rKeyCode.GetModifier() != 0 ) + // only interested in mere key presses + return; + + // if there are less than 2 panels, we cannot travel them ... + const size_t nPanelCount( m_pImpl->m_rPanelDeck.GetPanelCount() ); + if ( nPanelCount < 2 ) + return; + + OSL_PRECOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::KeyInput: we should have a focused item here!" ); + // if we get KeyInput events, we should have the focus. In this case, m_aFocusedItem should not be empty, + // except if there are no panels, but then we bail out of this method here earlier ... + + bool bFocusNext = false; + bool bFocusPrev = false; + + switch ( rKeyCode.GetCode() ) + { + case KEY_UP: bFocusPrev = true; break; + case KEY_DOWN: bFocusNext = true; break; + case KEY_LEFT: + if ( IsRTLEnabled() ) + bFocusNext = true; + else + bFocusPrev = true; + break; + case KEY_RIGHT: + if ( IsRTLEnabled() ) + bFocusPrev = true; + else + bFocusNext = true; + break; + case KEY_RETURN: + m_pImpl->m_rPanelDeck.ActivatePanel( *m_pImpl->m_aFocusedItem ); + break; + } + + if ( !bFocusNext && !bFocusPrev ) + return; + + m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem ); + if ( bFocusNext ) + { + m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + 1 ) % nPanelCount ); + } + else + { + m_pImpl->m_aFocusedItem.reset( ( *m_pImpl->m_aFocusedItem + nPanelCount - 1 ) % nPanelCount ); + } + m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem ); + + // don't delegate to base class + aKeyInputHandler.setHandled(); + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::DataChanged( const DataChangedEvent& i_rDataChanedEvent ) + { + Control::DataChanged( i_rDataChanedEvent ); + + if ( ( i_rDataChanedEvent.GetType() == DATACHANGED_SETTINGS ) + && ( ( i_rDataChanedEvent.GetFlags() & SETTINGS_STYLE ) != 0 ) + ) + { + Invalidate(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + bool PanelTabBar::IsVertical() const + { + return m_pImpl->IsVertical(); + } + + //------------------------------------------------------------------------------------------------------------------ + PushButton& PanelTabBar::GetScrollButton( const bool i_bForward ) + { + return i_bForward ? m_pImpl->m_aScrollForward : m_pImpl->m_aScrollBack; + } + + //------------------------------------------------------------------------------------------------------------------ + ::boost::optional< size_t > PanelTabBar::GetFocusedPanelItem() const + { + return m_pImpl->m_aFocusedItem; + } + + //------------------------------------------------------------------------------------------------------------------ + void PanelTabBar::FocusPanelItem( const size_t i_nItemPos ) + { + ENSURE_OR_RETURN_VOID( i_nItemPos < m_pImpl->m_rPanelDeck.GetPanelCount(), "PanelTabBar::FocusPanelItem: illegal item pos!" ); + + if ( !HasChildPathFocus() ) + GrabFocus(); + + m_pImpl->FocusItem( i_nItemPos ); + OSL_POSTCOND( !!m_pImpl->m_aFocusedItem, "PanelTabBar::FocusPanelItem: have the focus, but no focused item?" ); + if ( !!m_pImpl->m_aFocusedItem ) + m_pImpl->InvalidateItem( *m_pImpl->m_aFocusedItem ); + m_pImpl->m_aFocusedItem.reset( i_nItemPos ); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle PanelTabBar::GetItemScreenRect( const size_t i_nItemPos ) const + { + return m_pImpl->GetItemScreenRect( i_nItemPos ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWindowPeer > PanelTabBar::GetComponentInterface( BOOL i_bCreate ) + { + Reference< XWindowPeer > xWindowPeer( Control::GetComponentInterface( FALSE ) ); + if ( !xWindowPeer.is() && i_bCreate ) + { + xWindowPeer.set( new PanelTabBarPeer( *this ) ); + SetComponentInterface( xWindowPeer ); + } + return xWindowPeer; + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/paneltabbarpeer.cxx b/svtools/source/toolpanel/paneltabbarpeer.cxx new file mode 100644 index 000000000000..d8329109ffb4 --- /dev/null +++ b/svtools/source/toolpanel/paneltabbarpeer.cxx @@ -0,0 +1,101 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "paneltabbarpeer.hxx" +#include "svtools/toolpanel/paneltabbar.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace svt +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::accessibility::XAccessibleContext; + using ::com::sun::star::lang::DisposedException; + /** === end UNO using === **/ + + //================================================================================================================== + //= PanelTabBarPeer + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + PanelTabBarPeer::PanelTabBarPeer( PanelTabBar& i_rTabBar ) + :VCLXWindow() + ,m_pTabBar( &i_rTabBar ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + PanelTabBarPeer::~PanelTabBarPeer() + { + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessibleContext > PanelTabBarPeer::CreateAccessibleContext() + { + ::vos::OGuard aSolarGuard( GetMutex() ); + if ( m_pTabBar == NULL ) + throw DisposedException( ::rtl::OUString(), *this ); + + + + Window* pAccessibleParent( m_pTabBar->GetAccessibleParentWindow() ); + ENSURE_OR_RETURN( pAccessibleParent != NULL, "no accessible parent => no accessible context", NULL ); + Reference< XAccessible > xAccessibleParent( pAccessibleParent->GetAccessible(), UNO_SET_THROW ); + return m_aAccessibleFactory.getFactory().createAccessibleToolPanelTabBar( xAccessibleParent, m_pTabBar->GetPanelDeck(), *m_pTabBar ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL PanelTabBarPeer::dispose() throw(RuntimeException) + { + { + ::vos::OGuard aSolarGuard( GetMutex() ); + m_pTabBar = NULL; + } + VCLXWindow::dispose(); + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/paneltabbarpeer.hxx b/svtools/source/toolpanel/paneltabbarpeer.hxx new file mode 100644 index 000000000000..7c2e5188d994 --- /dev/null +++ b/svtools/source/toolpanel/paneltabbarpeer.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_PANELTABBARPEER_HXX +#define SVT_PANELTABBARPEER_HXX + +#include "svtaccessiblefactory.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <toolkit/awt/vclxwindow.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + class PanelTabBar; + //==================================================================== + //= PanelTabBarPeer + //==================================================================== + class PanelTabBarPeer : public VCLXWindow + { + public: + PanelTabBarPeer( PanelTabBar& i_rTabBar ); + + protected: + ~PanelTabBarPeer(); + + // VCLXWindow overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > CreateAccessibleContext(); + + // XComponent + void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + private: + AccessibleFactoryAccess m_aAccessibleFactory; + PanelTabBar* m_pTabBar; + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // SVT_PANELTABBARPEER_HXX diff --git a/svtools/source/toolpanel/refbase.cxx b/svtools/source/toolpanel/refbase.cxx new file mode 100644 index 000000000000..f41aa2d9bb9c --- /dev/null +++ b/svtools/source/toolpanel/refbase.cxx @@ -0,0 +1,56 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/refbase.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= RefBase + //==================================================================== + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL RefBase::acquire() + { + return osl_incrementInterlockedCount( &m_refCount ); + } + + //-------------------------------------------------------------------- + oslInterlockedCount SAL_CALL RefBase::release() + { + oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount ); + if ( 0 == newCount ) + delete this; + return newCount; + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/tabbargeometry.cxx b/svtools/source/toolpanel/tabbargeometry.cxx new file mode 100644 index 000000000000..45c40cee6ef2 --- /dev/null +++ b/svtools/source/toolpanel/tabbargeometry.cxx @@ -0,0 +1,328 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "tabbargeometry.hxx" + +#include <basegfx/range/b2drange.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/numeric/ftools.hxx> + +#include <vcl/window.hxx> + +#include <algorithm> + +// the width (or height, depending on alignment) of the scroll buttons +#define BUTTON_FLOW_WIDTH 20 +// the space between the scroll buttons and the items +#define BUTTON_FLOW_SPACE 2 +// outer space to apply between the tab bar borders and any content. Note that those refer to a "normalized" geometry, +// i.e. if the tab bar were aligned at the top +#define OUTER_SPACE_LEFT 2 +#define OUTER_SPACE_TOP 4 +#define OUTER_SPACE_RIGHT 4 +#define OUTER_SPACE_BOTTOM 2 + +// outer space to apply between the area for the items, and the actual items. They refer to a normalized geometry. +#define ITEMS_INSET_LEFT 4 +#define ITEMS_INSET_TOP 3 +#define ITEMS_INSET_RIGHT 4 +#define ITEMS_INSET_BOTTOM 0 + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + //================================================================================================================== + //= helper + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + static void lcl_transform( Rectangle& io_rRect, const ::basegfx::B2DHomMatrix& i_rTransformation ) + { + ::basegfx::B2DRange aRect( io_rRect.Left(), io_rRect.Top(), io_rRect.Right(), io_rRect.Bottom() ); + aRect.transform( i_rTransformation ); + io_rRect.Left() = long( aRect.getMinX() ); + io_rRect.Top() = long( aRect.getMinY() ); + io_rRect.Right() = long( aRect.getMaxX() ); + io_rRect.Bottom() = long( aRect.getMaxY() ); + } + + //-------------------------------------------------------------------------------------------------------------- + /** transforms the given, possible rotated playground, + */ + void lcl_rotate( const Rectangle& i_rReference, Rectangle& io_rArea, const bool i_bRight ) + { + // step 1: move the to-be-upper-left corner (left/bottom) of the rectangle to (0,0) + ::basegfx::B2DHomMatrix aTransformation; + aTransformation.translate( + i_bRight ? -i_rReference.Left() : -i_rReference.Right(), + i_bRight ? -i_rReference.Bottom() : -i_rReference.Top() + ); + + // step 2: rotate by -90 degrees + aTransformation.rotate( i_bRight ? +F_PI2 : -F_PI2 ); + // note: + // on the screen, the ordinate goes top-down, while basegfx calculates in a system where the + // ordinate goes bottom-up; thus the "wrong" sign before F_PI2 here + + // step 3: move back to original coordinates + aTransformation.translate( i_rReference.Left(), i_rReference.Top() ); + + // apply transformation + lcl_transform( io_rArea, aTransformation ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + void lcl_mirrorHorizontally( const Rectangle& i_rReferenceArea, Rectangle& io_rArea ) + { + io_rArea.Left() = i_rReferenceArea.Left() + i_rReferenceArea.Right() - io_rArea.Left(); + io_rArea.Right() = i_rReferenceArea.Left() + i_rReferenceArea.Right() - io_rArea.Right(); + ::std::swap( io_rArea.Left(), io_rArea.Right() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void lcl_mirrorVertically( const Rectangle& i_rReferenceArea, Rectangle& io_rArea ) + { + io_rArea.Top() = i_rReferenceArea.Top() + i_rReferenceArea.Bottom() - io_rArea.Top(); + io_rArea.Bottom() = i_rReferenceArea.Top() + i_rReferenceArea.Bottom() - io_rArea.Bottom(); + ::std::swap( io_rArea.Top(), io_rArea.Bottom() ); + } + + //================================================================================================================== + //= NormalizedArea + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + NormalizedArea::NormalizedArea() + :m_aReference() + { + } + + //------------------------------------------------------------------------------------------------------------------ + NormalizedArea::NormalizedArea( const Rectangle& i_rReference, const bool i_bIsVertical ) + :m_aReference( i_bIsVertical ? Rectangle( i_rReference.TopLeft(), Size( i_rReference.GetHeight(), i_rReference.GetWidth() ) ) : i_rReference ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle NormalizedArea::getTransformed( const Rectangle& i_rArea, const TabAlignment i_eTargetAlignment ) const + { + Rectangle aResult( i_rArea ); + + if ( ( i_eTargetAlignment == TABS_RIGHT ) + || ( i_eTargetAlignment == TABS_LEFT ) + ) + { + lcl_rotate( m_aReference, aResult, true ); + + if ( i_eTargetAlignment == TABS_LEFT ) + { + Rectangle aReference( m_aReference ); + aReference.Transpose(); + lcl_mirrorHorizontally( aReference, aResult ); + } + } + else + if ( i_eTargetAlignment == TABS_BOTTOM ) + { + lcl_mirrorVertically( m_aReference, aResult ); + } + + return aResult; + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle NormalizedArea::getNormalized( const Rectangle& i_rArea, const TabAlignment i_eTargetAlignment ) const + { + Rectangle aResult( i_rArea ); + + if ( ( i_eTargetAlignment == TABS_RIGHT ) + || ( i_eTargetAlignment == TABS_LEFT ) + ) + { + Rectangle aReference( m_aReference ); + lcl_rotate( m_aReference, aReference, true ); + + if ( i_eTargetAlignment == TABS_LEFT ) + { + lcl_mirrorHorizontally( aReference, aResult ); + } + + lcl_rotate( aReference, aResult, false ); + } + else + if ( i_eTargetAlignment == TABS_BOTTOM ) + { + lcl_mirrorVertically( m_aReference, aResult ); + } + return aResult; + } + + //================================================================================================================== + //= TabBarGeometry + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + TabBarGeometry::TabBarGeometry( const TabItemContent i_eItemContent ) + :m_eTabItemContent( i_eItemContent ) + ,m_aItemsInset() + ,m_aButtonBackRect() + ,m_aItemsRect() + ,m_aButtonForwardRect() + { + m_aItemsInset.Left() = ITEMS_INSET_LEFT; + m_aItemsInset.Top() = ITEMS_INSET_TOP; + m_aItemsInset.Right() = ITEMS_INSET_RIGHT; + m_aItemsInset.Bottom() = ITEMS_INSET_BOTTOM; + } + + //------------------------------------------------------------------------------------------------------------------ + TabBarGeometry::~TabBarGeometry() + { + } + + //------------------------------------------------------------------------------------------------------------------ + bool TabBarGeometry::impl_fitItems( ItemDescriptors& io_rItems ) const + { + if ( io_rItems.empty() ) + // nothing to do, "no items" perfectly fit into any space we have ... + return true; + + // the available size + Size aOutputSize( getItemsRect().GetSize() ); + // shrunk by the outer space + aOutputSize.Width() -= m_aItemsInset.Right(); + aOutputSize.Height() -= m_aItemsInset.Bottom(); + const Rectangle aFitInto( Point( 0, 0 ), aOutputSize ); + + TabItemContent eItemContent( getItemContent() ); + if ( eItemContent == TABITEM_AUTO ) + { + // the "content modes" to try + TabItemContent eTryThis[] = + { + TABITEM_IMAGE_ONLY, // assumed to have the smallest rects + TABITEM_TEXT_ONLY, + TABITEM_IMAGE_AND_TEXT // assumed to have the largest rects + }; + + + // determine which of the different version fits + eItemContent = eTryThis[0]; + size_t nTryIndex = 2; + while ( nTryIndex > 0 ) + { + const Point aBottomRight( io_rItems.rbegin()->GetRect( eTryThis[ nTryIndex ] ).BottomRight() ); + if ( aFitInto.IsInside( aBottomRight ) ) + { + eItemContent = eTryThis[ nTryIndex ]; + break; + } + --nTryIndex; + } + } + + // propagate to the items + for ( ItemDescriptors::iterator item = io_rItems.begin(); + item != io_rItems.end(); + ++item + ) + { + item->eContent = eItemContent; + } + + const ItemDescriptor& rLastItem( *io_rItems.rbegin() ); + const Point aLastItemBottomRight( rLastItem.GetCurrentRect().BottomRight() ); + return aFitInto.Left() <= aLastItemBottomRight.X() + && aFitInto.Right() >= aLastItemBottomRight.X(); + } + + //------------------------------------------------------------------------------------------------------------------ + Size TabBarGeometry::getOptimalSize( ItemDescriptors& io_rItems, const bool i_bMinimalSize ) const + { + if ( io_rItems.empty() ) + return Size( + m_aItemsInset.Left() + m_aItemsInset.Right(), + m_aItemsInset.Top() + m_aItemsInset.Bottom() + ); + + // the rect of the last item + const Rectangle& rLastItemRect( i_bMinimalSize ? io_rItems.rbegin()->aIconOnlyArea : io_rItems.rbegin()->aCompleteArea ); + return Size( + rLastItemRect.Left() + 1 + m_aItemsInset.Right(), + rLastItemRect.Top() + 1 + rLastItemRect.Bottom() + m_aItemsInset.Bottom() + ); + } + + //------------------------------------------------------------------------------------------------------------------ + void TabBarGeometry::relayout( const Size& i_rActualOutputSize, ItemDescriptors& io_rItems ) + { + // assume all items fit + Point aButtonBackPos( OUTER_SPACE_LEFT, OUTER_SPACE_TOP ); + m_aButtonBackRect = Rectangle( aButtonBackPos, Size( 1, 1 ) ); + m_aButtonBackRect.SetEmpty(); + + Point aButtonForwardPos( i_rActualOutputSize.Width(), OUTER_SPACE_TOP ); + m_aButtonForwardRect = Rectangle( aButtonForwardPos, Size( 1, 1 ) ); + m_aButtonForwardRect.SetEmpty(); + + Point aItemsPos( OUTER_SPACE_LEFT, 0 ); + Size aItemsSize( i_rActualOutputSize.Width() - OUTER_SPACE_LEFT - OUTER_SPACE_RIGHT, i_rActualOutputSize.Height() ); + m_aItemsRect = Rectangle( aItemsPos, aItemsSize ); + + if ( !impl_fitItems( io_rItems ) ) + { + // assumption was wrong, the items do not fit => calculate rects for the scroll buttons + const Size aButtonSize( BUTTON_FLOW_WIDTH, i_rActualOutputSize.Height() - OUTER_SPACE_TOP - OUTER_SPACE_BOTTOM ); + + aButtonBackPos = Point( OUTER_SPACE_LEFT, OUTER_SPACE_TOP ); + m_aButtonBackRect = Rectangle( aButtonBackPos, aButtonSize ); + + aButtonForwardPos = Point( i_rActualOutputSize.Width() - BUTTON_FLOW_WIDTH - OUTER_SPACE_RIGHT, OUTER_SPACE_TOP ); + m_aButtonForwardRect = Rectangle( aButtonForwardPos, aButtonSize ); + + aItemsPos.X() = aButtonBackPos.X() + aButtonSize.Width() + BUTTON_FLOW_SPACE; + aItemsSize.Width() = aButtonForwardPos.X() - BUTTON_FLOW_SPACE - aItemsPos.X(); + m_aItemsRect = Rectangle( aItemsPos, aItemsSize ); + + // fit items, again. In the TABITEM_AUTO case, the smaller playground for the items might lead to another + // item content. + impl_fitItems( io_rItems ); + } + } + + //------------------------------------------------------------------------------------------------------------------ + Point TabBarGeometry::getFirstItemPosition() const + { + return Point( m_aItemsInset.Left(), m_aItemsInset.Top() ); + } + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/tabbargeometry.hxx b/svtools/source/toolpanel/tabbargeometry.hxx new file mode 100644 index 000000000000..059d69a3e233 --- /dev/null +++ b/svtools/source/toolpanel/tabbargeometry.hxx @@ -0,0 +1,137 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef TABBARGEOMETRY_HXX +#define TABBARGEOMETRY_HXX + +#include "svtools/toolpanel/tabalignment.hxx" + +#include "tabitemdescriptor.hxx" + +#include <tools/gen.hxx> +#include <tools/svborder.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + //================================================================================================================== + //= NormalizedArea + //================================================================================================================== + /** a rectangle which automatically translates between unrotated and rotated geometry. + + It can be operated as if it were an unrotated area, but is able to provide corrdinates of rotated objects, + relative to its playground. + */ + class NormalizedArea + { + public: + NormalizedArea(); + NormalizedArea( const Rectangle& i_rReference, const bool i_bIsVertical ); + + /** transforms a rectangle, relative to our playground, into a coordinate system defined by the given alignment + @param i_rArea + the area which is to be transformed. + */ + Rectangle getTransformed( + const Rectangle& i_rArea, + const TabAlignment i_eTargetAlignment + ) const; + + /** normalizes an already transformed rectangle + @param i_rArea + the area which is to be normalized. + */ + Rectangle getNormalized( + const Rectangle& i_rArea, + const TabAlignment i_eTargetAlignment + ) const; + + + Size getReferenceSize() const { return m_aReference.GetSize(); } + const Rectangle& + getReference() const { return m_aReference; } + + private: + // the normalized reference area + Rectangle m_aReference; + }; + + //================================================================================================================== + //= TabBarGeometry + //================================================================================================================== + class TabBarGeometry_Impl; + class TabBarGeometry + { + public: + TabBarGeometry( const TabItemContent i_eItemContent ); + ~TabBarGeometry(); + + // retrieves the rectangle to be occupied by the button for scrolling backward through the items + const Rectangle& getButtonBackRect() const { return m_aButtonBackRect; } + // retrieves the rectangle to be occupied by the items + const Rectangle& getItemsRect() const { return m_aItemsRect; } + // retrieves the rectangle to be occupied by the button for scrolling forward through the items + const Rectangle& getButtonForwardRect() const { return m_aButtonForwardRect; } + + inline TabItemContent + getItemContent() const { return m_eTabItemContent; } + inline void setItemContent( const TabItemContent i_eItemContent ) { m_eTabItemContent = i_eItemContent; } + + /** adjusts the sizes of the buttons and the item's playground, plus the sizes of the items + */ + void relayout( const Size& i_rActualOutputSize, ItemDescriptors& io_rItems ); + + /** calculates the optimal size of the tab bar, depending on the item's sizes + */ + Size getOptimalSize( ItemDescriptors& io_rItems, const bool i_bMinimalSize ) const; + + /** retrieves the position where the first item should start, relative to the item rect + */ + Point getFirstItemPosition() const; + + private: + bool impl_fitItems( ItemDescriptors& io_rItems ) const; + + private: + /// specifies the content to be displayed in the tab items + TabItemContent m_eTabItemContent; + /// specifies the inset to be used in the items area, depends on the actual alignment + SvBorder m_aItemsInset; + // the (logical) rectangle to be used for the "back" button, empty if the button is not needed + Rectangle m_aButtonBackRect; + // the (logical) rectangle to be used for the items + Rectangle m_aItemsRect; + // the (logical) rectangle to be used for the "forward" button, empty if the button is not needed + Rectangle m_aButtonForwardRect; + }; + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... + +#endif // TABBARGEOMETRY_HXX diff --git a/svtools/source/toolpanel/tabitemdescriptor.hxx b/svtools/source/toolpanel/tabitemdescriptor.hxx new file mode 100644 index 000000000000..8005816b0fe2 --- /dev/null +++ b/svtools/source/toolpanel/tabitemdescriptor.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef TABITEMDESCRIPTOR_HXX +#define TABITEMDESCRIPTOR_HXX + +#include "svtools/toolpanel/toolpanel.hxx" +#include "svtools/toolpanel/tabitemcontent.hxx" + +#include <tools/gen.hxx> +#include <osl/diagnose.h> + +#include <vector> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //================================================================================================================== + //= ItemDescriptor + //================================================================================================================== + struct ItemDescriptor + { + PToolPanel pPanel; + Rectangle aCompleteArea; // bounding area if the both text and icon are to be rendererd + Rectangle aIconOnlyArea; // bounding area if the icon is to be rendererd + Rectangle aTextOnlyArea; // bounding area if the text is to be rendererd + TabItemContent eContent; + // content to be used for this particular item. Might differ from item content which has been set + // up for the complete control, in case not the complete content fits into the available space. + + ItemDescriptor() + :pPanel() + ,aCompleteArea() + ,aIconOnlyArea() + ,aTextOnlyArea() + ,eContent( TABITEM_IMAGE_AND_TEXT ) + { + } + + const Rectangle& GetRect( const TabItemContent i_eItemContent ) const + { + OSL_ENSURE( i_eItemContent != TABITEM_AUTO, "ItemDescriptor::GetRect: illegal value!" ); + + return ( i_eItemContent == TABITEM_IMAGE_AND_TEXT ) + ? aCompleteArea + : ( ( i_eItemContent == TABITEM_TEXT_ONLY ) + ? aTextOnlyArea + : aIconOnlyArea + ); + } + + const Rectangle& GetCurrentRect() const + { + return GetRect( eContent ); + } + }; + + typedef ::std::vector< ItemDescriptor > ItemDescriptors; + + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // TABITEMDESCRIPTOR_HXX diff --git a/svtools/source/toolpanel/tablayouter.cxx b/svtools/source/toolpanel/tablayouter.cxx new file mode 100755 index 000000000000..f68bbc1bbd0f --- /dev/null +++ b/svtools/source/toolpanel/tablayouter.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/tablayouter.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" +#include "svtools/toolpanel/paneltabbar.hxx" +#include "svtaccessiblefactory.hxx" + +#include <tools/gen.hxx> +#include <tools/diagnose_ex.h> + +//........................................................................ +namespace svt +{ +//........................................................................ + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::accessibility::XAccessible; + + //==================================================================== + //= TabDeckLayouter_Data + //==================================================================== + struct TabDeckLayouter_Data + { + TabAlignment eAlignment; + IToolPanelDeck& rPanels; + ::std::auto_ptr< PanelTabBar > pTabBar; + AccessibleFactoryAccess aAccessibleFactory; + + TabDeckLayouter_Data( Window& i_rParent, IToolPanelDeck& i_rPanels, + const TabAlignment i_eAlignment, const TabItemContent i_eItemContent ) + :eAlignment( i_eAlignment ) + ,rPanels( i_rPanels ) + ,pTabBar( new PanelTabBar( i_rParent, i_rPanels, i_eAlignment, i_eItemContent ) ) + { + pTabBar->Show(); + } + }; + + //==================================================================== + //= helper + //==================================================================== + namespace + { + static bool lcl_isVerticalTabBar( const TabAlignment i_eAlignment ) + { + return ( i_eAlignment == TABS_RIGHT ) + || ( i_eAlignment == TABS_LEFT ); + } + + static bool lcl_checkDisposed( const TabDeckLayouter_Data& i_rData ) + { + if ( !i_rData.pTabBar.get() ) + { + OSL_ENSURE( false, "lcl_checkDisposed: already disposed!" ); + return true; + } + return false; + } + } + + //==================================================================== + //= TabDeckLayouter + //==================================================================== + //-------------------------------------------------------------------- + TabDeckLayouter::TabDeckLayouter( Window& i_rParent, IToolPanelDeck& i_rPanels, + const TabAlignment i_eAlignment, const TabItemContent i_eItemContent ) + :m_pData( new TabDeckLayouter_Data( i_rParent, i_rPanels, i_eAlignment, i_eItemContent ) ) + { + } + + //-------------------------------------------------------------------- + TabDeckLayouter::~TabDeckLayouter() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( TabDeckLayouter ) + + //-------------------------------------------------------------------- + TabItemContent TabDeckLayouter::GetTabItemContent() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return TABITEM_IMAGE_AND_TEXT; + return m_pData->pTabBar->GetTabItemContent(); + } + + //-------------------------------------------------------------------- + void TabDeckLayouter::SetTabItemContent( const TabItemContent& i_eItemContent ) + { + if ( lcl_checkDisposed( *m_pData ) ) + return; + m_pData->pTabBar->SetTabItemContent( i_eItemContent ); + } + + //-------------------------------------------------------------------- + TabAlignment TabDeckLayouter::GetTabAlignment() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return TABS_RIGHT; + return m_pData->eAlignment; + } + + //-------------------------------------------------------------------- + ::boost::optional< size_t > TabDeckLayouter::GetFocusedPanelItem() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return ::boost::optional< size_t >(); + return m_pData->pTabBar->GetFocusedPanelItem(); + } + + //-------------------------------------------------------------------- + void TabDeckLayouter::FocusPanelItem( const size_t i_nItemPos ) + { + if ( lcl_checkDisposed( *m_pData ) ) + return; + m_pData->pTabBar->FocusPanelItem( i_nItemPos ); + } + + //-------------------------------------------------------------------- + bool TabDeckLayouter::IsPanelSelectorEnabled() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return false; + return m_pData->pTabBar->IsEnabled(); + } + + //-------------------------------------------------------------------- + bool TabDeckLayouter::IsPanelSelectorVisible() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return false; + return m_pData->pTabBar->IsVisible(); + } + + //-------------------------------------------------------------------- + Rectangle TabDeckLayouter::GetItemScreenRect( const size_t i_nItemPos ) const + { + if ( lcl_checkDisposed( *m_pData ) ) + return Rectangle(); + return m_pData->pTabBar->GetItemScreenRect( i_nItemPos ); + } + + //-------------------------------------------------------------------- + Rectangle TabDeckLayouter::Layout( const Rectangle& i_rDeckPlayground ) + { + if ( lcl_checkDisposed( *m_pData ) ) + return i_rDeckPlayground; + + const Size aPreferredSize( m_pData->pTabBar->GetOptimalSize( WINDOWSIZE_PREFERRED ) ); + if ( lcl_isVerticalTabBar( m_pData->eAlignment ) ) + { + Size aTabBarSize = ( aPreferredSize.Width() < i_rDeckPlayground.GetWidth() ) + ? aPreferredSize + : m_pData->pTabBar->GetOptimalSize( WINDOWSIZE_MINIMUM ); + aTabBarSize.Height() = i_rDeckPlayground.GetHeight(); + + Rectangle aPanelRect( i_rDeckPlayground ); + if ( m_pData->eAlignment == TABS_RIGHT ) + { + aPanelRect.Right() -= aTabBarSize.Width(); + Point aTabBarTopLeft( aPanelRect.TopRight() ); + aTabBarTopLeft.X() += 1; + m_pData->pTabBar->SetPosSizePixel( aTabBarTopLeft, aTabBarSize ); + } + else + { + m_pData->pTabBar->SetPosSizePixel( aPanelRect.TopLeft(), aTabBarSize ); + aPanelRect.Left() += aTabBarSize.Width(); + } + if ( aPanelRect.Left() >= aPanelRect.Right() ) + aPanelRect = Rectangle(); + + return aPanelRect; + } + + Size aTabBarSize = ( aPreferredSize.Height() < i_rDeckPlayground.GetHeight() ) + ? aPreferredSize + : m_pData->pTabBar->GetOptimalSize( WINDOWSIZE_MINIMUM ); + aTabBarSize.Width() = i_rDeckPlayground.GetWidth(); + + Rectangle aPanelRect( i_rDeckPlayground ); + if ( m_pData->eAlignment == TABS_TOP ) + { + m_pData->pTabBar->SetPosSizePixel( aPanelRect.TopLeft(), aTabBarSize ); + aPanelRect.Top() += aTabBarSize.Height(); + } + else + { + aPanelRect.Bottom() -= aTabBarSize.Height(); + Point aTabBarTopLeft( aPanelRect.BottomLeft() ); + aTabBarTopLeft.Y() -= 1; + m_pData->pTabBar->SetPosSizePixel( aTabBarTopLeft, aTabBarSize ); + } + if ( aPanelRect.Top() >= aPanelRect.Bottom() ) + aPanelRect = Rectangle(); + + return aPanelRect; + } + + //-------------------------------------------------------------------- + void TabDeckLayouter::Destroy() + { + m_pData->pTabBar.reset(); + } + + //-------------------------------------------------------------------- + void TabDeckLayouter::SetFocusToPanelSelector() + { + if ( lcl_checkDisposed( *m_pData ) ) + return; + m_pData->pTabBar->GrabFocus(); + } + + //-------------------------------------------------------------------- + size_t TabDeckLayouter::GetAccessibleChildCount() const + { + if ( lcl_checkDisposed( *m_pData ) ) + return 0; + + return 1; + } + + //-------------------------------------------------------------------- + Reference< XAccessible > TabDeckLayouter::GetAccessibleChild( const size_t i_nChildIndex, const Reference< XAccessible >& i_rParentAccessible ) + { + (void)i_nChildIndex; + (void)i_rParentAccessible; + if ( lcl_checkDisposed( *m_pData ) ) + return NULL; + + return m_pData->pTabBar->GetAccessible( TRUE ); + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/toolpanel.cxx b/svtools/source/toolpanel/toolpanel.cxx new file mode 100644 index 000000000000..f7b999494563 --- /dev/null +++ b/svtools/source/toolpanel/toolpanel.cxx @@ -0,0 +1,54 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "svtools/toolpanel/toolpanel.hxx" + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= ToolPanelBase + //==================================================================== + //-------------------------------------------------------------------- + ToolPanelBase::ToolPanelBase() + { + } + + //-------------------------------------------------------------------- + ToolPanelBase::~ToolPanelBase() + { + } + + //-------------------------------------------------------------------- + IMPLEMENT_IREFERENCE( ToolPanelBase ) + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/uno/unoifac2.hrc b/svtools/source/toolpanel/toolpanel.src index a31d07e0bd27..5908a8fbcf98 100644 --- a/svtools/source/uno/unoifac2.hrc +++ b/svtools/source/toolpanel/toolpanel.src @@ -1,5 +1,4 @@ /************************************************************************* - * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. @@ -25,28 +24,34 @@ * ************************************************************************/ -#ifndef _SVT_UNO_UNOIFAC_HRC_ -#define _SVT_UNO_UNOIFAC_HRC_ - - -#ifndef _SOLAR_HRC -#include <svl/solar.hrc> -#endif - -//! Um den Überblick über alle benutzten HelpID's zu behalten sind diese -//! zentral in <helpid.hrc> -#ifndef _SVT_HELPID_HRC -#include <svtools/helpid.hrc> -#endif - -// RID's fuer das Kontextmenu der Textkomponente -#define RID_CONTEXTMENU (RID_APP_START + 1024) -#define RID_OPEN_LINK (RID_APP_START + 10) -#define RID_OPEN_LINK_NEW (RID_APP_START + 11) -#define RID_DOWNLOAD (RID_APP_START + 12) -#define RID_ADD_BOOKMARK (RID_APP_START + 13) -#define RID_COPY_LINK (RID_APP_START + 14) - - -#endif - +#include "svtools/svtools.hrc" + +String STR_SVT_TOOL_PANEL_BUTTON_FWD +{ + Text [ en-US ] = "Tab Panel Scroll Button, backward"; +}; + +String STR_SVT_TOOL_PANEL_BUTTON_BACK +{ + Text [ en-US ] = "Tab Panel Scroll Button, forward"; +}; + +Image IMG_TRIANGLE_RIGHT +{ + ImageBitmap = Bitmap { File = "triangle_right.png"; }; +}; + +Image IMG_TRIANGLE_RIGHT_HC +{ + ImageBitmap = Bitmap { File = "triangle_right_hc.png"; }; +}; + +Image IMG_TRIANGLE_DOWN +{ + ImageBitmap = Bitmap { File = "triangle_down.png"; }; +}; + +Image IMG_TRIANGLE_DOWN_HC +{ + ImageBitmap = Bitmap { File = "plus.png"; } ; +}; diff --git a/svtools/source/toolpanel/toolpanelcollection.cxx b/svtools/source/toolpanel/toolpanelcollection.cxx new file mode 100644 index 000000000000..baefbd92400f --- /dev/null +++ b/svtools/source/toolpanel/toolpanelcollection.cxx @@ -0,0 +1,193 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "toolpanelcollection.hxx" +#include "paneldecklisteners.hxx" + +#include <tools/diagnose_ex.h> + +#include <vector> + +//........................................................................ +namespace svt +{ +//........................................................................ + + //==================================================================== + //= ToolPanelCollection_Data + //==================================================================== + struct ToolPanelCollection_Data + { + ::std::vector< PToolPanel > aPanels; + ::boost::optional< size_t > aActivePanel; + PanelDeckListeners aListeners; + }; + + //==================================================================== + //= ToolPanelCollection + //==================================================================== + //-------------------------------------------------------------------- + ToolPanelCollection::ToolPanelCollection() + :m_pData( new ToolPanelCollection_Data ) + { + } + + //-------------------------------------------------------------------- + ToolPanelCollection::~ToolPanelCollection() + { + m_pData->aListeners.Dying(); + } + + //-------------------------------------------------------------------- + size_t ToolPanelCollection::GetPanelCount() const + { + return m_pData->aPanels.size(); + } + + //-------------------------------------------------------------------- + ::boost::optional< size_t > ToolPanelCollection::GetActivePanel() const + { + return m_pData->aActivePanel; + } + + //-------------------------------------------------------------------- + void ToolPanelCollection::ActivatePanel( const ::boost::optional< size_t >& i_rPanel ) + { + if ( !!i_rPanel ) + { + OSL_ENSURE( *i_rPanel < GetPanelCount(), "ToolPanelCollection::ActivatePanel: illegal panel no.!" ); + if ( *i_rPanel >= GetPanelCount() ) + return; + } + + if ( m_pData->aActivePanel == i_rPanel ) + return; + + const ::boost::optional< size_t > aOldPanel( m_pData->aActivePanel ); + m_pData->aActivePanel = i_rPanel; + + // notify listeners + m_pData->aListeners.ActivePanelChanged( aOldPanel, m_pData->aActivePanel ); + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelCollection::GetPanel( const size_t i_nPos ) const + { + OSL_ENSURE( i_nPos < m_pData->aPanels.size(), "ToolPanelCollection::GetPanel: illegal position!" ); + if ( i_nPos >= m_pData->aPanels.size() ) + return PToolPanel(); + return m_pData->aPanels[ i_nPos ]; + } + + //-------------------------------------------------------------------- + size_t ToolPanelCollection::InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + OSL_ENSURE( i_pPanel.get(), "ToolPanelCollection::InsertPanel: illegal panel!" ); + if ( !i_pPanel.get() ) + return 0; + + // insert + const size_t position = i_nPosition < m_pData->aPanels.size() ? i_nPosition : m_pData->aPanels.size(); + m_pData->aPanels.insert( m_pData->aPanels.begin() + position, i_pPanel ); + + // update active panel + if ( !!m_pData->aActivePanel ) + { + if ( i_nPosition <= *m_pData->aActivePanel ) + ++*m_pData->aActivePanel; + } + + // notifications + m_pData->aListeners.PanelInserted( i_pPanel, i_nPosition ); + + return position; + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelCollection::RemovePanel( const size_t i_nPosition ) + { + OSL_ENSURE( i_nPosition < m_pData->aPanels.size(), "ToolPanelCollection::RemovePanel: illegal position!" ); + if ( i_nPosition >= m_pData->aPanels.size() ) + return NULL; + + // if the active panel is going to be removed, activate another one (before the actual removal) + if ( m_pData->aActivePanel == i_nPosition ) + { + const ::boost::optional< size_t > aOldActive( m_pData->aActivePanel ); + + if ( i_nPosition + 1 < GetPanelCount() ) + { + ++*m_pData->aActivePanel; + } + else if ( i_nPosition > 0 ) + { + --*m_pData->aActivePanel; + } + else + { + m_pData->aActivePanel.reset(); + } + + m_pData->aListeners.ActivePanelChanged( aOldActive, m_pData->aActivePanel ); + } + + // remember the removed panel for the aller + PToolPanel pRemovedPanel( m_pData->aPanels[ i_nPosition ] ); + + // actually remove + m_pData->aPanels.erase( m_pData->aPanels.begin() + i_nPosition ); + + if ( !!m_pData->aActivePanel ) + { + if ( i_nPosition < *m_pData->aActivePanel ) + { + --*m_pData->aActivePanel; + } + } + + // notify removed panel + m_pData->aListeners.PanelRemoved( i_nPosition ); + + return pRemovedPanel; + } + + //-------------------------------------------------------------------- + void ToolPanelCollection::AddListener( IToolPanelDeckListener& i_rListener ) + { + m_pData->aListeners.AddListener( i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelCollection::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + m_pData->aListeners.RemoveListener( i_rListener ); + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/toolpanelcollection.hxx b/svtools/source/toolpanel/toolpanelcollection.hxx new file mode 100644 index 000000000000..2bdba38546c9 --- /dev/null +++ b/svtools/source/toolpanel/toolpanelcollection.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#ifndef TOOLPANELCOLLECTION_HXX +#define TOOLPANELCOLLECTION_HXX + +#include "svtools/toolpanel/toolpaneldeck.hxx" + +#include <memory> + +//........................................................................ +namespace svt +{ +//........................................................................ + + struct ToolPanelCollection_Data; + + //==================================================================== + //= ToolPanelCollection + //==================================================================== + class ToolPanelCollection : public IToolPanelDeck + { + public: + ToolPanelCollection(); + ~ToolPanelCollection(); + + // IToolPanelDeck + virtual size_t GetPanelCount() const; + virtual PToolPanel GetPanel( const size_t i_nPos ) const; + virtual ::boost::optional< size_t > + GetActivePanel() const; + virtual void ActivatePanel( const ::boost::optional< size_t >& i_rPanel ); + virtual size_t InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ); + virtual PToolPanel RemovePanel( const size_t i_nPosition ); + virtual void AddListener( IToolPanelDeckListener& i_rListener ); + virtual void RemoveListener( IToolPanelDeckListener& i_rListener ); + + private: + ::std::auto_ptr< ToolPanelCollection_Data > m_pData; + }; + +//........................................................................ +} // namespace svt +//........................................................................ + +#endif // TOOLPANELCOLLECTION_HXX diff --git a/svtools/source/toolpanel/toolpaneldeck.cxx b/svtools/source/toolpanel/toolpaneldeck.cxx new file mode 100755 index 000000000000..e157090bbf0e --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldeck.cxx @@ -0,0 +1,560 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "dummypanel.hxx" +#include "toolpanelcollection.hxx" +#include "paneldecklisteners.hxx" +#include "toolpaneldeckpeer.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" +#include "svtools/toolpanel/tablayouter.hxx" +#include "svtools/toolpanel/drawerlayouter.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +#include <boost/optional.hpp> + +//........................................................................ +namespace svt +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::accessibility::XAccessible; + using ::com::sun::star::awt::XWindowPeer; + using ::com::sun::star::uno::UNO_SET_THROW; + /** === end UNO using === **/ + namespace AccessibleRole = ::com::sun::star::accessibility::AccessibleRole; + + enum DeckAction + { + /// activates the first panel + ACTION_ACTIVATE_FIRST, + // activates the panel after the currently active panel + ACTION_ACTIVATE_NEXT, + // activates the panel before the currently active panel + ACTION_ACTIVATE_PREV, + // activates the last panel + ACTION_ACTIVATE_LAST, + + // toggles the focus between the active panel and the panel selector + ACTION_TOGGLE_FOCUS, + }; + + //==================================================================== + //= ToolPanelDeck_Impl + //==================================================================== + class ToolPanelDeck_Impl : public IToolPanelDeckListener + { + public: + ToolPanelDeck_Impl( ToolPanelDeck& i_rDeck ) + :m_rDeck( i_rDeck ) + ,m_aPanelAnchor( &i_rDeck, WB_DIALOGCONTROL | WB_CHILDDLGCTRL ) + ,m_aPanels() + ,m_pDummyPanel( new DummyPanel ) + ,m_pLayouter() + ,m_bInDtor( false ) + ,m_pAccessibleParent( NULL ) + { + m_aPanels.AddListener( *this ); + m_aPanelAnchor.Show(); + m_aPanelAnchor.SetAccessibleRole( AccessibleRole::PANEL ); + } + + ~ToolPanelDeck_Impl() + { + m_bInDtor = true; + } + + PDeckLayouter GetLayouter() const { return m_pLayouter; } + void SetLayouter( const PDeckLayouter& i_pNewLayouter ); + + Window& GetPanelWindowAnchor() { return m_aPanelAnchor; } + const Window& GetPanelWindowAnchor() const { return m_aPanelAnchor; } + + bool IsDead() const { return m_bInDtor; } + + /// notifies our listeners that we're going to die. Only to be called from with our anti-impl's destructor + void NotifyDying() + { + m_aPanels.RemoveListener( *this ); + m_aListeners.Dying(); + } + + // IToolPanelDeck equivalents + size_t GetPanelCount() const; + PToolPanel GetPanel( const size_t i_nPos ) const; + ::boost::optional< size_t > + GetActivePanel() const; + void ActivatePanel( const ::boost::optional< size_t >& i_rPanel ); + size_t InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ); + PToolPanel RemovePanel( const size_t i_nPosition ); + void AddListener( IToolPanelDeckListener& i_rListener ); + void RemoveListener( IToolPanelDeckListener& i_rListener ); + + /// re-layouts everything + void LayoutAll() { ImplDoLayout(); } + + void DoAction( const DeckAction i_eAction ); + + bool FocusActivePanel(); + + void SetAccessibleParentWindow( Window* i_pAccessibleParent ); + Window* GetAccessibleParentWindow() const { return m_pAccessibleParent; } + + protected: + // IToolPanelDeckListener + virtual void PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ); + virtual void PanelRemoved( const size_t i_nPosition ); + virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ); + virtual void LayouterChanged( const PDeckLayouter& i_rNewLayouter ); + virtual void Dying(); + + private: + void ImplDoLayout(); + PToolPanel GetActiveOrDummyPanel_Impl(); + + private: + ToolPanelDeck& m_rDeck; + Window m_aPanelAnchor; + ToolPanelCollection m_aPanels; + PToolPanel m_pDummyPanel; + PanelDeckListeners m_aListeners; + PDeckLayouter m_pLayouter; + bool m_bInDtor; + Window* m_pAccessibleParent; + }; + + //-------------------------------------------------------------------- + PToolPanel ToolPanelDeck_Impl::GetActiveOrDummyPanel_Impl() + { + ::boost::optional< size_t > aActivePanel( m_aPanels.GetActivePanel() ); + if ( !aActivePanel ) + return m_pDummyPanel; + return m_aPanels.GetPanel( *aActivePanel ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::SetLayouter( const PDeckLayouter& i_pNewLayouter ) + { + ENSURE_OR_RETURN_VOID( i_pNewLayouter.get(), "invalid layouter" ); + + if ( m_pLayouter.get() ) + m_pLayouter->Destroy(); + + m_pLayouter = i_pNewLayouter; + + ImplDoLayout(); + + m_aListeners.LayouterChanged( m_pLayouter ); + } + + //-------------------------------------------------------------------- + size_t ToolPanelDeck_Impl::GetPanelCount() const + { + return m_aPanels.GetPanelCount(); + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelDeck_Impl::GetPanel( const size_t i_nPos ) const + { + return m_aPanels.GetPanel( i_nPos ); + } + + //-------------------------------------------------------------------- + ::boost::optional< size_t > ToolPanelDeck_Impl::GetActivePanel() const + { + return m_aPanels.GetActivePanel(); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::ActivatePanel( const ::boost::optional< size_t >& i_rPanel ) + { + m_aPanels.ActivatePanel( i_rPanel ); + } + + //-------------------------------------------------------------------- + size_t ToolPanelDeck_Impl::InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + return m_aPanels.InsertPanel( i_pPanel, i_nPosition ); + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelDeck_Impl::RemovePanel( const size_t i_nPosition ) + { + return m_aPanels.RemovePanel( i_nPosition ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::ImplDoLayout() + { + const Rectangle aDeckPlayground( Point(), m_rDeck.GetOutputSizePixel() ); + + // ask the layouter what is left for our panel, and position the panel container window appropriately + Rectangle aPlaygroundArea( aDeckPlayground ); + OSL_ENSURE( m_pLayouter.get(), "ToolPanelDeck_Impl::ImplDoLayout: no layouter!" ); + if ( m_pLayouter.get() ) + { + aPlaygroundArea = m_pLayouter->Layout( aDeckPlayground ); + } + m_aPanelAnchor.SetPosSizePixel( aPlaygroundArea.TopLeft(), aPlaygroundArea.GetSize() ); + + // position the active panel + const PToolPanel pActive( GetActiveOrDummyPanel_Impl() ); + pActive->SetSizePixel( m_aPanelAnchor.GetOutputSizePixel() ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::AddListener( IToolPanelDeckListener& i_rListener ) + { + m_aListeners.AddListener( i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + m_aListeners.RemoveListener( i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::DoAction( const DeckAction i_eAction ) + { + const size_t nPanelCount( m_aPanels.GetPanelCount() ); + ::boost::optional< size_t > aActivatePanel; + ::boost::optional< size_t > aCurrentPanel( GetActivePanel() ); + + switch ( i_eAction ) + { + case ACTION_ACTIVATE_FIRST: + if ( nPanelCount > 0 ) + aActivatePanel = 0; + break; + case ACTION_ACTIVATE_PREV: + if ( !aCurrentPanel && ( nPanelCount > 0 ) ) + aActivatePanel = nPanelCount - 1; + else + if ( !!aCurrentPanel && ( *aCurrentPanel > 0 ) ) + aActivatePanel = *aCurrentPanel - 1; + break; + case ACTION_ACTIVATE_NEXT: + if ( !aCurrentPanel && ( nPanelCount > 0 ) ) + aActivatePanel = 0; + else + if ( !!aCurrentPanel && ( *aCurrentPanel < nPanelCount - 1 ) ) + aActivatePanel = *aCurrentPanel + 1; + break; + case ACTION_ACTIVATE_LAST: + if ( nPanelCount > 0 ) + aActivatePanel = nPanelCount - 1; + break; + case ACTION_TOGGLE_FOCUS: + { + PToolPanel pActivePanel( GetActiveOrDummyPanel_Impl() ); + if ( !m_aPanelAnchor.HasChildPathFocus() ) + pActivePanel->GrabFocus(); + else + GetLayouter()->SetFocusToPanelSelector(); + } + break; + } + + if ( !!aActivatePanel ) + { + ActivatePanel( aActivatePanel ); + } + } + + //-------------------------------------------------------------------- + bool ToolPanelDeck_Impl::FocusActivePanel() + { + ::boost::optional< size_t > aActivePanel( m_aPanels.GetActivePanel() ); + if ( !aActivePanel ) + return false; + + PToolPanel pActivePanel( m_aPanels.GetPanel( *aActivePanel ) ); + pActivePanel->GrabFocus(); + return true; + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::PanelInserted( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + // multiplex to our own listeners + m_aListeners.PanelInserted( i_pPanel, i_nPosition ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::PanelRemoved( const size_t i_nPosition ) + { + // multiplex to our own listeners + m_aListeners.PanelRemoved( i_nPosition ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) + { + // hide the old panel + if ( !!i_rOldActive ) + { + const PToolPanel pOldActive( m_aPanels.GetPanel( *i_rOldActive ) ); + pOldActive->Deactivate(); + } + + // position and show the new panel + const PToolPanel pNewActive( !i_rNewActive ? m_pDummyPanel : m_aPanels.GetPanel( *i_rNewActive ) ); + pNewActive->Activate( m_aPanelAnchor ); + pNewActive->GrabFocus(); + + // resize the panel (cannot guarantee it has ever been resized before + pNewActive->SetSizePixel( m_aPanelAnchor.GetOutputSizePixel() ); + + // multiplex to our own listeners + m_aListeners.ActivePanelChanged( i_rOldActive, i_rNewActive ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::LayouterChanged( const PDeckLayouter& i_rNewLayouter ) + { + // not interested in + (void)i_rNewLayouter; + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::Dying() + { + // not interested in. Since the ToolPanelCollection is our member, this just means we ourself + // are dying, and we already sent this notification in our dtor. + } + + //-------------------------------------------------------------------- + void ToolPanelDeck_Impl::SetAccessibleParentWindow( Window* i_pAccessibleParent ) + { + m_pAccessibleParent = i_pAccessibleParent; + } + + //==================================================================== + //= ToolPanelDeck + //==================================================================== + //-------------------------------------------------------------------- + ToolPanelDeck::ToolPanelDeck( Window& i_rParent, const WinBits i_nStyle ) + :Control( &i_rParent, i_nStyle ) + ,m_pImpl( new ToolPanelDeck_Impl( *this ) ) + { + // use a default layouter +// SetLayouter( PDeckLayouter( new TabDeckLayouter( *this, *this, TABS_RIGHT, TABITEM_IMAGE_AND_TEXT ) ) ); + SetLayouter( PDeckLayouter( new DrawerDeckLayouter( *this, *this ) ) ); + } + + //-------------------------------------------------------------------- + ToolPanelDeck::~ToolPanelDeck() + { + m_pImpl->NotifyDying(); + GetLayouter()->Destroy(); + + Hide(); + for ( size_t i=0; i<GetPanelCount(); ++i ) + { + PToolPanel pPanel( GetPanel( i ) ); + pPanel->Dispose(); + } + } + + //-------------------------------------------------------------------- + size_t ToolPanelDeck::GetPanelCount() const + { + return m_pImpl->GetPanelCount(); + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelDeck::GetPanel( const size_t i_nPos ) const + { + return m_pImpl->GetPanel( i_nPos ); + } + + //-------------------------------------------------------------------- + ::boost::optional< size_t > ToolPanelDeck::GetActivePanel() const + { + return m_pImpl->GetActivePanel(); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::ActivatePanel( const ::boost::optional< size_t >& i_rPanel ) + { + m_pImpl->ActivatePanel( i_rPanel ); + } + + //-------------------------------------------------------------------- + size_t ToolPanelDeck::InsertPanel( const PToolPanel& i_pPanel, const size_t i_nPosition ) + { + return m_pImpl->InsertPanel( i_pPanel, i_nPosition ); + } + + //-------------------------------------------------------------------- + PToolPanel ToolPanelDeck::RemovePanel( const size_t i_nPosition ) + { + return m_pImpl->RemovePanel( i_nPosition ); + } + + //-------------------------------------------------------------------- + PDeckLayouter ToolPanelDeck::GetLayouter() const + { + return m_pImpl->GetLayouter(); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::SetLayouter( const PDeckLayouter& i_pNewLayouter ) + { + return m_pImpl->SetLayouter( i_pNewLayouter ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::AddListener( IToolPanelDeckListener& i_rListener ) + { + m_pImpl->AddListener( i_rListener ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::RemoveListener( IToolPanelDeckListener& i_rListener ) + { + m_pImpl->RemoveListener( i_rListener ); + } + + //-------------------------------------------------------------------- + Window& ToolPanelDeck::GetPanelWindowAnchor() + { + return m_pImpl->GetPanelWindowAnchor(); + } + + //-------------------------------------------------------------------- + const Window& ToolPanelDeck::GetPanelWindowAnchor() const + { + return m_pImpl->GetPanelWindowAnchor(); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::Resize() + { + Control::Resize(); + m_pImpl->LayoutAll(); + } + + //-------------------------------------------------------------------- + long ToolPanelDeck::Notify( NotifyEvent& i_rNotifyEvent ) + { + bool bHandled = false; + if ( i_rNotifyEvent.GetType() == EVENT_KEYINPUT ) + { + const KeyEvent* pEvent = i_rNotifyEvent.GetKeyEvent(); + const KeyCode& rKeyCode = pEvent->GetKeyCode(); + if ( rKeyCode.GetModifier() == KEY_MOD1 ) + { + bHandled = true; + switch ( rKeyCode.GetCode() ) + { + case KEY_HOME: + m_pImpl->DoAction( ACTION_ACTIVATE_FIRST ); + break; + case KEY_PAGEUP: + m_pImpl->DoAction( ACTION_ACTIVATE_PREV ); + break; + case KEY_PAGEDOWN: + m_pImpl->DoAction( ACTION_ACTIVATE_NEXT ); + break; + case KEY_END: + m_pImpl->DoAction( ACTION_ACTIVATE_LAST ); + break; + default: + bHandled = false; + break; + } + } + else if ( rKeyCode.GetModifier() == ( KEY_MOD1 | KEY_SHIFT ) ) + { + if ( rKeyCode.GetCode() == KEY_E ) + { + m_pImpl->DoAction( ACTION_TOGGLE_FOCUS ); + bHandled = true; + } + } + } + + if ( bHandled ) + return 1; + + return Control::Notify( i_rNotifyEvent ); + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::GetFocus() + { + Control::GetFocus(); + if ( m_pImpl->IsDead() ) + return; + if ( !m_pImpl->FocusActivePanel() ) + { + PDeckLayouter pLayouter( GetLayouter() ); + ENSURE_OR_RETURN_VOID( pLayouter.get(), "ToolPanelDeck::GetFocus: no layouter?!" ); + pLayouter->SetFocusToPanelSelector(); + } + } + + //-------------------------------------------------------------------- + void ToolPanelDeck::SetAccessibleParentWindow( Window* i_pAccessibleParent ) + { + m_pImpl->SetAccessibleParentWindow( i_pAccessibleParent ); + } + + //-------------------------------------------------------------------- + Window* ToolPanelDeck::GetAccessibleParentWindow() const + { + Window* pAccessibleParent( m_pImpl->GetAccessibleParentWindow() ); + if ( !pAccessibleParent ) + pAccessibleParent = Window::GetAccessibleParentWindow(); + return pAccessibleParent; + } + + //-------------------------------------------------------------------- + Reference< XWindowPeer > ToolPanelDeck::GetComponentInterface( BOOL i_bCreate ) + { + Reference< XWindowPeer > xWindowPeer( Control::GetComponentInterface( FALSE ) ); + if ( !xWindowPeer.is() && i_bCreate ) + { + xWindowPeer.set( new ToolPanelDeckPeer( *this ) ); + SetComponentInterface( xWindowPeer ); + } + return xWindowPeer; + } + +//........................................................................ +} // namespace svt +//........................................................................ diff --git a/svtools/source/toolpanel/toolpaneldeckpeer.cxx b/svtools/source/toolpanel/toolpaneldeckpeer.cxx new file mode 100755 index 000000000000..0a84a90b4fb3 --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldeckpeer.cxx @@ -0,0 +1,99 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "toolpaneldeckpeer.hxx" +#include "svtools/toolpanel/toolpaneldeck.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::accessibility::XAccessibleContext; + using ::com::sun::star::lang::DisposedException; + /** === end UNO using === **/ + + //================================================================================================================== + //= ToolPanelDeckPeer + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDeckPeer::ToolPanelDeckPeer( ToolPanelDeck& i_rDeck ) + :VCLXWindow() + ,m_pDeck( &i_rDeck ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDeckPeer::~ToolPanelDeckPeer() + { + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessibleContext > ToolPanelDeckPeer::CreateAccessibleContext() + { + ::vos::OGuard aSolarGuard( GetMutex() ); + if ( m_pDeck == NULL ) + throw DisposedException( ::rtl::OUString(), *this ); + + Window* pAccessibleParent( m_pDeck->GetAccessibleParentWindow() ); + ENSURE_OR_RETURN( pAccessibleParent != NULL, "no accessible parent => no accessible context", NULL ); + Reference< XAccessible > xAccessibleParent( pAccessibleParent->GetAccessible(), UNO_SET_THROW ); + return m_aAccessibleFactory.getFactory().createAccessibleToolPanelDeck( xAccessibleParent, *m_pDeck ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL ToolPanelDeckPeer::dispose() throw(RuntimeException) + { + { + ::vos::OGuard aSolarGuard( GetMutex() ); + m_pDeck = NULL; + } + VCLXWindow::dispose(); + } + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/toolpaneldeckpeer.hxx b/svtools/source/toolpanel/toolpaneldeckpeer.hxx new file mode 100755 index 000000000000..4b6607ecbd05 --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldeckpeer.hxx @@ -0,0 +1,69 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_TOOLPANELDECKPEER_HXX +#define SVT_TOOLPANELDECKPEER_HXX + +#include "svtaccessiblefactory.hxx" + +/** === begin UNO includes === **/ +/** === end UNO includes === **/ + +#include <toolkit/awt/vclxwindow.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + class ToolPanelDeck; + //================================================================================================================== + //= ToolPanelDeckPeer + //================================================================================================================== + class ToolPanelDeckPeer : public VCLXWindow + { + public: + ToolPanelDeckPeer( ToolPanelDeck& i_rDeck ); + + protected: + ~ToolPanelDeckPeer(); + + // VCLXWindow overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > CreateAccessibleContext(); + + // XComponent + void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + private: + AccessibleFactoryAccess m_aAccessibleFactory; + ToolPanelDeck* m_pDeck; + }; + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... + +#endif // SVT_TOOLPANELDECKPEER_HXX diff --git a/svtools/source/toolpanel/toolpaneldrawer.cxx b/svtools/source/toolpanel/toolpaneldrawer.cxx new file mode 100644 index 000000000000..851556bc7874 --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldrawer.cxx @@ -0,0 +1,373 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "toolpaneldrawer.hxx" +#include "toolpaneldrawerpeer.hxx" +#include "svtools/svtdata.hxx" +#include "svtools/svtools.hrc" + +#include <com/sun/star/accessibility/AccessibleRole.hpp> + +#include <vcl/lineinfo.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> +#include <vcl/vclevent.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::awt::XWindowPeer; + namespace AccessibleRole = ::com::sun::star::accessibility::AccessibleRole; + + static const int s_nIndentationWidth = 16; + + //================================================================================================================== + //= DrawerVisualization + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + DrawerVisualization::DrawerVisualization( ToolPanelDrawer& i_rParent ) + :Window( &i_rParent ) + ,m_rDrawer( i_rParent ) + { + SetMouseTransparent( TRUE ); + Show(); + SetAccessibleRole( AccessibleRole::LABEL ); + } + + //------------------------------------------------------------------------------------------------------------------ + DrawerVisualization::~DrawerVisualization() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void DrawerVisualization::Paint( const Rectangle& i_rBoundingBox ) + { + Window::Paint( i_rBoundingBox ); + m_rDrawer.Paint(); + } + + //================================================================================================================== + //= ToolPanelDrawer + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDrawer::ToolPanelDrawer( Window& i_rParent, const ::rtl::OUString& i_rTitle ) + :Window( &i_rParent, WB_TABSTOP ) + ,m_pPaintDevice( new VirtualDevice( *this ) ) + ,m_aVisualization( *this ) + ,m_bFocused( false ) + ,m_bExpanded( false ) + { + EnableMapMode( FALSE ); + SetBackground( Wallpaper() ); + SetPointer( POINTER_REFHAND ); + + SetAccessibleRole( AccessibleRole::LIST_ITEM ); + + SetText( i_rTitle ); + SetAccessibleName( i_rTitle ); + SetAccessibleDescription( i_rTitle ); + + m_aVisualization.SetAccessibleName( i_rTitle ); + m_aVisualization.SetAccessibleDescription( i_rTitle ); + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDrawer::~ToolPanelDrawer() + { + } + + //------------------------------------------------------------------------------------------------------------------ + long ToolPanelDrawer::GetPreferredHeightPixel() const + { + Rectangle aTitleBarBox( impl_calcTitleBarBox( impl_calcTextBoundingBox() ) ); + return aTitleBarBox.GetHeight(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::Paint() + { + m_pPaintDevice->SetMapMode( GetMapMode() ); + m_pPaintDevice->SetOutputSize( GetOutputSizePixel() ); + m_pPaintDevice->SetSettings( GetSettings() ); + m_pPaintDevice->SetDrawMode( GetDrawMode() ); + + const Rectangle aTextBox( impl_calcTextBoundingBox() ); + impl_paintBackground( impl_calcTitleBarBox( aTextBox ) ); + + Rectangle aFocusBox( impl_paintExpansionIndicator( aTextBox ) ); + + m_pPaintDevice->DrawText( aTextBox, GetText(), impl_getTextStyle() ); + + aFocusBox.Union( aTextBox ); + aFocusBox.Left() += 2; + impl_paintFocusIndicator( aFocusBox ); + + m_aVisualization.DrawOutDev( + Point(), GetOutputSizePixel(), + Point(), GetOutputSizePixel(), + *m_pPaintDevice + ); + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle ToolPanelDrawer::impl_paintExpansionIndicator( const Rectangle& i_rTextBox ) + { + Rectangle aExpansionIndicatorArea; + + Image aImage( impl_getExpansionIndicator() ); + const int nHeight( aImage.GetSizePixel().Height() ); + if ( nHeight > 0 ) + { + Point aPosition( + 0, + i_rTextBox.Top() + ( GetTextHeight() - nHeight ) / 2 + ); + m_pPaintDevice->DrawImage( aPosition, aImage ); + + aExpansionIndicatorArea = Rectangle( aPosition, aImage.GetSizePixel() ); + } + + return aExpansionIndicatorArea; + } + + //------------------------------------------------------------------------------------------------------------------ + Image ToolPanelDrawer::impl_getExpansionIndicator() const + { + const bool bHighContrastMode( GetSettings().GetStyleSettings().GetHighContrastMode() != 0 ); + USHORT nResourceId = 0; + if ( m_bExpanded ) + if ( bHighContrastMode ) + nResourceId = IMG_TRIANGLE_DOWN_HC; + else + nResourceId = IMG_TRIANGLE_DOWN; + else + if ( bHighContrastMode ) + nResourceId = IMG_TRIANGLE_RIGHT_HC; + else + nResourceId = IMG_TRIANGLE_RIGHT; + return Image( SvtResId( nResourceId ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + USHORT ToolPanelDrawer::impl_getTextStyle() const + { + const USHORT nBasicStyle = TEXT_DRAW_LEFT + | TEXT_DRAW_TOP + | TEXT_DRAW_WORDBREAK; + + if ( IsEnabled() ) + return nBasicStyle; + + return nBasicStyle | TEXT_DRAW_DISABLE; + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::impl_paintBackground( const Rectangle& i_rTitleBarBox ) + { + m_pPaintDevice->SetFillColor( GetSettings().GetStyleSettings().GetDialogColor() ); + m_pPaintDevice->DrawRect( i_rTitleBarBox ); + + m_pPaintDevice->SetFillColor(); + m_pPaintDevice->SetLineColor( GetSettings().GetStyleSettings().GetLightColor() ); + m_pPaintDevice->DrawLine( i_rTitleBarBox.TopLeft(), i_rTitleBarBox.TopRight() ); + m_pPaintDevice->DrawLine( i_rTitleBarBox.TopLeft(), i_rTitleBarBox.BottomLeft() ); + + m_pPaintDevice->SetLineColor( GetSettings().GetStyleSettings().GetShadowColor() ); + m_pPaintDevice->DrawLine( i_rTitleBarBox.BottomLeft(), i_rTitleBarBox.BottomRight() ); + m_pPaintDevice->DrawLine( i_rTitleBarBox.TopRight(), i_rTitleBarBox.BottomRight() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::impl_paintFocusIndicator( const Rectangle& i_rTextBox ) + { + if ( m_bFocused ) + { + const Rectangle aTextPixelBox( m_pPaintDevice->LogicToPixel( i_rTextBox ) ); + + m_pPaintDevice->EnableMapMode( FALSE ); + m_pPaintDevice->SetFillColor(); + + Rectangle aBox( i_rTextBox ); + aBox.Top() -= 1; + aBox.Bottom() += 1; + + m_pPaintDevice->DrawRect( aTextPixelBox ); + + LineInfo aDottedStyle( LINE_DASH ); + aDottedStyle.SetDashCount( 0 ); + aDottedStyle.SetDotCount( 1 ); + aDottedStyle.SetDotLen( 1 ); + aDottedStyle.SetDistance( 1 ); + + m_pPaintDevice->SetLineColor( COL_BLACK ); + m_pPaintDevice->DrawPolyLine( Polygon( aTextPixelBox ), aDottedStyle ); + m_pPaintDevice->EnableMapMode( FALSE ); + } + else + HideFocus(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::GetFocus() + { + m_bFocused = true; + Invalidate(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::LoseFocus() + { + m_bFocused = false; + Invalidate(); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::Resize() + { + Window::Resize(); + m_aVisualization.SetPosSizePixel( Point(), GetOutputSizePixel() ); + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::MouseButtonDown( const MouseEvent& i_rMouseEvent ) + { + // consume this event, and do not forward to the base class - it would sent a NotifyEvent, which in turn, when + // we live in a DockingWindow, would start undocking + (void)i_rMouseEvent; + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::DataChanged( const DataChangedEvent& i_rEvent ) + { + Window::DataChanged( i_rEvent ); + + switch ( i_rEvent.GetType() ) + { + case DATACHANGED_SETTINGS: + if ( ( i_rEvent.GetFlags() & SETTINGS_STYLE ) == 0 ) + break; + SetSettings( Application::GetSettings() ); + m_pPaintDevice.reset( new VirtualDevice( *this ) ); + + // fall through. + + case DATACHANGED_FONTS: + case DATACHANGED_FONTSUBSTITUTION: + { + const StyleSettings& rStyleSettings( GetSettings().GetStyleSettings() ); + + // Font. + Font aFont = rStyleSettings.GetAppFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + + // Color. + Color aColor; + if ( IsControlForeground() ) + aColor = GetControlForeground(); + else + aColor = rStyleSettings.GetButtonTextColor(); + SetTextColor( aColor ); + SetTextFillColor(); + + Invalidate(); + } + break; + } + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWindowPeer > ToolPanelDrawer::GetComponentInterface( BOOL i_bCreate ) + { + Reference< XWindowPeer > xWindowPeer( Window::GetComponentInterface( FALSE ) ); + if ( !xWindowPeer.is() && i_bCreate ) + { + xWindowPeer.set( new ToolPanelDrawerPeer() ); + SetComponentInterface( xWindowPeer ); + } + return xWindowPeer; + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle ToolPanelDrawer::impl_calcTextBoundingBox() const + { + Font aFont( GetFont() ); + if ( m_bExpanded ) + aFont.SetWeight( m_bExpanded ? WEIGHT_BOLD : WEIGHT_NORMAL ); + m_pPaintDevice->SetFont( aFont ); + + int nAvailableWidth = m_pPaintDevice->GetTextWidth( GetText() ); + + Rectangle aTextBox( + Point(), + Size( + nAvailableWidth, + GetSettings().GetStyleSettings().GetTitleHeight() + ) + ); + aTextBox.Top() += ( aTextBox.GetHeight() - GetTextHeight() ) / 2; + aTextBox.Left() += s_nIndentationWidth; + aTextBox.Right() -= 1; + + aTextBox = m_pPaintDevice->GetTextRect( aTextBox, GetText(), impl_getTextStyle() ); + return aTextBox; + } + + //------------------------------------------------------------------------------------------------------------------ + Rectangle ToolPanelDrawer::impl_calcTitleBarBox( const Rectangle& i_rTextBox ) const + { + Rectangle aTitleBarBox( i_rTextBox ); + aTitleBarBox.Bottom() += aTitleBarBox.Top(); + aTitleBarBox.Top() = 0; + aTitleBarBox.Left() = 0; + + const long nWidth = GetOutputSizePixel().Width(); + if ( aTitleBarBox.GetWidth() < nWidth ) + aTitleBarBox.Right() = nWidth - 1; + + return aTitleBarBox; + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawer::SetExpanded( const bool i_bExpanded ) + { + if ( m_bExpanded != i_bExpanded ) + { + m_bExpanded = i_bExpanded; + CallEventListeners( m_bExpanded ? VCLEVENT_ITEM_EXPANDED : VCLEVENT_ITEM_COLLAPSED ); + Invalidate(); + } + } + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/toolpaneldrawer.hxx b/svtools/source/toolpanel/toolpaneldrawer.hxx new file mode 100644 index 000000000000..a465a0a6c9e1 --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldrawer.hxx @@ -0,0 +1,113 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include <vcl/window.hxx> +#include <vcl/virdev.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + class ToolPanelDrawer; + //================================================================================================================== + //= DrawerVisualization + //================================================================================================================== + /** serves a single purpose - let ZoomText read the drawers ... + + Strange enough, ZoomText does not read the drawers when they get the focus (in none of the combinations + of AccessibleRoles I tried), except when it does have an AccessibleChild with the role LABEL. To "inject" + such a child into the A11Y hierarchy, we use this window here. + + (We could also inject the A11Y component on the A11Y level only, but this would mean additional code. With + this approach here, VCL/toolkit will take care of creating and maintaining the A11Y component for us.) + */ + class DrawerVisualization : public Window + { + public: + DrawerVisualization( ToolPanelDrawer& i_rParent ); + ~DrawerVisualization(); + + protected: + // Window overridables + virtual void Paint( const Rectangle& i_rBoundingBox ); + + private: + ToolPanelDrawer& m_rDrawer; + }; + + //================================================================================================================== + //= ToolPanelDrawer + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + class ToolPanelDrawer : public Window + { + public: + ToolPanelDrawer( Window& i_rParent, const ::rtl::OUString& i_rTitle ); + ~ToolPanelDrawer(); + + long GetPreferredHeightPixel() const; + void SetExpanded( const bool i_bExpanded ); + bool IsExpanded() const { return m_bExpanded; } + + void Paint(); + + protected: + // Window overridables + virtual void GetFocus(); + virtual void LoseFocus(); + virtual void Resize(); + virtual void DataChanged( const DataChangedEvent& i_rEvent ); + virtual void MouseButtonDown( const MouseEvent& i_rMouseEvent ); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > + GetComponentInterface( BOOL i_bCreate ); + + private: + Rectangle impl_calcTextBoundingBox() const; + Rectangle impl_calcTitleBarBox( const Rectangle& i_rTextBox ) const; + void impl_paintBackground( const Rectangle& i_rTitleBarBox ); + USHORT impl_getTextStyle() const; + void impl_paintFocusIndicator( const Rectangle& i_rTextBox ); + Rectangle impl_paintExpansionIndicator( const Rectangle& i_rTextBox ); + Image impl_getExpansionIndicator() const; + + // don't expose SetText. Our text is used as AccessibleName/Desc, and those are not expected to change. + using Window::SetText; + using Window::Paint; + + private: + ::std::auto_ptr< VirtualDevice > m_pPaintDevice; + DrawerVisualization m_aVisualization; + bool m_bFocused; + bool m_bExpanded; + }; + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/toolpaneldrawerpeer.cxx b/svtools/source/toolpanel/toolpaneldrawerpeer.cxx new file mode 100644 index 000000000000..959527330897 --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldrawerpeer.cxx @@ -0,0 +1,142 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "toolpaneldrawerpeer.hxx" +#include "toolpaneldrawer.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> +#include <toolkit/awt/vclxaccessiblecomponent.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <vcl/vclevent.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::accessibility::XAccessibleContext; + /** === end UNO using === **/ + namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType; + namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId; + + //================================================================================================================== + //= ToolPanelDrawerContext + //================================================================================================================== + class ToolPanelDrawerContext : public VCLXAccessibleComponent + { + public: + ToolPanelDrawerContext( VCLXWindow& i_rWindow ) + :VCLXAccessibleComponent( &i_rWindow ) + { + } + + virtual void ProcessWindowEvent( const VclWindowEvent& i_rVclWindowEvent ); + virtual void FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& i_rStateSet ); + + protected: + ~ToolPanelDrawerContext() + { + } + }; + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawerContext::ProcessWindowEvent( const VclWindowEvent& i_rVclWindowEvent ) + { + VCLXAccessibleComponent::ProcessWindowEvent( i_rVclWindowEvent ); + + switch ( i_rVclWindowEvent.GetId() ) + { + case VCLEVENT_ITEM_EXPANDED: + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, Any(), makeAny( AccessibleStateType::EXPANDED ) ); + break; + case VCLEVENT_ITEM_COLLAPSED: + NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, makeAny( AccessibleStateType::EXPANDED ), Any() ); + break; + } + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelDrawerContext::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& i_rStateSet ) + { + VCLXAccessibleComponent::FillAccessibleStateSet( i_rStateSet ); + if ( !GetWindow() ) + return; + + i_rStateSet.AddState( AccessibleStateType::EXPANDABLE ); + i_rStateSet.AddState( AccessibleStateType::FOCUSABLE ); + + const ToolPanelDrawer* pDrawer( dynamic_cast< const ToolPanelDrawer* > ( GetWindow() ) ); + ENSURE_OR_RETURN_VOID( pDrawer, "ToolPanelDrawerContext::FillAccessibleStateSet: illegal window!" ); + if ( pDrawer->IsExpanded() ) + i_rStateSet.AddState( AccessibleStateType::EXPANDED ); + + if ( pDrawer->HasChildPathFocus() ) + i_rStateSet.AddState( AccessibleStateType::FOCUSED ); + } + + //================================================================================================================== + //= ToolPanelDrawerPeer + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDrawerPeer::ToolPanelDrawerPeer() + :VCLXWindow() + { + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelDrawerPeer::~ToolPanelDrawerPeer() + { + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessibleContext > ToolPanelDrawerPeer::CreateAccessibleContext() + { + ::vos::OGuard aSolarGuard( GetMutex() ); + return new ToolPanelDrawerContext( *this ); + } + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... diff --git a/svtools/source/toolpanel/toolpaneldrawerpeer.hxx b/svtools/source/toolpanel/toolpaneldrawerpeer.hxx new file mode 100644 index 000000000000..5fcf0ac0ae7c --- /dev/null +++ b/svtools/source/toolpanel/toolpaneldrawerpeer.hxx @@ -0,0 +1,56 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_TOOLPANELDRAWERPEER_HXX +#define SVT_TOOLPANELDRAWERPEER_HXX + +#include <toolkit/awt/vclxwindow.hxx> + +//...................................................................................................................... +namespace svt +{ +//...................................................................................................................... + + //================================================================================================================== + //= ToolPanelDrawerPeer + //================================================================================================================== + class ToolPanelDrawerPeer : public VCLXWindow + { + public: + ToolPanelDrawerPeer(); + + protected: + ~ToolPanelDrawerPeer(); + + // VCLXWindow overridables + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > CreateAccessibleContext(); + }; + +//...................................................................................................................... +} // namespace svt +//...................................................................................................................... + +#endif // SVT_TOOLPANELDRAWERPEER_HXX diff --git a/svtools/source/uno/makefile.mk b/svtools/source/uno/makefile.mk index 7bfe37624947..7c1c44006047 100644 --- a/svtools/source/uno/makefile.mk +++ b/svtools/source/uno/makefile.mk @@ -38,9 +38,6 @@ ENABLE_EXCEPTIONS=TRUE # --- Files -------------------------------------------------------- -SRS1NAME= uno -SRC1FILES= unoifac2.src - SLOFILES= \ $(SLO)$/addrtempuno.obj \ $(SLO)$/contextmenuhelper.obj \ @@ -55,7 +52,9 @@ SLOFILES= \ $(SLO)$/unoevent.obj \ $(SLO)$/unoiface.obj \ $(SLO)$/unoimap.obj \ - $(SLO)$/svtxgridcontrol.obj + $(SLO)$/svtxgridcontrol.obj \ + $(SLO)$/popupwindowcontroller.obj \ + $(SLO)$/popupmenucontrollerbase.obj # --- Targets ------------------------------------------------------ diff --git a/svtools/source/uno/miscservices.cxx b/svtools/source/uno/miscservices.cxx index 433c1e1acbcb..e16a1ecb56dc 100644 --- a/svtools/source/uno/miscservices.cxx +++ b/svtools/source/uno/miscservices.cxx @@ -38,10 +38,13 @@ #include <uno/mapping.hxx> #include "provider.hxx" #include "renderer.hxx" +#include "unowizard.hxx" #include <com/sun/star/registry/XRegistryKey.hpp> #include "comphelper/servicedecl.hxx" +#include "cppuhelper/implementationentry.hxx" + using namespace ::com::sun::star::uno; using namespace ::com::sun::star::registry; using namespace ::com::sun::star::lang; @@ -67,6 +70,20 @@ extern sdecl::ServiceDecl const serviceDecl; Reference< XInterface > SAL_CALL ImplName##_CreateInstance( const Reference< XMultiServiceFactory >& ); \ } +namespace +{ + static struct ::cppu::ImplementationEntry s_aServiceEntries[] = + { + { + ::svt::uno::Wizard::Create, + ::svt::uno::Wizard::getImplementationName_static, + ::svt::uno::Wizard::getSupportedServiceNames_static, + ::cppu::createSingleComponentFactory, NULL, 0 + }, + { 0, 0, 0, 0, 0, 0 } + }; +} + // ------------------------------------------------------------------------------------- DECLARE_CREATEINSTANCE_NAMESPACE( svt, OAddressBookSourceDialogUno ) @@ -126,9 +143,9 @@ SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL component_writeInfo ( xNewKey->createKey( aServices.getConstArray()[ i ] ); if ( !component_writeInfoHelper( reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ), reinterpret_cast< registry::XRegistryKey* >( _pRegistryKey ), serviceDecl ) ) - return false; + return false; - return sal_True; + return ::cppu::component_writeInfoHelper( pServiceManager, _pRegistryKey, s_aServiceEntries ); } return sal_False; } @@ -185,6 +202,8 @@ SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( else { pResult = component_getFactoryHelper( pImplementationName, reinterpret_cast< lang::XMultiServiceFactory * >( _pServiceManager ),reinterpret_cast< registry::XRegistryKey* >( pRegistryKey ), serviceDecl ); + if ( !pResult ) + pResult = ::cppu::component_getFactoryHelper( pImplementationName, _pServiceManager, pRegistryKey, s_aServiceEntries ); } if ( xFactory.is() ) diff --git a/svtools/source/uno/popupmenucontrollerbase.cxx b/svtools/source/uno/popupmenucontrollerbase.cxx new file mode 100644 index 000000000000..ac75a1b9a24b --- /dev/null +++ b/svtools/source/uno/popupmenucontrollerbase.cxx @@ -0,0 +1,420 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +//_________________________________________________________________________________________________________________ +// my own includes +//_________________________________________________________________________________________________________________ +#include "svtools/popupmenucontrollerbase.hxx" + + +//_________________________________________________________________________________________________________________ +// interface includes +//_________________________________________________________________________________________________________________ +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/awt/MenuItemStyle.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/awt/XMenuExtended.hpp> + +//_________________________________________________________________________________________________________________ +// includes of other projects +//_________________________________________________________________________________________________________________ + +#ifndef _VCL_MENU_HXX_ +#include <vcl/menu.hxx> +#endif +#include <vcl/svapp.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/logfile.hxx> +#include <vos/mutex.hxx> + +//_________________________________________________________________________________________________________________ +// Defines +//_________________________________________________________________________________________________________________ +// + +using ::rtl::OUString; + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::frame; +using namespace com::sun::star::beans; +using namespace com::sun::star::util; + +namespace svt +{ + +struct PopupMenuControllerBaseDispatchInfo +{ + Reference< XDispatch > mxDispatch; + const URL maURL; + const Sequence< PropertyValue > maArgs; + + PopupMenuControllerBaseDispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs ) + : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {} +}; + +PopupMenuControllerBase::PopupMenuControllerBase( const Reference< XMultiServiceFactory >& xServiceManager ) : + ::comphelper::OBaseMutex(), + PopupMenuControllerBaseType(m_aMutex), + m_bInitialized( false ), + m_xServiceManager( xServiceManager ) +{ + if ( m_xServiceManager.is() ) + m_xURLTransformer.set( m_xServiceManager->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))),UNO_QUERY ); +} + +PopupMenuControllerBase::~PopupMenuControllerBase() +{ +} + +// protected function +void PopupMenuControllerBase::throwIfDisposed() throw ( RuntimeException ) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + throw com::sun::star::lang::DisposedException(); +} + +// protected function +void PopupMenuControllerBase::resetPopupMenu( com::sun::star::uno::Reference< com::sun::star::awt::XPopupMenu >& rPopupMenu ) +{ + VCLXPopupMenu* pPopupMenu = 0; + if ( rPopupMenu.is() && rPopupMenu->getItemCount() > 0 ) + { + pPopupMenu = (VCLXPopupMenu *)VCLXMenu::GetImplementation( rPopupMenu ); + if ( pPopupMenu ) + { + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + PopupMenu* pVCLPopupMenu = (PopupMenu *)pPopupMenu->GetMenu(); + pVCLPopupMenu->Clear(); + } + } +} + +void SAL_CALL PopupMenuControllerBase::disposing() +{ + // Reset our members and set disposed flag + osl::MutexGuard aLock( m_aMutex ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xPopupMenu.clear(); + m_xServiceManager.clear(); +} + +// XServiceInfo + +sal_Bool SAL_CALL PopupMenuControllerBase::supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException) +{ + const Sequence< rtl::OUString > aSNL( getSupportedServiceNames() ); + const rtl::OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// XEventListener +void SAL_CALL PopupMenuControllerBase::disposing( const EventObject& ) throw ( RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + m_xFrame.clear(); + m_xDispatch.clear(); + m_xPopupMenu.clear(); +} + +// XMenuListener +void SAL_CALL PopupMenuControllerBase::highlight( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void PopupMenuControllerBase::impl_select(const Reference< XDispatch >& _xDispatch,const URL& aURL) +{ + Sequence<PropertyValue> aArgs; + OSL_ENSURE(_xDispatch.is(),"PopupMenuControllerBase::impl_select: No dispatch"); + if ( _xDispatch.is() ) + _xDispatch->dispatch( aURL, aArgs ); +} + +void SAL_CALL PopupMenuControllerBase::select( const awt::MenuEvent& rEvent ) throw (RuntimeException) +{ + throwIfDisposed(); + + osl::MutexGuard aLock( m_aMutex ); + + Reference< awt::XMenuExtended > xExtMenu( m_xPopupMenu, UNO_QUERY ); + if( xExtMenu.is() ) + { + Sequence<PropertyValue> aArgs; + dispatchCommand( xExtMenu->getCommand( rEvent.MenuId ), aArgs ); + } +} + +void PopupMenuControllerBase::dispatchCommand( const ::rtl::OUString& sCommandURL, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) +{ + osl::MutexGuard aLock( m_aMutex ); + + throwIfDisposed(); + + try + { + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW ); + URL aURL; + aURL.Complete = sCommandURL; + m_xURLTransformer->parseStrict( aURL ); + + Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW ); + + Application::PostUserEvent( STATIC_LINK(0, PopupMenuControllerBase, ExecuteHdl_Impl), new PopupMenuControllerBaseDispatchInfo( xDispatch, aURL, rArgs ) ); + + } + catch( Exception& ) + { + } + +} + +IMPL_STATIC_LINK_NOINSTANCE( PopupMenuControllerBase, ExecuteHdl_Impl, PopupMenuControllerBaseDispatchInfo*, pDispatchInfo ) +{ + pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs ); + delete pDispatchInfo; + return 0; +} + +void SAL_CALL PopupMenuControllerBase::activate( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void SAL_CALL PopupMenuControllerBase::deactivate( const awt::MenuEvent& ) throw (RuntimeException) +{ +} + +void SAL_CALL PopupMenuControllerBase::updatePopupMenu() throw ( ::com::sun::star::uno::RuntimeException ) +{ + osl::ClearableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + updateCommand( m_aCommandURL ); +} + +void SAL_CALL PopupMenuControllerBase::updateCommand( const rtl::OUString& rCommandURL ) +{ + osl::ClearableMutexGuard aLock( m_aMutex ); + Reference< XStatusListener > xStatusListener( static_cast< OWeakObject* >( this ), UNO_QUERY ); + Reference< XDispatch > xDispatch( m_xDispatch ); + URL aTargetURL; + aTargetURL.Complete = rCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + aLock.clear(); + + // Add/remove status listener to get a status update once + if ( xDispatch.is() ) + { + xDispatch->addStatusListener( xStatusListener, aTargetURL ); + xDispatch->removeStatusListener( xStatusListener, aTargetURL ); + } +} + + +// XDispatchProvider +Reference< XDispatch > SAL_CALL +PopupMenuControllerBase::queryDispatch( + const URL& /*aURL*/, + const rtl::OUString& /*sTarget*/, + sal_Int32 /*nFlags*/ ) +throw( RuntimeException ) +{ + // must be implemented by subclass + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); + + return Reference< XDispatch >(); +} + +Sequence< Reference< XDispatch > > SAL_CALL PopupMenuControllerBase::queryDispatches( const Sequence< DispatchDescriptor >& lDescriptor ) throw( RuntimeException ) +{ + // Create return list - which must have same size then the given descriptor + // It's not allowed to pack it! + osl::ClearableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + sal_Int32 nCount = lDescriptor.getLength(); + uno::Sequence< uno::Reference< frame::XDispatch > > lDispatcher( nCount ); + + // Step over all descriptors and try to get any dispatcher for it. + for( sal_Int32 i=0; i<nCount; ++i ) + { + lDispatcher[i] = queryDispatch( lDescriptor[i].FeatureURL , + lDescriptor[i].FrameName , + lDescriptor[i].SearchFlags ); + } + + return lDispatcher; +} + +// XDispatch +void SAL_CALL +PopupMenuControllerBase::dispatch( + const URL& /*aURL*/, + const Sequence< PropertyValue >& /*seqProperties*/ ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + // must be implemented by subclass + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); +} + +void SAL_CALL +PopupMenuControllerBase::addStatusListener( + const Reference< XStatusListener >& xControl, + const URL& aURL ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + osl::ResettableMutexGuard aLock( m_aMutex ); + throwIfDisposed(); + aLock.clear(); + + bool bStatusUpdate( false ); + rBHelper.addListener( ::getCppuType( &xControl ), xControl ); + + aLock.reset(); + if ( aURL.Complete.indexOf( m_aBaseURL ) == 0 ) + bStatusUpdate = true; + aLock.clear(); + + if ( bStatusUpdate ) + { + // Dummy update for popup menu controllers + FeatureStateEvent aEvent; + aEvent.FeatureURL = aURL; + aEvent.IsEnabled = sal_True; + aEvent.Requery = sal_False; + aEvent.State = Any(); + xControl->statusChanged( aEvent ); + } +} + +void SAL_CALL PopupMenuControllerBase::removeStatusListener( + const Reference< XStatusListener >& xControl, + const URL& /*aURL*/ ) +throw( ::com::sun::star::uno::RuntimeException ) +{ + rBHelper.removeListener( ::getCppuType( &xControl ), xControl ); +} + +::rtl::OUString PopupMenuControllerBase::determineBaseURL( const ::rtl::OUString& aURL ) +{ + // Just use the main part of the URL for popup menu controllers + sal_Int32 nQueryPart( 0 ); + sal_Int32 nSchemePart( 0 ); + rtl::OUString aMainURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.popup:" )); + + nSchemePart = aURL.indexOf( ':' ); + if (( nSchemePart > 0 ) && + ( aURL.getLength() > ( nSchemePart+1 ))) + { + nQueryPart = aURL.indexOf( '?', nSchemePart ); + if ( nQueryPart > 0 ) + aMainURL += aURL.copy( nSchemePart, nQueryPart-nSchemePart ); + else if ( nQueryPart == -1 ) + aMainURL += aURL.copy( nSchemePart+1 ); + } + + return aMainURL; +} + +// XInitialization +void SAL_CALL PopupMenuControllerBase::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + + sal_Bool bInitalized( m_bInitialized ); + if ( !bInitalized ) + { + PropertyValue aPropValue; + rtl::OUString aCommandURL; + Reference< XFrame > xFrame; + + for ( int i = 0; i < aArguments.getLength(); i++ ) + { + if ( aArguments[i] >>= aPropValue ) + { + if ( aPropValue.Name.equalsAscii( "Frame" )) + aPropValue.Value >>= xFrame; + else if ( aPropValue.Name.equalsAscii( "CommandURL" )) + aPropValue.Value >>= aCommandURL; + } + } + + if ( xFrame.is() && aCommandURL.getLength() ) + { + m_xFrame = xFrame; + m_aCommandURL = aCommandURL; + m_aBaseURL = determineBaseURL( aCommandURL ); + m_bInitialized = true; + } + } +} +// XPopupMenuController +void SAL_CALL PopupMenuControllerBase::setPopupMenu( const Reference< awt::XPopupMenu >& xPopupMenu ) throw ( RuntimeException ) +{ + osl::MutexGuard aLock( m_aMutex ); + throwIfDisposed(); + + if ( m_xFrame.is() && !m_xPopupMenu.is() ) + { + // Create popup menu on demand + vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); + + m_xPopupMenu = xPopupMenu; + m_xPopupMenu->addMenuListener( Reference< awt::XMenuListener >( (OWeakObject*)this, UNO_QUERY )); + + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY ); + + URL aTargetURL; + aTargetURL.Complete = m_aCommandURL; + m_xURLTransformer->parseStrict( aTargetURL ); + m_xDispatch = xDispatchProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 ); + + impl_setPopupMenu(); + + updatePopupMenu(); + } +} +void PopupMenuControllerBase::impl_setPopupMenu() +{ +} +} diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx new file mode 100644 index 000000000000..4fbaff23714d --- /dev/null +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -0,0 +1,258 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svtools.hxx" + +#include <toolkit/helper/vclunohelper.hxx> + +#include <vcl/toolbox.hxx> +#include <vcl/svapp.hxx> + +#include "svtools/popupwindowcontroller.hxx" +#include "svtools/toolbarmenu.hxx" + +using rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + + +namespace svt +{ + +class PopupWindowControllerImpl +{ +public: + PopupWindowControllerImpl(); + ~PopupWindowControllerImpl(); + + void SetPopupWindow( ::Window* pPopupWindow, ToolBox* pToolBox ); + + DECL_LINK( WindowEventListener, VclSimpleEvent* ); + DECL_STATIC_LINK( PopupWindowControllerImpl, AsyncDeleteWindowHdl, Window* ); + +private: + ::Window* mpPopupWindow; + ToolBox* mpToolBox; +}; + +PopupWindowControllerImpl::PopupWindowControllerImpl() +: mpPopupWindow( 0 ) +, mpToolBox( 0 ) +{ +} + +PopupWindowControllerImpl::~PopupWindowControllerImpl() +{ + if( mpPopupWindow ) + SetPopupWindow(0,0); +} + +void PopupWindowControllerImpl::SetPopupWindow( ::Window* pPopupWindow, ToolBox* pToolBox ) +{ + if( mpPopupWindow ) + { + mpPopupWindow->RemoveEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ) ); + Application::PostUserEvent( STATIC_LINK( this, PopupWindowControllerImpl, AsyncDeleteWindowHdl ), mpPopupWindow ); + } + mpPopupWindow = pPopupWindow; + mpToolBox = pToolBox; + + if( mpPopupWindow ) + { + mpPopupWindow->AddEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener )); + } +} + +IMPL_LINK( PopupWindowControllerImpl, WindowEventListener, VclSimpleEvent*, pEvent ) +{ + VclWindowEvent* pWindowEvent = dynamic_cast< VclWindowEvent* >( pEvent ); + if( pWindowEvent ) + { + switch( pWindowEvent->GetId() ) + { + case VCLEVENT_WINDOW_CLOSE: + case VCLEVENT_WINDOW_ENDPOPUPMODE: + SetPopupWindow(0,0); + break; + + case VCLEVENT_WINDOW_SHOW: + { + if( mpPopupWindow ) + { + if( mpToolBox ) + mpToolBox->CallEventListeners( VCLEVENT_DROPDOWN_OPEN, (void*)mpPopupWindow ); + mpPopupWindow->CallEventListeners( VCLEVENT_WINDOW_GETFOCUS, 0 ); + + svtools::ToolbarMenu* pToolbarMenu = dynamic_cast< svtools::ToolbarMenu* >( mpPopupWindow ); + if( pToolbarMenu ) + pToolbarMenu->highlightFirstEntry(); + break; + } + break; + } + case VCLEVENT_WINDOW_HIDE: + { + if( mpPopupWindow ) + { + mpPopupWindow->CallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS, 0 ); + if( mpToolBox ) + mpToolBox->CallEventListeners( VCLEVENT_DROPDOWN_CLOSE, (void*)mpPopupWindow ); + } + break; + } + } + } + return 1; +} + +//-------------------------------------------------------------------- + +IMPL_STATIC_LINK( PopupWindowControllerImpl, AsyncDeleteWindowHdl, Window*, pWindow ) +{ + (void)*pThis; + delete pWindow; + return 0; +} + +//======================================================================== +// class PopupWindowController +//======================================================================== + +PopupWindowController::PopupWindowController( const Reference< lang::XMultiServiceFactory >& rServiceManager, + const Reference< frame::XFrame >& xFrame, + const OUString& aCommandURL ) +: svt::ToolboxController( rServiceManager, xFrame, aCommandURL ) +, mpImpl( new PopupWindowControllerImpl() ) +{ +} + +PopupWindowController::~PopupWindowController() +{ +} + +// XInterface +Any SAL_CALL PopupWindowController::queryInterface( const Type& aType ) +throw (RuntimeException) +{ + Any a( ToolboxController::queryInterface( aType ) ); + if ( a.hasValue() ) + return a; + + return ::cppu::queryInterface( aType, static_cast< lang::XServiceInfo* >( this )); +} + +void SAL_CALL PopupWindowController::acquire() throw () +{ + ToolboxController::acquire(); +} + +void SAL_CALL PopupWindowController::release() throw () +{ + ToolboxController::release(); +} + +// XServiceInfo +sal_Bool SAL_CALL PopupWindowController::supportsService( const OUString& ServiceName ) throw(RuntimeException) +{ + const Sequence< OUString > aSNL( getSupportedServiceNames() ); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return true; + + return false; +} + +// XInitialization +void SAL_CALL PopupWindowController::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + svt::ToolboxController::initialize( aArguments ); + if( m_aCommandURL.getLength() ) + addStatusListener( m_aCommandURL ); +} + +// XComponent +void SAL_CALL PopupWindowController::dispose() throw (RuntimeException) +{ + if( m_aCommandURL.getLength() ) + removeStatusListener( m_aCommandURL ); + + svt::ToolboxController::dispose(); +} + + +// XStatusListener +void SAL_CALL PopupWindowController::statusChanged( const frame::FeatureStateEvent& rEvent ) throw ( RuntimeException ) +{ + svt::ToolboxController::statusChanged(rEvent); + enable( rEvent.IsEnabled ); +} + +// XToolbarController +void SAL_CALL PopupWindowController::execute( sal_Int16 KeyModifier ) throw (RuntimeException) +{ + svt::ToolboxController::execute( KeyModifier ); +} + +void SAL_CALL PopupWindowController::click() throw (RuntimeException) +{ + svt::ToolboxController::click(); +} + +void SAL_CALL PopupWindowController::doubleClick() throw (RuntimeException) +{ + svt::ToolboxController::doubleClick(); +} + +Reference< awt::XWindow > SAL_CALL PopupWindowController::createPopupWindow() throw (RuntimeException) +{ + ToolBox* pToolBox = dynamic_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); + if( pToolBox ) + { + ::Window* pItemWindow = pToolBox->GetItemWindow( pToolBox->GetDownItemId() ); + ::Window* pWin = createPopupWindow( pItemWindow ? pItemWindow : pToolBox ); + if( pWin ) + { + pWin->EnableDocking(true); + mpImpl->SetPopupWindow(pWin,pToolBox); + ::Window::GetDockingManager()->StartPopupMode( pToolBox, pWin, FLOATWIN_POPUPMODE_NOFOCUSCLOSE|FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE ); + } + } + return Reference< awt::XWindow >(); +} + +Reference< awt::XWindow > SAL_CALL PopupWindowController::createItemWindow( const Reference< awt::XWindow >& /*Parent*/ ) + throw (RuntimeException) +{ + return Reference< awt::XWindow >(); +} + +} + diff --git a/svtools/source/uno/svtxgridcontrol.cxx b/svtools/source/uno/svtxgridcontrol.cxx index b411181c2aab..99b36c390f23 100755 --- a/svtools/source/uno/svtxgridcontrol.cxx +++ b/svtools/source/uno/svtxgridcontrol.cxx @@ -79,7 +79,6 @@ SVTXGridControl::SVTXGridControl() //-------------------------------------------------------------------- SVTXGridControl::~SVTXGridControl() { - DELETEZ(m_pTableModel); } ::com::sun::star::uno::Any SVTXGridControl::queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException) @@ -129,6 +128,18 @@ void SVTXGridControl::setProperty( const ::rtl::OUString& PropertyName, const An TableControl* pTable = (TableControl*)GetWindow(); switch( GetPropertyId( PropertyName ) ) { + case BASEPROPERTY_BACKGROUNDCOLOR: + { + // let the base class handle this for the TableControl + VCLXWindow::setProperty( PropertyName, aValue ); + // and forward to the grid control's data window + if ( pTable->IsBackground() ) + pTable->getDataWindow()->SetBackground( pTable->GetBackground() ); + else + pTable->getDataWindow()->SetBackground(); + } + break; + case BASEPROPERTY_GRID_SELECTIONMODE: { SelectionType eSelectionType; @@ -410,6 +421,7 @@ void SVTXGridControl::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds ) } void SAL_CALL SVTXGridControl::setVisible( sal_Bool bVisible ) throw(::com::sun::star::uno::RuntimeException) { + ::vos::OGuard aGuard( GetMutex() ); TableControl* pTable = (TableControl*)GetWindow(); if ( pTable ) { @@ -425,6 +437,8 @@ void SAL_CALL SVTXGridControl::setFocus() throw(::com::sun::star::uno::RuntimeEx } void SAL_CALL SVTXGridControl::rowAdded(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) { + ::vos::OGuard aGuard( GetMutex() ); + std::vector< Any > newRow; Sequence< Any > rawRowData = Event.rowData; int colCount = m_xColumnModel->getColumnCount(); @@ -471,6 +485,8 @@ void SAL_CALL SVTXGridControl::rowAdded(const ::com::sun::star::awt::grid::GridD void SAL_CALL SVTXGridControl::rowRemoved(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) { + ::vos::OGuard aGuard( GetMutex() ); + TableControl* pTable = (TableControl*)GetWindow(); if(Event.index == -1) { @@ -478,6 +494,7 @@ void SAL_CALL SVTXGridControl::rowRemoved(const ::com::sun::star::awt::grid::Gri deselectAllRows(); if(m_pTableModel->hasRowHeaders()) m_pTableModel->getRowHeaderName().clear(); + pTable->clearSelection(); m_pTableModel->getCellContent().clear(); if(pTable->isAccessibleAlive()) { @@ -511,6 +528,8 @@ void SAL_CALL SVTXGridControl::rowRemoved(const ::com::sun::star::awt::grid::Gri void SAL_CALL SVTXGridControl::columnChanged(const ::com::sun::star::awt::grid::GridColumnEvent& Event ) throw (::com::sun::star::uno::RuntimeException) { + ::vos::OGuard aGuard( GetMutex() ); + TableControl* pTable = (TableControl*)GetWindow(); if(Event.valueName == rtl::OUString::createFromAscii("ColumnResize")) { @@ -558,6 +577,8 @@ void SAL_CALL SVTXGridControl::columnChanged(const ::com::sun::star::awt::grid: } void SAL_CALL SVTXGridControl::dataChanged(const ::com::sun::star::awt::grid::GridDataEvent& Event ) throw (::com::sun::star::uno::RuntimeException) { + ::vos::OGuard aGuard( GetMutex() ); + TableControl* pTable = (TableControl*)GetWindow(); if(Event.valueName == rtl::OUString::createFromAscii("RowHeight")) { diff --git a/svtools/source/uno/svtxgridcontrol.hxx b/svtools/source/uno/svtxgridcontrol.hxx index bcb8badf72e5..b15507e4614f 100755 --- a/svtools/source/uno/svtxgridcontrol.hxx +++ b/svtools/source/uno/svtxgridcontrol.hxx @@ -51,7 +51,7 @@ class SVTXGridControl : public ::cppu::ImplInheritanceHelper3< VCLXWindow, ::com ::com::sun::star::awt::grid::XGridDataListener, ::com::sun::star::awt::grid::XGridColumnListener> { private: - UnoControlTableModel* m_pTableModel; + ::boost::shared_ptr< UnoControlTableModel > m_pTableModel; ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridDataModel >m_xDataModel; ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridColumnModel >m_xColumnModel; bool m_bHasColumnHeaders; diff --git a/svtools/source/uno/toolboxcontroller.cxx b/svtools/source/uno/toolboxcontroller.cxx index 3f0b4e7c0ee6..92ae93f5080d 100644 --- a/svtools/source/uno/toolboxcontroller.cxx +++ b/svtools/source/uno/toolboxcontroller.cxx @@ -42,6 +42,14 @@ #include <toolkit/unohlp.hxx> #endif #include <vcl/toolbox.hxx> +//shizhobo +#include <com/sun/star/beans/PropertyAttribute.hpp> +const int TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIABLE = 1; +const int TOOLBARCONTROLLER_PROPCOUNT = 1; +const rtl::OUString TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIABLE( RTL_CONSTASCII_USTRINGPARAM( "SupportsVisiable" )); +//end + +using ::rtl::OUString; using namespace ::cppu; using namespace ::com::sun::star::awt; @@ -54,17 +62,38 @@ using namespace ::com::sun::star::frame; namespace svt { + +struct DispatchInfo +{ + Reference< XDispatch > mxDispatch; + const URL maURL; + const Sequence< PropertyValue > maArgs; + + DispatchInfo( const Reference< XDispatch >& xDispatch, const URL& rURL, const Sequence< PropertyValue >& rArgs ) + : mxDispatch( xDispatch ), maURL( rURL ), maArgs( rArgs ) {} +}; + struct ToolboxController_Impl { ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > m_xParentWindow; ::com::sun::star::uno::Reference< ::com::sun::star::util::XURLTransformer > m_xUrlTransformer; + rtl::OUString m_sModuleName; + sal_uInt16 m_nToolBoxId; + + DECL_STATIC_LINK( ToolboxController_Impl, ExecuteHdl_Impl, DispatchInfo* ); + + ToolboxController_Impl() + : m_nToolBoxId( SAL_MAX_UINT16 ) + {} }; ToolboxController::ToolboxController( + const Reference< XMultiServiceFactory >& rServiceManager, const Reference< XFrame >& xFrame, const ::rtl::OUString& aCommandURL ) : - OWeakObject() + OPropertyContainer(GetBroadcastHelper()) + , OWeakObject() , m_bInitialized( sal_False ) , m_bDisposed( sal_False ) , m_xFrame(xFrame) @@ -72,6 +101,10 @@ ToolboxController::ToolboxController( , m_aCommandURL( aCommandURL ) , m_aListenerContainer( m_aMutex ) { + //registger Propertyh by shizhoubo + registerProperty(TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIABLE, TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIABLE, com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY, + &m_bSupportVisiable, getCppuType(&m_bSupportVisiable)); + m_pImpl = new ToolboxController_Impl; try @@ -86,11 +119,16 @@ ToolboxController::ToolboxController( } ToolboxController::ToolboxController() : - OWeakObject() + OPropertyContainer(GetBroadcastHelper()) + , OWeakObject() , m_bInitialized( sal_False ) , m_bDisposed( sal_False ) , m_aListenerContainer( m_aMutex ) { + //registger Propertyh by shizhoubo + registerProperty(TOOLBARCONTROLLER_PROPNAME_SUPPORTSVISIABLE, TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIABLE, com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY, + &m_bSupportVisiable, getCppuType(&m_bSupportVisiable)); + m_pImpl = new ToolboxController_Impl; } @@ -146,11 +184,16 @@ throw ( RuntimeException ) static_cast< XInitialization* >( this ), static_cast< XComponent* >( this ), static_cast< XUpdatable* >( this )); - - if ( a.hasValue() ) - return a; - - return OWeakObject::queryInterface( rType ); + if ( !a.hasValue()) + { + a = ::cppu::queryInterface(rType + ,static_cast<XPropertySet*>(this) + ,static_cast<XMultiPropertySet*>(this) + ,static_cast<XFastPropertySet*>(this)); + if (!a.hasValue()) + return OWeakObject::queryInterface( rType ); + } + return a; } void SAL_CALL ToolboxController::acquire() throw () @@ -166,11 +209,6 @@ void SAL_CALL ToolboxController::release() throw () void SAL_CALL ToolboxController::initialize( const Sequence< Any >& aArguments ) throw ( Exception, RuntimeException ) { - const rtl::OUString aFrameName( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); - const rtl::OUString aCommandURLName( RTL_CONSTASCII_USTRINGPARAM( "CommandURL" )); - const rtl::OUString aServiceManagerName( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager" )); - const rtl::OUString aParentWindow( RTL_CONSTASCII_USTRINGPARAM( "ParentWindow" )); - bool bInitialized( true ); { @@ -186,20 +224,23 @@ throw ( Exception, RuntimeException ) { vos::OGuard aSolarMutexGuard( Application::GetSolarMutex() ); m_bInitialized = sal_True; - + //shizhoubo add + m_bSupportVisiable = sal_False; PropertyValue aPropValue; for ( int i = 0; i < aArguments.getLength(); i++ ) { if ( aArguments[i] >>= aPropValue ) { - if ( aPropValue.Name.equalsAscii( "Frame" )) + if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Frame") )) m_xFrame.set(aPropValue.Value,UNO_QUERY); - else if ( aPropValue.Name.equalsAscii( "CommandURL" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CommandURL") )) aPropValue.Value >>= m_aCommandURL; - else if ( aPropValue.Name.equalsAscii( "ServiceManager" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ServiceManager") )) m_xServiceManager.set(aPropValue.Value,UNO_QUERY); - else if ( aPropValue.Name.equalsAscii( "ParentWindow" )) + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ParentWindow") )) m_pImpl->m_xParentWindow.set(aPropValue.Value,UNO_QUERY); + else if ( aPropValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ModuleName" ) ) ) + aPropValue.Value >>= m_pImpl->m_sModuleName; } } @@ -704,4 +745,142 @@ Reference< ::com::sun::star::awt::XWindow > ToolboxController::getParent() const { return m_pImpl->m_xParentWindow; } + +const rtl::OUString& ToolboxController::getModuleName() const +{ + return m_pImpl->m_sModuleName; +} + +void ToolboxController::dispatchCommand( const OUString& sCommandURL, const Sequence< PropertyValue >& rArgs ) +{ + try + { + Reference< XDispatchProvider > xDispatchProvider( m_xFrame, UNO_QUERY_THROW ); + URL aURL; + aURL.Complete = sCommandURL; + getURLTransformer()->parseStrict( aURL ); + + Reference< XDispatch > xDispatch( xDispatchProvider->queryDispatch( aURL, OUString(), 0 ), UNO_QUERY_THROW ); + + Application::PostUserEvent( STATIC_LINK(0, ToolboxController_Impl, ExecuteHdl_Impl), new DispatchInfo( xDispatch, aURL, rArgs ) ); + + } + catch( Exception& ) + { + } +} + +// +//------------------------------------------------------------------------- +// XPropertySet by shizhoubo +com::sun::star::uno::Reference< com::sun::star::beans::XPropertySetInfo > SAL_CALL ToolboxController::getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException) +{ + Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) ); + return xInfo; +} +//------------------------------------------------------------------------- +::cppu::IPropertyArrayHelper& ToolboxController::getInfoHelper() +{ + return *const_cast<ToolboxController*>(this)->getArrayHelper(); +} +//OPropertyArrayUsageHelper by shizhoubo +//------------------------------------------------------------------------------ +::cppu::IPropertyArrayHelper* ToolboxController::createArrayHelper( ) const +{ + com::sun::star::uno::Sequence< Property > aProps; + describeProperties(aProps); + return new ::cppu::OPropertyArrayHelper(aProps); +} +//shizhoubo for supportsvisiable +void ToolboxController::setSupportVisiableProperty(sal_Bool bValue) +{ + m_bSupportVisiable = bValue; +} +//OPropertySetHelper by shizhoubo +sal_Bool SAL_CALL ToolboxController::convertFastPropertyValue( com::sun::star::uno::Any& aConvertedValue , + com::sun::star::uno::Any& aOldValue , + sal_Int32 nHandle , + const com::sun::star::uno::Any& aValue ) throw( com::sun::star::lang::IllegalArgumentException ) +{ + switch (nHandle) + { + case TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIABLE: + { + sal_Bool aNewValue; + aValue >>= aNewValue; + if (aNewValue != m_bSupportVisiable) + { + aConvertedValue <<= aNewValue; + aOldValue <<= m_bSupportVisiable; + return sal_True; + } + return sal_False; + } + } + return OPropertyContainer::convertFastPropertyValue(aConvertedValue, aOldValue, nHandle, aValue); +} + +void SAL_CALL ToolboxController::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const com::sun::star::uno::Any& aValue ) +throw( com::sun::star::uno::Exception) +{ + OPropertyContainer::setFastPropertyValue_NoBroadcast(nHandle, aValue); + if (TOOLBARCONTROLLER_PROPHANDLE_SUPPORTSVISIABLE == nHandle) + { + sal_Bool rValue(sal_False); + if (( aValue >>= rValue ) && m_bInitialized) + this->setSupportVisiableProperty( rValue ); + } +} + +//-------------------------------------------------------------------- + +IMPL_STATIC_LINK_NOINSTANCE( ToolboxController_Impl, ExecuteHdl_Impl, DispatchInfo*, pDispatchInfo ) +{ + pDispatchInfo->mxDispatch->dispatch( pDispatchInfo->maURL, pDispatchInfo->maArgs ); + delete pDispatchInfo; + return 0; +} + +void ToolboxController::enable( bool bEnable ) +{ + ToolBox* pToolBox = 0; + sal_uInt16 nItemId = 0; + if( getToolboxId( nItemId, &pToolBox ) ) + { + pToolBox->EnableItem( nItemId, bEnable ? TRUE : FALSE ); + } +} + +bool ToolboxController::getToolboxId( sal_uInt16& rItemId, ToolBox** ppToolBox ) +{ + if( (m_pImpl->m_nToolBoxId != SAL_MAX_UINT16) && (ppToolBox == 0) ) + return m_pImpl->m_nToolBoxId; + + ToolBox* pToolBox = static_cast< ToolBox* >( VCLUnoHelper::GetWindow( getParent() ) ); + + if( (m_pImpl->m_nToolBoxId == SAL_MAX_UINT16) && pToolBox ) + { + const sal_uInt16 nCount = pToolBox->GetItemCount(); + for ( sal_uInt16 nPos = 0; nPos < nCount; ++nPos ) + { + const sal_uInt16 nItemId = pToolBox->GetItemId( nPos ); + if ( pToolBox->GetItemCommand( nItemId ) == String( m_aCommandURL ) ) + { + m_pImpl->m_nToolBoxId = nItemId; + break; + } + } + } + + if( ppToolBox ) + *ppToolBox = pToolBox; + + rItemId = m_pImpl->m_nToolBoxId; + + return (rItemId != SAL_MAX_UINT16) && (( ppToolBox == 0) || (*ppToolBox != 0) ); +} +//end + } // svt diff --git a/svtools/source/uno/treecontrolpeer.cxx b/svtools/source/uno/treecontrolpeer.cxx index a46b9605a00d..7fb1a007960f 100644 --- a/svtools/source/uno/treecontrolpeer.cxx +++ b/svtools/source/uno/treecontrolpeer.cxx @@ -34,6 +34,7 @@ #include <com/sun/star/lang/DisposedException.hpp> #include <com/sun/star/view/SelectionType.hpp> #include <toolkit/helper/property.hxx> +#include <toolkit/helper/vclunohelper.hxx> #include <com/sun/star/awt/tree/XMutableTreeNode.hpp> #include <treecontrolpeer.hxx> @@ -208,7 +209,9 @@ void TreeControlPeer::removeEntry( UnoTreeListEntry* pEntry ) { TreeNodeMap::iterator aIter( mpTreeNodeMap->find( pEntry->mxNode ) ); if( aIter != mpTreeNodeMap->end() ) + { mpTreeNodeMap->erase( aIter ); + } } } @@ -280,14 +283,14 @@ UnoTreeListEntry* TreeControlPeer::createEntry( const Reference< XTreeNode >& xN pEntry->AddItem( pUnoItem ); + mpTreeImpl->insert( pEntry, pParent, nPos ); + if( msDefaultExpandedGraphicURL.getLength() ) mpTreeImpl->SetExpandedEntryBmp( pEntry, maDefaultExpandedImage ); if( msDefaultCollapsedGraphicURL.getLength() ) mpTreeImpl->SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage ); - mpTreeImpl->insert( pEntry, pParent, nPos ); - updateEntry( pEntry ); } return pEntry; @@ -915,6 +918,19 @@ Reference< XTreeNode > SAL_CALL TreeControlPeer::getClosestNodeForLocation( sal_ // ------------------------------------------------------------------- +awt::Rectangle SAL_CALL TreeControlPeer::getNodeRect( const Reference< XTreeNode >& i_Node ) throw (IllegalArgumentException, RuntimeException) +{ + ::vos::OGuard aGuard( GetMutex() ); + + UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow(); + UnoTreeListEntry* pEntry = getEntry( i_Node, true ); + + ::Rectangle aEntryRect( rTree.GetFocusRect( pEntry, rTree.GetEntryPosition( pEntry ).Y() ) ); + return VCLUnoHelper::ConvertToAWTRect( aEntryRect ); +} + +// ------------------------------------------------------------------- + sal_Bool SAL_CALL TreeControlPeer::isEditing( ) throw (RuntimeException) { ::vos::OGuard aGuard( GetMutex() ); diff --git a/svtools/source/uno/treecontrolpeer.hxx b/svtools/source/uno/treecontrolpeer.hxx index 015e131321f8..336830804a6f 100644 --- a/svtools/source/uno/treecontrolpeer.hxx +++ b/svtools/source/uno/treecontrolpeer.hxx @@ -91,6 +91,7 @@ public: virtual void SAL_CALL removeTreeExpansionListener( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::tree::XTreeExpansionListener >& Listener ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::tree::XTreeNode > SAL_CALL getNodeForLocation( ::sal_Int32 x, ::sal_Int32 y ) throw (::com::sun::star::uno::RuntimeException); virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::tree::XTreeNode > SAL_CALL getClosestNodeForLocation( ::sal_Int32 x, ::sal_Int32 y ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getNodeRect( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::tree::XTreeNode >& Node ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); virtual ::sal_Bool SAL_CALL isEditing( ) throw (::com::sun::star::uno::RuntimeException); virtual ::sal_Bool SAL_CALL stopEditing( ) throw (::com::sun::star::uno::RuntimeException); virtual void SAL_CALL cancelEditing( ) throw (::com::sun::star::uno::RuntimeException); diff --git a/svtools/source/uno/unoifac2.src b/svtools/source/uno/unoifac2.src deleted file mode 100644 index 406701ca4fc1..000000000000 --- a/svtools/source/uno/unoifac2.src +++ /dev/null @@ -1,107 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - - - -#ifndef _SVT_UNO_UNOIFAC_HRC_ -#include <unoifac2.hrc> -#endif - - -Menu RID_CONTEXTMENU -{ - ItemList = - { - MenuItem - { - Identifier = RID_OPEN_LINK ; - HelpId = HID_TEXTCPNT_OPEN_LINK ; - Text [ en-US ] = "~Open"; - }; - MenuItem - { - Identifier = RID_OPEN_LINK_NEW ; - HelpId = HID_TEXTCPNT_OPEN_LINK_NEW ; - Text [ en-US ] = "Open in New ~Window"; - }; - MenuItem - { - Identifier = RID_DOWNLOAD ; - HelpId = HID_TEXTCPNT_DOWNLOAD ; - Text [ en-US ] = "~Download..."; - }; - MenuItem - { - Separator = TRUE; - }; - MenuItem - { - Identifier = RID_ADD_BOOKMARK ; - HelpId = HID_TEXTCPNT_ADD_BOOKMARK ; - Text [ en-US ] = "Add ~Link"; - }; - MenuItem - { - Separator = TRUE; - }; - MenuItem - { - Identifier = RID_COPY_LINK ; - HelpId = HID_TEXTCPNT_COPY_LINK ; - Text [ en-US ] = "Cop~y Link" ; - }; - }; -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/svtools/source/uno/unowizard.hxx b/svtools/source/uno/unowizard.hxx new file mode 100644 index 000000000000..ceb8fac14eb6 --- /dev/null +++ b/svtools/source/uno/unowizard.hxx @@ -0,0 +1,117 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_UNO_WIZARD_HXX +#define SVT_UNO_WIZARD_HXX + +#include "svtools/genericunodialog.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/dialogs/XWizard.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/ui/dialogs/XWizardController.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/implbase1.hxx> +#include <comphelper/componentcontext.hxx> + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + //================================================================================================================== + //= Wizard - declaration + //================================================================================================================== + typedef ::cppu::ImplInheritanceHelper1 < ::svt::OGenericUnoDialog + , ::com::sun::star::ui::dialogs::XWizard + > Wizard_Base; + class Wizard; + typedef ::comphelper::OPropertyArrayUsageHelper< Wizard > Wizard_PBase; + class Wizard : public Wizard_Base + , public Wizard_PBase + { + public: + Wizard( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& i_rContext ); + + // ::com::sun::star::lang::XServiceInfo - static version + static ::rtl::OUString SAL_CALL getImplementationName_static() throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static() throw(::com::sun::star::uno::RuntimeException); + static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL Create( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& i_rContext ); + + protected: + // ::com::sun::star::lang::XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::beans::XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException); + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + + // OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // ::com::sun::star::ui::dialogs::XWizard + virtual ::rtl::OUString SAL_CALL getHelpURL() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setHelpURL( const ::rtl::OUString& _helpurl ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL getDialogWindow() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardPage > SAL_CALL getCurrentPage( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL enableButton( ::sal_Int16 WizardButton, ::sal_Bool Enable ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setDefaultButton( ::sal_Int16 WizardButton ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL travelNext( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL travelPrevious( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL enablePage( ::sal_Int16 PageID, ::sal_Bool Enable ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::util::InvalidStateException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL updateTravelUI( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL advanceTo( ::sal_Int16 PageId ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL goBackTo( ::sal_Int16 PageId ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL activatePath( ::sal_Int16 PathIndex, ::sal_Bool Final ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::util::InvalidStateException, ::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::ui::dialogs::XExecutableDialog + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL execute( ) throw (::com::sun::star::uno::RuntimeException); + + // ::com::sun::star::lang::XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + protected: + ~Wizard(); + + protected: + virtual Dialog* createDialog( Window* _pParent ); + virtual void destroyDialog(); + + private: + ::comphelper::ComponentContext m_aContext; + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< sal_Int16 > > m_aWizardSteps; + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardController > m_xController; + ::rtl::OUString m_sHelpURL; + }; + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... + +#endif // SVT_UNO_WIZARD_HXX diff --git a/svtools/source/uno/wizard/makefile.mk b/svtools/source/uno/wizard/makefile.mk new file mode 100644 index 000000000000..521496fc5d48 --- /dev/null +++ b/svtools/source/uno/wizard/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=../../.. + +PRJNAME=svtools +TARGET=unowiz +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/svt.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES= \ + $(SLO)$/unowizard.obj \ + $(SLO)$/wizardshell.obj \ + $(SLO)$/wizardpagecontroller.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/svtools/source/uno/wizard/unowizard.cxx b/svtools/source/uno/wizard/unowizard.cxx new file mode 100644 index 000000000000..9440c0e69f26 --- /dev/null +++ b/svtools/source/uno/wizard/unowizard.cxx @@ -0,0 +1,452 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "../unowizard.hxx" +#include "wizardshell.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/ucb/AlreadyInitializedException.hpp> +#include <com/sun/star/ui/dialogs/XWizardController.hpp> +#include <com/sun/star/ui/dialogs/WizardButton.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> +#include <rtl/strbuf.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::lang::XServiceInfo; + using ::com::sun::star::ui::dialogs::XWizard; + using ::com::sun::star::lang::XInitialization; + using ::com::sun::star::beans::XPropertySetInfo; + using ::com::sun::star::uno::XComponentContext; + using ::com::sun::star::beans::Property; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::ucb::AlreadyInitializedException; + using ::com::sun::star::ui::dialogs::XWizardController; + using ::com::sun::star::ui::dialogs::XWizardPage; + using ::com::sun::star::container::NoSuchElementException; + using ::com::sun::star::util::InvalidStateException; + using ::com::sun::star::awt::XWindow; + /** === end UNO using === **/ + namespace WizardButton = ::com::sun::star::ui::dialogs::WizardButton; + + //------------------------------------------------------------------------------------------------------------------ + namespace + { + sal_uInt32 lcl_convertWizardButtonToWZB( const sal_Int16 i_nWizardButton ) + { + switch ( i_nWizardButton ) + { + case WizardButton::NONE: return WZB_NONE; + case WizardButton::NEXT: return WZB_NEXT; + case WizardButton::PREVIOUS: return WZB_PREVIOUS; + case WizardButton::FINISH: return WZB_FINISH; + case WizardButton::CANCEL: return WZB_CANCEL; + case WizardButton::HELP: return WZB_HELP; + } + OSL_ENSURE( false, "lcl_convertWizardButtonToWZB: invalid WizardButton constant!" ); + return WZB_NONE; + } + } + + //================================================================================================================== + //= Wizard - implementation + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + Wizard::Wizard( const Reference< XComponentContext >& _rxContext ) + :Wizard_Base( _rxContext ) + ,m_aContext( _rxContext ) + { + } + + //-------------------------------------------------------------------- + Wizard::~Wizard() + { + // we do this here cause the base class' call to destroyDialog won't reach us anymore : we're within an dtor, + // so this virtual-method-call the base class does does not work, we're already dead then ... + if ( m_pDialog ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_pDialog ) + destroyDialog(); + } + } + + //-------------------------------------------------------------------- + Reference< XInterface > SAL_CALL Wizard::Create( const Reference< XComponentContext >& _rxContext ) + { + return *(new Wizard( _rxContext ) ); + } + + //-------------------------------------------------------------------- + namespace + { + static void lcl_checkPaths( const Sequence< Sequence< sal_Int16 > >& i_rPaths, const Reference< XInterface >& i_rContext ) + { + // need at least one path + if ( i_rPaths.getLength() == 0 ) + throw IllegalArgumentException( ::rtl::OUString(), i_rContext, 2 ); + + // each path must be of length 1, at least + for ( sal_Int32 i = 0; i < i_rPaths.getLength(); ++i ) + { + if ( i_rPaths[i].getLength() == 0 ) + throw IllegalArgumentException( ::rtl::OUString(), i_rContext, 2 ); + + // page IDs must be in ascending order + sal_Int16 nPreviousPageID = i_rPaths[i][0]; + for ( sal_Int32 j=1; j<i_rPaths[i].getLength(); ++j ) + { + if ( i_rPaths[i][j] <= nPreviousPageID ) + { + ::rtl::OStringBuffer message; + message.append( "Path " ); + message.append( i ); + message.append( ": invalid page ID sequence - each page ID must be greater than the previous one." ); + throw IllegalArgumentException( + ::rtl::OStringToOUString( message.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ), + i_rContext, 2 ); + } + nPreviousPageID = i_rPaths[i][j]; + } + } + + // if we have one path, that's okay + if ( i_rPaths.getLength() == 1 ) + return; + + // if we have multiple paths, they must start with the same page id + const sal_Int16 nFirstPageId = i_rPaths[0][0]; + for ( sal_Int32 i = 0; i < i_rPaths.getLength(); ++i ) + { + if ( i_rPaths[i][0] != nFirstPageId ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "All paths must start with the same page id." ) ), + i_rContext, 2 ); + } + } + } + + //-------------------------------------------------------------------- + void SAL_CALL Wizard::initialize( const Sequence< Any >& i_Arguments ) throw (Exception, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + if ( m_bInitialized ) + throw AlreadyInitializedException( ::rtl::OUString(), *this ); + + if ( i_Arguments.getLength() != 2 ) + throw IllegalArgumentException( ::rtl::OUString(), *this, -1 ); + + // the second argument must be a XWizardController, for each constructor + m_xController.set( i_Arguments[1], UNO_QUERY ); + if ( !m_xController.is() ) + throw IllegalArgumentException( ::rtl::OUString(), *this, 2 ); + + // the first arg is either a single path (short[]), or multiple paths (short[][]) + Sequence< sal_Int16 > aSinglePath; + i_Arguments[0] >>= aSinglePath; + Sequence< Sequence< sal_Int16 > > aMultiplePaths; + i_Arguments[0] >>= aMultiplePaths; + + if ( !aMultiplePaths.getLength() ) + { + aMultiplePaths.realloc(1); + aMultiplePaths[0] = aSinglePath; + } + lcl_checkPaths( aMultiplePaths, *this ); + // if we survived this, the paths are valid, and we're done here ... + m_aWizardSteps = aMultiplePaths; + + m_bInitialized = true; + } + + //-------------------------------------------------------------------- + Dialog* Wizard::createDialog( Window* i_pParent ) + { + WizardShell* pDialog( new WizardShell( i_pParent, this, m_xController, m_aWizardSteps ) ); + pDialog->SetSmartHelpId( SmartId( m_sHelpURL ) ); + pDialog->setTitleBase( m_sTitle ); + return pDialog; + } + + //-------------------------------------------------------------------- + void Wizard::destroyDialog() + { + if ( m_pDialog ) + m_sHelpURL = m_pDialog->GetSmartHelpId().GetStr(); + + Wizard_Base::destroyDialog(); + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL Wizard::getImplementationName_static() throw(RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.svtools.uno.Wizard" ) ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL Wizard::getSupportedServiceNames_static() throw(RuntimeException) + { + Sequence< ::rtl::OUString > aServices(1); + aServices[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.Wizard" ) ); + return aServices; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL Wizard::getImplementationName() throw(RuntimeException) + { + return getImplementationName_static(); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL Wizard::getSupportedServiceNames() throw(RuntimeException) + { + return getSupportedServiceNames_static(); + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL Wizard::getPropertySetInfo() throw(RuntimeException) + { + return createPropertySetInfo( getInfoHelper() ); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& SAL_CALL Wizard::getInfoHelper() + { + return *const_cast< Wizard* >( this )->getArrayHelper(); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper* Wizard::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL Wizard::getHelpURL() throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pDialog ) + return m_sHelpURL; + + const SmartId aSmartId( m_pDialog->GetSmartHelpId() ); + return aSmartId.GetStr(); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::setHelpURL( const ::rtl::OUString& i_HelpURL ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( !m_pDialog ) + m_sHelpURL = i_HelpURL; + else + m_pDialog->SetSmartHelpId( SmartId( i_HelpURL ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWindow > SAL_CALL Wizard::getDialogWindow() throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + ENSURE_OR_RETURN( m_pDialog, "Wizard::getDialogWindow: illegal call (execution did not start, yet)!", NULL ); + return Reference< XWindow >( m_pDialog->GetComponentInterface(), UNO_QUERY ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::enableButton( ::sal_Int16 i_WizardButton, ::sal_Bool i_Enable ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enableButtons: invalid dialog implementation!" ); + + pWizardImpl->enableButtons( lcl_convertWizardButtonToWZB( i_WizardButton ), i_Enable ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::setDefaultButton( ::sal_Int16 i_WizardButton ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::setDefaultButton: invalid dialog implementation!" ); + + pWizardImpl->defaultButton( lcl_convertWizardButtonToWZB( i_WizardButton ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool SAL_CALL Wizard::travelNext( ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelNext: invalid dialog implementation!" ); + + return pWizardImpl->travelNext(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool SAL_CALL Wizard::travelPrevious( ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::travelPrevious: invalid dialog implementation!" ); + + return pWizardImpl->travelPrevious(); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::enablePage( ::sal_Int16 i_PageID, ::sal_Bool i_Enable ) throw (NoSuchElementException, InvalidStateException, RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::enablePage: invalid dialog implementation!" ); + + if ( !pWizardImpl->knowsPage( i_PageID ) ) + throw NoSuchElementException( ::rtl::OUString(), *this ); + + if ( i_PageID == pWizardImpl->getCurrentPage() ) + throw InvalidStateException( ::rtl::OUString(), *this ); + + pWizardImpl->enablePage( i_PageID, i_Enable ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::updateTravelUI( ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::updateTravelUI: invalid dialog implementation!" ); + + pWizardImpl->updateTravelUI(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::sal_Bool SAL_CALL Wizard::advanceTo( ::sal_Int16 i_PageId ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::advanceTo: invalid dialog implementation!" ); + + return pWizardImpl->advanceTo( i_PageId ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::sal_Bool SAL_CALL Wizard::goBackTo( ::sal_Int16 i_PageId ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::goBackTo: invalid dialog implementation!" ); + + return pWizardImpl->goBackTo( i_PageId ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWizardPage > SAL_CALL Wizard::getCurrentPage( ) throw (RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_FALSE( pWizardImpl, "Wizard::getCurrentPage: invalid dialog implementation!" ); + + return pWizardImpl->getCurrentWizardPage(); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::activatePath( ::sal_Int16 i_PathIndex, ::sal_Bool i_Final ) throw (NoSuchElementException, InvalidStateException, RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + ::osl::MutexGuard aGuard( m_aMutex ); + + if ( ( i_PathIndex < 0 ) || ( i_PathIndex >= m_aWizardSteps.getLength() ) ) + throw NoSuchElementException( ::rtl::OUString(), *this ); + + WizardShell* pWizardImpl = dynamic_cast< WizardShell* >( m_pDialog ); + ENSURE_OR_RETURN_VOID( pWizardImpl, "Wizard::activatePath: invalid dialog implementation!" ); + + pWizardImpl->activatePath( i_PathIndex, i_Final ); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL Wizard::setTitle( const ::rtl::OUString& i_Title ) throw (RuntimeException) + { + // simply disambiguate + Wizard_Base::OGenericUnoDialog::setTitle( i_Title ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::sal_Int16 SAL_CALL Wizard::execute( ) throw (RuntimeException) + { + return Wizard_Base::OGenericUnoDialog::execute(); + } + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... diff --git a/svtools/source/uno/wizard/wizardpagecontroller.cxx b/svtools/source/uno/wizard/wizardpagecontroller.cxx new file mode 100644 index 000000000000..d6f7029b477c --- /dev/null +++ b/svtools/source/uno/wizard/wizardpagecontroller.cxx @@ -0,0 +1,190 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "wizardpagecontroller.hxx" +#include "wizardshell.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/awt/XControl.hpp> +/** === end UNO includes === **/ + +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::ui::dialogs::XWizardController; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::awt::XControl; + /** === end UNO using === **/ + using namespace ::com::sun::star; + + //================================================================================================================== + //= WizardPageController + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + WizardPageController::WizardPageController( WizardShell& i_rParent, const Reference< XWizardController >& i_rController, + const sal_Int16 i_nPageId ) + :m_xController( i_rController ) + ,m_xWizardPage() + ,m_nPageId( i_nPageId ) + { + ENSURE_OR_THROW( m_xController.is(), "no controller" ); + try + { + m_xWizardPage.set( m_xController->createPage( + Reference< XWindow >( i_rParent.GetComponentInterface( TRUE ), UNO_QUERY_THROW ), + m_nPageId + ), UNO_SET_THROW ); + + Reference< XWindow > xPageWindow( m_xWizardPage->getWindow(), UNO_SET_THROW ); + xPageWindow->setVisible( sal_True ); + + TabPage* pTabPage( getTabPage() ); + if ( pTabPage ) + pTabPage->SetStyle( pTabPage->GetStyle() | WB_CHILDDLGCTRL | WB_DIALOGCONTROL ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + WizardPageController::~WizardPageController() + { + try + { + if ( m_xWizardPage.is() ) + m_xWizardPage->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + TabPage* WizardPageController::getTabPage() const + { + ENSURE_OR_RETURN( m_xWizardPage.is(), "WizardPageController::getTabPage: no external wizard page!", NULL ); + try + { + Reference< XWindow > xPageWindow( m_xWizardPage->getWindow(), UNO_SET_THROW ); + Window* pPageWindow = VCLUnoHelper::GetWindow( xPageWindow ); + if ( pPageWindow == NULL ) + { + // windows created via the XContainerWindowProvider might be controls, not real windows, so resolve + // that one indirection + const Reference< XControl > xPageControl( m_xWizardPage->getWindow(), UNO_QUERY_THROW ); + xPageWindow.set( xPageControl->getPeer(), UNO_QUERY_THROW ); + pPageWindow = VCLUnoHelper::GetWindow( xPageWindow ); + } + + OSL_ENSURE( pPageWindow != NULL, "WizardPageController::getTabPage: unable to find the Window implementation for the page's window!" ); + return dynamic_cast< TabPage* >( pPageWindow ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return NULL; + } + + //------------------------------------------------------------------------------------------------------------------ + void WizardPageController::initializePage() + { + if ( !m_xWizardPage.is() ) + return; + + try + { + m_xWizardPage->activatePage(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool WizardPageController::commitPage( WizardTypes::CommitPageReason i_eReason ) + { + if ( !m_xWizardPage.is() ) + return sal_True; + + try + { + return m_xWizardPage->commitPage( WizardShell::convertCommitReasonToTravelType( i_eReason ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sal_True; + } + + //------------------------------------------------------------------------------------------------------------------ + bool WizardPageController::canAdvance() const + { + if ( !m_xWizardPage.is() ) + return true; + + try + { + return m_xWizardPage->canAdvance(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return true; + } + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... diff --git a/svtools/source/uno/wizard/wizardpagecontroller.hxx b/svtools/source/uno/wizard/wizardpagecontroller.hxx new file mode 100644 index 000000000000..9de04d2f0dd4 --- /dev/null +++ b/svtools/source/uno/wizard/wizardpagecontroller.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_UNOWIZ_WIZARDPAGECONTROLLER_HXX +#define SVT_UNOWIZ_WIZARDPAGECONTROLLER_HXX + +#include "svtools/wizardmachine.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/dialogs/XWizardController.hpp> +/** === end UNO includes === **/ + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + class WizardShell; + + //================================================================================================================== + //= WizardPageController + //================================================================================================================== + class WizardPageController : public IWizardPageController + { + public: + WizardPageController( + WizardShell& i_rParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardController >& i_rController, + const sal_Int16 i_nPageId + ); + ~WizardPageController(); + + // IWizardPageController overridables + virtual void initializePage(); + virtual sal_Bool commitPage( WizardTypes::CommitPageReason _eReason ); + virtual bool canAdvance() const; + + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardPage >& + getWizardPage() const { return m_xWizardPage; } + TabPage* getTabPage() const; + + private: + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardController > m_xController; + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardPage > m_xWizardPage; + const sal_Int16 m_nPageId; + }; + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... + +#endif // SVT_UNOWIZ_WIZARDPAGECONTROLLER_HXX diff --git a/svtools/source/uno/wizard/wizardshell.cxx b/svtools/source/uno/wizard/wizardshell.cxx new file mode 100644 index 000000000000..7737b214ac1f --- /dev/null +++ b/svtools/source/uno/wizard/wizardshell.cxx @@ -0,0 +1,279 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_svtools.hxx" + +#include "wizardshell.hxx" +#include "wizardpagecontroller.hxx" + +#include <tools/diagnose_ex.h> + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/dialogs/WizardTravelType.hpp> +/** === end UNO includes === **/ + +#include <vcl/msgbox.hxx> + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::uno::Sequence; + using ::com::sun::star::uno::Type; + using ::com::sun::star::ui::dialogs::XWizardController; + using ::com::sun::star::ui::dialogs::XWizard; + using ::com::sun::star::ui::dialogs::XWizardPage; + /** === end UNO using === **/ + namespace WizardTravelType = ::com::sun::star::ui::dialogs::WizardTravelType; + + //================================================================================================================== + namespace + { + //-------------------------------------------------------------------------------------------------------------- + sal_Int16 lcl_determineFirstPageID( const Sequence< Sequence< sal_Int16 > >& i_rPaths ) + { + ENSURE_OR_THROW( ( i_rPaths.getLength() > 0 ) && ( i_rPaths[0].getLength() > 0 ), "illegal paths" ); + return i_rPaths[0][0]; + } + } + + //================================================================================================================== + //= WizardShell + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + WizardShell::WizardShell( Window* i_pParent, const Reference< XWizard >& i_rWizard, const Reference< XWizardController >& i_rController, + const Sequence< Sequence< sal_Int16 > >& i_rPaths ) + :WizardShell_Base( i_pParent, WB_MOVEABLE | WB_CLOSEABLE ) + ,m_xWizard( i_rWizard ) + ,m_xController( i_rController ) + ,m_nFirstPageID( lcl_determineFirstPageID( i_rPaths ) ) + { + ENSURE_OR_THROW( m_xWizard.is() && m_xController.is(), "invalid wizard/controller" ); + + // declare the paths + for ( sal_Int32 i=0; i<i_rPaths.getLength(); ++i ) + { + const Sequence< sal_Int16 >& rPath( i_rPaths[i] ); + WizardPath aPath( rPath.getLength() ); + for ( sal_Int32 j=0; j<rPath.getLength(); ++j ) + aPath[j] = impl_pageIdToState( rPath[j] ); + declarePath( i, aPath ); + } + + // create the first page, to know the page size + TabPage* pStartPage = GetOrCreatePage( impl_pageIdToState( i_rPaths[0][0] ) ); + SetPageSizePixel( pStartPage->GetSizePixel() ); + + // some defaults + ShowButtonFixedLine( true ); + SetRoadmapInteractive( true ); + enableAutomaticNextButtonState(); + } + + //------------------------------------------------------------------------------------------------------------------ + WizardShell::~WizardShell() + { + } + + //------------------------------------------------------------------------------------------------------------------ + short WizardShell::Execute() + { + ActivatePage(); + return WizardShell_Base::Execute(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Int16 WizardShell::convertCommitReasonToTravelType( const CommitPageReason i_eReason ) + { + switch ( i_eReason ) + { + case WizardTypes::eTravelForward: + return WizardTravelType::FORWARD; + + case WizardTypes::eTravelBackward: + return WizardTravelType::BACKWARD; + + case WizardTypes::eFinish: + return WizardTravelType::FINISH; + + default: + break; + } + OSL_ENSURE( false, "WizardShell::convertCommitReasonToTravelType: unsupported CommitPageReason!" ); + return WizardTravelType::FINISH; + } + + //------------------------------------------------------------------------------------------------------------------ + void WizardShell::enterState( WizardState i_nState ) + { + WizardShell_Base::enterState( i_nState ); + + if ( !m_xController.is() ) + return; + + try + { + m_xController->onActivatePage( impl_stateToPageId( i_nState ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool WizardShell::leaveState( WizardState i_nState ) + { + if ( !WizardShell_Base::leaveState( i_nState ) ) + return sal_False; + + if ( !m_xController.is() ) + return sal_True; + + try + { + m_xController->onDeactivatePage( impl_stateToPageId( i_nState ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sal_True; + } + + //------------------------------------------------------------------------------------------------------------------ + PWizardPageController WizardShell::impl_getController( TabPage* i_pPage ) const + { + Page2ControllerMap::const_iterator pos = m_aPageControllers.find( i_pPage ); + ENSURE_OR_RETURN( pos != m_aPageControllers.end(), "WizardShell::impl_getController: no controller for this page!", PWizardPageController() ); + return pos->second; + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWizardPage > WizardShell::getCurrentWizardPage() const + { + const WizardState eState = getCurrentState(); + + PWizardPageController pController( impl_getController( GetPage( eState ) ) ); + ENSURE_OR_RETURN( pController, "WizardShell::getCurrentWizardPage: invalid page/controller!", NULL ); + + return pController->getWizardPage(); + } + + //------------------------------------------------------------------------------------------------------------------ + void WizardShell::enablePage( const sal_Int16 i_nPageID, const sal_Bool i_bEnable ) + { + enableState( impl_pageIdToState( i_nPageID ), i_bEnable ); + } + + //------------------------------------------------------------------------------------------------------------------ + TabPage* WizardShell::createPage( WizardState i_nState ) + { + ENSURE_OR_RETURN( m_xController.is(), "WizardShell::createPage: no WizardController!", NULL ); + + ::boost::shared_ptr< WizardPageController > pController( new WizardPageController( *this, m_xController, impl_stateToPageId( i_nState ) ) ); + TabPage* pPage = pController->getTabPage(); + OSL_ENSURE( pPage != NULL, "WizardShell::createPage: illegal tab page!" ); + if ( pPage == NULL ) + { + // fallback for ill-behaved clients: empty page + pPage = new TabPage( this, 0 ); + pPage->SetSizePixel( LogicToPixel( Size( 280, 185 ), MAP_APPFONT ) ); + } + + m_aPageControllers[ pPage ] = pController; + return pPage; + } + + //------------------------------------------------------------------------------------------------------------------ + IWizardPageController* WizardShell::getPageController( TabPage* i_pCurrentPage ) const + { + return impl_getController( i_pCurrentPage ).get(); + } + + //------------------------------------------------------------------------------------------------------------------ + String WizardShell::getStateDisplayName( WizardState i_nState ) const + { + try + { + if ( m_xController.is() ) + return m_xController->getPageTitle( impl_stateToPageId( i_nState ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + // fallback for ill-behaved clients: the numeric state + return String::CreateFromInt32( i_nState ); + } + + //------------------------------------------------------------------------------------------------------------------ + bool WizardShell::canAdvance() const + { + try + { + if ( m_xController.is() && !m_xController->canAdvance() ) + return false; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return WizardShell_Base::canAdvance(); + } + + //------------------------------------------------------------------------------------------------------------------ + sal_Bool WizardShell::onFinish() + { + try + { + if ( m_xController.is() && !m_xController->confirmFinish() ) + return sal_False; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return WizardShell_Base::onFinish(); + } + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... diff --git a/svtools/source/uno/wizard/wizardshell.hxx b/svtools/source/uno/wizard/wizardshell.hxx new file mode 100644 index 000000000000..338b4f38dc4a --- /dev/null +++ b/svtools/source/uno/wizard/wizardshell.hxx @@ -0,0 +1,147 @@ +/************************************************************************* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SVT_UNO_WIZARD_SHELL +#define SVT_UNO_WIZARD_SHELL + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/dialogs/XWizardController.hpp> +#include <com/sun/star/ui/dialogs/XWizard.hpp> +/** === end UNO includes === **/ + +#include <svtools/roadmapwizard.hxx> + +#include <boost/shared_ptr.hpp> +#include <map> + +//...................................................................................................................... +namespace svt { namespace uno +{ +//...................................................................................................................... + + class WizardPageController; + typedef ::boost::shared_ptr< WizardPageController > PWizardPageController; + + //================================================================================================================== + //= WizardShell + //================================================================================================================== + typedef ::svt::RoadmapWizard WizardShell_Base; + class WizardShell : public WizardShell_Base + { + public: + WizardShell( + Window* _pParent, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizard >& i_rWizard, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardController >& i_rController, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< sal_Int16 > >& i_rPaths + ); + virtual ~WizardShell(); + + // Dialog overridables + virtual short Execute(); + + // OWizardMachine overridables + virtual TabPage* createPage( WizardState i_nState ); + virtual void enterState( WizardState i_nState ); + virtual sal_Bool leaveState( WizardState i_nState ); + virtual String getStateDisplayName( WizardState i_nState ) const; + virtual bool canAdvance() const; + virtual sal_Bool onFinish(); + virtual IWizardPageController* + getPageController( TabPage* _pCurrentPage ) const; + + // attribute access + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizard >& + getWizard() const { return m_xWizard; } + + static sal_Int16 convertCommitReasonToTravelType( const CommitPageReason i_eReason ); + + // operations + sal_Bool advanceTo( const sal_Int16 i_nPageId ) + { + return skipUntil( impl_pageIdToState( i_nPageId ) ); + } + sal_Bool goBackTo( const sal_Int16 i_nPageId ) + { + return skipBackwardUntil( impl_pageIdToState( i_nPageId ) ); + } + sal_Bool travelNext() { return WizardShell_Base::travelNext(); } + sal_Bool travelPrevious() { return WizardShell_Base::travelPrevious(); } + + void activatePath( const sal_Int16 i_nPathID, const sal_Bool i_bFinal ) + { + WizardShell_Base::activatePath( PathId( i_nPathID ), i_bFinal ); + } + + ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardPage > + getCurrentWizardPage() const; + + sal_Int16 getCurrentPage() const + { + return impl_stateToPageId( getCurrentState() ); + } + + void enablePage( const sal_Int16 i_PageID, const sal_Bool i_Enable ); + + bool knowsPage( const sal_Int16 i_nPageID ) const + { + return knowsState( impl_pageIdToState( i_nPageID ) ); + } + + private: + sal_Int16 impl_stateToPageId( const WizardTypes::WizardState i_nState ) const + { + return static_cast< sal_Int16 >( i_nState + m_nFirstPageID ); + } + + WizardState impl_pageIdToState( const sal_Int16 i_nPageId ) const + { + return static_cast< WizardState >( i_nPageId - m_nFirstPageID ); + } + + PWizardPageController impl_getController( TabPage* i_pPage ) const; + + // prevent outside access to some base class members + using WizardShell_Base::skip; + using WizardShell_Base::skipUntil; + using WizardShell_Base::skipBackwardUntil; + using WizardShell_Base::getCurrentState; + using WizardShell_Base::activatePath; + + private: + typedef ::std::map< TabPage*, PWizardPageController > Page2ControllerMap; + + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizard > m_xWizard; + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::dialogs::XWizardController > m_xController; + const sal_Int16 m_nFirstPageID; + Page2ControllerMap m_aPageControllers; + }; + +//...................................................................................................................... +} } // namespace svt::uno +//...................................................................................................................... + +#endif // SVT_UNO_WIZARD_SHELL |