diff options
Diffstat (limited to 'sd/source/ui/toolpanel')
67 files changed, 17186 insertions, 0 deletions
diff --git a/sd/source/ui/toolpanel/ConstrainedIterator.cxx b/sd/source/ui/toolpanel/ConstrainedIterator.cxx new file mode 100644 index 000000000000..261017ee3e1d --- /dev/null +++ b/sd/source/ui/toolpanel/ConstrainedIterator.cxx @@ -0,0 +1,267 @@ +/************************************************************************* + * + * 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_sd.hxx" + +// This is a definition file of a template class. It is therefore +// included by other files and thus has to be guarded against multiple +// inclusion. + +#ifndef SD_TOOLPANEL_CONSTRAINED_ITERATOR_CXX +#define SD_TOOLPANEL_CONSTRAINED_ITERATOR_CXX + +namespace sd { namespace toolpanel { + + +template <class Container> +ConstrainedIterator<Container>::value_type& + ConstrainedIterator<Container>::operator* (void) +{ + return *maIterator; +} + + + + +template <class Container> +const ConstrainedIterator<Container>::value_type& + ConstrainedIterator<Container>::operator* (void) + const +{ + return *maIterator; +} + + + + +template <class Container> +ConstrainedIterator<Container>::value_type& + ConstrainedIterator<Container>::operator-> (void) +{ + return *maIterator; +} + + + + +template <class Container> +const ConstrainedIterator<Container>::value_type& + ConstrainedIterator<Container>::operator-> (void) + const +{ + return *maIterator; +} + + + + + +template <class Container> +ConstrainedIterator<Container> + ::ConstrainedIterator (void) + : mpContainer (NULL) +{ +} + + + + +template <class Container> +ConstrainedIterator<Container>::ConstrainedIterator ( + const Container& rContainer, + const Container::iterator& rIterator) + : mpContainer(&rContainer), + maIterator (rIterator), + mpConstraint (NULL) +{ + AdvanceToNextValidElement(); +} + + + + +template <class Container> +ConstrainedIterator<Container>::ConstrainedIterator ( + const Container& rContainer, + const Container::iterator& rIterator, + const Constraint<Container>& rConstraint) + : mpContainer(&rContainer), + maIterator (rIterator), + mpConstraint (&rConstraint) +{ + AdvanceToNextValidElement(); +} + + + + +template <class Container> +ConstrainedIterator<Container>::ConstrainedIterator ( + const ConstrainedIterator& rIterator) + : mpContainer (rIterator.mpContainer), + maIterator (rIterator.maIterator), + mpConstraint (rIterator.mpConstraint) +{ + // Everything has been done in the initializer +} + + + + +template <class Container> +ConstrainedIterator<Container>& + ConstrainedIterator<Container> + ::operator= (const ConstrainedIterator& rIterator) +{ + mpContainer = rIterator.mpContainer; + maIterator = rIterator.maIterator; + mpConstraint = rIterator.mpConstraint; + + AdvanceToNextValidElement(); + + return *this; +} + + + + +template <class Container> +bool ConstrainedIterator<Container>::operator== ( + const ConstrainedIterator& aIterator) const +{ + return ! operator!=(aIterator); +} + + + + +template <class Container> +bool ConstrainedIterator<Container>::operator!= ( + const ConstrainedIterator& aIterator) const +{ + return maIterator != aIterator.maIterator; +} + + + + +template <class Container> +ConstrainedIterator<Container>& + ConstrainedIterator<Container>::operator++ (void) +{ + maIterator++; + AdvanceToNextValidElement(); + return *this; +} + + + + +template <class Container> +ConstrainedIterator<Container> + ConstrainedIterator<Container>::operator++ (int) +{ + ConstrainedIterator aIterator (*this); + ++(*this); + return aIterator; +} + + + + +template <class Container> +ConstrainedIterator<Container>& + ConstrainedIterator<Container>::operator-- (void) +{ + maIterator--; + AdvanceToPreviousValidElement(); + return *this; +} + + + + +template <class Container> +ConstrainedIterator<Container> + ConstrainedIterator<Container>::operator-- (int) +{ + ConstrainedIterator aIterator (*this); + --(*this); + return aIterator; +} + + + + +template <class Container> +ConstrainedIterator<Container> + ConstrainedIterator<Container>::operator+ (int nValue) const +{ + return ConstrainedIterator (*mpContainer, maIterator+nValue); +} + + + +template <class Container> +ConstrainedIterator<Container> + ConstrainedIterator<Container>::operator- (int nValue) const +{ + return ConstrainedIterator (*mpContainer, maIterator-nValue); +} + + + +template <class Container> +void ConstrainedIterator<Container>::AdvanceToNextValidElement (void) +{ + if (mpContainer!=NULL && mpConstraint!=NULL) + { + while (maIterator != mpContainer->end() + && ! mpConstraint->operator()(*mpContainer, maIterator)) + ++maIterator; + } +} + + + + +template <class Container> +void ConstrainedIterator<Container>::AdvanceToPreviousValidElement (void) +{ + if (mpContainer!=NULL && mpConstraint!=NULL) + { + while (maIterator != mpContainer->begin() + && ! mpConstraint->operator()(*mpContainer, maIterator)) + --maIterator; + } +} + + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/ConstrainedIterator.hxx b/sd/source/ui/toolpanel/ConstrainedIterator.hxx new file mode 100644 index 000000000000..8f81ba89ebe7 --- /dev/null +++ b/sd/source/ui/toolpanel/ConstrainedIterator.hxx @@ -0,0 +1,104 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONSTRAINED_ITERATOR_HXX +#define SD_TOOLPANEL_CONSTRAINED_ITERATOR_HXX + +#include <iterator> + +namespace sd { namespace toolpanel { + + +template <class Container> +class Constraint +{ +public: + virtual bool operator() ( + const Container& rContainer, + const Container::iterator& rIterator) const = 0; +}; + + + + +/** This iterator is a bidirectional iterator with something of random + access thrown in. It uses a constraint object to jump over + elements in the underlying container that do not meet the + constraint. +*/ +template <class Container> +class ConstrainedIterator + : public ::std::bidirectional_iterator_tag +{ +public: + typedef Container::value_type value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + + ConstrainedIterator (void); + ConstrainedIterator ( + const Container& rContainer, + const Container::iterator& rIterator); + ConstrainedIterator ( + const Container& rContainer, + const Container::iterator& rIterator, + const Constraint<Container>& pConstraint); + ConstrainedIterator ( + const ConstrainedIterator& rIterator); + + ConstrainedIterator& operator= ( + const ConstrainedIterator& aIterator); + + reference operator* (void); + const_reference operator* (void) const; + reference operator-> (void); + const_reference operator-> (void) const; + + bool operator== (const ConstrainedIterator& aIterator) const; + bool operator!= (const ConstrainedIterator& aIterator) const; + + ConstrainedIterator& operator++ (void); + ConstrainedIterator operator++ (int); + ConstrainedIterator& operator-- (void); + ConstrainedIterator operator-- (int); + + ConstrainedIterator operator+ (int nValue) const; + ConstrainedIterator operator- (int nValue) const; + + +private: + const Container* mpContainer; + Container::iterator maIterator; + const Constraint<Container>* mpConstraint; + + void AdvanceToNextValidElement (void); + void AdvanceToPreviousValidElement (void); +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/ControlContainer.cxx b/sd/source/ui/toolpanel/ControlContainer.cxx new file mode 100755 index 000000000000..78e4125b024d --- /dev/null +++ b/sd/source/ui/toolpanel/ControlContainer.cxx @@ -0,0 +1,445 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/ControlContainer.hxx" + +#include "taskpane/TaskPaneTreeNode.hxx" + +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> + +namespace sd { namespace toolpanel { + + +ControlContainer::ControlContainer (TreeNode* pNode) + : mpNode(pNode), + mnActiveControlIndex((sal_uInt32)-1), + mbMultiSelection(false) +{ +} + + + + +ControlContainer::~ControlContainer (void) +{ + // Set mpNode to NULL so that no one calls it from now on. + mpNode = NULL; + DeleteChildren(); +} + + + + +void ControlContainer::DeleteChildren (void) +{ + // Deleting the children may lead to calls back to the container. To + // prevent the container from accessing the just deleted children, the + // maControlList member is first cleared (by transferring its content to + // a local list) before the children are destroyed. + ControlList maList; + maList.swap(maControlList); + ControlList::iterator I; + ControlList::iterator Iend (maList.end()); + for (I=maList.begin(); I!=Iend; ++I) + delete *I; + + if (mpNode != NULL) + mpNode->FireStateChangeEvent(EID_ALL_CHILDREN_REMOVED); +} + + + +sal_uInt32 ControlContainer::AddControl (::std::auto_ptr<TreeNode> pControl) +{ + ::osl::MutexGuard aGuard (maMutex); + + pControl->GetWindow()->Show(); + sal_uInt32 nIndex = maControlList.size(); + maControlList.push_back (pControl.get()); + pControl.release(); + + ListHasChanged (); + + if (mpNode != NULL) + mpNode->FireStateChangeEvent(EID_CHILD_ADDED, pControl.get()); + + return nIndex; +} + + + + +void ControlContainer::SetExpansionState ( + UINT32 nIndex, + ExpansionState aState) +{ + ::osl::MutexGuard aGuard (maMutex); + + bool bResizeNecessary (false); + + if (mbMultiSelection) + { + TreeNode* pControl = GetControl(nIndex); + switch (aState) + { + case ES_TOGGLE: + bResizeNecessary = pControl->Expand( ! pControl->IsExpanded()); + break; + + case ES_EXPAND: + bResizeNecessary = pControl->Expand(true); + break; + + case ES_COLLAPSE: + bResizeNecessary = pControl->Expand(false); + break; + } + } + else + { + // When bExpansionState is true then the control to expand is the + // one with the given index. If bExpansionState is false and the + // given index points to the active control then then following + // control (in cyclic order) it is expanded. When there is only one + // control then that is always expanded. + do + { + // Ignore a call with an invalid index. (The seperate comparison + // with -1 is not strictly necessary but it is here just in + // case.) + if (nIndex>=GetControlCount() || nIndex==(sal_uInt32)-1) + break; + + bool bExpand; + switch (aState) + { + default: + case ES_TOGGLE: + bExpand = ! GetControl(nIndex)->IsExpanded(); + break; + + case ES_EXPAND: + bExpand = true; + break; + + case ES_COLLAPSE: + bExpand = false; + break; + } + if (bExpand) + { + // Make the specified control the active one and expand it. + mnActiveControlIndex = nIndex; + } + else + { + if (nIndex == mnActiveControlIndex) + { + // We have to determine a new active control since the + // current one is about to be collapsed. Choose the + // previous one for the last and the next one for all + // other. + if (mnActiveControlIndex+1 == GetControlCount()) + mnActiveControlIndex + = GetPreviousIndex(mnActiveControlIndex); + else + mnActiveControlIndex + = GetNextIndex (mnActiveControlIndex); + } + } + + // Update the expansion state of all controls. + for (UINT32 i=0; i<GetControlCount(); i=GetNextIndex(i)) + { + TreeNode* pControl = GetControl(i); + bResizeNecessary |= pControl->Expand(i == mnActiveControlIndex); + } + } + while (false); + } + + if (bResizeNecessary && mpNode != NULL) + mpNode->RequestResize(); +} + + + + +void ControlContainer::SetExpansionState ( + TreeNode* pControl, + ExpansionState aState) +{ + SetExpansionState (GetControlIndex(pControl), aState); +} + + + + +sal_uInt32 ControlContainer::GetControlIndex (TreeNode* pControlToExpand) const +{ + sal_uInt32 nIndex; + for (nIndex=0; nIndex<GetControlCount(); nIndex++) + { + TreeNode* pControl = GetControl(nIndex); + if (pControl == pControlToExpand) + break; + } + return nIndex; +} + + + + +void ControlContainer::ListHasChanged (void) +{ +} + + + + +sal_uInt32 ControlContainer::GetControlCount (void) const +{ + return maControlList.size(); +} + + + + +sal_uInt32 ControlContainer::GetVisibleControlCount (void) const +{ + sal_uInt32 nCount (0); + + UINT32 nIndex; + sal_uInt32 nAllCount (maControlList.size()); + for (nIndex=0; nIndex<nAllCount; nIndex=GetNextIndex(nIndex,true)) + { + if (maControlList[nIndex]->GetWindow()->IsVisible()) + nCount += 1; + } + + return nCount; +} + + + + +TreeNode* ControlContainer::GetControl (sal_uInt32 nIndex) const +{ + if (nIndex<maControlList.size() && nIndex!=(sal_uInt32)-1) + return maControlList[nIndex]; + else + return NULL; +} + + + + +sal_uInt32 ControlContainer::GetPreviousIndex ( + sal_uInt32 nIndex, + bool bIncludeHidden, + bool bCycle) const +{ + sal_uInt32 nCandidate (nIndex); + + while (true) + { + if (nCandidate==0) + if ( ! bCycle) + { + // We have reached the head of the list of controls and must + // not cycle to its end. + nCandidate = maControlList.size(); + break; + } + else + { + // Cycle to the end of the list. + nCandidate = maControlList.size() - 1; + } + else + // Go to the regular predecessor. + nCandidate -= 1; + + if (nCandidate == nIndex) + { + // Made one full loop and found no valid control. + nCandidate = maControlList.size(); + break; + } + else if (bIncludeHidden) + { + // Return the candidate index regardless of whether the control + // is hidden or not. + break; + } + else if (maControlList[nCandidate]->GetWindow()->IsVisible()) + { + // Found a visible control. + break; + } + + // The candidate does not meet our constraints so do one more loop. + } + + return nCandidate; +} + + + +sal_uInt32 ControlContainer::GetNextIndex ( + sal_uInt32 nIndex, + bool bIncludeHidden, + bool bCycle) const +{ + sal_uInt32 nCandidate (nIndex); + + while (true) + { + // Go to the regular successor. + nCandidate += 1; + if (nCandidate==maControlList.size()) + { + if ( ! bCycle) + { + // We have reached the end of the list of controls and must + // not cycle to its head. + break; + } + else + { + // Cycle to the head of the list. + nCandidate = 0; + } + } + + if (nCandidate == nIndex) + { + // Made one full loop and found no valid control. + nCandidate = maControlList.size(); + break; + } + else if (bIncludeHidden) + { + // Return the candidate index regardless of whether the control + // is hidden or not. + break; + } + else if (maControlList[nCandidate]->GetWindow()->IsVisible()) + { + // Found a visible control. + break; + } + + // The candidate does not meet our constraints so do one more loop. + } + + return nCandidate; +} + + + + +void ControlContainer::SetMultiSelection (bool bFlag) +{ + mbMultiSelection = bFlag; +} + + + + +void ControlContainer::SetVisibilityState ( + sal_uInt32 nControlIndex, + VisibilityState aState) +{ + TreeNode* pControl = GetControl (nControlIndex); + if (pControl != NULL) + { + bool bShow; + switch (aState) + { + default: + case VS_TOGGLE: + bShow = ! pControl->IsShowing(); + break; + case VS_SHOW: + bShow = true; + break; + case VS_HIDE: + bShow = false; + break; + } + + bool bControlWasExpanded = pControl->IsExpanded(); + if (bShow != pControl->IsShowing()) + { + pControl->Show (bShow); + + if (bShow) + { + // If we just turned on the first control then expand it, too. + // If we turned on another control collapse it. + if (GetVisibleControlCount() == 1) + SetExpansionState (nControlIndex, ES_EXPAND); + else + SetExpansionState (nControlIndex, ES_COLLAPSE); + } + else + { + if (GetVisibleControlCount() > 0) + { + if (bControlWasExpanded) + { + // We turned off an expanded control. Make sure that + // one of the still visible ones is expanded. + sal_uInt32 nIndex = GetNextIndex( + nControlIndex, + false, + false); + if (nIndex == GetControlCount()) + nIndex = GetPreviousIndex( + nControlIndex, + false, + false); + SetExpansionState (nIndex, ES_EXPAND); + } + } + } + + if (mpNode != NULL) + mpNode->RequestResize(); + } + } +} + + + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/ControlContainerDescriptor.hxx b/sd/source/ui/toolpanel/ControlContainerDescriptor.hxx new file mode 100644 index 000000000000..3557200880d2 --- /dev/null +++ b/sd/source/ui/toolpanel/ControlContainerDescriptor.hxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * 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 SD_TASKPANE_CONTROL_CONTAINER_DESCRIPTOR_HXX +#define SD_TASKPANE_CONTROL_CONTAINER_DESCRIPTOR_HXX + +#include "taskpane/ILayoutableWindow.hxx" +#include "taskpane/TitleBar.hxx" +#include <tools/string.hxx> +#include <tools/gen.hxx> +#ifndef SD_WINDOW_HXX +#include <vcl/window.hxx> +#endif +#include <memory> + +class Window; + +namespace sd { namespace toolpanel { + +class ControlContainer; + +/** Collection of information the describes entries of the tool + panel. A descriptor owns the control it is associated with. +*/ +class ControlContainerDescriptor + : public ::Window, + public virtual ILayoutableWindow +{ +public: + /** Create a new descriptor for the given control. + @param rContainer + The container to inform about selection (caused by mouse + clicks or keyboard.) + @param pParent + The parent window of the new descriptor. + @param pControl + The control that is shown when being in the expanded + state. + @param rTitle + String that is shown as title in the title area above the + control. + @param eType + Type of the title bar. This specifies how the title bar + will be formated. For more information see TitleBar. + + */ + ControlContainerDescriptor ( + ControlContainer& rContainer, + ::Window* pParent, + ::std::auto_ptr<ILayoutableWindow> pControl, + const String& rTitle, + TitleBar::TitleBarType eType); + + virtual ~ControlContainerDescriptor (void); + + + virtual Size GetPreferredSize (void); + virtual int GetPreferredWidth (int nHeight); + virtual int GetPreferredHeight (int nWidth); + virtual bool IsResizable (void); + virtual ::Window* GetWindow (void); + + virtual void Resize (void); + virtual void GetFocus (void); + virtual void LoseFocus (void); + virtual void MouseButtonUp (const MouseEvent& rMouseEvent); + virtual void KeyInput (const KeyEvent& rEvent); + + void Select (bool bExpansionState); + + // const Rectangle& GetTitleBarBox (void) const; + + Window* GetControl (void) const; + const String& GetTitle (void) const; + + void Expand (bool bExpanded = true); + void Collapse (void); + bool IsExpanded (void) const; + + /** Ownership of the given data remains with the caller. The data + is thus not destroyed when the destructor of this class is + called. + */ + void SetUserData (void* pUserData); + void* GetUserData (void) const; + + bool IsVisible (void) const; + void SetVisible (bool bVisible); + + using Window::GetWindow; + using sd::toolpanel::ILayoutableWindow::GetPreferredWidth; + using sd::toolpanel::ILayoutableWindow::GetPreferredHeight; + +private: + ControlContainer& mrContainer; + ::std::auto_ptr<TitleBar> mpTitleBar; + ::std::auto_ptr<ILayoutableWindow> mpControl; + String msTitle; + bool mbExpanded; + bool mbVisible; + void* mpUserData; + bool mnVisible; + + /// Do not use! Assignment operator is not supported. + const ControlContainerDescriptor& operator= ( + const ControlContainerDescriptor& aDescriptor); + + void UpdateStates (void); + + DECL_LINK(WindowEventListener, VclSimpleEvent*); +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/ControlList.hxx b/sd/source/ui/toolpanel/ControlList.hxx new file mode 100644 index 000000000000..623a9567215f --- /dev/null +++ b/sd/source/ui/toolpanel/ControlList.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROL_LIST_HXX +#define SD_TOOLPANEL_CONTROL_LIST_HXX + +#include "ConstrainedIterator.hxx" +#include "ConstrainedIterator.cxx" +#include "TitledControl.hxx" + +#include <vector> + +namespace sd { namespace toolpanel { + + +typedef ::std::vector<TitledControl*> ControlList; +typedef ConstrainedIterator<ControlList> ControlIterator; + + +class VisibilityConstraint + : public Constraint<ControlList> +{ +public: + virtual bool operator() ( + const ControlList& rContainer, + const ControlList::iterator& rIterator) const + { + return (**rIterator).GetWindow()->IsVisible(); + } +}; + + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/LayoutMenu.cxx b/sd/source/ui/toolpanel/LayoutMenu.cxx new file mode 100755 index 000000000000..ec4eb1e43d4d --- /dev/null +++ b/sd/source/ui/toolpanel/LayoutMenu.cxx @@ -0,0 +1,1012 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "LayoutMenu.hxx" + +#include "TaskPaneShellManager.hxx" +#include "pres.hxx" +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "sdpage.hxx" +#include "glob.hxx" +#include "glob.hrc" +#include "app.hrc" +#include "helpids.h" +#include "res_bmp.hrc" +#include "strings.hrc" +#include "ViewShellBase.hxx" +#include "DrawViewShell.hxx" +#include "SlideSorterViewShell.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" +#include "taskpane/ToolPanelViewShell.hxx" +#include "taskpane/ScrollPanel.hxx" +#include "tools/SlotStateListener.hxx" +#include "EventMultiplexer.hxx" +#include "DrawController.hxx" +#include "framework/FrameworkHelper.hxx" + +#include <vector> +#include <memory> +#include <sfx2/objface.hxx> +#include "sdresid.hxx" +#include <vcl/image.hxx> +#include <svl/languageoptions.hxx> +#include <sfx2/app.hxx> +#include "taskpane/TitledControl.hxx" +#include <sfx2/dispatch.hxx> +#include <sfx2/request.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/viewfrm.hxx> + +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/drawing/framework/XControllerManager.hpp> +#include <com/sun/star/drawing/framework/XView.hpp> +#include <com/sun/star/drawing/framework/ResourceId.hpp> + +using namespace ::sd::toolpanel; +#define LayoutMenu +#include "sdslots.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::drawing::framework; +using namespace ::sd::slidesorter; +using ::sd::framework::FrameworkHelper; + +namespace sd { namespace toolpanel { + +class LayoutMenuRootFactory + : public ControlFactory +{ +public: + LayoutMenuRootFactory (ToolPanelViewShell& i_rPanelViewShell) + :mrPanelViewShell(i_rPanelViewShell) + { + } + +protected: + virtual TreeNode* InternalCreateControl( ::Window& i_rParent ) + { + ScrollPanel* pScrollPanel = new ScrollPanel (i_rParent); + ::std::auto_ptr<TreeNode> pMenu ( + new LayoutMenu ( + pScrollPanel, + mrPanelViewShell)); + pScrollPanel->AddControl(pMenu); + return pScrollPanel; + } + +private: + ToolPanelViewShell& mrPanelViewShell; +}; + + +SFX_IMPL_INTERFACE(LayoutMenu, SfxShell, + SdResId(STR_TASKPANELAYOUTMENU)) +{ + SFX_POPUPMENU_REGISTRATION(SdResId(RID_TASKPANE_LAYOUTMENU_POPUP)); +} + +TYPEINIT1(LayoutMenu, SfxShell); + +struct snewfoil_value_info +{ + USHORT mnBmpResId; + USHORT mnHCBmpResId; + USHORT mnStrResId; + WritingMode meWritingMode; + AutoLayout maAutoLayout; +}; + +static snewfoil_value_info notes[] = +{ + {BMP_FOILN_01, BMP_FOILN_01_H, STR_AUTOLAYOUT_NOTES, WritingMode_LR_TB, + AUTOLAYOUT_NOTES}, + {0, 0, 0, WritingMode_LR_TB, AUTOLAYOUT_NONE}, +}; + +static snewfoil_value_info handout[] = +{ + {BMP_FOILH_01, BMP_FOILH_01_H, STR_AUTOLAYOUT_HANDOUT1, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT1}, + {BMP_FOILH_02, BMP_FOILH_02_H, STR_AUTOLAYOUT_HANDOUT2, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT2}, + {BMP_FOILH_03, BMP_FOILH_03_H, STR_AUTOLAYOUT_HANDOUT3, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT3}, + {BMP_FOILH_04, BMP_FOILH_04_H, STR_AUTOLAYOUT_HANDOUT4, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT4}, + {BMP_FOILH_06, BMP_FOILH_06_H, STR_AUTOLAYOUT_HANDOUT6, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT6}, + {BMP_FOILH_09, BMP_FOILH_09_H, STR_AUTOLAYOUT_HANDOUT9, WritingMode_LR_TB, + AUTOLAYOUT_HANDOUT9}, + {0, 0, 0, WritingMode_LR_TB, AUTOLAYOUT_NONE}, +}; + +static snewfoil_value_info standard[] = +{ + {BMP_LAYOUT_EMPTY, BMP_LAYOUT_EMPTY_H, STR_AUTOLAYOUT_NONE, WritingMode_LR_TB, AUTOLAYOUT_NONE}, + {BMP_LAYOUT_HEAD03, BMP_LAYOUT_HEAD03_H, STR_AUTOLAYOUT_TITLE, WritingMode_LR_TB, AUTOLAYOUT_TITLE}, + {BMP_LAYOUT_HEAD02, BMP_LAYOUT_HEAD02_H, STR_AUTOLAYOUT_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_ENUM}, + {BMP_LAYOUT_HEAD02A, BMP_LAYOUT_HEAD02A_H, STR_AUTOLAYOUT_2CONTENT, WritingMode_LR_TB, AUTOLAYOUT_2TEXT}, + {BMP_LAYOUT_HEAD01, BMP_LAYOUT_HEAD01_H, STR_AUTOLAYOUT_ONLY_TITLE, WritingMode_LR_TB, AUTOLAYOUT_ONLY_TITLE}, + {BMP_LAYOUT_TEXTONLY, BMP_LAYOUT_TEXTONLY_H, STR_AUTOLAYOUT_ONLY_TEXT, WritingMode_LR_TB, AUTOLAYOUT_ONLY_TEXT}, + {BMP_LAYOUT_HEAD03B, BMP_LAYOUT_HEAD03B_H, STR_AUTOLAYOUT_2CONTENT_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_2OBJTEXT}, + {BMP_LAYOUT_HEAD03C, BMP_LAYOUT_HEAD03C_H, STR_AUTOLAYOUT_CONTENT_2CONTENT, WritingMode_LR_TB, AUTOLAYOUT_TEXT2OBJ}, + {BMP_LAYOUT_HEAD03A, BMP_LAYOUT_HEAD03A_H, STR_AUTOLAYOUT_2CONTENT_OVER_CONTENT,WritingMode_LR_TB, AUTOLAYOUT_2OBJOVERTEXT}, + {BMP_LAYOUT_HEAD02B, BMP_LAYOUT_HEAD02B_H, STR_AUTOLAYOUT_CONTENT_OVER_CONTENT, WritingMode_LR_TB, AUTOLAYOUT_OBJOVERTEXT}, + {BMP_LAYOUT_HEAD04, BMP_LAYOUT_HEAD04_H, STR_AUTOLAYOUT_4CONTENT, WritingMode_LR_TB, AUTOLAYOUT_4OBJ}, + {BMP_LAYOUT_HEAD06, BMP_LAYOUT_HEAD06_H, STR_AUTOLAYOUT_6CONTENT, WritingMode_LR_TB, AUTOLAYOUT_6CLIPART}, + + // vertical + {BMP_LAYOUT_VERTICAL02, BMP_LAYOUT_VERTICAL02_H, STR_AL_VERT_TITLE_TEXT_CHART, WritingMode_TB_RL,AUTOLAYOUT_VERTICAL_TITLE_TEXT_CHART}, + {BMP_LAYOUT_VERTICAL01, BMP_LAYOUT_VERTICAL01_H, STR_AL_VERT_TITLE_VERT_OUTLINE, WritingMode_TB_RL, AUTOLAYOUT_VERTICAL_TITLE_VERTICAL_OUTLINE}, + {BMP_LAYOUT_HEAD02, BMP_LAYOUT_HEAD02_H, STR_AL_TITLE_VERT_OUTLINE, WritingMode_TB_RL, AUTOLAYOUT_TITLE_VERTICAL_OUTLINE}, + {BMP_LAYOUT_HEAD02A, BMP_LAYOUT_HEAD02A_H, STR_AL_TITLE_VERT_OUTLINE_CLIPART, WritingMode_TB_RL, AUTOLAYOUT_TITLE_VERTICAL_OUTLINE_CLIPART}, + {0, 0, 0, WritingMode_LR_TB, AUTOLAYOUT_NONE} +}; + +LayoutMenu::LayoutMenu( TreeNode* pParent, ToolPanelViewShell& i_rPanelViewShell ) + : ValueSet (pParent->GetWindow()), + TreeNode(pParent), + DragSourceHelper(this), + DropTargetHelper(this), + mrBase( i_rPanelViewShell.GetViewShellBase() ), + mpShellManager (&i_rPanelViewShell.GetSubShellManager()), + mbUseOwnScrollBar( false ), + mnPreferredColumnCount(3), + mxListener(NULL), + mbSelectionUpdatePending(true), + mbIsMainViewChangePending(false) +{ + implConstruct( *mrBase.GetDocument()->GetDocSh() ); +} + + +void LayoutMenu::implConstruct( DrawDocShell& rDocumentShell ) +{ + OSL_ENSURE( mrBase.GetDocument()->GetDocSh() == &rDocumentShell, + "LayoutMenu::implConstruct: hmm?" ); + // if this fires, then my assumption that the rDocumentShell parameter to our first ctor is superfluous ... + + SetStyle ( + ( GetStyle() & ~(WB_ITEMBORDER) ) + | WB_TABSTOP + | WB_NO_DIRECTSELECT + ); + if (mbUseOwnScrollBar) + SetStyle (GetStyle() | WB_VSCROLL); + SetExtraSpacing(2); + SetSelectHdl (LINK(this, LayoutMenu, ClickHandler)); + SetPool (&rDocumentShell.GetDoc()->GetPool()); + SetName(String(RTL_CONSTASCII_USTRINGPARAM("LayoutMenu"))); + InvalidateContent(); + + Link aEventListenerLink (LINK(this,LayoutMenu,EventMultiplexerListener)); + mrBase.GetEventMultiplexer()->AddEventListener(aEventListenerLink, + ::sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE + | ::sd::tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION + | ::sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED + | ::sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED + | ::sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED + | ::sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL + | ::sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER); + + SetSmartHelpId(SmartId(HID_SD_TASK_PANE_PREVIEW_LAYOUTS)); + SetAccessibleName(SdResId(STR_TASKPANEL_LAYOUT_MENU_TITLE)); + + Link aStateChangeLink (LINK(this,LayoutMenu,StateChangeHandler)); + mxListener = new ::sd::tools::SlotStateListener( + aStateChangeLink, + Reference<frame::XDispatchProvider>(mrBase.GetController()->getFrame(), UNO_QUERY), + ::rtl::OUString::createFromAscii(".uno:VerticalTextState")); + + // Add this new object as shell to the shell factory. + GetShellManager()->AddSubShell(HID_SD_TASK_PANE_PREVIEW_LAYOUTS,this,this); +} + + + +LayoutMenu::~LayoutMenu (void) +{ + // Tell the shell factory that this object is no longer available. + if (GetShellManager() != NULL) + GetShellManager()->RemoveSubShell(this); + + Reference<lang::XComponent> xComponent (mxListener, UNO_QUERY); + if (xComponent.is()) + xComponent->dispose(); + + Clear(); + Link aLink (LINK(this,LayoutMenu,EventMultiplexerListener)); + mrBase.GetEventMultiplexer()->RemoveEventListener (aLink); +} + + + + +::std::auto_ptr<ControlFactory> LayoutMenu::CreateControlFactory ( + ToolPanelViewShell& i_rPanelViewShell ) +{ + return ::std::auto_ptr<ControlFactory>(new LayoutMenuRootFactory(i_rPanelViewShell)); +} + + + + +AutoLayout LayoutMenu::GetSelectedAutoLayout (void) +{ + AutoLayout aResult = AUTOLAYOUT_NONE; + + if ( ! IsNoSelection() && GetSelectItemId()!=0) + { + AutoLayout* pLayout = static_cast<AutoLayout*>(GetItemData(GetSelectItemId())); + if (pLayout != NULL) + aResult = *pLayout; + } + + return aResult; +} + + + + +/** The preferred size depends on the preferred number of columns, the + number of items, and the size of the items. +*/ +Size LayoutMenu::GetPreferredSize (void) +{ + Size aItemSize = CalcItemSizePixel (Size()); + Size aPreferredWindowSize = CalcWindowSizePixel ( + aItemSize, + (USHORT)mnPreferredColumnCount, + (USHORT)CalculateRowCount (aItemSize,mnPreferredColumnCount)); + return aPreferredWindowSize; +} + + + + +sal_Int32 LayoutMenu::GetPreferredWidth (sal_Int32 nHeight) +{ + sal_Int32 nPreferredWidth = 100; + if (GetItemCount() > 0) + { + Image aImage = GetItemImage(GetItemId(0)); + Size aItemSize = CalcItemSizePixel (aImage.GetSizePixel()); + if (nHeight>0 && aItemSize.Height()>0) + { + int nRowCount = nHeight / aItemSize.Height(); + if (nRowCount <= 0) + nRowCount = 1; + int nColumnCount = (GetItemCount() + nRowCount-1) / nRowCount; + nPreferredWidth = nColumnCount * aItemSize.Width(); + } + } + + return nPreferredWidth; +} + + + + +sal_Int32 LayoutMenu::GetPreferredHeight (sal_Int32 nWidth) +{ + sal_Int32 nPreferredHeight = 200; + if ( ! mbUseOwnScrollBar && GetItemCount()>0) + { + Image aImage = GetItemImage(GetItemId(0)); + Size aItemSize = CalcItemSizePixel (aImage.GetSizePixel()); + if (nWidth>0 && aItemSize.Width()>0) + { + aItemSize.Width() += 8; + aItemSize.Height() += 8; + int nColumnCount = nWidth / aItemSize.Width(); + if (nColumnCount <= 0) + nColumnCount = 1; + else if (nColumnCount > 4) + nColumnCount = 4; + int nRowCount = (GetItemCount() + nColumnCount-1) / nColumnCount; + nPreferredHeight = nRowCount * aItemSize.Height(); + } + } + return nPreferredHeight; +} + + + + +sal_Int32 LayoutMenu::GetMinimumWidth (void) +{ + sal_Int32 nMinimumWidth = 0; + if (GetItemCount()>0) + { + Image aImage = GetItemImage(GetItemId(0)); + Size aItemSize = CalcItemSizePixel (aImage.GetSizePixel()); + nMinimumWidth = aItemSize.Width(); + } + return nMinimumWidth; +} + + + + +bool LayoutMenu::IsResizable (void) +{ + return true; +} + + + + +void LayoutMenu::UpdateEnabledState (const MasterMode eMode) +{ + bool bIsEnabled (false); + + ::boost::shared_ptr<ViewShell> pMainViewShell (mrBase.GetMainViewShell()); + if (pMainViewShell) + { + switch (pMainViewShell->GetShellType()) + { + case ViewShell::ST_NONE: + case ViewShell::ST_OUTLINE: + case ViewShell::ST_PRESENTATION: + case ViewShell::ST_TASK_PANE: + // The complete task pane is disabled for these values or + // not even visible. Disabling the LayoutMenu would be + // logical but unnecessary. The main disadvantage is that + // after re-enabling it (typically) another panel is + // expanded. + bIsEnabled = true; + break; + + case ViewShell::ST_DRAW: + case ViewShell::ST_IMPRESS: + { + switch (eMode) + { + case MM_UNKNOWN: + { + ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( + ::boost::dynamic_pointer_cast<DrawViewShell>(pMainViewShell)); + if (pDrawViewShell) + bIsEnabled = pDrawViewShell->GetEditMode() != EM_MASTERPAGE; + break; + } + case MM_NORMAL: + bIsEnabled = true; + break; + + case MM_MASTER: + bIsEnabled = false; + break; + } + break; + } + + case ViewShell::ST_HANDOUT: + case ViewShell::ST_NOTES: + case ViewShell::ST_SLIDE_SORTER: + default: + bIsEnabled = true; + break; + } + + TreeNode* pParentNode = GetParentNode(); + if (pParentNode != NULL) + { + TitledControl* pGrandParentNode + = dynamic_cast<TitledControl*>(pParentNode->GetParentNode()); + if (pGrandParentNode != NULL) + pGrandParentNode->SetEnabledState(bIsEnabled); + } + + } +} + + + + +::Window* LayoutMenu::GetWindow (void) +{ + return this; +} + + + + +void LayoutMenu::Paint (const Rectangle& rRect) +{ + SetBackground (GetSettings().GetStyleSettings().GetWindowColor()); + + if (mbSelectionUpdatePending) + { + mbSelectionUpdatePending = false; + UpdateSelection(); + } + ValueSet::Paint (rRect); + + SetBackground (Wallpaper()); +} + + + + +void LayoutMenu::Resize (void) +{ + Size aWindowSize = GetOutputSizePixel(); + if (IsVisible() && aWindowSize.Width() > 0) + { + // Calculate the number of rows and columns. + if (GetItemCount() > 0) + { + Image aImage = GetItemImage(GetItemId(0)); + Size aItemSize = CalcItemSizePixel ( + aImage.GetSizePixel()); + aItemSize.Width() += 8; + aItemSize.Height() += 8; + int nColumnCount = aWindowSize.Width() / aItemSize.Width(); + if (nColumnCount < 1) + nColumnCount = 1; + else if (nColumnCount > 4) + nColumnCount = 4; + + int nRowCount = CalculateRowCount (aItemSize, nColumnCount); + + SetColCount ((USHORT)nColumnCount); + SetLineCount ((USHORT)nRowCount); + } + } + + ValueSet::Resize (); +} + + + + +void LayoutMenu::MouseButtonDown (const MouseEvent& rEvent) +{ + // As a preparation for the context menu the item under the mouse is + // selected. + if (rEvent.IsRight()) + { + ReleaseMouse(); + USHORT nIndex = GetItemId (rEvent.GetPosPixel()); + if (nIndex > 0) + SelectItem(nIndex); + } + + ValueSet::MouseButtonDown (rEvent); +} + + + + +void LayoutMenu::Execute (SfxRequest& rRequest) +{ + switch (rRequest.GetSlot()) + { + case SID_TP_APPLY_TO_SELECTED_SLIDES: + AssignLayoutToSelectedSlides(GetSelectedAutoLayout()); + rRequest.Done(); + break; + + case SID_INSERTPAGE_LAYOUT_MENU: + // Add arguments to this slot and forward it to the main view + // shell. + InsertPageWithLayout(GetSelectedAutoLayout()); + break; + } +} + + + + +void LayoutMenu::GetState (SfxItemSet& rItemSet) +{ + // Cut and paste is not supported. The SID_(CUT,COPY,PASTE) entries + // therefore must not show up in the context menu. + rItemSet.DisableItem (SID_CUT); + rItemSet.DisableItem (SID_COPY); + rItemSet.DisableItem (SID_PASTE); + + // The SID_INSERTPAGE_LAYOUT_MENU slot depends on the SID_INSERTPAGE + // slot being supported elsewhere. + const SfxPoolItem* pItem = NULL; + const SfxItemState aState ( + mrBase.GetViewFrame()->GetDispatcher()->QueryState(SID_INSERTPAGE, pItem)); + if (aState == SFX_ITEM_DISABLED) + rItemSet.DisableItem(SID_INSERTPAGE_LAYOUT_MENU); +} + + + + +void LayoutMenu::InsertPageWithLayout (AutoLayout aLayout) +{ + ViewShell* pViewShell = mrBase.GetMainViewShell().get(); + if (pViewShell == NULL) + return; + + SfxViewFrame* pViewFrame = mrBase.GetViewFrame(); + if (pViewFrame == NULL) + return; + + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + if (pDispatcher == NULL) + return; + + // Call SID_INSERTPAGE with the right arguments. This is because + // the popup menu can not call this slot with arguments directly. + SfxRequest aRequest (CreateRequest(SID_INSERTPAGE, aLayout)); + if (aRequest.GetArgs() != NULL) + { + pDispatcher->Execute( + SID_INSERTPAGE, + SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, + *aRequest.GetArgs()); + } + UpdateSelection(); +} + + + + +TaskPaneShellManager* LayoutMenu::GetShellManager() +{ + if ( mpShellManager ) + return mpShellManager; + return TreeNode::GetShellManager(); +} + +void LayoutMenu::InvalidateContent (void) +{ + // The number of items may have changed. Request a resize so that the + // vertical size of this control can be adapted. + RequestResize(); + + // Throw away the current set and fill the menu anew according to the + // current settings (this includes the support for vertical writing.) + Fill(); +} + + + + +int LayoutMenu::CalculateRowCount (const Size&, int nColumnCount) +{ + int nRowCount = 0; + + if (GetItemCount() > 0 && nColumnCount > 0) + { + nRowCount = (GetItemCount() + nColumnCount - 1) / nColumnCount; + // nRowCount = GetOutputSizePixel().Height() / rItemSize.Height(); + if (nRowCount < 1) + nRowCount = 1; + } + + return nRowCount; +} + + + + +IMPL_LINK(LayoutMenu, ClickHandler, ValueSet*, EMPTYARG) +{ + AssignLayoutToSelectedSlides (GetSelectedAutoLayout()); + return 0; +} + + + + +/** The specified layout is assigned to the current page of the view shell + in the center pane. +*/ +void LayoutMenu::AssignLayoutToSelectedSlides (AutoLayout aLayout) +{ + using namespace ::sd::slidesorter; + using namespace ::sd::slidesorter::controller; + + do + { + // The view shell in the center pane has to be present. + ViewShell* pMainViewShell = mrBase.GetMainViewShell().get(); + if (pMainViewShell == NULL) + break; + + // Determine if the current view is in an invalid master page mode. + // The handout view is always in master page mode and therefore not + // invalid. + bool bMasterPageMode (false); + switch (pMainViewShell->GetShellType()) + { + case ViewShell::ST_NOTES: + case ViewShell::ST_IMPRESS: + { + DrawViewShell* pDrawViewShell = static_cast<DrawViewShell*>(pMainViewShell); + if (pDrawViewShell != NULL) + if (pDrawViewShell->GetEditMode() == EM_MASTERPAGE) + bMasterPageMode = true; + } + default: + break; + } + if (bMasterPageMode) + break; + + // Get a list of all selected slides and call the SID_MODIFYPAGE + // slot for all of them. + ::sd::slidesorter::SharedPageSelection pPageSelection; + + // Get a list of selected pages. + // First we try to obtain this list from a slide sorter. This is + // possible only some of the view shells in the center pane. When + // no valid slide sorter is available then ask the main view shell + // for its current page. + SlideSorterViewShell* pSlideSorter = NULL; + switch (pMainViewShell->GetShellType()) + { + case ViewShell::ST_IMPRESS: + case ViewShell::ST_NOTES: + case ViewShell::ST_SLIDE_SORTER: + pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase); + break; + default: + break; + } + if (pSlideSorter != NULL) + { + // There is a slide sorter visible so get the list of selected pages from it. + pPageSelection = pSlideSorter->GetPageSelection(); + } + + if( (pSlideSorter == NULL) || (pPageSelection.get() == 0) || pPageSelection->empty() ) + { + // No valid slide sorter available. Ask the main view shell for + // its current page. + pPageSelection.reset(new ::sd::slidesorter::SlideSorterViewShell::PageSelection()); + pPageSelection->push_back(pMainViewShell->GetActualPage()); + } + + + if (pPageSelection->empty()) + break; + + ::std::vector<SdPage*>::iterator iPage; + for (iPage=pPageSelection->begin(); iPage!=pPageSelection->end(); ++iPage) + { + if ((*iPage) == NULL) + continue; + + // Call the SID_ASSIGN_LAYOUT slot with all the necessary parameters. + SfxRequest aRequest (mrBase.GetViewFrame(), SID_ASSIGN_LAYOUT); + aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATPAGE, ((*iPage)->GetPageNum()-1)/2)); + aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, aLayout)); + pMainViewShell->ExecuteSlot (aRequest, BOOL(FALSE)); + } + } + while(false); +} + + + + +SfxRequest LayoutMenu::CreateRequest ( + USHORT nSlotId, + AutoLayout aLayout) +{ + SfxRequest aRequest (mrBase.GetViewFrame(), nSlotId); + + do + { + SdrLayerAdmin& rLayerAdmin (mrBase.GetDocument()->GetLayerAdmin()); + BYTE aBackground (rLayerAdmin.GetLayerID( + String(SdResId(STR_LAYER_BCKGRND)), FALSE)); + BYTE aBackgroundObject (rLayerAdmin.GetLayerID( + String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE)); + ViewShell* pViewShell = mrBase.GetMainViewShell().get(); + if (pViewShell == NULL) + break; + SdPage* pPage = pViewShell->GetActualPage(); + if (pPage == NULL) + break; + + SetOfByte aVisibleLayers (pPage->TRG_GetMasterPageVisibleLayers()); + + aRequest.AppendItem( + SfxStringItem (ID_VAL_PAGENAME, String()));//pPage->GetName())); + aRequest.AppendItem(SfxUInt32Item (ID_VAL_WHATLAYOUT, aLayout)); + aRequest.AppendItem( + SfxBoolItem(ID_VAL_ISPAGEBACK, aVisibleLayers.IsSet(aBackground))); + aRequest.AppendItem( + SfxBoolItem( + ID_VAL_ISPAGEOBJ, + aVisibleLayers.IsSet(aBackgroundObject))); + } + while (false); + + return aRequest; +} + + + + +void LayoutMenu::Fill (void) +{ + const bool bHighContrast = GetSettings().GetStyleSettings().GetHighContrastMode(); + SvtLanguageOptions aLanguageOptions; + sal_Bool bVertical = aLanguageOptions.IsVerticalTextEnabled(); + SdDrawDocument* pDocument = mrBase.GetDocument(); + sal_Bool bRightToLeft = (pDocument!=NULL + && pDocument->GetDefaultWritingMode() == WritingMode_RL_TB); + + // Get URL of the view in the center pane. + ::rtl::OUString sCenterPaneViewName; + try + { + Reference<XControllerManager> xControllerManager ( + Reference<XWeak>(&mrBase.GetDrawController()), UNO_QUERY_THROW); + Reference<XResourceId> xPaneId (ResourceId::create( + ::comphelper::getProcessComponentContext(), + FrameworkHelper::msCenterPaneURL)); + Reference<XView> xView (FrameworkHelper::Instance(mrBase)->GetView(xPaneId)); + if (xView.is()) + sCenterPaneViewName = xView->getResourceId()->getResourceURL(); + } + catch (RuntimeException&) + {} + + snewfoil_value_info* pInfo = NULL; + if (sCenterPaneViewName.equals(framework::FrameworkHelper::msNotesViewURL)) + { + pInfo = notes; + } + else if (sCenterPaneViewName.equals(framework::FrameworkHelper::msHandoutViewURL)) + { + pInfo = handout; + } + else if (sCenterPaneViewName.equals(framework::FrameworkHelper::msImpressViewURL) + || sCenterPaneViewName.equals(framework::FrameworkHelper::msSlideSorterURL)) + { + pInfo = standard; + } + else + { + pInfo = NULL; + } + + Clear(); + int n = 0; + for (sal_uInt16 i=1; pInfo!=NULL&&pInfo->mnBmpResId!=0; i++,pInfo++) + { + if ((WritingMode_TB_RL != pInfo->meWritingMode) || bVertical) + { + BitmapEx aBmp (SdResId (bHighContrast + ? pInfo->mnHCBmpResId + : pInfo->mnBmpResId)); + + if (bRightToLeft && (WritingMode_TB_RL != pInfo->meWritingMode)) + aBmp.Mirror (BMP_MIRROR_HORZ); + + InsertItem (i, aBmp, String (SdResId (pInfo->mnStrResId))); + SetItemData (i, new AutoLayout(pInfo->maAutoLayout)); + n++; + } + } + + mbSelectionUpdatePending = true; +} + + + + +void LayoutMenu::Clear (void) +{ + for (USHORT nId=1; nId<=GetItemCount(); nId++) + delete static_cast<AutoLayout*>(GetItemData(nId)); + ValueSet::Clear(); +} + + + +void LayoutMenu::StartDrag (sal_Int8 , const Point& ) +{ +} + + + + +sal_Int8 LayoutMenu::AcceptDrop (const AcceptDropEvent& ) +{ + return 0; +} + + + + +sal_Int8 LayoutMenu::ExecuteDrop (const ExecuteDropEvent& ) +{ + return 0; +} + + + + +void LayoutMenu::Command (const CommandEvent& rEvent) +{ + switch (rEvent.GetCommand()) + { + case COMMAND_CONTEXTMENU: + if ( ! SD_MOD()->GetWaterCan()) + { + if (GetShellManager() != NULL) + GetShellManager()->MoveToTop(this); + if (rEvent.IsMouseEvent()) + { + // Do not show the context menu when the mouse was not + // pressed over an item. + if (GetItemId(rEvent.GetMousePosPixel()) > 0) + mrBase.GetViewFrame()->GetDispatcher()->ExecutePopup( + SdResId(RID_TASKPANE_LAYOUTMENU_POPUP)); + } + else + { + // When the command event was not caused by a mouse + // event (for example a key press instead) then show the + // popup menu at the center of the current item. + if (GetSelectItemId() != (USHORT)-1) + { + Rectangle aBBox (GetItemRect(GetSelectItemId())); + Point aPosition (aBBox.Center()); + mrBase.GetViewFrame()->GetDispatcher()->ExecutePopup( + SdResId(RID_TASKPANE_LAYOUTMENU_POPUP), + this, + &aPosition); + } + } + } + break; + + default: + ValueSet::Command(rEvent); + break; + } +} + + + + +IMPL_LINK(LayoutMenu, StateChangeHandler, ::rtl::OUString*, EMPTYARG) +{ + InvalidateContent(); + return 0; +} + + + + +void LayoutMenu::UpdateSelection (void) +{ + bool bItemSelected = false; + + do + { + // Get current page of main view. + ViewShell* pViewShell = mrBase.GetMainViewShell().get(); + if (pViewShell == NULL) + break; + + SdPage* pCurrentPage = pViewShell->getCurrentPage(); + if (pCurrentPage == NULL) + break; + + // Get layout of current page. + AutoLayout aLayout (pCurrentPage->GetAutoLayout()); + if (aLayout<AUTOLAYOUT__START || aLayout>AUTOLAYOUT__END) + break; + + // Find the entry of the menu for to the layout. + USHORT nItemCount (GetItemCount()); + for (USHORT nId=1; nId<=nItemCount; nId++) + { + if (*static_cast<AutoLayout*>(GetItemData(nId)) == aLayout) + { + SelectItem(nId); + bItemSelected = true; + break; + } + } + } + while (false); + + if ( ! bItemSelected) + SetNoSelection(); +} + + + + +IMPL_LINK(LayoutMenu, EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent*, pEvent) +{ + switch (pEvent->meEventId) + { + case ::sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE: + case ::sd::tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION: + if ( ! mbSelectionUpdatePending) + UpdateSelection(); + break; + + case ::sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED: + mbIsMainViewChangePending = true; + UpdateEnabledState(MM_UNKNOWN); + break; + + case ::sd::tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED: + HideFocus(); + break; + + case ::sd::tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED: + if (mbIsMainViewChangePending) + { + mbIsMainViewChangePending = false; + InvalidateContent(); + } + break; + + case ::sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL: + UpdateEnabledState(MM_NORMAL); + break; + + case ::sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER: + UpdateEnabledState(MM_MASTER); + break; + + default: + /* Ignored */ + break; + } + + return 0; +} + + + + +void LayoutMenu::DataChanged (const DataChangedEvent& rEvent) +{ + Fill(); + ValueSet::DataChanged(rEvent); +} + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/LayoutMenu.hxx b/sd/source/ui/toolpanel/LayoutMenu.hxx new file mode 100755 index 000000000000..627a363fb576 --- /dev/null +++ b/sd/source/ui/toolpanel/LayoutMenu.hxx @@ -0,0 +1,239 @@ +/************************************************************************* + * + * 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 SD_TASKPANE_LAYOUT_MENU_HXX +#define SD_TASKPANE_LAYOUT_MENU_HXX + +#include "taskpane/TaskPaneTreeNode.hxx" + +#ifndef _COM_SUN_STAR_FRAME_XSTATUS_LISTENER_HPP_ +#include <com/sun/star/frame/XStatusListener.hpp> +#endif + +#include "glob.hxx" +#include "pres.hxx" +#include <vcl/ctrl.hxx> +#include <svtools/valueset.hxx> +#include <svtools/transfer.hxx> +#include <sfx2/shell.hxx> + + +class SfxModule; + + +namespace sd { +class DrawDocShell; +class PaneManagerEvent; +class ViewShellBase; +} + + +namespace sd { namespace tools { +class EventMultiplexerEvent; +} } + + +namespace sd { namespace toolpanel { + +class ControlFactory; +class ToolPanelViewShell; + + +class LayoutMenu + : public ValueSet, + public TreeNode, + public SfxShell, + public DragSourceHelper, + public DropTargetHelper +{ +public: + TYPEINFO(); + SFX_DECL_INTERFACE(SD_IF_SDLAYOUTMENU) + + /** Create a new layout menu. Depending on the given flag it + displays its own scroll bar or lets a surrounding window + handle that. + @param i_pParent + the parent node in the control tree + @param i_rPanelViewShell + the view shell of the task pane. + */ + LayoutMenu ( + TreeNode* i_pParent, + ToolPanelViewShell& i_rPanelViewShell); + virtual ~LayoutMenu (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory ( + ToolPanelViewShell& i_rPanelViewShell ); + + /** Return a numerical value representing the currently selected + layout. + */ + AutoLayout GetSelectedAutoLayout (void); + + + // From ILayoutableWindow + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeight); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual sal_Int32 GetMinimumWidth (void); + virtual bool IsResizable (void); + virtual ::Window* GetWindow (void); + + // From ::Window + virtual void Paint (const Rectangle& rRect); + virtual void Resize (void); + + /** Show a context menu when the right mouse button is pressed. + */ + virtual void MouseButtonDown (const MouseEvent& rEvent); + + void Execute (SfxRequest& rRequest); + void GetState (SfxItemSet& rItemSet); + + /** The LayoutMenu does not support some main views. In this case the + LayoutMenu is disabled. This state is updated in this method. + @param eMode + On some occasions the edit mode is being switched when this + method is called can not (yet) be reliably detected. Luckily, + in these cases the new value is provided by some broadcaster. + On other occasions the edit mode is not modified and is also not + provided. Therefore the Unknown value. + */ + enum MasterMode { MM_NORMAL, MM_MASTER, MM_UNKNOWN }; + void UpdateEnabledState (const MasterMode eMode); + + // TreeNode overridables + virtual TaskPaneShellManager* GetShellManager (void); + + /** Call this method when the set of displayed layouts is not up-to-date + anymore. It will re-assemple this set according to the current + settings. + */ + void InvalidateContent (void); + + // DragSourceHelper + virtual void StartDrag (sal_Int8 nAction, const Point& rPosPixel); + + // DropTargetHelper + virtual sal_Int8 AcceptDrop (const AcceptDropEvent& rEvent); + virtual sal_Int8 ExecuteDrop (const ExecuteDropEvent& rEvent); + + /** The context menu is requested over this Command() method. + */ + virtual void Command (const CommandEvent& rEvent); + + /** Call Fill() when switching to or from high contrast mode so that the + correct set of icons is displayed. + */ + virtual void DataChanged (const DataChangedEvent& rEvent); + + using Window::GetWindow; + using ValueSet::StartDrag; + +private: + ViewShellBase& mrBase; + + TaskPaneShellManager* mpShellManager; + + /** Do we use our own scroll bar or is viewport handling done by + our parent? + */ + bool mbUseOwnScrollBar; + + /** If we are asked for the preferred window size, then use this + many columns for the calculation. + */ + const int mnPreferredColumnCount; + + ::com::sun::star::uno::Reference<com::sun::star::frame::XStatusListener> mxListener; + + bool mbSelectionUpdatePending; + + bool mbIsMainViewChangePending; + + /** Calculate the number of displayed rows. This depends on the given + item size, the given number of columns, and the size of the + control. Note that this is not the number of rows managed by the + valueset. This number may be larger. In that case a vertical + scroll bar is displayed. + */ + int CalculateRowCount (const Size& rItemSize, int nColumnCount); + + /** Fill the value set with the layouts that are applicable to the + current main view shell. + */ + void Fill (void); + + /** Remove all items from the value set. + */ + void Clear (void); + + /** Assign the given layout to all selected slides of a slide sorter. + If no slide sorter is active then this call is ignored. The slide + sorter in the center pane is preferred if the choice exists. + */ + void AssignLayoutToSelectedSlides (AutoLayout aLayout); + + /** Insert a new page with the given layout. The page is inserted via + the main view shell, i.e. its SID_INSERTPAGE slot is called. It it + does not support this slot then inserting a new page does not take + place. The new page is inserted after the currently active one (the + one returned by ViewShell::GetActualPage().) + */ + void InsertPageWithLayout (AutoLayout aLayout); + + /** Create a request structure that can be used with the SID_INSERTPAGE + and SID_MODIFYPAGE slots. The parameters are set so that the given + layout is assigned to the current page of the main view shell. + @param nSlotId + Supported slots are SID_INSERTPAGE and SID_MODIFYPAGE. + @param aLayout + Layout of the page to insert or to assign. + */ + SfxRequest CreateRequest ( + USHORT nSlotId, + AutoLayout aLayout); + + /** Select the layout that is used by the current page. + */ + void UpdateSelection (void); + + // internal ctor + void implConstruct( DrawDocShell& rDocumentShell ); + + /** When clicked then set the current page of the view in the center pane. + */ + DECL_LINK(ClickHandler, ValueSet*); + DECL_LINK(RightClickHandler, MouseEvent*); + DECL_LINK(StateChangeHandler, ::rtl::OUString*); + DECL_LINK(EventMultiplexerListener, ::sd::tools::EventMultiplexerEvent*); +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/MethodGuard.hxx b/sd/source/ui/toolpanel/MethodGuard.hxx new file mode 100644 index 000000000000..45b81367c8de --- /dev/null +++ b/sd/source/ui/toolpanel/MethodGuard.hxx @@ -0,0 +1,67 @@ +/************************************************************************* + * 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 SD_METHODGUARD_HXX +#define SD_METHODGUARD_HXX + +#include <osl/mutex.hxx> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + //================================================================================================================== + //= MethodGuard + //================================================================================================================== + template < class COMPONENT > + class MethodGuard + { + public: + MethodGuard( COMPONENT& i_rComponent ) + :m_aGuard( i_rComponent.getMutex() ) + { + i_rComponent.checkDisposed(); + } + + ~MethodGuard() + { + } + + inline void clear() + { + m_aGuard.clear(); + } + + private: + ::osl::ClearableMutexGuard m_aGuard; + }; + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... + +#endif // SD_METHODGUARD_HXX diff --git a/sd/source/ui/toolpanel/ScrollPanel.cxx b/sd/source/ui/toolpanel/ScrollPanel.cxx new file mode 100755 index 000000000000..33fd325313a3 --- /dev/null +++ b/sd/source/ui/toolpanel/ScrollPanel.cxx @@ -0,0 +1,815 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/ScrollPanel.hxx" + +#include "taskpane/ControlContainer.hxx" +#include "TaskPaneFocusManager.hxx" +#include "taskpane/TitledControl.hxx" +#include "AccessibleScrollPanel.hxx" + +#include <vcl/svapp.hxx> +#include <svtools/valueset.hxx> + +namespace sd { namespace toolpanel { + +ScrollPanel::ScrollPanel ( + ::Window& i_rParentWindow) + : Control (&i_rParentWindow, WB_DIALOGCONTROL), + TreeNode(NULL), + maScrollWindow(this, WB_DIALOGCONTROL), + maVerticalScrollBar(this, WB_VERT), + maHorizontalScrollBar(this, WB_HORZ), + maScrollBarFiller(this), + maScrollWindowFiller(&maScrollWindow), + mbIsRearrangePending(true), + mbIsLayoutPending(true), + mnChildrenWidth(0), + mnVerticalBorder(2), + mnVerticalGap(3), + mnHorizontalBorder(2) +{ + Construct(); +} + +void ScrollPanel::Construct() +{ + SetAccessibleName ( + ::rtl::OUString::createFromAscii("Sub Task Panel")); + mpControlContainer->SetMultiSelection (true); + + SetBorderStyle (WINDOW_BORDER_NORMAL); + SetMapMode (MapMode(MAP_PIXEL)); + + // To reduce flickering during repaints make the container windows + // transparent and rely on their children to paint the whole area. + SetBackground(Wallpaper()); + maScrollWindow.SetBackground(Wallpaper()); + maScrollWindowFiller.SetBackground( + Application::GetSettings().GetStyleSettings().GetWindowColor()); + + maScrollWindow.Show(); + + // Initialize the scroll bars. + maVerticalScrollBar.SetScrollHdl ( + LINK(this, ScrollPanel, ScrollBarHandler)); + maVerticalScrollBar.EnableDrag (TRUE); + maHorizontalScrollBar.SetScrollHdl ( + LINK(this, ScrollPanel, ScrollBarHandler)); + maHorizontalScrollBar.EnableDrag (TRUE); +} + + + + +ScrollPanel::~ScrollPanel (void) +{ + sal_uInt32 nCount = mpControlContainer->GetControlCount(); + for (sal_uInt32 nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pNode = mpControlContainer->GetControl(nIndex); + TreeNode* pControl = pNode; + // When the node has been created as TitledControl then use its + // control instead of pNode directly. + TitledControl* pTitledControl = static_cast<TitledControl*>(pNode); + if (pTitledControl != NULL) + pControl = pTitledControl->GetControl(); + + // Remove this object as listener from the control. + if (pControl != NULL && pControl->GetWindow()!=NULL) + { + pControl->GetWindow()->RemoveEventListener( + LINK(this,ScrollPanel,WindowEventListener)); + } + } + mpControlContainer->DeleteChildren(); +} + + + + +TitledControl* ScrollPanel::AddControl ( + ::std::auto_ptr<TreeNode> pControl, + const String& rTitle, + ULONG nHelpId) +{ + // We are interested only in the title. The control itself is + // managed by the content object. + TitledControl* pTitledControl = new TitledControl( + this, + pControl, + rTitle, + TitledControlStandardClickHandler(GetControlContainer(), ControlContainer::ES_TOGGLE), + TitleBar::TBT_SUB_CONTROL_HEADLINE); + pTitledControl->GetTitleBar()->SetHelpId(nHelpId); + + AddControl(::std::auto_ptr<TreeNode>(pTitledControl)); + + return pTitledControl; +} + + + + +void ScrollPanel::AddControl (::std::auto_ptr<TreeNode> pControl) +{ + if (pControl.get() != NULL) + { + // Add a window event listener which does two things: + // 1. Listen for controls being shown or hidden so that the layout + // can be adapted. + // 2. Track selection changes in order to make the selected elements + // visible. + const Link aWindowListener(LINK(this,ScrollPanel,WindowEventListener)); + OSL_ASSERT(pControl->GetWindow()!=NULL); + pControl->GetWindow()->AddEventListener(aWindowListener); + + TitledControl* pTitledControl = dynamic_cast<TitledControl*>(pControl.get()); + if (pTitledControl != NULL) + { + OSL_ASSERT(pTitledControl->GetControl()!=NULL); + OSL_ASSERT(pTitledControl->GetControl()->GetWindow()!=NULL); + pTitledControl->GetControl()->GetWindow()->AddEventListener(aWindowListener); + } + + FocusManager& rFocusManager (FocusManager::Instance()); + int nControlCount (mpControlContainer->GetControlCount()); + // Replace the old links for cycling between first and last child by + // current ones. + if (nControlCount > 0) + { + ::Window* pFirst = mpControlContainer->GetControl(0)->GetWindow(); + ::Window* pLast = mpControlContainer->GetControl(nControlCount-1)->GetWindow(); + rFocusManager.RemoveLinks(pFirst,pLast); + rFocusManager.RemoveLinks(pLast,pFirst); + + rFocusManager.RegisterLink(pFirst,pControl->GetWindow(), KEY_UP); + rFocusManager.RegisterLink(pControl->GetWindow(),pFirst, KEY_DOWN); + } + + + // Add a down link only for the first control so that when entering + // the sub tool panel the focus is set to the first control. + if (nControlCount == 0) + rFocusManager.RegisterDownLink(GetParent(), pControl->GetWindow()); + rFocusManager.RegisterUpLink(pControl->GetWindow(), GetParent()); + + pControl->GetWindow()->SetParent(&maScrollWindow); + mpControlContainer->AddControl (pControl); + mpControlContainer->SetExpansionState( + mpControlContainer->GetControlCount()-1, + ControlContainer::ES_EXPAND); + } +} + + + + +void ScrollPanel::Paint (const Rectangle& rRect) +{ + if (mbIsRearrangePending) + Rearrange(); + if (mbIsLayoutPending) + LayoutChildren(); + ::Window::Paint (rRect); + + // Paint the outer border and the space between every two children. + Color aOriginalLineColor (maScrollWindow.GetLineColor()); + Color aOriginalFillColor (maScrollWindow.GetFillColor()); + + maScrollWindow.SetLineColor (); + maScrollWindow.SetFillColor ( + GetSettings().GetStyleSettings().GetWindowColor()); + + Size aSize (maScrollWindow.GetOutputSizePixel()); + // Paint left and right vertical border. + Rectangle aVerticalArea ( + Point(0,0), + Size(mnHorizontalBorder,aSize.Height())); + maScrollWindow.DrawRect (aVerticalArea); + aVerticalArea.Right() += mnHorizontalBorder + mnChildrenWidth - 1; + aVerticalArea.Left() = aVerticalArea.Right() + mnHorizontalBorder; + maScrollWindow.DrawRect (aVerticalArea); + + // Paint horizontal stripes. + Rectangle aStripeArea ( + Point (mnHorizontalBorder,0), + Size(mnChildrenWidth,0)); + StripeList::const_iterator iStripe; + for (iStripe=maStripeList.begin(); iStripe!=maStripeList.end(); iStripe++) + { + aStripeArea.Top() = iStripe->first; + aStripeArea.Bottom() = iStripe->second; + if (aStripeArea.Bottom() < 0) + continue; + if (aStripeArea.Top() >= aSize.Height()) + break; + maScrollWindow.DrawRect (aStripeArea); + } + + maScrollWindow.SetLineColor (aOriginalLineColor); + maScrollWindow.SetFillColor (aOriginalFillColor); +} + + + + +void ScrollPanel::Resize (void) +{ + ::Window::Resize(); + mbIsRearrangePending = true; + mbIsLayoutPending = true; +} + + + + +void ScrollPanel::RequestResize (void) +{ + mbIsRearrangePending = true; + mbIsLayoutPending = true; + Invalidate(); +} + + + + +Size ScrollPanel::GetPreferredSize (void) +{ + return GetRequiredSize(); +} + + + + +sal_Int32 ScrollPanel::GetPreferredWidth (sal_Int32 ) +{ + return GetPreferredSize().Width(); +} + + + + +sal_Int32 ScrollPanel::GetPreferredHeight (sal_Int32 ) +{ + return GetPreferredSize().Height(); +} + + + + +bool ScrollPanel::IsResizable (void) +{ + return true; +} + + + + +::Window* ScrollPanel::GetWindow (void) +{ + return this; +} + + + + +sal_Int32 ScrollPanel::GetMinimumWidth (void) +{ + return TreeNode::GetMinimumWidth(); +} + + + + +void ScrollPanel::ExpandControl ( + TreeNode* pControl, + bool bExpansionState) +{ + // Toggle expand status. + pControl->Expand (bExpansionState); + + Rearrange (); + Invalidate (); +} + + + + +bool ScrollPanel::IsVerticalScrollBarVisible (void) const +{ + return maVerticalScrollBar.IsReallyVisible(); +} + + + + +bool ScrollPanel::IsHorizontalScrollBarVisible (void) const +{ + return maHorizontalScrollBar.IsReallyVisible(); +} + + + + +ScrollBar& ScrollPanel::GetVerticalScrollBar (void) +{ + return maVerticalScrollBar; +} + + + + +ScrollBar& ScrollPanel::GetHorizontalScrollBar (void) +{ + return maHorizontalScrollBar; +} + + + + +/** This control shows an expansion bar for every control and in a + separate area below that expansion area it shows all controls each + with its title bar. When there is not enough space then show a + scroll bar in the control area. +*/ +void ScrollPanel::Rearrange (void) +{ + Size aRequiredSize (GetRequiredSize()); + if (aRequiredSize.Width()>0 && aRequiredSize.Height()>0) + { + Size aAvailableSize (SetupScrollBars (aRequiredSize)); + maScrollWindow.SetPosSizePixel( + Point(0,0), + aAvailableSize); + + // Make the children at least as wide as the sub tool panel. + if (aRequiredSize.Width() < aAvailableSize.Width()) + aRequiredSize.Width() = aAvailableSize.Width(); + mnChildrenWidth = -2*mnHorizontalBorder; + if (maHorizontalScrollBar.IsVisible()) + mnChildrenWidth += aRequiredSize.Width(); + else + mnChildrenWidth += aAvailableSize.Width(); + + sal_Int32 nChildrenHeight (LayoutChildren()); + maVerticalScrollBar.SetRangeMax ( + nChildrenHeight + mnVerticalBorder); + + mbIsRearrangePending = false; + } +} + + + + +Size ScrollPanel::GetRequiredSize (void) +{ + // First determine the width of the children. This is the maximum of + // the current window width and the individual minimum widths of the + // children. + int nChildrenWidth (GetSizePixel().Width()); + unsigned int nCount = mpControlContainer->GetControlCount(); + unsigned int nIndex; + for (nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + int nMinimumWidth (pChild->GetMinimumWidth()); + if (nMinimumWidth > nChildrenWidth) + nChildrenWidth = nMinimumWidth; + } + + // Determine the accumulated width of all children when scaled to the + // minimum width. + nChildrenWidth -= 2*mnHorizontalBorder; + Size aTotalSize (nChildrenWidth, + 2*mnVerticalBorder + (nCount-1) * mnVerticalGap); + for (nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + sal_Int32 nHeight = pChild->GetPreferredHeight(nChildrenWidth); + aTotalSize.Height() += nHeight; + } + + return aTotalSize; +} + + + + +sal_Int32 ScrollPanel::LayoutChildren (void) +{ + maStripeList.clear(); + + Point aPosition (maScrollOffset); + aPosition.X() += mnHorizontalBorder; + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + aPosition.Y() + mnVerticalBorder - 1)); + aPosition.Y() += mnVerticalBorder; + + // Place the controls one over the other. + unsigned int nCount (mpControlContainer->GetControlCount()); + for (unsigned int nIndex=0; nIndex<nCount; nIndex++) + { + if (nIndex > 0) + { + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + aPosition.Y() + mnVerticalGap - 1)); + aPosition.Y() += mnVerticalGap; + } + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + int nControlHeight = pChild->GetPreferredHeight(mnChildrenWidth); + pChild->GetWindow()->SetPosSizePixel( + aPosition, + Size(mnChildrenWidth, nControlHeight)); + aPosition.Y() += nControlHeight; + } + + // If the children do not cover their parent window completely + // (regarding the height) we put a filler below that is responsible for + // painting the remaining space. + int nWindowHeight = maScrollWindow.GetSizePixel().Height(); + if (aPosition.Y() < nWindowHeight) + { + maScrollWindowFiller.SetPosSizePixel ( + aPosition, + Size(mnChildrenWidth, nWindowHeight-aPosition.Y())); + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + nWindowHeight-1)); + // maScrollWindowFiller.Show(); + aPosition.Y() = nWindowHeight; + } + else + maScrollWindowFiller.Hide(); + + aPosition.Y() += mnVerticalBorder; + mbIsLayoutPending = false; + + return aPosition.Y()-maScrollOffset.Y(); +} + + + + +Size ScrollPanel::SetupScrollBars (const Size& rRequiredSize) +{ + Size aWindowSize (GetSizePixel()); + Size aScrollBarSize ( + maVerticalScrollBar.GetSizePixel().Width(), + maHorizontalScrollBar.GetSizePixel().Height()); + Size aRemainingSize (aWindowSize); + + // Determine which scroll bars have to be shown. + bool bShowHorizontal = false; + if (rRequiredSize.Width() > aWindowSize.Width()) + bShowHorizontal = true; + bool bShowVertical = false; + if (rRequiredSize.Height() > aWindowSize.Height()) + bShowVertical = true; + // Showing one scroll bar may reduce the available size so that the + // other one has to be shown as well. + if (bShowHorizontal && ! bShowVertical) + { + if ((rRequiredSize.Height() + aScrollBarSize.Height()) + > aWindowSize.Height()) + bShowVertical = true; + } + else if (bShowVertical && ! bShowHorizontal) + { + if (GetMinimumWidth() + aScrollBarSize.Width() > aWindowSize.Width()) + bShowHorizontal = true; + } + + // Setup the scroll bars. + aRemainingSize.Width() + = SetupVerticalScrollBar (bShowVertical, rRequiredSize.Height()); + aRemainingSize.Height() + = SetupHorizontalScrollBar (bShowHorizontal, rRequiredSize.Width()); + + // Place the filler. + if (bShowHorizontal && bShowVertical) + { + maScrollBarFiller.SetPosSizePixel ( + Point(aWindowSize.Width(), aWindowSize.Height()), + aScrollBarSize); + maScrollBarFiller.Show(); + } + else + maScrollBarFiller.Hide(); + + + return aRemainingSize; +} + + + + +sal_Int32 ScrollPanel::SetupVerticalScrollBar (bool bShow, sal_Int32 nRange) +{ + Size aScrollBarSize ( + maVerticalScrollBar.GetSizePixel().Width(), + maHorizontalScrollBar.GetSizePixel().Height()); + Size aWindowSize (GetOutputSizePixel()); + sal_Int32 nRemainingWidth (aWindowSize.Width()); + + // Setup the verical scroll bar. + if (bShow) + { + int nWidth = aScrollBarSize.Width(); + int nHeight = aWindowSize.Height(); + maVerticalScrollBar.SetPosSizePixel( + Point(aWindowSize.Width()-nWidth,0), + Size(nWidth, nHeight)); + maVerticalScrollBar.Show(); + + // Set the scroll bar range and thumb size. + maVerticalScrollBar.SetRangeMin (0); + maVerticalScrollBar.SetRangeMax ( + nRange + 2*mnVerticalBorder); + maVerticalScrollBar.SetVisibleSize (aWindowSize.Height()); + // Make page size approx. 10% of visible area. + maVerticalScrollBar.SetLineSize (aWindowSize.Height()/10); + // Make page size approx. 100% of visible area. + maVerticalScrollBar.SetPageSize (aWindowSize.Height()); + // Make sure that thumb is inside the valid range. + maVerticalScrollBar.SetThumbPos(-maScrollOffset.Y()); + long nMinPos = maVerticalScrollBar.GetRangeMin(); + if (maVerticalScrollBar.GetThumbPos() < nMinPos) + maVerticalScrollBar.SetThumbPos(nMinPos); + long nMaxPos = maVerticalScrollBar.GetRangeMax() + - maVerticalScrollBar.GetVisibleSize(); + if (maVerticalScrollBar.GetThumbPos() >= nMaxPos) + maVerticalScrollBar.SetThumbPos(nMaxPos); + // Set offset to match thumb pos. + maScrollOffset.Y() = -maVerticalScrollBar.GetThumbPos(); + + nRemainingWidth -= aScrollBarSize.Width(); + } + else + { + maVerticalScrollBar.Hide(); + maScrollOffset.Y() = 0; + } + + return nRemainingWidth; +} + + + + +sal_Int32 ScrollPanel::SetupHorizontalScrollBar (bool bShow, sal_Int32 nRange) +{ + Size aScrollBarSize ( + maVerticalScrollBar.GetSizePixel().Width(), + maHorizontalScrollBar.GetSizePixel().Height()); + Size aWindowSize (GetOutputSizePixel()); + sal_Int32 nRemainingHeight (aWindowSize.Height()); + + // Setup the horizontal scroll bar. + if (bShow) + { + int nHeight = aScrollBarSize.Height(); + int nWidth = GetOutputSizePixel().Width(); + maHorizontalScrollBar.SetPosSizePixel( + Point(0, aWindowSize.Height()-nHeight), + Size(nWidth,nHeight)); + maHorizontalScrollBar.Show(); + + // Set the scroll bar range and thumb size. + maHorizontalScrollBar.SetRangeMin (0); + maHorizontalScrollBar.SetRangeMax ( + nRange + 2*mnHorizontalBorder); + maHorizontalScrollBar.SetVisibleSize (aWindowSize.Width()); + // Make page size approx. 5% of visible area. + maHorizontalScrollBar.SetLineSize (aWindowSize.Width()/20+1); + // Make page size approx. 50% of visible area. + maHorizontalScrollBar.SetPageSize (aWindowSize.Width()/2+1); + // Make sure that thumb is inside the valid range. + maHorizontalScrollBar.SetThumbPos(-maScrollOffset.X()); + long nMinPos = maHorizontalScrollBar.GetRangeMin(); + if (maHorizontalScrollBar.GetThumbPos() < nMinPos) + maHorizontalScrollBar.SetThumbPos(nMinPos); + long nMaxPos = maHorizontalScrollBar.GetRangeMax() + - maHorizontalScrollBar.GetVisibleSize(); + if (maHorizontalScrollBar.GetThumbPos() >= nMaxPos) + maHorizontalScrollBar.SetThumbPos(nMaxPos); + // Set offset to match thumb pos. + maScrollOffset.X() = -maHorizontalScrollBar.GetThumbPos(); + + nRemainingHeight -= aScrollBarSize.Height(); + } + else + { + maHorizontalScrollBar.Hide(); + maScrollOffset.X() = 0; + } + + return nRemainingHeight; +} + + +IMPL_LINK(ScrollPanel, ScrollBarHandler, ScrollBar*, EMPTYARG) +{ + maScrollOffset.X() -= maHorizontalScrollBar.GetDelta(); + maScrollOffset.Y() -= maVerticalScrollBar.GetDelta(); + + // Scrolling is done by moving the child windows up or down. + mbIsLayoutPending = true; + Invalidate(); + // LayoutChildren(); + + return 0; +} + + + + +long ScrollPanel::Notify( NotifyEvent& rNEvt ) +{ + long nRet = FALSE; + if( rNEvt.GetType() == EVENT_COMMAND ) + { + // note: dynamic_cast is not possible as GetData() returns a void* + CommandEvent* pCmdEvent = reinterpret_cast< CommandEvent* >(rNEvt.GetData()); + DBG_ASSERT( pCmdEvent!=0 && + ( pCmdEvent->IsMouseEvent() == TRUE || + pCmdEvent->IsMouseEvent() == FALSE ), + "Invalid CommandEvent" ); + if (pCmdEvent) + switch (pCmdEvent->GetCommand()) + { + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + { + nRet = HandleScrollCommand (*pCmdEvent, &maHorizontalScrollBar, &maVerticalScrollBar); + break; + } + } + } + + if( ! nRet ) + nRet = ::Window::Notify( rNEvt ); + + return nRet; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> ScrollPanel::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + return new ::accessibility::AccessibleScrollPanel ( + *this, + ::rtl::OUString::createFromAscii("Scroll Panel"), + ::rtl::OUString::createFromAscii("Scroll Panel")); +} + + + + +void ScrollPanel::MakeRectangleVisible ( + Rectangle& aRectangle, + ::Window* pWindow) +{ + if (maVerticalScrollBar.IsVisible() && aRectangle.GetWidth()>0 && aRectangle.GetHeight()>0) + { + const Rectangle aRelativeBox (pWindow->GetWindowExtentsRelative(&maScrollWindow)); + + aRectangle.Move( + -maScrollOffset.X() + aRelativeBox.Left(), + -maScrollOffset.Y() + aRelativeBox.Top()); + + const int nVisibleHeight (maVerticalScrollBar.GetVisibleSize()); + const int nVisibleTop (maVerticalScrollBar.GetThumbPos()); + if (aRectangle.Bottom() >= nVisibleTop+nVisibleHeight) + maVerticalScrollBar.DoScroll(aRectangle.Bottom() - nVisibleHeight); + else if (aRectangle.Top() < nVisibleTop) + maVerticalScrollBar.DoScroll(aRectangle.Top()); + } +} + + + + +IMPL_LINK(ScrollPanel,WindowEventListener,VclSimpleEvent*,pEvent) +{ + VclWindowEvent* pWindowEvent = dynamic_cast<VclWindowEvent*>(pEvent); + if (pWindowEvent != NULL) + { + switch (pWindowEvent->GetId()) + { + case VCLEVENT_WINDOW_KEYUP: + case VCLEVENT_WINDOW_MOUSEBUTTONUP: + { + // Make the currently selected item visible. + ValueSet* pControl = dynamic_cast<ValueSet*>(pWindowEvent->GetWindow()); + if (pControl != NULL) + { + // Get the bounding box of the currently selected item + // and enlarge this so that the selection frame is + // inside as well. + Rectangle aBox (pControl->GetItemRect(pControl->GetSelectItemId())); + aBox.Top()-=4; + aBox.Bottom()+=4; + + MakeRectangleVisible(aBox, pControl); + } + } + break; + + case VCLEVENT_WINDOW_MOUSEBUTTONDOWN: + { + // Make the item under the mouse visible. We need this case + // for right clicks that open context menus. For these we + // only get the mouse down event. The following mouse up + // event is sent to the context menu. + ValueSet* pControl = dynamic_cast<ValueSet*>(pWindowEvent->GetWindow()); + if (pControl != NULL) + { + // Get the bounding box of the item at the mouse + // position and enlarge this so that the selection frame + // is inside as well. + MouseEvent* pMouseEvent + = reinterpret_cast<MouseEvent*>(pWindowEvent->GetData()); + if (pMouseEvent != NULL) + { + Point aPosition (pMouseEvent->GetPosPixel()); + Rectangle aBox (pControl->GetItemRect(pControl->GetItemId(aPosition))); + aBox.Top()-=4; + aBox.Bottom()+=4; + + MakeRectangleVisible(aBox, pControl); + } + } + } + break; + + + case VCLEVENT_WINDOW_GETFOCUS: + { + // Move title bars into the visible area when they get the + // focus (::Window wise their enclosing TitledControl gets + // the focus.) + TitledControl* pTitledControl = dynamic_cast<TitledControl*>(pWindowEvent->GetWindow()); + if (pTitledControl!=NULL && pTitledControl->GetTitleBar()!=NULL) + { + ::Window* pTitleBarWindow = pTitledControl->GetTitleBar()->GetWindow(); + Rectangle aBox(pTitleBarWindow->GetPosPixel(),pTitleBarWindow->GetSizePixel()); + MakeRectangleVisible( + aBox, + pTitleBarWindow); + } + } + break; + + case VCLEVENT_WINDOW_SHOW: + case VCLEVENT_WINDOW_HIDE: + case VCLEVENT_WINDOW_ACTIVATE: + case VCLEVENT_WINDOW_RESIZE: + // Rearrange the children of the scroll panel when one of + // the children changes its size or visibility. + RequestResize(); + break; + } + } + return 0; +} + + + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/SlideSorterCacheDisplay.cxx b/sd/source/ui/toolpanel/SlideSorterCacheDisplay.cxx new file mode 100755 index 000000000000..a032b6ef02f0 --- /dev/null +++ b/sd/source/ui/toolpanel/SlideSorterCacheDisplay.cxx @@ -0,0 +1,372 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/SlideSorterCacheDisplay.hxx" + +#ifdef USE_SLIDE_SORTER_CACHE_DISPLAY + +#include "taskpane/ScrollPanel.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" + +#include <vcl/window.hxx> +#include <vcl/lstbox.hxx> +#include <vcl/button.hxx> + +namespace { + +static const Color maBackgroundColor (255,250,245); + +class PageCacheWindow : public ::Window +{ +public: + PageCacheWindow ( + ::Window* pParentWindow, + ::sd::toolpanel::SlideSorterCacheDisplay* pDisplay) + : ::Window(pParentWindow), + mpDisplay(pDisplay) + { + SetBackground(Wallpaper(maBackgroundColor)); + } + + virtual void Paint (const Rectangle& rBoundingBox) + { mpDisplay->Paint(rBoundingBox); ::Window::Paint(rBoundingBox); } + virtual void Resize (void) { mpDisplay->Resize(); ::Window::Resize(); } + +private: + ::sd::toolpanel::SlideSorterCacheDisplay* mpDisplay; +}; + +} + + + +namespace sd { namespace toolpanel { + +::std::map<const SdDrawDocument*, SlideSorterCacheDisplay*> SlideSorterCacheDisplay::maDisplays; + +SlideSorterCacheDisplay::SlideSorterCacheDisplay (const SdDrawDocument* pDocument) + : TreeNode(NULL), + mpWindow(NULL), + mnPageCount(0), + mnColumnCount(0), + mnRowCount(0), + maCellSize(0,0), + mnHorizontalBorder(0), + mnVerticalBorder(0) +{ + SlideSorterCacheDisplay::AddInstance(pDocument,this); +} + + + + +SlideSorterCacheDisplay::~SlideSorterCacheDisplay (void) +{ + if (mpWindow != NULL) + delete mpWindow; + SlideSorterCacheDisplay::RemoveInstance(this); +} + + + + +void SlideSorterCacheDisplay::SetParentWindow (::Window* pParentWindow) +{ + mpWindow = new PageCacheWindow(pParentWindow, this); +} + + + + +void SlideSorterCacheDisplay::Paint (const Rectangle& rBoundingBox) +{ + if (maCellSize.Width()>0 && maCellSize.Height()>0 && mpWindow!=NULL) + { + Color maSavedFillColor (mpWindow->GetFillColor()); + Color maSavedLineColor (mpWindow->GetLineColor()); + sal_Int32 nC0 = (rBoundingBox.Left() - mnHorizontalBorder) / maCellSize.Width(); + sal_Int32 nC1 = (rBoundingBox.Right() - mnHorizontalBorder) / maCellSize.Width(); + sal_Int32 nR0 = (rBoundingBox.Top() - mnVerticalBorder) / maCellSize.Height(); + sal_Int32 nR1 = (rBoundingBox.Bottom() - mnVerticalBorder) / maCellSize.Height(); + for (sal_Int32 nC=nC0; nC<=nC1; ++nC) + for (sal_Int32 nR=nR0; nR<=nR1; ++nR) + { + sal_Int32 nPageIndex (nC + nR*mnColumnCount); + if (nPageIndex < mnPageCount) + { + Rectangle aBox (GetPageBox(nPageIndex)); + if ( ! maPageDescriptors[nPageIndex].mbVisible) + { + mpWindow->SetLineColor(); + mpWindow->SetFillColor(maBackgroundColor); + mpWindow->DrawRect(aBox); + + aBox.Left() += maCellSize.Width()/4; + aBox.Right() -= maCellSize.Width()/4; + aBox.Top() += maCellSize.Height()/4; + aBox.Bottom() -= maCellSize.Height()/4; + } + + switch (maPageDescriptors[nPageIndex].meStatus) + { + case NONE : mpWindow->SetFillColor (Color(95,255,128)); break; + case RENDERING : mpWindow->SetFillColor (Color(236,125,128)); break; + case IN_QUEUE_PRIORITY_0 : mpWindow->SetFillColor (Color(255,243,0)); break; + case IN_QUEUE_PRIORITY_1 : mpWindow->SetFillColor (Color(255,199,0)); break; + case IN_QUEUE_PRIORITY_2 : mpWindow->SetFillColor (Color(20,255,128)); break; + default : mpWindow->SetFillColor (COL_BLACK); break; + } + mpWindow->SetLineColor(COL_BLACK); + mpWindow->DrawRect(aBox); + + if ( ! maPageDescriptors[nPageIndex].mbUpToDate) + mpWindow->DrawLine(aBox.TopLeft(), aBox.BottomRight()); + } + } + mpWindow->SetLineColor(maSavedLineColor); + mpWindow->SetFillColor(maSavedFillColor); + } +} + + + + +void SlideSorterCacheDisplay::Resize (void) +{ + if (mpWindow != NULL) + { + double nW = mpWindow->GetSizePixel().Width(); + double nH = mpWindow->GetSizePixel().Height(); + if (nH > 0) + { + double nAspect = nW / nH; + sal_Int32 nR = 1; + sal_Int32 nC = 1; + while (nR * nC < mnPageCount) + { + if (double(nC) / double(nR) > nAspect) + ++nR; + else + ++nC; + } + double nAspect2 = double(nC) / double(nR); + + mnRowCount = nR; + mnColumnCount = nC; + mnHorizontalGap = 2; + mnVerticalGap = 2; + maCellSize = Size( + (int)((nW-(nC-1)*mnHorizontalGap) / nC), + (int)((nH-(nR-1)*mnVerticalGap) / nR)); + mnHorizontalBorder = (int)(nW - nC*maCellSize.Width() - ((nC-1)*mnHorizontalGap))/2; + mnVerticalBorder = (int)(nH - nR*maCellSize.Height() - ((nR-1)*mnVerticalGap))/2; + } + } +} + + + + +SlideSorterCacheDisplay* SlideSorterCacheDisplay::Instance (const SdDrawDocument* pDocument) +{ + SlideSorterCacheDisplay* pDisplay = NULL; + ::std::map<const SdDrawDocument*, SlideSorterCacheDisplay*>::iterator iDisplay; + for (iDisplay=maDisplays.begin(); iDisplay!=maDisplays.end(); ++iDisplay) + if (iDisplay->first == pDocument) + pDisplay = iDisplay->second; + + if (pDisplay == NULL) + { + pDisplay = new SlideSorterCacheDisplay(pDocument); + } + + return pDisplay; +} + + + + +void SlideSorterCacheDisplay::SetPageCount (sal_Int32 nPageCount) +{ + mnPageCount = nPageCount; + maPageDescriptors.resize(nPageCount); + Resize(); + if (mpWindow != NULL) + mpWindow->Invalidate(); +} + + + + +void SlideSorterCacheDisplay::SetPageStatus (sal_Int32 nPageIndex, PageStatus eStatus) +{ + ProvideSize(nPageIndex); + maPageDescriptors[nPageIndex].meStatus = eStatus; + PaintPage(nPageIndex); +} + + + + +void SlideSorterCacheDisplay::SetPageVisibility (sal_Int32 nPageIndex, bool bVisible) +{ + ProvideSize(nPageIndex); + maPageDescriptors[nPageIndex].mbVisible = bVisible; + PaintPage(nPageIndex); +} + + + + +void SlideSorterCacheDisplay::SetUpToDate (sal_Int32 nPageIndex, bool bUpToDate) +{ + ProvideSize(nPageIndex); + maPageDescriptors[nPageIndex].mbUpToDate = bUpToDate; + PaintPage(nPageIndex); +} + + + + +Rectangle SlideSorterCacheDisplay::GetPageBox (sal_Int32 nPageIndex) +{ + sal_Int32 nRow = nPageIndex / mnColumnCount; + sal_Int32 nColumn = nPageIndex % mnColumnCount; + return Rectangle( + Point(mnHorizontalBorder + nColumn * maCellSize.Width() + nColumn*mnHorizontalGap, + mnVerticalBorder + nRow * maCellSize.Height() + nRow*mnVerticalGap), + maCellSize); +} + + + + +void SlideSorterCacheDisplay::AddInstance ( + const SdDrawDocument* pDocument, + SlideSorterCacheDisplay* pControl) +{ + maDisplays[pDocument] = pControl; +} + + + + +void SlideSorterCacheDisplay::RemoveInstance (SlideSorterCacheDisplay* pControl) +{ + ::std::map<const SdDrawDocument*, SlideSorterCacheDisplay*>::iterator iDisplay; + for (iDisplay=maDisplays.begin(); iDisplay!=maDisplays.end(); ++iDisplay) + if (iDisplay->second == pControl) + { + maDisplays.erase(iDisplay); + break; + } +} + + + + +void SlideSorterCacheDisplay::ProvideSize (sal_Int32 nPageIndex) +{ + if (maPageDescriptors.size() <= (sal_uInt32)nPageIndex) + maPageDescriptors.resize(nPageIndex+1); + if (mnPageCount <= nPageIndex) + mnPageCount = nPageIndex; +} + + + + +Size SlideSorterCacheDisplay::GetPreferredSize (void) +{ + return Size(100,100); +} + + + + +sal_Int32 SlideSorterCacheDisplay::GetPreferredWidth (sal_Int32 nHeigh) +{ + return GetPreferredSize().Width(); +} + + + + +sal_Int32 SlideSorterCacheDisplay::GetPreferredHeight (sal_Int32 nWidth) +{ + return GetPreferredSize().Height(); +} + + + +::Window* SlideSorterCacheDisplay::GetWindow (void) +{ + return mpWindow; +} + + + + +bool SlideSorterCacheDisplay::IsResizable (void) +{ + return true; +} + + + + +bool SlideSorterCacheDisplay::IsExpandable (void) const +{ + return true; +} + + + + +bool SlideSorterCacheDisplay::IsExpanded (void) const +{ + return true; +} + + + + +void SlideSorterCacheDisplay::PaintPage (sal_Int32 nPageIndex) +{ + if (mpWindow != NULL) + { + Paint(GetPageBox(nPageIndex)); + } +} + + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/SubToolPanel.cxx b/sd/source/ui/toolpanel/SubToolPanel.cxx new file mode 100755 index 000000000000..4e85d8c9fec9 --- /dev/null +++ b/sd/source/ui/toolpanel/SubToolPanel.cxx @@ -0,0 +1,390 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/SubToolPanel.hxx" + +#include "TaskPaneFocusManager.hxx" +#include "taskpane/TitleBar.hxx" +#include "taskpane/TitledControl.hxx" +#include "taskpane/ControlContainer.hxx" +#include "AccessibleTreeNode.hxx" +#include <vcl/decoview.hxx> +#include <vcl/svapp.hxx> + +namespace sd { namespace toolpanel { + + +SubToolPanel::SubToolPanel ( + Window& i_rParentWindow) + : Control (&i_rParentWindow, WB_DIALOGCONTROL), + TreeNode(NULL), + maWindowFiller(this), + mbIsRearrangePending(true), + mbIsLayoutPending(true), + mnChildrenWidth(0), + mnVerticalBorder(0), + mnVerticalGap(3), + mnHorizontalBorder(2) +{ + SetAccessibleName ( + ::rtl::OUString::createFromAscii("Sub Task Panel")); + mpControlContainer->SetMultiSelection (true); + + SetBorderStyle (WINDOW_BORDER_NORMAL); + SetMapMode (MapMode(MAP_PIXEL)); + + // To reduce flickering during repaints make the container windows + // transparent and rely on their children to paint the whole area. + SetBackground(Wallpaper()); + maWindowFiller.SetBackground( + Application::GetSettings().GetStyleSettings().GetWindowColor()); +} + + + + +SubToolPanel::~SubToolPanel (void) +{ + sal_uInt32 nCount = mpControlContainer->GetControlCount(); + for (sal_uInt32 nIndex=0; nIndex<nCount; nIndex++) + { + TitledControl* pControl = static_cast<TitledControl*>( + mpControlContainer->GetControl(nIndex)); + pControl->GetControl()->GetWindow()->RemoveEventListener( + LINK(this,SubToolPanel,WindowEventListener)); + } + mpControlContainer->DeleteChildren(); +} + + + + +void SubToolPanel::Paint (const Rectangle& rRect) +{ + if (mbIsRearrangePending) + Rearrange(); + if (mbIsLayoutPending) + LayoutChildren(); + ::Window::Paint (rRect); + + // Paint the outer border and the space between every two children. + Color aOriginalLineColor (GetLineColor()); + Color aOriginalFillColor (GetFillColor()); + + SetLineColor (); + SetFillColor (GetSettings().GetStyleSettings().GetWindowColor()); + + Size aSize (GetOutputSizePixel()); + // Paint left and right vertical border. + Rectangle aVerticalArea ( + Point(0,0), + Size(mnHorizontalBorder,aSize.Height())); + DrawRect (aVerticalArea); + aVerticalArea.Right() += mnHorizontalBorder + mnChildrenWidth - 1; + aVerticalArea.Left() = aVerticalArea.Right() + mnHorizontalBorder; + DrawRect (aVerticalArea); + + // Paint horizontal stripes. + Rectangle aStripeArea ( + Point (mnHorizontalBorder,0), + Size(mnChildrenWidth,0)); + StripeList::const_iterator iStripe; + for (iStripe=maStripeList.begin(); iStripe!=maStripeList.end(); iStripe++) + { + aStripeArea.Top() = iStripe->first; + aStripeArea.Bottom() = iStripe->second; + if (aStripeArea.Bottom() < 0) + continue; + if (aStripeArea.Top() >= aSize.Height()) + break; + DrawRect (aStripeArea); + } + + SetLineColor (aOriginalLineColor); + SetFillColor (aOriginalFillColor); +} + + + + +void SubToolPanel::Resize (void) +{ + ::Window::Resize(); + mbIsRearrangePending = true; + mbIsLayoutPending = true; +} + + + + +void SubToolPanel::RequestResize (void) +{ + mbIsRearrangePending = true; + mbIsLayoutPending = true; + Invalidate(); +} + + + + +Size SubToolPanel::GetPreferredSize (void) +{ + return GetRequiredSize(); +} + + + + +sal_Int32 SubToolPanel::GetPreferredWidth (sal_Int32 ) +{ + return GetPreferredSize().Width(); +} + + + + +sal_Int32 SubToolPanel::GetPreferredHeight (sal_Int32 ) +{ + return GetPreferredSize().Height(); +} + + + + +bool SubToolPanel::IsResizable (void) +{ + return true; +} + + + + +::Window* SubToolPanel::GetWindow (void) +{ + return this; +} + + + + +sal_Int32 SubToolPanel::GetMinimumWidth (void) +{ + return TreeNode::GetMinimumWidth(); +} + + + + +void SubToolPanel::ExpandControl ( + TreeNode* pControl, + bool bExpansionState) +{ + // Toggle expand status. + pControl->Expand (bExpansionState); + + Rearrange (); + Invalidate (); +} + + + + +/** This control shows an expansion bar for every control and in a + separate area below that expansion area it shows all controls each + with its title bar. When there is not enough space then show a + scroll bar in the control area. +*/ +void SubToolPanel::Rearrange (void) +{ + Size aRequiredSize (GetRequiredSize()); + if (aRequiredSize.Width()>0 && aRequiredSize.Height()>0) + { + Size aAvailableSize (GetOutputSizePixel()); + + // Make the children at least as wide as the sub tool panel. + if (aRequiredSize.Width() < aAvailableSize.Width()) + aRequiredSize.Width() = aAvailableSize.Width(); + mnChildrenWidth = -2*mnHorizontalBorder; + mnChildrenWidth += aAvailableSize.Width(); + + LayoutChildren(); + + mbIsRearrangePending = false; + } +} + + + + +Size SubToolPanel::GetRequiredSize (void) +{ + // First determine the width of the children. This is the maximum of + // the current window width and the individual minimum widths of the + // children. + int nChildrenWidth (GetSizePixel().Width()); + unsigned int nCount = mpControlContainer->GetControlCount(); + unsigned int nIndex; + for (nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + int nMinimumWidth (pChild->GetMinimumWidth()); + if (nMinimumWidth > nChildrenWidth) + nChildrenWidth = nMinimumWidth; + } + + // Determine the accumulated width of all children when scaled to the + // minimum width. + nChildrenWidth -= 2*mnHorizontalBorder; + Size aTotalSize (nChildrenWidth, + 2*mnVerticalBorder + (nCount-1) * mnVerticalGap); + for (nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + sal_Int32 nHeight = pChild->GetPreferredHeight(nChildrenWidth); + aTotalSize.Height() += nHeight; + } + + return aTotalSize; +} + + + + +sal_Int32 SubToolPanel::LayoutChildren (void) +{ + // Determine vertical space that can be distributed to sizable children. + unsigned int nCount (mpControlContainer->GetControlCount()); + unsigned int nResizableCount = 0; + int nAvailableHeight = GetSizePixel().Height() - 2*mnVerticalBorder; + unsigned int nIndex; + for (nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + int nControlHeight = pChild->GetPreferredHeight(mnChildrenWidth); + if (pChild->IsResizable()) + nResizableCount++; + else + nAvailableHeight -= nControlHeight; + } + + maStripeList.clear(); + + Point aPosition (0,0); + aPosition.X() += mnHorizontalBorder; + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + aPosition.Y() + mnVerticalBorder - 1)); + aPosition.Y() += mnVerticalBorder; + + // Place the controls one over the other. + for (nIndex=0; nIndex<nCount; nIndex++) + { + if (nIndex > 0) + { + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + aPosition.Y() + mnVerticalGap - 1)); + aPosition.Y() += mnVerticalGap; + } + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + int nControlHeight = pChild->GetPreferredHeight(mnChildrenWidth); + if (pChild->IsResizable()) + { + nControlHeight = nAvailableHeight / nResizableCount; + nResizableCount--; + } + nAvailableHeight -= nControlHeight; + pChild->GetWindow()->SetPosSizePixel( + aPosition, + Size(mnChildrenWidth, nControlHeight)); + aPosition.Y() += nControlHeight; + } + + // If the children do not cover their parent window completely + // (regarding the height) we put a filler below that is responsible for + // painting the remaining space. + int nWindowHeight = GetSizePixel().Height(); + if (aPosition.Y() < nWindowHeight) + { + maWindowFiller.SetPosSizePixel ( + aPosition, + Size(mnChildrenWidth, nWindowHeight-aPosition.Y())); + maStripeList.push_back( ::std::pair<int,int>( + aPosition.Y(), + nWindowHeight-1)); + // maScrollWindowFiller.Show(); + aPosition.Y() = nWindowHeight; + } + else + maWindowFiller.Hide(); + + aPosition.Y() += mnVerticalBorder; + mbIsLayoutPending = false; + + return aPosition.Y(); +} + + + + +IMPL_LINK(SubToolPanel, WindowEventListener, VclSimpleEvent*, pEvent) +{ + if (pEvent!=NULL && pEvent->ISA(VclWindowEvent)) + { + VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); + switch (pWindowEvent->GetId()) + { + case VCLEVENT_WINDOW_SHOW: + case VCLEVENT_WINDOW_HIDE: + case VCLEVENT_WINDOW_ACTIVATE: + case VCLEVENT_WINDOW_RESIZE: + RequestResize(); + break; + } + } + return 0; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> SubToolPanel::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + return new ::accessibility::AccessibleTreeNode ( + *this, + ::rtl::OUString::createFromAscii("Sub Task Panel"), + ::rtl::OUString::createFromAscii("Sub Task Panel"), + ::com::sun::star::accessibility::AccessibleRole::PANEL); +} + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TaskPaneControlFactory.cxx b/sd/source/ui/toolpanel/TaskPaneControlFactory.cxx new file mode 100755 index 000000000000..4ad610df7f7f --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneControlFactory.cxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/TaskPaneControlFactory.hxx" + +#include <vos/diagnose.hxx> + +namespace sd { namespace toolpanel { + +ControlFactory::ControlFactory (void) +{ +} + + + + +ControlFactory::~ControlFactory (void) +{ +} + + + + +::std::auto_ptr<TreeNode> ControlFactory::CreateControl( ::Window& i_rParent ) +{ + TreeNode* pNewNode = InternalCreateControl( i_rParent ); + return ::std::auto_ptr<TreeNode>( pNewNode ); +} + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TaskPaneFocusManager.cxx b/sd/source/ui/toolpanel/TaskPaneFocusManager.cxx new file mode 100644 index 000000000000..48882d0f2f9e --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneFocusManager.cxx @@ -0,0 +1,325 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "TaskPaneFocusManager.hxx" + +#include <vcl/window.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <vcl/event.hxx> +#include <hash_map> + +namespace { + +class WindowHash +{ +public: + size_t operator()(const ::Window* argument) const + { return reinterpret_cast<unsigned long>(argument); } +}; + +class EventDescriptor +{ +public: + EventDescriptor (const KeyCode& rKey, ::Window* pWindow) + : maKeyCode(rKey), mpTargetWindow(pWindow) {} + KeyCode maKeyCode; + ::Window* mpTargetWindow; +}; + +} // end of anonymous namespace + + + + +namespace sd { namespace toolpanel { + + + +class FocusManager::LinkMap + : public ::std::hash_multimap< ::Window*, EventDescriptor, WindowHash> +{ +}; + + + +FocusManager* FocusManager::spInstance = NULL; + + +FocusManager& FocusManager::Instance (void) +{ + if (spInstance == NULL) + { + ::vos::OGuard aGuard (::Application::GetSolarMutex()); + if (spInstance == NULL) + spInstance = new FocusManager (); + } + return *spInstance; +} + + + + +FocusManager::FocusManager (void) + : mpLinks(new LinkMap()) +{ +} + + + + +FocusManager::~FocusManager (void) +{ + Clear(); +} + + + + +void FocusManager::Clear (void) +{ + if (mpLinks.get() != NULL) + { + while ( ! mpLinks->empty()) + { + ::Window* pWindow = mpLinks->begin()->first; + if (pWindow == NULL) + { + mpLinks->erase(mpLinks->begin()); + } + else + { + RemoveLinks(pWindow); + } + } + } +} + + + + +void FocusManager::RegisterUpLink (::Window* pSource, ::Window* pTarget) +{ + RegisterLink(pSource, pTarget, KEY_ESCAPE); +} + + + + +void FocusManager::RegisterDownLink (::Window* pSource, ::Window* pTarget) +{ + RegisterLink(pSource, pTarget, KEY_RETURN); +} + + + + +void FocusManager::RegisterLink ( + ::Window* pSource, + ::Window* pTarget, + const KeyCode& rKey) +{ + OSL_ASSERT(pSource!=NULL); + OSL_ASSERT(pTarget!=NULL); + + if (pSource==NULL || pTarget==NULL) + return; + + // Register this focus manager as event listener at the source window. + if (mpLinks->equal_range(pSource).first == mpLinks->end()) + pSource->AddEventListener (LINK (this, FocusManager, WindowEventListener)); + mpLinks->insert(LinkMap::value_type(pSource, EventDescriptor(rKey,pTarget))); +} + + + + +void FocusManager::RemoveLinks ( + ::Window* pSourceWindow, + ::Window* pTargetWindow) +{ + OSL_ASSERT(pSourceWindow!=NULL); + OSL_ASSERT(pTargetWindow!=NULL); + + if (pSourceWindow==NULL || pTargetWindow==NULL) + { + // This method was called with invalid arguments. To avoid + // referencing windows that will soon be deleted we clear *all* + // links as an emergency fallback. + Clear(); + return; + } + + ::std::pair<LinkMap::iterator,LinkMap::iterator> aCandidates; + LinkMap::iterator iCandidate; + bool bLoop (mpLinks->size() > 0); + while (bLoop) + { + aCandidates = mpLinks->equal_range(pSourceWindow); + if (aCandidates.first == mpLinks->end()) + { + // No links for the source window found -> nothing more to do. + bLoop = false; + } + else + { + // Set the loop control to false so that when no candidate for + // deletion is found the loop is left. + bLoop = false; + for (iCandidate=aCandidates.first; iCandidate!=aCandidates.second; ++iCandidate) + if (iCandidate->second.mpTargetWindow == pTargetWindow) + { + mpLinks->erase(iCandidate); + // One link erased. The iterators have become invalid so + // start the search for links to delete anew. + bLoop = true; + break; + } + } + } + + RemoveUnusedEventListener(pSourceWindow); +} + + + + +void FocusManager::RemoveLinks (::Window* pWindow) +{ + OSL_ASSERT(pWindow!=NULL); + + if (pWindow == NULL) + { + // This method was called with invalid arguments. To avoid + // referencing windows that will soon be deleted we clear *all* + // links as an emergency fallback. + Clear(); + return; + } + + // Make sure that we are not called back for the window. + pWindow->RemoveEventListener (LINK (this, FocusManager, WindowEventListener)); + + // Remove the links from the given window. + ::std::pair<LinkMap::iterator,LinkMap::iterator> aCandidates(mpLinks->equal_range(pWindow)); + mpLinks->erase(aCandidates.first, aCandidates.second); + + // Remove links to the given window. + bool bLinkRemoved; + do + { + bLinkRemoved = false; + LinkMap::iterator iLink; + for (iLink=mpLinks->begin(); iLink!=mpLinks->end(); ++iLink) + { + if (iLink->second.mpTargetWindow == pWindow) + { + RemoveUnusedEventListener(iLink->first); + mpLinks->erase(iLink); + bLinkRemoved = true; + break; + } + } + } + while (bLinkRemoved); +} + + + + +void FocusManager::RemoveUnusedEventListener (::Window* pWindow) +{ + OSL_ASSERT(pWindow!=NULL); + + if (pWindow == NULL) + return; + + // When there are no more links from the window to another window + // then remove the event listener from the window. + if (mpLinks->find(pWindow) == mpLinks->end()) + pWindow->RemoveEventListener (LINK (this, FocusManager, WindowEventListener)); +} + + + + +bool FocusManager::TransferFocus ( + ::Window* pSourceWindow, + const KeyCode& rKeyCode) +{ + bool bSuccess (false); + + OSL_ASSERT(pSourceWindow!=NULL); + if (pSourceWindow == NULL) + return bSuccess; + + ::std::pair<LinkMap::iterator,LinkMap::iterator> aCandidates ( + mpLinks->equal_range(pSourceWindow)); + LinkMap::const_iterator iCandidate; + for (iCandidate=aCandidates.first; iCandidate!=aCandidates.second; ++iCandidate) + if (iCandidate->second.maKeyCode == rKeyCode) + { + OSL_ASSERT(iCandidate->second.mpTargetWindow != NULL); + iCandidate->second.mpTargetWindow->GrabFocus(); + bSuccess = true; + break; + } + + return bSuccess; +} + + + + +IMPL_LINK(FocusManager, WindowEventListener, VclSimpleEvent*, pEvent) +{ + if (pEvent!=NULL && pEvent->ISA(VclWindowEvent)) + { + VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); + switch (pWindowEvent->GetId()) + { + case VCLEVENT_WINDOW_KEYINPUT: + { + ::Window* pSource = pWindowEvent->GetWindow(); + KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); + TransferFocus(pSource, pKeyEvent->GetKeyCode()); + } + break; + + case VCLEVENT_OBJECT_DYING: + RemoveLinks(pWindowEvent->GetWindow()); + break; + } + } + return 1; +} + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TaskPaneFocusManager.hxx b/sd/source/ui/toolpanel/TaskPaneFocusManager.hxx new file mode 100644 index 000000000000..b9b28154dc5b --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneFocusManager.hxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_FOCUS_MANAGER_HXX +#define SD_TOOLPANEL_FOCUS_MANAGER_HXX + +#include <tools/link.hxx> + +#include <memory> + +class KeyCode; +class VclSimpleEvent; +class Window; + +namespace sd { namespace toolpanel { + +/** On certain key presses the focus is moved from one window to another. + For this to work every window that wants its focus managed has to + register or be registered and tell where to put the focus on what key + press. +*/ +class FocusManager +{ +public: + /** Return an instance of the focus manager. + */ + static FocusManager& Instance (void); + + /** Register a link from one window to another so that any time the + specified key is pressed while the source window is focused, the + focus is transferred to the target window. + @param pSource + The window from which the focus will be transferred. + @param pTarget + The window to which the focus will be transferred. + @param rKey + The key for which the focus is transferred from the source + window to the target window. + */ + void RegisterLink ( + ::Window* pSource, + ::Window* pTarget, + const KeyCode& rKey); + + /** Register a link that will move the focus from the source window to + the target window when the source window is focused and KEY_ESCAPE + is pressed. + @param pSource + The window from which the focus will be transferred. + @param pTarget + The window to which the focus will be transferred. + */ + void RegisterUpLink (::Window* pSource, ::Window* pTarget); + + /** Register a link that will move the focus from the source window to + the target window when the source window is focused and KEY_RETURN + is pressed. + @param pSource + The window from which the focus will be transferred. + @param pTarget + The window to which the focus will be transferred. + */ + void RegisterDownLink (::Window* pSource, ::Window* pTarget); + + /** Remove all links from the source window to the target window. When + there are links from the target window to the source window then + these are not touced. + */ + void RemoveLinks ( + ::Window* pSource, + ::Window* pTarget); + + /** Let the focus manager transfer the focus from the specified source + window to a target window that is determined according the the + registered links and the given key code. + When there is no rule for this combination of source window and key + code then the focus stays where it is. + */ + bool TransferFocus (::Window* pSource, const KeyCode& rCode); + +private: + static FocusManager* spInstance; + class LinkMap; + ::std::auto_ptr<LinkMap> mpLinks; + + FocusManager (void); + ~FocusManager (void); + + /** Clear the list of focus transfer links. This removes all window + listeners. + */ + void Clear (void); + + /** Remove all links from or to the given window. + */ + void RemoveLinks (::Window* pWindow); + + /** Unregister as event listener from the given window when there are no + links from this window anymore. + */ + void RemoveUnusedEventListener (::Window* pWindow); + + /** Listen for key events and on KEY_RETURN go down and on + KEY_ESCAPE go up. + */ + DECL_LINK(WindowEventListener, VclSimpleEvent*); +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/TaskPaneShellManager.cxx b/sd/source/ui/toolpanel/TaskPaneShellManager.cxx new file mode 100755 index 000000000000..0a9667dd2431 --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneShellManager.cxx @@ -0,0 +1,183 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "TaskPaneShellManager.hxx" + +#include "ViewShellManager.hxx" +#include <tools/diagnose_ex.h> +#include <vcl/window.hxx> + +#include <algorithm> + +namespace sd { namespace toolpanel { + +TaskPaneShellManager::TaskPaneShellManager ( + const ::boost::shared_ptr<ViewShellManager>& rpViewShellManager, + const ViewShell& rViewShell) + : mpViewShellManager(rpViewShellManager), + mrViewShell(rViewShell), + maSubShells() +{ +} + + + + +TaskPaneShellManager::~TaskPaneShellManager (void) +{ + while ( ! maSubShells.empty()) + RemoveSubShell(maSubShells.begin()->second.mpShell); +} + + + + +SfxShell* TaskPaneShellManager::CreateShell( ShellId nId, ::Window* , FrameView* ) +{ + SubShells::const_iterator iShell (maSubShells.find(nId)); + if (iShell != maSubShells.end()) + return iShell->second.mpShell; + else + return NULL; +} + + + + +void TaskPaneShellManager::ReleaseShell (SfxShell* ) +{ + // Nothing to do. +} + +void TaskPaneShellManager::AddSubShell ( + ShellId nId, + SfxShell* pShell, + ::Window* pWindow) +{ + if (pShell != NULL) + { + maSubShells[nId] = ShellDescriptor(pShell,pWindow); + if (pWindow != NULL) + { + pWindow->AddEventListener(LINK(this,TaskPaneShellManager,WindowCallback)); + if (pWindow->IsReallyVisible()) + mpViewShellManager->ActivateSubShell(mrViewShell, nId); + } + else + mpViewShellManager->ActivateSubShell(mrViewShell, nId); + } +} + + + + +void TaskPaneShellManager::RemoveSubShell (const ShellId i_nShellId) +{ + SubShells::iterator pos = maSubShells.find( i_nShellId ); + ENSURE_OR_RETURN_VOID( pos != maSubShells.end(), "no shell for this ID" ); + if ( pos->second.mpWindow != NULL ) + { + pos->second.mpWindow->RemoveEventListener( LINK( this, TaskPaneShellManager, WindowCallback ) ); + } + mpViewShellManager->DeactivateSubShell( mrViewShell, pos->first ); + maSubShells.erase( pos ); +} + + + + +void TaskPaneShellManager::RemoveSubShell (const SfxShell* pShell) +{ + if (pShell != NULL) + { + SubShells::iterator iShell; + for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell) + if (iShell->second.mpShell == pShell) + { + if (iShell->second.mpWindow != NULL) + iShell->second.mpWindow->RemoveEventListener( + LINK(this,TaskPaneShellManager,WindowCallback)); + mpViewShellManager->DeactivateSubShell(mrViewShell,iShell->first); + maSubShells.erase(iShell); + break; + } + } +} + + + + +void TaskPaneShellManager::MoveToTop (SfxShell* pShell) +{ + SubShells::const_iterator iShell; + for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell) + if (iShell->second.mpShell == pShell) + { + ViewShellManager::UpdateLock aLocker (mpViewShellManager); + mpViewShellManager->MoveSubShellToTop(mrViewShell,iShell->first); + mpViewShellManager->MoveToTop(mrViewShell); + break; + } +} + + + + +IMPL_LINK(TaskPaneShellManager, WindowCallback, VclWindowEvent*, pEvent) +{ + if (pEvent != NULL) + { + SubShells::const_iterator iShell; + ::Window* pWindow = pEvent->GetWindow(); + for (iShell=maSubShells.begin(); iShell!=maSubShells.end(); ++iShell) + if (iShell->second.mpWindow == pWindow) + break; + if (iShell != maSubShells.end()) + switch (pEvent->GetId()) + { + case VCLEVENT_WINDOW_SHOW: + mpViewShellManager->ActivateSubShell(mrViewShell,iShell->first); + break; + + case VCLEVENT_WINDOW_HIDE: + // Do not activate the sub shell. This leads to + // problems with shapes currently being in text edit + // mode: Deactivating the shell leads to leaving the + // text editing mode. + // mpViewShellManager->DeactivateSubShell(mrViewShell,iShell->first); + break; + } + } + + return 0; +} + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TaskPaneShellManager.hxx b/sd/source/ui/toolpanel/TaskPaneShellManager.hxx new file mode 100755 index 000000000000..92e7b6b83b8d --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneShellManager.hxx @@ -0,0 +1,121 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_TASK_PANE_SHELL_MANAGER_HXX +#define SD_TOOLPANEL_TASK_PANE_SHELL_MANAGER_HXX + +#include "ShellFactory.hxx" +#include "ViewShellManager.hxx" +#include <map> + +class FrameView; +class SfxShell; +class VclWindowEvent; +class Window; + +namespace sd { +class ViewShell; +} + +namespace sd { namespace toolpanel { + +/** The TaskPaneShellManager implements the ViewShellManager::ShellFactory + interface. However, it does not create or delete shells. It only + gives the ViewShellManager access to the sub shells of the + ToolPanelViewShell. Life time control of the sub shells is managed by + the sub shells themselves. +*/ +class TaskPaneShellManager + : public ShellFactory<SfxShell> +{ +public: + /** Create a shell manager that manages the stacked shells for the given + view shell. It works together with the given view shell manager. + */ + TaskPaneShellManager ( + const ::boost::shared_ptr<ViewShellManager>& rpViewShellManager, + const ViewShell& rViewShell); + ~TaskPaneShellManager (void); + + /** Return the requested sub shell. + @param nId + The id of the requested sub shell. + @return + When there is no sub shell currently registered under the given + id then NULL is returned. + */ + virtual SfxShell* CreateShell ( + ShellId nId, + ::Window* pParentWindow, + FrameView* pFrameView = NULL); + + virtual void ReleaseShell (SfxShell* pShell); + + /** Add a sub shell to the set of sub shells managed by the + TaskPaneShellManager. Only shells added by this method are returned + by CreateShell(). + */ + void AddSubShell (ShellId nId, SfxShell* pShell, ::Window* pWindow); + + /** Remove the given shell from the set of sub shells managed by the + TaskPaneShellManager. Following calls to CreateShell() will return + NULL when this shell is requested. + */ + void RemoveSubShell (const SfxShell* pShell); + /** removes the shell given by its ID from the set of sub shells managed by the + TaskPaneShellManager. Subsequent calls to CreateShell() will return + NULL when this shell is requested. + */ + void RemoveSubShell (const ShellId i_nShellId); + + /** Move the given sub-shell to the top of the local shell stack. + Furthermore move the view shell whose sub-shells this class manages + to the top of the global shell stack. + */ + void MoveToTop (SfxShell* pShell); + + DECL_LINK(WindowCallback,VclWindowEvent*); + +private: + ::boost::shared_ptr<ViewShellManager> mpViewShellManager; + + /// The view shell whose sub-shells this class manages. + const ViewShell& mrViewShell; + + class ShellDescriptor { public: + SfxShell* mpShell; + ::Window* mpWindow; + ShellDescriptor(void) : mpShell(NULL),mpWindow(NULL){} + ShellDescriptor(SfxShell*pShell,::Window*pWindow) : mpShell(pShell),mpWindow(pWindow){} + }; + typedef ::std::map<ShellId,ShellDescriptor> SubShells; + SubShells maSubShells; +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/TaskPaneTreeNode.cxx b/sd/source/ui/toolpanel/TaskPaneTreeNode.cxx new file mode 100755 index 000000000000..8c69e12c504d --- /dev/null +++ b/sd/source/ui/toolpanel/TaskPaneTreeNode.cxx @@ -0,0 +1,292 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/TaskPaneTreeNode.hxx" + +#include "taskpane/ControlContainer.hxx" +#include "taskpane/TitledControl.hxx" + +#include <vector> +#include <algorithm> + +namespace sd { namespace toolpanel { + +TreeNode::TreeNode( TreeNode* pParent) +: mpControlContainer (new ControlContainer(this)) +, mpParent (pParent) +, maStateChangeListeners() +{ +} + + + + +TreeNode::~TreeNode (void) +{ +} + + + + +void TreeNode::SetParentNode (TreeNode* pNewParent) +{ + mpParent = pNewParent; + GetWindow()->SetParent (pNewParent->GetWindow()); +} + + + + +TreeNode* TreeNode::GetParentNode (void) +{ + return mpParent; +} + + + + +::Window* TreeNode::GetWindow (void) +{ + return NULL; +} + + + + +const ::Window* TreeNode::GetConstWindow (void) const +{ + return const_cast<TreeNode*>(this)->GetWindow(); +} + + + + +sal_Int32 TreeNode::GetMinimumWidth (void) +{ + sal_Int32 nTotalMinimumWidth = 0; + unsigned int nCount = mpControlContainer->GetControlCount(); + for (unsigned int nIndex=0; nIndex<nCount; nIndex++) + { + TreeNode* pChild = mpControlContainer->GetControl (nIndex); + sal_Int32 nMinimumWidth = pChild->GetMinimumWidth (); + if (nMinimumWidth > nTotalMinimumWidth) + nTotalMinimumWidth = nMinimumWidth; + } + + return nTotalMinimumWidth;; +} + + + + +bool TreeNode::IsResizable (void) +{ + return false; +} + + + + +void TreeNode::RequestResize (void) +{ + if (mpParent != NULL) + mpParent->RequestResize(); +} + + + + +ControlContainer& TreeNode::GetControlContainer (void) +{ + return *mpControlContainer.get(); +} + + + + +bool TreeNode::Expand (bool bExpansionState) +{ + bool bExpansionStateChanged (false); + + if (IsExpandable() && IsExpanded()!=bExpansionState) + { + if (bExpansionState) + GetWindow()->Show(); + else + GetWindow()->Hide(); + bExpansionStateChanged = true; + + FireStateChangeEvent (EID_EXPANSION_STATE_CHANGED); + } + + return bExpansionStateChanged; +} + + + + +bool TreeNode::IsExpanded (void) const +{ + if (GetConstWindow()!=NULL) + return GetConstWindow()->IsVisible(); + else + return false; +} + + + + +bool TreeNode::IsExpandable (void) const +{ + return GetConstWindow()!=NULL; +} + + + + +void TreeNode::Show (bool bExpansionState) +{ + if (GetWindow() != NULL) + { + bool bWasShowing (IsShowing()); + GetWindow()->Show (bExpansionState); + if (bWasShowing != bExpansionState) + FireStateChangeEvent (EID_SHOWING_STATE_CHANGED); + } +} + + + + +bool TreeNode::IsShowing (void) const +{ + const ::Window* pWindow = const_cast<TreeNode*>(this)->GetWindow(); + if (pWindow != NULL) + return pWindow->IsVisible(); + else + return false; +} + + + + +TaskPaneShellManager* TreeNode::GetShellManager (void) +{ + if (mpParent != NULL) + return mpParent->GetShellManager(); + else + return NULL; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> TreeNode::GetAccessibleObject (void) +{ + ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> xAccessible; + ::Window* pWindow = GetWindow(); + if (pWindow != NULL) + { + xAccessible = pWindow->GetAccessible(FALSE); + if ( ! xAccessible.is()) + { + ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> xParent; + if (pWindow!=NULL && pWindow->GetAccessibleParentWindow()!=NULL) + xParent = pWindow->GetAccessibleParentWindow()->GetAccessible(); + xAccessible = CreateAccessibleObject(xParent); + pWindow->SetAccessible(xAccessible); + } + } + return xAccessible; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> TreeNode::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + if (GetWindow() != NULL) + return GetWindow()->CreateAccessible(); + else + return NULL; +} + + + + +void TreeNode::AddStateChangeListener (const Link& rListener) +{ + if (::std::find ( + maStateChangeListeners.begin(), + maStateChangeListeners.end(), + rListener) == maStateChangeListeners.end()) + { + maStateChangeListeners.push_back(rListener); + } +} + + + + +void TreeNode::FireStateChangeEvent ( + TreeNodeStateChangeEventId eEventId, + TreeNode* pChild) const +{ + TreeNodeStateChangeEvent aEvent (*this, eEventId, pChild); + StateChangeListenerContainer aContainerCopy(maStateChangeListeners); + StateChangeListenerContainer::iterator aLink (aContainerCopy.begin()); + StateChangeListenerContainer::iterator aEnd (aContainerCopy.end()); + while (aLink!=aEnd) + { + aLink->Call (&aEvent); + ++aLink; + } +} + + + +TreeNodeStateChangeEvent::TreeNodeStateChangeEvent ( + const TreeNode& rNode, + TreeNodeStateChangeEventId eEventId, + TreeNode* pChild) + : mrSource(rNode), + meEventId(eEventId), + mpChild(pChild) +{ +} + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TestMenu.cxx b/sd/source/ui/toolpanel/TestMenu.cxx new file mode 100755 index 000000000000..a8f0b6df7893 --- /dev/null +++ b/sd/source/ui/toolpanel/TestMenu.cxx @@ -0,0 +1,318 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "TestMenu.hxx" + +#include "taskpane/TaskPaneControlFactory.hxx" + +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> + +namespace sd { namespace toolpanel { + +#ifdef SHOW_COLOR_MENU +/** This factory class is used to create instances of ColorMenu. It can be + extended so that its constructor stores arguments that later are passed + to new ColorMenu objects. +*/ +class ColorMenuFactory + : public ControlFactory +{ +protected: + virtual TreeNode* InternalCreateControl( ::Window& i_rParent ) + { + return new ColorMenu (&i_rParent); + } +}; + + +ColorMenu::ColorMenu (::Window* i_pParent) + : Window (i_pParent), + TreeNode(NULL), + maSet (this), + mnPreferredColumnCount(2) +{ + WinBits aStyle = + WB_ITEMBORDER + | WB_DOUBLEBORDER + | WB_NAMEFIELD + | WB_FLATVALUESET + | WB_TABSTOP + | WB_VSCROLL; + + maSet.SetStyle (maSet.GetStyle() | aStyle); + maSet.SetExtraSpacing(2); + + Fill (); + maSet.Show(); + i_pParent->Resize(); +} + + + + +ColorMenu::~ColorMenu (void) +{ +} + + +::std::auto_ptr<ControlFactory> ColorMenu::CreateControlFactory (void) +{ + return ::std::auto_ptr<ControlFactory>(new ColorMenuFactory()); +} + + +/** The preferred size depends on the preferred number of columns, the + number of items, and the size of the items. +*/ +Size ColorMenu::GetPreferredSize (void) +{ + Size aItemSize = maSet.CalcItemSizePixel (Size()); + Size aPreferredWindowSize = maSet.CalcWindowSizePixel ( + aItemSize, + (USHORT)mnPreferredColumnCount, + (USHORT)CalculateRowCount (aItemSize, (USHORT)mnPreferredColumnCount)); + return aPreferredWindowSize; +} + + + + +sal_Int32 ColorMenu::GetPreferredWidth (sal_Int32 nHeight) +{ + sal_Int32 nPreferredWidth = 0; + if (maSet.GetItemCount() > 0) + { + Image aImage = maSet.GetItemImage(maSet.GetItemId(0)); + Size aItemSize = maSet.CalcItemSizePixel (aImage.GetSizePixel()); + if (nHeight>0 && aItemSize.Height()>0) + { + int nRowCount = nHeight / aItemSize.Height(); + if (nRowCount <= 0) + nRowCount = 1; + int nColumnCount = (maSet.GetItemCount() + nRowCount-1) + / nRowCount; + nPreferredWidth = nColumnCount * aItemSize.Width(); + } + } + + return nPreferredWidth; +} + + + + +sal_Int32 ColorMenu::GetPreferredHeight (sal_Int32 nWidth) +{ + sal_Int32 nPreferredHeight = 0; + if (maSet.GetItemCount()>0) + { + Image aImage = maSet.GetItemImage(maSet.GetItemId(0)); + Size aItemSize = maSet.CalcItemSizePixel (aImage.GetSizePixel()); + if (nWidth>0 && aItemSize.Width()>0) + { + int nColumnCount = nWidth / aItemSize.Width(); + if (nColumnCount <= 0) + nColumnCount = 1; + else if (nColumnCount > 4) + nColumnCount = 4; + int nRowCount = (maSet.GetItemCount() + nColumnCount-1) + / nColumnCount; + nPreferredHeight = nRowCount * aItemSize.Height(); + } + } + return nPreferredHeight; +} + + + + +bool ColorMenu::IsResizable (void) +{ + return true; +} + + + + +::Window* ColorMenu::GetWindow (void) +{ + return this; +} + + + + +void ColorMenu::Resize (void) +{ + ::Window::Resize(); + Size aWindowSize = GetOutputSizePixel(); + maSet.SetPosSizePixel (Point(0,0), aWindowSize); + if (IsVisible() && aWindowSize.Width() > 0) + { + // maSet.SetPosSizePixel ( + // Point (0,0), + // aWindowSize); + + // Calculate the number of rows and columns. + if (maSet.GetItemCount() > 0) + { + Image aImage = maSet.GetItemImage(maSet.GetItemId(0)); + Size aItemSize = maSet.CalcItemSizePixel ( + aImage.GetSizePixel()); + int nColumnCount = aWindowSize.Width() / 30; + if (nColumnCount < 1) + nColumnCount = 1; + else if (nColumnCount > 4) + nColumnCount = 4; + + USHORT nRowCount = (USHORT)CalculateRowCount (aItemSize, nColumnCount); + + maSet.SetColCount ((USHORT)nColumnCount); + maSet.SetLineCount (nRowCount); + } + } + +} + + + + +int ColorMenu::CalculateRowCount (const Size&, int nColumnCount) +{ + int nRowCount = 0; + + if (maSet.GetItemCount()>0 && nColumnCount>0) + { + nRowCount = GetOutputSizePixel().Height() / 30; + if (nRowCount < 1) + nRowCount = 1; + } + + return nRowCount; +} + + + + +void ColorMenu::Fill (void) +{ + const StyleSettings& rSettings ( + Application::GetSettings().GetStyleSettings()); + maSet.Clear(); + maSet.SetItemWidth (30); + maSet.SetItemHeight (30); + USHORT i = 0; + maSet.InsertItem (++i, rSettings.GetFaceColor()); + maSet.SetItemText (i, String::CreateFromAscii("FaceColor")); + maSet.InsertItem (++i, rSettings.GetCheckedColor()); + maSet.SetItemText (i, String::CreateFromAscii("CheckedColor")); + maSet.InsertItem (++i, rSettings.GetLightColor()); + maSet.SetItemText (i, String::CreateFromAscii("LightColor")); + maSet.InsertItem (++i, rSettings.GetLightBorderColor()); + maSet.SetItemText (i, String::CreateFromAscii("LightBorderColor")); + maSet.InsertItem (++i, rSettings.GetShadowColor()); + maSet.SetItemText (i, String::CreateFromAscii("ShadowColor")); + maSet.InsertItem (++i, rSettings.GetDarkShadowColor()); + maSet.SetItemText (i, String::CreateFromAscii("DarkShadowColor")); + maSet.InsertItem (++i, rSettings.GetButtonTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("ButtonTextColor")); + maSet.InsertItem (++i, rSettings.GetRadioCheckTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("RadioCheckTextColor")); + maSet.InsertItem (++i, rSettings.GetGroupTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("GroupTextColor")); + maSet.InsertItem (++i, rSettings.GetLabelTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("LabelTextColor")); + maSet.InsertItem (++i, rSettings.GetInfoTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("InfoTextColor")); + maSet.InsertItem (++i, rSettings.GetWindowColor()); + maSet.SetItemText (i, String::CreateFromAscii("WindowColor")); + maSet.InsertItem (++i, rSettings.GetWindowTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("WindowTextColor")); + maSet.InsertItem (++i, rSettings.GetDialogColor()); + maSet.SetItemText (i, String::CreateFromAscii("DialogColor")); + maSet.InsertItem (++i, rSettings.GetDialogTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("DialogTextColor")); + maSet.InsertItem (++i, rSettings.GetWorkspaceColor()); + maSet.SetItemText (i, String::CreateFromAscii("WorkspaceColor")); + maSet.InsertItem (++i, rSettings.GetFieldColor()); + maSet.SetItemText (i, String::CreateFromAscii("FieldColor")); + maSet.InsertItem (++i, rSettings.GetFieldTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("FieldTextColor")); + maSet.InsertItem (++i, rSettings.GetActiveColor()); + maSet.SetItemText (i, String::CreateFromAscii("ActiveColor")); + maSet.InsertItem (++i, rSettings.GetActiveColor2()); + maSet.SetItemText (i, String::CreateFromAscii("ActiveColor2")); + maSet.InsertItem (++i, rSettings.GetActiveTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("ActiveTextColor")); + maSet.InsertItem (++i, rSettings.GetActiveBorderColor()); + maSet.SetItemText (i, String::CreateFromAscii("ActiveBorderColor")); + maSet.InsertItem (++i, rSettings.GetDeactiveColor()); + maSet.SetItemText (i, String::CreateFromAscii("DeactiveColor")); + maSet.InsertItem (++i, rSettings.GetDeactiveColor2()); + maSet.SetItemText (i, String::CreateFromAscii("DeactiveColor2")); + maSet.InsertItem (++i, rSettings.GetDeactiveTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("DeactiveTextColor")); + maSet.InsertItem (++i, rSettings.GetDeactiveBorderColor()); + maSet.SetItemText (i, String::CreateFromAscii("DeactiveBorderColor")); + maSet.InsertItem (++i, rSettings.GetHighlightColor()); + maSet.SetItemText (i, String::CreateFromAscii("HighlightColor")); + maSet.InsertItem (++i, rSettings.GetHighlightTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("HighlightTextColor")); + maSet.InsertItem (++i, rSettings.GetDisableColor()); + maSet.SetItemText (i, String::CreateFromAscii("DisableColor")); + maSet.InsertItem (++i, rSettings.GetHelpColor()); + maSet.SetItemText (i, String::CreateFromAscii("HelpColor")); + maSet.InsertItem (++i, rSettings.GetHelpTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("HelpTextColor")); + maSet.InsertItem (++i, rSettings.GetMenuColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuColor")); + maSet.InsertItem (++i, rSettings.GetMenuBarColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuBarColor")); + maSet.InsertItem (++i, rSettings.GetMenuBorderColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuBorderColor")); + maSet.InsertItem (++i, rSettings.GetMenuTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuTextColor")); + maSet.InsertItem (++i, rSettings.GetMenuHighlightColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuHighlightColor")); + maSet.InsertItem (++i, rSettings.GetMenuHighlightTextColor()); + maSet.SetItemText (i, String::CreateFromAscii("MenuHighlightTextColor")); + maSet.InsertItem (++i, rSettings.GetLinkColor()); + maSet.SetItemText (i, String::CreateFromAscii("LinkColor")); + maSet.InsertItem (++i, rSettings.GetVisitedLinkColor()); + maSet.SetItemText (i, String::CreateFromAscii("VisitedLinkColor")); + maSet.InsertItem (++i, rSettings.GetHighlightLinkColor()); + maSet.SetItemText (i, String::CreateFromAscii("HighlightLinkColor")); + maSet.InsertItem (++i, rSettings.GetFontColor()); + maSet.SetItemText (i, String::CreateFromAscii("FontColor")); +} +#endif + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TestMenu.hxx b/sd/source/ui/toolpanel/TestMenu.hxx new file mode 100755 index 000000000000..0c4b3bfe6530 --- /dev/null +++ b/sd/source/ui/toolpanel/TestMenu.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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 SD_TASKPANE_COLOR_MENU_HXX +#define SD_TASKPANE_COLOR_MENU_HXX + +#include "taskpane/TaskPaneTreeNode.hxx" +#include <svtools/valueset.hxx> +#include <vcl/window.hxx> + +#include <memory> + + +namespace sd { namespace toolpanel { + +class ControlFactory; + +#ifdef SHOW_COLOR_MENU + +/** This demo menu shows the colors that are available from the + StyleSettings. +*/ +class ColorMenu + : public ::Window, + public TreeNode +{ +public: + ColorMenu (::Window* i_pParent); + virtual ~ColorMenu (void); + + static ::std::auto_ptr<ControlFactory> CreateControlFactory (void); + + // From ILayoutableWindow + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeight); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual bool IsResizable (void); + virtual ::Window* GetWindow (void); + + // From ::Window + virtual void Resize (void); + + using Window::GetWindow; + +private: + ValueSet maSet; + int mnPreferredColumnCount; + + /** Depending on the given number of columns and the item size + calculate the number of rows that are necessary to display all + items. + */ + int CalculateRowCount (const Size& rItemSize, int nColumnCount); + void Fill (void); +}; +#endif + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/TestPanel.cxx b/sd/source/ui/toolpanel/TestPanel.cxx new file mode 100755 index 000000000000..044b40dcdb4f --- /dev/null +++ b/sd/source/ui/toolpanel/TestPanel.cxx @@ -0,0 +1,174 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "TestPanel.hxx" +#include "taskpane/ScrollPanel.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" + +#include <vcl/lstbox.hxx> +#include <vcl/button.hxx> + +namespace sd { namespace toolpanel { + +#ifdef SHOW_TEST_PANEL +/** This factory class is used to create instances of TestPanel. It can be + extended so that its constructor stores arguments that later are passed + to new TestPanel objects. +*/ +class TestPanelFactory + : public ControlFactory +{ +protected: + virtual TreeNode* InternalCreateControl( ::Window& i_rParent ) + { + return new TestPanel (i_rParent); + } +}; + + +class Wrapper + : public TreeNode +{ +public: + Wrapper ( + TreeNode* pParent, + Size aPreferredSize, + ::Window* pWrappedControl, + bool bIsResizable) + : TreeNode (pParent), + maPreferredSize(aPreferredSize), + mpWrappedControl(pWrappedControl), + mbIsResizable(bIsResizable) + { + mpWrappedControl->Show(); + } + virtual ~Wrapper (void) + { + delete mpWrappedControl; + } + + virtual Size GetPreferredSize (void) + { + return maPreferredSize; + } + virtual sal_Int32 GetPreferredWidth (sal_Int32 ) + { + return maPreferredSize.Width(); + } + virtual sal_Int32 GetPreferredHeight (sal_Int32 ) + { + return maPreferredSize.Height(); + } + virtual ::Window* GetWindow (void) + { + return mpWrappedControl; + } + virtual bool IsResizable (void) + { + return mbIsResizable; + } + virtual bool IsExpandable (void) const + { + return false; + } + virtual bool IsExpanded (void) const + { + return true; + } + +private: + Size maPreferredSize; + ::Window* mpWrappedControl; + bool mbIsResizable; +}; + + +TestPanel::TestPanel (::Window& i_rParent) + : SubToolPanel (i_rParent) +{ + // Create a scrollable panel with two list boxes. + ScrollPanel* pScrollPanel = new ScrollPanel (this); + + ListBox* pBox = new ListBox (pScrollPanel->GetWindow()); + int i; + for (i=1; i<=20; i++) + { + XubString aString (XubString::CreateFromAscii("Text ")); + aString.Append (XubString::CreateFromInt32(i)); + aString.Append (XubString::CreateFromAscii("/20")); + pBox->InsertEntry (aString); + } + pScrollPanel->AddControl ( + ::std::auto_ptr<TreeNode>(new Wrapper ( + pScrollPanel, Size (200,300), pBox, true)), + String::CreateFromAscii ("First ListBox"), + 0); + + pBox = new ListBox (pScrollPanel->GetWindow()); + for (i=1; i<=20; i++) + { + XubString aString (XubString::CreateFromAscii("More Text ")); + aString.Append (XubString::CreateFromInt32(i)); + aString.Append (XubString::CreateFromAscii("/20")); + pBox->InsertEntry (aString); + } + pScrollPanel->AddControl ( + ::std::auto_ptr<TreeNode>(new Wrapper ( + pScrollPanel, Size (200,300), pBox, true)), + String::CreateFromAscii ("Second ListBox"), + 0); + + AddControl (::std::auto_ptr<TreeNode>(pScrollPanel)); + + // Add a fixed size button. + Button* pButton = new OKButton (this); + AddControl ( + ::std::auto_ptr<TreeNode>(new Wrapper ( + this, Size (100,30), pButton, false)), + String::CreateFromAscii ("Button Area"), + 0); +} + + + + + +TestPanel::~TestPanel (void) +{ +} + +std::auto_ptr<ControlFactory> TestPanel::CreateControlFactory (void) +{ + return std::auto_ptr<ControlFactory>(new TestPanelFactory()); +} +#endif + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TestPanel.hxx b/sd/source/ui/toolpanel/TestPanel.hxx new file mode 100755 index 000000000000..494e5086b179 --- /dev/null +++ b/sd/source/ui/toolpanel/TestPanel.hxx @@ -0,0 +1,57 @@ +/************************************************************************* + * + * 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 SD_TASKPANE_TEST_PANEL_HXX +#define SD_TASKPANE_TEST_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + + +namespace sd { namespace toolpanel { + +class ControlFactory; +class TreeNode; + +#ifdef SHOW_TEST_PANEL + +/** This panel demonstrates how to create a panel for the task pane. +*/ +class TestPanel + : public SubToolPanel +{ +public: + TestPanel (::Window& i_rParent); + virtual ~TestPanel (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory (void); +}; + +#endif + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/TitleBar.cxx b/sd/source/ui/toolpanel/TitleBar.cxx new file mode 100755 index 000000000000..de49b7a6abb5 --- /dev/null +++ b/sd/source/ui/toolpanel/TitleBar.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/TitleBar.hxx" + +#include "ControlContainerDescriptor.hxx" +#include "tools/IconCache.hxx" +#include "AccessibleTreeNode.hxx" +#include <vcl/decoview.hxx> +#include <vcl/window.hxx> +#include <vcl/virdev.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include "sdresid.hxx" +#include <vcl/bitmap.hxx> +#include <vcl/lineinfo.hxx> +#include <vcl/bitmapex.hxx> +#include <tools/color.hxx> +#include <svx/xdash.hxx> +#include <svl/itemset.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/svdobj.hxx> +#include <svx/svdpool.hxx> +#include <svtools/colorcfg.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xfillit0.hxx> +#include "res_bmp.hrc" + + +namespace sd { namespace toolpanel { + +const int TitleBar::snIndentationWidth = 16; + +TitleBar::TitleBar ( ::Window* pParent, const String& rsTitle, TitleBarType eType, bool bIsExpandable) +: ::Window (pParent, WB_TABSTOP) +, TreeNode(this) +, meType(eType) +, msTitle(rsTitle) +, mbExpanded(false) +, mbFocused(false) +, mpDevice(new VirtualDevice (*this)) +, mbIsExpandable (bIsExpandable) +{ + EnableMapMode (FALSE); + + SetBackground (Wallpaper()); + + // Change the mouse pointer shape so that it acts as a mouse over effect. + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + if (mbIsExpandable) + SetPointer (POINTER_REFHAND); + break; + } +} + + + + +TitleBar::~TitleBar (void) +{ +} + + + + +Size TitleBar::GetPreferredSize (void) +{ + int nWidth = GetOutputSizePixel().Width(); + Rectangle aTitleBarBox ( + CalculateTitleBarBox( + CalculateTextBoundingBox(nWidth, true), + nWidth)); + + return aTitleBarBox.GetSize(); +} + + + + +sal_Int32 TitleBar::GetPreferredWidth (sal_Int32 ) +{ + Rectangle aTitleBarBox ( + CalculateTitleBarBox( + CalculateTextBoundingBox(0, true), + 0)); + return aTitleBarBox.GetWidth(); +} + + + + +sal_Int32 TitleBar::GetPreferredHeight (sal_Int32 nWidth) +{ + Rectangle aTitleBarBox ( + CalculateTitleBarBox( + CalculateTextBoundingBox(nWidth, true), + nWidth)); + + return aTitleBarBox.GetHeight(); +} + + + + +bool TitleBar::IsResizable (void) +{ + return true; +} + + + + +::Window* TitleBar::GetWindow (void) +{ + return this; +} + + + + +sal_Int32 TitleBar::GetMinimumWidth (void) +{ + return 20; +} + + + + +void TitleBar::Paint (const Rectangle& rBoundingBox) +{ + mpDevice->SetMapMode(GetMapMode()); + mpDevice->SetOutputSize (GetOutputSizePixel()); + mpDevice->SetSettings(GetSettings()); + mpDevice->SetDrawMode(GetDrawMode()); + + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + PaintSubPanelHeadLineBar (); + break; + } + + DrawOutDev ( + Point(0,0), + GetOutputSizePixel(), + Point(0,0), + GetOutputSizePixel(), + *mpDevice); + + ::Window::Paint (rBoundingBox); +} + + + + +bool TitleBar::Expand (bool bFlag) +{ + bool bExpansionStateChanged (bFlag!=IsExpanded()); + mbExpanded = bFlag; + Invalidate (); + return bExpansionStateChanged; +} + + + + +bool TitleBar::IsExpanded (void) const +{ + return mbExpanded; +} + + +void TitleBar::SetEnabledState(bool bFlag) +{ + if(bFlag) + Enable(); + else + Disable(); + Invalidate (); +} + + + + +void TitleBar::GetFocus() +{ + mbFocused = true; + Invalidate(); +} + + + + +void TitleBar::LoseFocus() +{ + mbFocused = false; + Invalidate(); +} + + + + +bool TitleBar::HasExpansionIndicator (void) const +{ + bool bHasExpansionIndicator (false); + if (mbIsExpandable) + { + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + bHasExpansionIndicator = true; + break; + } + } + return bHasExpansionIndicator; +} + + + + +Image TitleBar::GetExpansionIndicator (void) const +{ + Image aIndicator; + bool bHighContrastMode (GetSettings().GetStyleSettings().GetHighContrastMode() != 0); + if (mbIsExpandable) + { + USHORT nResourceId = 0; + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + if (mbExpanded) + if (bHighContrastMode) + nResourceId = BMP_COLLAPSE_H; + else + nResourceId = BMP_COLLAPSE; + else + if (bHighContrastMode) + nResourceId = BMP_EXPAND_H; + else + nResourceId = BMP_EXPAND; + + aIndicator = IconCache::Instance().GetIcon(nResourceId); + break; + } + } + + return aIndicator; +} + + + + +void TitleBar::PaintSubPanelHeadLineBar (void) +{ + int nWidth (GetOutputSizePixel().Width()); + Rectangle aTextBox (CalculateTextBoundingBox (nWidth, true)); + + Rectangle aTitleBarBox (CalculateTitleBarBox(aTextBox, nWidth)); + int nVerticalOffset = -aTitleBarBox.Top(); + aTitleBarBox.Top() += nVerticalOffset; + aTitleBarBox.Bottom() += nVerticalOffset; + aTextBox.Top() += nVerticalOffset; + aTextBox.Bottom() += nVerticalOffset; + + PaintBackground (aTitleBarBox); + Rectangle aFocusBox (PaintExpansionIndicator (aTextBox)); + PaintText (aTextBox); + + aFocusBox.Union (aTextBox); + aFocusBox.Left() -= 2; + aFocusBox.Right() += 1; + PaintFocusIndicator (aFocusBox); +} + + + + +void TitleBar::PaintFocusIndicator (const Rectangle& rTextBox) +{ + if (mbFocused) + { + Rectangle aTextPixelBox (mpDevice->LogicToPixel (rTextBox)); + mpDevice->EnableMapMode (FALSE); + Rectangle aBox (rTextBox); + aBox.Top() -= 1; + aBox.Bottom() += 1; + + mpDevice->SetFillColor (); + + mpDevice->DrawRect (aTextPixelBox); + + LineInfo aDottedStyle (LINE_DASH); + aDottedStyle.SetDashCount (0); + aDottedStyle.SetDotCount (1); + aDottedStyle.SetDotLen (1); + aDottedStyle.SetDistance (1); + + mpDevice->SetLineColor (COL_BLACK); + mpDevice->DrawPolyLine (Polygon(aTextPixelBox), aDottedStyle); + mpDevice->EnableMapMode (FALSE); + } + else + HideFocus (); +} + + + + +Rectangle TitleBar::PaintExpansionIndicator (const Rectangle& rTextBox) +{ + Rectangle aExpansionIndicatorArea; + + if (HasExpansionIndicator()) + { + Image aImage = GetExpansionIndicator(); + int nHeight (aImage.GetSizePixel().Height()); + if (nHeight > 0) + { + Point aPosition ( + 0, + rTextBox.Top() + (GetTextHeight() - nHeight) / 2); + if (meType == TBT_SUB_CONTROL_HEADLINE) + aPosition.X() += 3; + mpDevice->DrawImage (aPosition, aImage); + + aExpansionIndicatorArea = Rectangle ( + aPosition, aImage.GetSizePixel()); + } + } + + return aExpansionIndicatorArea; +} + + + + +void TitleBar::PaintText (const Rectangle& rTextBox) +{ + mpDevice->DrawText (rTextBox, msTitle, GetTextStyle()); +} + + + + +USHORT TitleBar::GetTextStyle (void) +{ + if(IsEnabled()) + { + return TEXT_DRAW_LEFT + | TEXT_DRAW_TOP + | TEXT_DRAW_MULTILINE + | TEXT_DRAW_WORDBREAK; + } + else + { + return TEXT_DRAW_DISABLE; + } +} + + + +void TitleBar::PaintBackground (const Rectangle& rTitleBarBox) +{ + // Fill a slightly rounded rectangle. + Color aFillColor (GetFillColor()); + Color aLineColor (GetLineColor()); + + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + { + Color aColor (GetSettings().GetStyleSettings().GetDialogColor()); + if (mbExpanded) + { + // Make the color a little bit darker. + aColor.SetRed(UINT8(((UINT16)aColor.GetRed()) * 8 / 10)); + aColor.SetGreen(UINT8(((UINT16)aColor.GetGreen()) * 8 / 10)); + aColor.SetBlue(UINT8(((UINT16)aColor.GetBlue()) * 8 / 10)); + } + + mpDevice->SetFillColor (aColor); + mpDevice->SetLineColor (); + mpDevice->DrawRect (rTitleBarBox); + + // Erase the four corner pixels to make the rectangle appear + // rounded. + mpDevice->SetLineColor ( + GetSettings().GetStyleSettings().GetWindowColor()); + mpDevice->DrawPixel ( + rTitleBarBox.TopLeft()); + mpDevice->DrawPixel ( + Point(rTitleBarBox.Right(), rTitleBarBox.Top())); + mpDevice->DrawPixel ( + Point(rTitleBarBox.Left(), rTitleBarBox.Bottom())); + mpDevice->DrawPixel ( + Point(rTitleBarBox.Right(), rTitleBarBox.Bottom())); + } + break; + } +} + + + + +Rectangle TitleBar::CalculateTextBoundingBox ( + int nAvailableWidth, + bool bEmphasizeExpanded) +{ + // Show the title of expanded controls in bold font. + const Font& rOriginalFont (GetFont()); + Font aFont (rOriginalFont); + if (bEmphasizeExpanded && mbExpanded) + aFont.SetWeight (WEIGHT_BOLD); + else + aFont.SetWeight (WEIGHT_NORMAL); + mpDevice->SetFont (aFont); + + // Use the natural width of the text when no width is given. + if (nAvailableWidth == 0) + nAvailableWidth = GetTextWidth (msTitle); + + Rectangle aTextBox ( + Point(0,0), + Size (nAvailableWidth, + GetSettings().GetStyleSettings().GetTitleHeight())); + aTextBox.Top() += (aTextBox.GetHeight() - GetTextHeight()) / 2; + if (HasExpansionIndicator()) + aTextBox.Left() += snIndentationWidth; + else + aTextBox.Left() += 3; + aTextBox.Right() -= 1; + + aTextBox = mpDevice->GetTextRect (aTextBox, msTitle, GetTextStyle()); + + return aTextBox; +} + + + + +Rectangle TitleBar::CalculateTitleBarBox ( + const Rectangle& rTextBox, + int nWidth) +{ + Rectangle aTitleBarBox (rTextBox); + + switch (meType) + { + case TBT_SUB_CONTROL_HEADLINE: + aTitleBarBox.Top() -= 3; + aTitleBarBox.Bottom() += 3; + break; + + } + aTitleBarBox.Left() = 0; + if (aTitleBarBox.GetWidth() < nWidth) + aTitleBarBox.Right() = nWidth-1; + + return aTitleBarBox; +} + + + + +void TitleBar::MouseMove (const MouseEvent& ) +{ +} + + + + +void TitleBar::MouseButtonDown (const MouseEvent& ) +{ + // Do not forward to parent window so that the mouse button handler of + // the docking window is not invoked. +} + + + + +void TitleBar::MouseButtonUp (const MouseEvent& ) +{ + // Do not forward to parent window so that the mouse button handler of + // the docking window is not invoked. +} + + + + +void TitleBar::DataChanged (const DataChangedEvent& rEvent) +{ + ::Window::DataChanged (rEvent); + + switch (rEvent.GetType()) + { + case DATACHANGED_SETTINGS: + if ((rEvent.GetFlags() & SETTINGS_STYLE) == 0) + break; + SetSettings(Application::GetSettings()); + mpDevice.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(); + + Resize(); + Invalidate(); + } + break; + } +} + + + + +String TitleBar::GetTitle (void) const +{ + return msTitle; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > TitleBar::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + return new ::accessibility::AccessibleTreeNode( + *this, + GetTitle(), + GetTitle(), + ::com::sun::star::accessibility::AccessibleRole::LABEL); +} + + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/TitledControl.cxx b/sd/source/ui/toolpanel/TitledControl.cxx new file mode 100755 index 000000000000..e83e6c47c10a --- /dev/null +++ b/sd/source/ui/toolpanel/TitledControl.cxx @@ -0,0 +1,432 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "taskpane/TitledControl.hxx" + +#include "AccessibleTreeNode.hxx" +#include "taskpane/ControlContainer.hxx" +#include "TaskPaneFocusManager.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" +#include <vcl/ctrl.hxx> +#include <vcl/svapp.hxx> + + +namespace sd { namespace toolpanel { + + +TitledControl::TitledControl ( + TreeNode* pParent, + ::std::auto_ptr<TreeNode> pControl, + const String& rTitle, + const ClickHandler& rClickHandler, + TitleBar::TitleBarType eType) + : ::Window (pParent->GetWindow(), WB_TABSTOP), + TreeNode(pParent), + msTitle(rTitle), + mbVisible(true), + mpUserData(NULL), + mpClickHandler(new ClickHandler(rClickHandler)) +{ + mpControlContainer->AddControl (::std::auto_ptr<TreeNode> ( + new TitleBar (this, rTitle, eType, pControl->IsExpandable()))); + pControl->SetParentNode (this); + mpControlContainer->AddControl (pControl); + + FocusManager::Instance().RegisterDownLink( GetTitleBar()->GetWindow(), GetControl()->GetWindow() ); + FocusManager::Instance().RegisterUpLink( GetControl()->GetWindow(), GetTitleBar()->GetWindow() ); + + SetBackground (Wallpaper()); + + GetTitleBar()->GetWindow()->Show (); + GetTitleBar()->GetWindow()->AddEventListener ( + LINK(this,TitledControl,WindowEventListener)); + + UpdateStates (); +} + + + + +TitledControl::~TitledControl (void) +{ + GetTitleBar()->GetWindow()->RemoveEventListener ( + LINK(this,TitledControl,WindowEventListener)); +} + + + + +Size TitledControl::GetPreferredSize (void) +{ + Size aPreferredSize; + if (GetControl() != NULL) + { + aPreferredSize = GetControl()->GetPreferredSize(); + if ( ! IsExpanded()) + aPreferredSize.Height() = 0; + } + else + aPreferredSize = Size (GetSizePixel().Width(), 0); + if (aPreferredSize.Width() == 0) + aPreferredSize.Width() = 300; + aPreferredSize.Height() += GetTitleBar()->GetPreferredHeight( + aPreferredSize.Width()); + + return aPreferredSize; +} + + + + +sal_Int32 TitledControl::GetPreferredWidth (sal_Int32 nHeight) +{ + int nPreferredWidth = 0; + if (GetControl() != NULL) + nPreferredWidth = GetControl()->GetPreferredWidth( + nHeight - GetTitleBar()->GetWindow()->GetSizePixel().Height()); + else + nPreferredWidth = GetSizePixel().Width(); + if (nPreferredWidth == 0) + nPreferredWidth = 300; + + return nPreferredWidth; +} + + + + +sal_Int32 TitledControl::GetPreferredHeight (sal_Int32 nWidth) +{ + int nPreferredHeight = 0; + if (IsExpanded() && GetControl()!=NULL) + nPreferredHeight = GetControl()->GetPreferredHeight(nWidth); + nPreferredHeight += GetTitleBar()->GetPreferredHeight(nWidth); + + return nPreferredHeight; +} + + + + +bool TitledControl::IsResizable (void) +{ + return IsExpanded() + && GetControl()->IsResizable(); +} + + + + +::Window* TitledControl::GetWindow (void) +{ + return this; +} + + + + +void TitledControl::Resize (void) +{ + Size aWindowSize (GetOutputSizePixel()); + + int nTitleBarHeight + = GetTitleBar()->GetPreferredHeight(aWindowSize.Width()); + GetTitleBar()->GetWindow()->SetPosSizePixel ( + Point (0,0), + Size (aWindowSize.Width(), nTitleBarHeight)); + + + TreeNode* pControl = GetControl(); + if (pControl != NULL + && pControl->GetWindow() != NULL + && pControl->GetWindow()->IsVisible()) + { + pControl->GetWindow()->SetPosSizePixel ( + Point (0,nTitleBarHeight), + Size (aWindowSize.Width(), aWindowSize.Height()-nTitleBarHeight)); + } +} + + + + +void TitledControl::GetFocus (void) +{ + ::Window::GetFocus(); + if (GetTitleBar() != NULL) + GetTitleBar()->GrabFocus(); +} + + + + +void TitledControl::KeyInput (const KeyEvent& rEvent) +{ + KeyCode nCode = rEvent.GetKeyCode(); + if (nCode == KEY_SPACE) + { + // Toggle the expansion state of the control (when toggling is + // supported.) The focus remains on this control. + GetParentNode()->GetControlContainer().SetExpansionState ( + this, + ControlContainer::ES_TOGGLE); + } + else if (nCode == KEY_RETURN) + { + // Return, also called enter, enters the control and puts the + // focus to the first child. If the control is not yet + // expanded then do that first. + GetParentNode()->GetControlContainer().SetExpansionState ( + this, + ControlContainer::ES_EXPAND); + + if ( ! FocusManager::Instance().TransferFocus(this,nCode)) + { + // When already expanded then put focus on first child. + TreeNode* pControl = GetControl(); + if (pControl!=NULL && IsExpanded()) + if (pControl->GetWindow() != NULL) + pControl->GetWindow()->GrabFocus(); + } + } + else if (nCode == KEY_ESCAPE) + { + if ( ! FocusManager::Instance().TransferFocus(this,nCode)) + // Put focus to parent. + GetParent()->GrabFocus(); + } + else + Window::KeyInput (rEvent); +} + + + + +const String& TitledControl::GetTitle (void) const +{ + return msTitle; +} + + + + +bool TitledControl::Expand (bool bExpanded) +{ + bool bExpansionStateChanged (false); + + if (IsExpandable() && IsEnabled()) + { + if (GetTitleBar()->IsExpanded() != bExpanded) + bExpansionStateChanged |= GetTitleBar()->Expand (bExpanded); + // Get the control. Use the bExpanded parameter as argument to + // indicate that a control is created via its factory only when it + // is to be expanded. When it is collapsed this is not necessary. + TreeNode* pControl = GetControl(); + if (pControl != NULL + && GetControl()->IsExpanded() != bExpanded) + { + bExpansionStateChanged |= pControl->Expand (bExpanded); + } + if (bExpansionStateChanged) + UpdateStates(); + } + + return bExpansionStateChanged; +} + + + + +bool TitledControl::IsExpandable (void) const +{ + const TreeNode* pControl = GetConstControl(); + if (pControl != NULL) + return pControl->IsExpandable(); + else + // When a control factory is given but the control has not yet been + // created we assume that the control is expandable. + return true; +} + + + + +bool TitledControl::IsExpanded (void) const +{ + const TreeNode* pControl = GetConstControl(); + if (pControl != NULL) + return pControl->IsExpanded(); + else + return false; +} + +void TitledControl::SetEnabledState(bool bFlag) +{ + if (!bFlag) + { + GetParentNode()->GetControlContainer().SetExpansionState ( + this, + ControlContainer::ES_COLLAPSE); + Disable(); + } + else + { +/* + GetParentNode()->GetControlContainer().SetExpansionState ( + this, + ControlContainer::ES_EXPAND); +*/ + Enable(); + } + + GetTitleBar()->SetEnabledState(bFlag); +} + + + +bool TitledControl::IsShowing (void) const +{ + return mbVisible; +} + + + + +void TitledControl::Show (bool bVisible) +{ + if (mbVisible != bVisible) + { + mbVisible = bVisible; + UpdateStates (); + } +} + + + + +void TitledControl::UpdateStates (void) +{ + if (mbVisible) + GetWindow()->Show(); + else + GetWindow()->Hide(); + + TreeNode* pControl = GetControl(); + if (pControl!=NULL && pControl->GetWindow() != NULL) + { + if (IsVisible() && IsExpanded()) + pControl->GetWindow()->Show(); + else + pControl->GetWindow()->Hide(); + } +} + + + + +IMPL_LINK(TitledControl, WindowEventListener, + VclSimpleEvent*, pEvent) +{ + if (pEvent!=NULL && pEvent->ISA(VclWindowEvent)) + { + VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent); + switch (pWindowEvent->GetId()) + { + case VCLEVENT_WINDOW_MOUSEBUTTONUP: + if (IsEnabled()) + (*mpClickHandler)(*this); + break; + } + } + return 0; +} + + + + +TreeNode* TitledControl::GetControl (void) +{ + return mpControlContainer->GetControl(1); +} + + + + +const TreeNode* TitledControl::GetConstControl () const +{ + return const_cast<TitledControl*>(this)->GetControl(); +} + + + + +TitleBar* TitledControl::GetTitleBar (void) +{ + return static_cast<TitleBar*>(mpControlContainer->GetControl(0)); +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> TitledControl::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + return new ::accessibility::AccessibleTreeNode( + *this, + GetTitle(), + GetTitle(), + ::com::sun::star::accessibility::AccessibleRole::LIST_ITEM); +} + + + + +//===== TitledControlStandardClickHandler ===================================== + +TitledControlStandardClickHandler::TitledControlStandardClickHandler ( + ControlContainer& rControlContainer, + ControlContainer::ExpansionState eExpansionState) + : mrControlContainer(rControlContainer), + meExpansionState(eExpansionState) +{ +} + + + + +void TitledControlStandardClickHandler::operator () (TitledControl& rTitledControl) +{ + // Toggle expansion. + mrControlContainer.SetExpansionState (&rTitledControl, meExpansionState); +} + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/ToolPanel.cxx b/sd/source/ui/toolpanel/ToolPanel.cxx new file mode 100755 index 000000000000..6dbcae52547a --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanel.cxx @@ -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_sd.hxx" + +#include "ToolPanel.hxx" +#include "MethodGuard.hxx" +#include <taskpane/TaskPaneTreeNode.hxx> + +/** === begin UNO includes === **/ +#include <com/sun/star/lang/DisposedException.hpp> +/** === end UNO includes === **/ + +#include <vcl/window.hxx> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + /** === 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::DisposedException; + using ::com::sun::star::awt::XWindow; + using ::com::sun::star::accessibility::XAccessible; + /** === end UNO using === **/ + + typedef MethodGuard< ToolPanel > ToolPanelGuard; + + //================================================================================================================== + //= ToolPanel + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ToolPanel::ToolPanel( ::std::auto_ptr< TreeNode >& i_rControl ) + :ToolPanel_Base( m_aMutex ) + ,m_pControl( i_rControl ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanel::~ToolPanel() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanel::checkDisposed() + { + if ( m_pControl.get() == NULL ) + throw DisposedException( ::rtl::OUString(), *this ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XWindow > SAL_CALL ToolPanel::getWindow() throw (RuntimeException) + { + ToolPanelGuard aGuard( *this ); + return Reference< XWindow >( m_pControl->GetWindow()->GetComponentInterface(), UNO_QUERY_THROW ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XAccessible > SAL_CALL ToolPanel::createAccessible( const Reference< XAccessible >& i_rParentAccessible ) throw (RuntimeException) + { + ToolPanelGuard aGuard( *this ); + Reference< XAccessible > xAccessible( m_pControl->GetWindow()->GetAccessible( FALSE ) ); + if ( !xAccessible.is() ) + { + xAccessible.set( m_pControl->CreateAccessibleObject( i_rParentAccessible ) ); + m_pControl->GetWindow()->SetAccessible( xAccessible ); + } + return xAccessible; + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL ToolPanel::disposing() + { + m_pControl.reset(); + } + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... diff --git a/sd/source/ui/toolpanel/ToolPanel.hxx b/sd/source/ui/toolpanel/ToolPanel.hxx new file mode 100644 index 000000000000..2fe4a64c71be --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanel.hxx @@ -0,0 +1,80 @@ +/************************************************************************* + * 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 SD_TOOLPANEL_HXX +#define SD_TOOLPANEL_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/XToolPanel.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase1.hxx> + +#include <memory> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + class TreeNode; + + //================================================================================================================== + //= ToolPanel + //================================================================================================================== + typedef ::cppu::WeakComponentImplHelper1 < ::com::sun::star::ui::XToolPanel + > ToolPanel_Base; + class ToolPanel :public ::cppu::BaseMutex + ,public ToolPanel_Base + { + public: + ToolPanel( + ::std::auto_ptr< TreeNode >& i_rControl + ); + + // XToolPanel + virtual ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow > SAL_CALL getWindow() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL createAccessible( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& ParentAccessible ) throw (::com::sun::star::uno::RuntimeException); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + ::osl::Mutex& getMutex() { return m_aMutex; } + void checkDisposed(); + + protected: + ~ToolPanel(); + + private: + ::std::auto_ptr< TreeNode > m_pControl; + }; + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... + +#endif // SD_TOOLPANEL_HXX diff --git a/sd/source/ui/toolpanel/ToolPanelDescriptor.hxx b/sd/source/ui/toolpanel/ToolPanelDescriptor.hxx new file mode 100644 index 000000000000..4ac31ef53e23 --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanelDescriptor.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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 SD_TOOL_PANEL_DESCRIPTOR_HXX +#define SD_TOOL_PANEL_DESCRIPTOR_HXX + +#include <tools/string.hxx> +#include <tools/gen.hxx> +#include <memory> + +class Window; + +namespace sd { namespace toolpanel { + + +/** Collection of information the describes entries of the tool + panel. A descriptor owns the control it is associated with. +*/ +class ToolPanelDescriptor +{ +public: + /** Create a new descriptor for the given control. + @param pControl + */ + ToolPanelDescriptor (::std::auto_ptr< ::Window> pControl, + const String& rTitle); + + ~ToolPanelDescriptor (void); + + /** Return the height of the title bar. + @return + The title bar height is returned in pixels. + */ + int GetTitleBarHeight (void) const; + + + void SetPositionAndSize (const Point& aPosition, + const Size& aSize); + void SetPositionAndSize (const Rectangle& aBox); + void SetWeight (double nWeight); + + Window* GetControl (void) const; + const String& GetTitle (void) const; + const Rectangle& GetTitleBox (void) const; + Rectangle GetPositionAndSize (void) const; + double GetWeight (void) const; + + int GetTotalHeight (void) const; + int GetWindowHeight (void) const; + +private: + ::std::auto_ptr< ::Window> mpControl; + String msTitle; + Rectangle maTitleBox; + double mnWeight; + int mnTotalHeight; + + /// Do not use! Assignment operator is not supported. + const ToolPanelDescriptor& operator= ( + const ToolPanelDescriptor& aDescriptor); +}; + +} } // end of namespace ::sd::toolpanel + +#endif diff --git a/sd/source/ui/toolpanel/ToolPanelFactory.cxx b/sd/source/ui/toolpanel/ToolPanelFactory.cxx new file mode 100644 index 000000000000..db4602c991d0 --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanelFactory.cxx @@ -0,0 +1,255 @@ +/************************************************************************* + * 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_sd.hxx" + +#include "taskpane/ToolPanelViewShell.hxx" +#include "framework/FrameworkHelper.hxx" +#include "PaneChildWindows.hxx" +#include "ViewShellBase.hxx" +#include "app.hrc" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/XUIElementFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/awt/XWindow.hpp> +/** === end UNO includes === **/ + +#include <sfx2/frame.hxx> +#include <vcl/svapp.hxx> +#include <vos/mutex.hxx> +#include <sfx2/viewfrm.hxx> +#include <cppuhelper/implbase3.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + /** === 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::uno::XComponentContext; + using ::com::sun::star::ui::XUIElementFactory; + using ::com::sun::star::ui::XUIElement; + using ::com::sun::star::beans::PropertyValue; + using ::com::sun::star::container::NoSuchElementException; + using ::com::sun::star::lang::IllegalArgumentException; + using ::com::sun::star::lang::XServiceInfo; + using ::com::sun::star::lang::XInitialization; + using ::com::sun::star::frame::XFrame; + using ::com::sun::star::awt::XWindow; + /** === end UNO using === **/ + + //================================================================================================================== + //= ToolPanelFactory + //================================================================================================================== + typedef ::cppu::WeakImplHelper3 < XUIElementFactory + , XServiceInfo + , XInitialization + > ToolPanelFactory_Base; + class ToolPanelFactory : public ToolPanelFactory_Base + { + public: + ToolPanelFactory( const Reference< XComponentContext >& i_rContext ); + + // XUIElementFactory + virtual Reference< XUIElement > SAL_CALL createUIElement( const ::rtl::OUString& ResourceURL, const Sequence< PropertyValue >& Args ) throw (NoSuchElementException, IllegalArgumentException, RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException); + virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException); + virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException); + + protected: + virtual ~ToolPanelFactory(); + + private: + const Reference< XComponentContext > m_xContext; + }; + + //------------------------------------------------------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ToolPanelFactory_createInstance( const Reference< XComponentContext >& i_rContext ) + { + return Reference< XInterface >( *new ToolPanelFactory( i_rContext ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString ToolPanelFactory_getImplementationName() throw(RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.drawing.ToolPanelFactory" ) ); + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ToolPanelFactory_getSupportedServiceNames (void) + throw (RuntimeException) + { + const ::rtl::OUString sServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DefaultToolPanelFactory" ) ); + return Sequence< ::rtl::OUString >( &sServiceName, 1 ); + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelFactory::ToolPanelFactory( const Reference< XComponentContext >& i_rContext ) + :m_xContext( i_rContext ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelFactory::~ToolPanelFactory() + { + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XUIElement > SAL_CALL ToolPanelFactory::createUIElement( const ::rtl::OUString& i_rResourceURL, const Sequence< PropertyValue >& i_rArgs ) throw (NoSuchElementException, IllegalArgumentException, RuntimeException) + { + ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); + + const PanelId ePanelId( toolpanel::GetStandardPanelId( i_rResourceURL ) ); + if ( ePanelId == PID_UNKNOWN ) + throw NoSuchElementException( i_rResourceURL, *this ); + + const ::comphelper::NamedValueCollection aArgs( i_rArgs ); + const Reference< XFrame > xDocFrame( aArgs.getOrDefault( "Frame", Reference< XFrame >() ) ); + const Reference< XWindow > xParentWindow( aArgs.getOrDefault( "ParentWindow", Reference< XWindow >() ) ); + if ( !xDocFrame.is() || !xParentWindow.is() ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "For creating a standard tool panel, a Frame and a Parent window are needed." ) ), + *this, + 2 + ); + + // look up the Sfx(View)Frame for the given XFrame + SfxViewFrame* pViewFrame = NULL; + for ( SfxFrame* pFrame = SfxFrame::GetFirst(); + pFrame != NULL; + pFrame = SfxFrame::GetNext( *pFrame ) + ) + { + if ( pFrame->GetFrameInterface() == xDocFrame ) + { + pViewFrame = pFrame->GetCurrentViewFrame(); + break; + } + } + + if ( !pViewFrame || !pViewFrame->HasChildWindow( SID_TASKPANE ) ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Illegal frame." ) ), + *this, + 2 + ); + + // retrieve the task pane + ToolPanelChildWindow* pToolPanelWindow( dynamic_cast< ToolPanelChildWindow* >( pViewFrame->GetChildWindow( SID_TASKPANE ) ) ); + if ( !pToolPanelWindow ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No Impress document, or no Impress Task Pane." ) ), + *this, + 2 + ); + + // retrieve the ViewShellBase, and the view shell of the task pane + ViewShellBase* pViewShellBase = dynamic_cast< ViewShellBase* >( pViewFrame->GetViewShell() ); + ::boost::shared_ptr< framework::FrameworkHelper > pFrameworkHelper; + if ( pViewShellBase ) + pFrameworkHelper = framework::FrameworkHelper::Instance( *pViewShellBase ); + ::boost::shared_ptr< ViewShell > pViewShell; + if ( pFrameworkHelper.get() ) + pViewShell = pFrameworkHelper->GetViewShell( framework::FrameworkHelper::msRightPaneURL ); + ToolPanelViewShell* pToolPanelShell = dynamic_cast< ToolPanelViewShell* >( pViewShell.get() ); + + if ( !pToolPanelShell ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Wrong document type." ) ), + *this, + 2 + ); + + ::Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); + if ( !pParentWindow || !pToolPanelShell->IsPanelAnchorWindow( *pParentWindow ) ) + throw IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported parent window." ) ), + *this, + 2 + ); + + return pToolPanelShell->CreatePanelUIElement( xDocFrame, i_rResourceURL ); + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ToolPanelFactory::getImplementationName( ) throw (RuntimeException) + { + return ToolPanelFactory_getImplementationName(); + } + + //------------------------------------------------------------------------------------------------------------------ + ::sal_Bool SAL_CALL ToolPanelFactory::supportsService( const ::rtl::OUString& i_rServiceName ) throw (RuntimeException) + { + const Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + for ( const ::rtl::OUString* pSupported = aSupported.getConstArray(); + pSupported != aSupported.getConstArray() + aSupported.getLength(); + ++pSupported + ) + if ( *pSupported == i_rServiceName ) + return sal_True; + + return sal_False; + } + + //------------------------------------------------------------------------------------------------------------------ + Sequence< ::rtl::OUString > SAL_CALL ToolPanelFactory::getSupportedServiceNames( ) throw (RuntimeException) + { + return ToolPanelFactory_getSupportedServiceNames(); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL ToolPanelFactory::initialize( const Sequence< Any >& i_rArguments ) throw (Exception, RuntimeException) + { + ::comphelper::NamedValueCollection aArgs( i_rArguments ); + (void)aArgs; + // TODO + } + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... diff --git a/sd/source/ui/toolpanel/ToolPanelUIElement.cxx b/sd/source/ui/toolpanel/ToolPanelUIElement.cxx new file mode 100644 index 000000000000..e81f683bcfa7 --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanelUIElement.cxx @@ -0,0 +1,134 @@ +/************************************************************************* + * 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_sd.hxx" + +#include "ToolPanelUIElement.hxx" +#include "MethodGuard.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/UIElementType.hpp> +#include <com/sun/star/lang/XComponent.hpp> +/** === end UNO includes === **/ + +#include <tools/diagnose_ex.h> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + /** === 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::frame::XFrame; + using ::com::sun::star::lang::XComponent; + using ::com::sun::star::ui::XToolPanel; + using ::com::sun::star::lang::DisposedException; + /** === end UNO using === **/ + namespace UIElementType = ::com::sun::star::ui::UIElementType; + + typedef MethodGuard< ToolPanelUIElement > UIElementMethodGuard; + + //================================================================================================================== + //= ToolPanelUIElement + //================================================================================================================== + //------------------------------------------------------------------------------------------------------------------ + ToolPanelUIElement::ToolPanelUIElement( const Reference< XFrame >& i_rFrame, const ::rtl::OUString& i_rResourceURL, + const Reference< XToolPanel >& i_rToolPanel ) + :ToolPanelUIElement_Base( m_aMutex ) + ,m_xFrame( i_rFrame ) + ,m_sResourceURL( i_rResourceURL ) + ,m_xToolPanel( i_rToolPanel ) + { + } + + //------------------------------------------------------------------------------------------------------------------ + ToolPanelUIElement::~ToolPanelUIElement() + { + } + + //------------------------------------------------------------------------------------------------------------------ + void ToolPanelUIElement::checkDisposed() + { + if ( !m_xToolPanel.is() ) + throw DisposedException( ::rtl::OUString(), *this ); + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XFrame > SAL_CALL ToolPanelUIElement::getFrame() throw (RuntimeException) + { + UIElementMethodGuard aGuard( *this ); + return m_xFrame; + } + + //------------------------------------------------------------------------------------------------------------------ + ::rtl::OUString SAL_CALL ToolPanelUIElement::getResourceURL() throw (RuntimeException) + { + UIElementMethodGuard aGuard( *this ); + return m_sResourceURL; + } + + //------------------------------------------------------------------------------------------------------------------ + ::sal_Int16 SAL_CALL ToolPanelUIElement::getType() throw (RuntimeException) + { + UIElementMethodGuard aGuard( *this ); + return UIElementType::TOOLPANEL; + } + + //------------------------------------------------------------------------------------------------------------------ + Reference< XInterface > SAL_CALL ToolPanelUIElement::getRealInterface( ) throw (RuntimeException) + { + UIElementMethodGuard aGuard( *this ); + return m_xToolPanel.get(); + } + + //------------------------------------------------------------------------------------------------------------------ + void SAL_CALL ToolPanelUIElement::disposing() + { + try + { + Reference< XComponent > xPanelComponent( m_xToolPanel, UNO_QUERY_THROW ); + xPanelComponent->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... diff --git a/sd/source/ui/toolpanel/ToolPanelUIElement.hxx b/sd/source/ui/toolpanel/ToolPanelUIElement.hxx new file mode 100644 index 000000000000..0a74b7bd449e --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanelUIElement.hxx @@ -0,0 +1,87 @@ +/************************************************************************* + * 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 SD_TOOLPANELUIELEMENT_HXX +#define SD_TOOLPANELUIELEMENT_HXX + +/** === begin UNO includes === **/ +#include <com/sun/star/ui/XUIElement.hpp> +#include <com/sun/star/ui/XToolPanel.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <memory> + +//...................................................................................................................... +namespace sd { namespace toolpanel +{ +//...................................................................................................................... + + class TreeNode; + + //================================================================================================================== + //= ToolPanelUIElement + //================================================================================================================== + typedef ::cppu::WeakComponentImplHelper1 < ::com::sun::star::ui::XUIElement + > ToolPanelUIElement_Base; + class ToolPanelUIElement :public ::cppu::BaseMutex + ,public ToolPanelUIElement_Base + { + public: + ToolPanelUIElement( + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& i_rFrame, + const ::rtl::OUString& i_rResourceURL, + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XToolPanel >& i_rToolPanel + ); + + // XUIElement + virtual ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SAL_CALL getFrame() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getResourceURL() throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int16 SAL_CALL getType() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getRealInterface( ) throw (::com::sun::star::uno::RuntimeException); + + void checkDisposed(); + ::osl::Mutex& getMutex() { return m_aMutex; } + + protected: + virtual ~ToolPanelUIElement(); + + // OComponentHelper + virtual void SAL_CALL disposing(); + + private: + const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > m_xFrame; + const ::rtl::OUString m_sResourceURL; + const ::com::sun::star::uno::Reference< ::com::sun::star::ui::XToolPanel > m_xToolPanel; + }; + +//...................................................................................................................... +} } // namespace sd::toolpanel +//...................................................................................................................... + +#endif // SD_TOOLPANELUIELEMENT_HXX diff --git a/sd/source/ui/toolpanel/ToolPanelViewShell.cxx b/sd/source/ui/toolpanel/ToolPanelViewShell.cxx new file mode 100755 index 000000000000..eb465789e7dc --- /dev/null +++ b/sd/source/ui/toolpanel/ToolPanelViewShell.cxx @@ -0,0 +1,901 @@ +/************************************************************************* + * 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_sd.hxx" + +#include "taskpane/ToolPanelViewShell.hxx" + +#include "TaskPaneShellManager.hxx" +#include "TaskPaneFocusManager.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" +#include "controls/MasterPagesPanel.hxx" +#include "LayoutMenu.hxx" +#include "DrawDocShell.hxx" +#include "controls/TableDesignPanel.hxx" +#include "controls/CustomAnimationPanel.hxx" +#include "controls/SlideTransitionPanel.hxx" +#include "controls/MasterPagesSelector.hxx" +#include "ToolPanel.hxx" +#include "ToolPanelUIElement.hxx" +#include "PaneDockingWindow.hxx" +#include "FrameView.hxx" +#include "Window.hxx" +#include "sdmod.hxx" +#include "app.hrc" +#include "glob.hrc" +#include "res_bmp.hrc" +#include "helpids.h" +#include "strings.hrc" +#include "sdresid.hxx" +#include "framework/FrameworkHelper.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/drawing/framework/XResourceId.hpp> +#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> +#include <com/sun/star/drawing/framework/AnchorBindingMode.hpp> +#include <com/sun/star/drawing/framework/ResourceActivationMode.hpp> +#include <com/sun/star/drawing/XDrawSubController.hpp> +/** === end UNO includes === **/ + +#include <svtools/toolpanel/toolpanel.hxx> +#include <svtools/toolpanel/toolpaneldeck.hxx> +#include <svx/dlgctrl.hxx> +#include <sfx2/taskpane.hxx> +#include <sfx2/imagemgr.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/msg.hxx> +#include <sfx2/objface.hxx> +#include <svx/colrctrl.hxx> +#include <svx/xtable.hxx> +#include <vcl/dockwin.hxx> +#include "sdtreelb.hxx" +#include "DrawViewShell.hxx" +#include "drawdoc.hxx" +#include "ViewShellBase.hxx" +#include <svx/ruler.hxx> +#include <vcl/svapp.hxx> +#include <vcl/toolbox.hxx> +#include <tools/diagnose_ex.h> +#include <unotools/confignode.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <vector> + +using namespace ::sd::toolpanel; + +#define ToolPanelViewShell +#include "sdslots.hxx" + +/** === 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::XAccessible; +using ::com::sun::star::drawing::XDrawSubController; +using ::com::sun::star::frame::XFrame; +using ::com::sun::star::drawing::framework::XResourceId; +using ::com::sun::star::drawing::framework::XConfigurationChangeListener; +using ::com::sun::star::drawing::framework::ConfigurationChangeEvent; +using ::com::sun::star::lang::EventObject; +using ::com::sun::star::lang::DisposedException; +using ::com::sun::star::drawing::framework::XConfigurationControllerBroadcaster; +using ::com::sun::star::drawing::framework::XConfigurationController; +using ::com::sun::star::drawing::framework::XConfiguration; +using ::com::sun::star::drawing::framework::AnchorBindingMode_DIRECT; +using ::com::sun::star::ui::XUIElement; +using ::com::sun::star::ui::XToolPanel; +using ::com::sun::star::drawing::framework::ResourceActivationMode_REPLACE; +/** === end UNO using === **/ + +using ::sd::framework::FrameworkHelper; + +namespace sd { namespace toolpanel { + +// ===================================================================================================================== +// = misc helper +// ===================================================================================================================== +// --------------------------------------------------------------------------------------------------------------------- +PanelId GetStandardPanelId( const ::rtl::OUString& i_rTaskPanelResourceURL, const bool i_bIgnoreUnknown ) +{ + PanelId ePanelId( PID_UNKNOWN ); + + if ( i_rTaskPanelResourceURL.equals( FrameworkHelper::msMasterPagesTaskPanelURL ) ) + { + ePanelId = PID_MASTER_PAGES; + } + else if ( i_rTaskPanelResourceURL.equals( FrameworkHelper::msLayoutTaskPanelURL ) ) + { + ePanelId = PID_LAYOUT; + } + else if ( i_rTaskPanelResourceURL.equals( FrameworkHelper::msTableDesignPanelURL ) ) + { + ePanelId = PID_TABLE_DESIGN; + } + else if ( i_rTaskPanelResourceURL.equals( FrameworkHelper::msCustomAnimationTaskPanelURL ) ) + { + ePanelId = PID_CUSTOM_ANIMATION; + } + else if ( i_rTaskPanelResourceURL.equals( FrameworkHelper::msSlideTransitionTaskPanelURL ) ) + { + ePanelId = PID_SLIDE_TRANSITION; + } + else + { + OSL_ENSURE( i_bIgnoreUnknown, "GetStandardPanelId: cannot translate the given resource URL!" ); + (void)i_bIgnoreUnknown; + } + + return ePanelId; +} + +// --------------------------------------------------------------------------------------------------------------------- +PanelId GetStandardPanelId( const ::rtl::OUString& i_rTaskPanelResourceURL ) +{ + return GetStandardPanelId( i_rTaskPanelResourceURL, false ); +} + +// ===================================================================================================================== +// = ConfigurationListener - declaration +// ===================================================================================================================== +typedef ::cppu::WeakImplHelper1 < XConfigurationChangeListener + > ConfigurationListener_Base; + +class ConfigurationListener :public ::cppu::BaseMutex + ,public ConfigurationListener_Base +{ +public: + ConfigurationListener( ToolPanelViewShell_Impl& i_rShellImpl ); + + // XConfigurationChangeListener + virtual void SAL_CALL notifyConfigurationChange( const ConfigurationChangeEvent& aEvent ) throw (RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException); + + // XComponent equivalents (not available per UNO interface) + void dispose(); + +protected: + ~ConfigurationListener(); + + void impl_checkDisposed_throw() + { + if ( !m_pShellImpl ) + throw DisposedException( ::rtl::OUString(), *this ); + } + +private: + ToolPanelViewShell_Impl* m_pShellImpl; +}; + +// ===================================================================================================================== +// = ToolPanelViewShell_Impl - declaration +// ===================================================================================================================== +/** Inner implementation class of ToolPanelViewShell. +*/ +class ToolPanelViewShell_Impl :public ::boost::noncopyable + ,public ::svt::IToolPanelDeckListener + ,public ::sfx2::IToolPanelCompare +{ +public: + static const size_t mnInvalidId = static_cast< size_t >( -1 ); + + ToolPanelViewShell_Impl( ToolPanelViewShell& i_rPanelViewShell, ::Window& i_rPanelDeckParent ); + ~ToolPanelViewShell_Impl(); + + ToolPanelViewShell& GetAntiImpl() { return m_rPanelViewShell; } + + /** Here the panels are created that are shown in the task pane. + */ + void Setup(); + + /** clean up the instance + */ + void Cleanup(); + + /** activates the panel which has the given resource URL + */ + void ActivatePanelByResource( const ::rtl::OUString& i_rPanelResourceURL ); + + /** de-activates the panel given by its resource URL, bypassing the configuration controller + + If the panel is not active currently, nothing happens. + */ + void DeactivatePanelByResource( const ::rtl::OUString& i_rPanelResourceURL ); + + /** provides access to the the VCL window of the panel deck + */ + ::sfx2::ModuleTaskPane& GetTaskPane() { return *m_pTaskPane; } + const ::sfx2::ModuleTaskPane& GetTaskPane() const { return *m_pTaskPane; } + + ::svt::ToolPanelDeck& GetToolPanelDeck() { return GetTaskPane().GetPanelDeck(); } + const ::svt::ToolPanelDeck& GetToolPanelDeck() const { return GetTaskPane().GetPanelDeck(); } + + Reference< XAccessible > + CreateAccessible( ::sd::Window& i_rWindow ); + + void ConnectToDockingWindow(); + +private: + // IToolPanelDeckListener overridables + virtual void PanelInserted( const ::svt::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 ::svt::PDeckLayouter& i_rNewLayouter ); + virtual void Dying(); + + // IToolPanelCompare overridables + virtual short compareToolPanelsURLs( const ::rtl::OUString& i_rLHS, const ::rtl::OUString& i_rRHS ) const; + +private: + struct InitialPanel + { + ::rtl::OUString sPanelResourceURL; + bool bActivateDirectly; + InitialPanel() + :sPanelResourceURL() + ,bActivateDirectly( true ) + { + } + }; + InitialPanel impl_determineInitialPanel(); + ::rtl::OUString impl_getPanelURL( const ::boost::optional< size_t >& i_rPanel ); + +private: + ToolPanelViewShell& m_rPanelViewShell; + ::boost::scoped_ptr< ::sfx2::ModuleTaskPane > m_pTaskPane; + ::std::auto_ptr< ::sfx2::TaskPaneController > m_pTaskPaneController; + ::rtl::Reference< ConfigurationListener > m_pConfigListener; + bool m_bInitialized; +}; + +// ===================================================================================================================== +// = ConfigurationListener - implementation +// ===================================================================================================================== +// --------------------------------------------------------------------------------------------------------------------- +ConfigurationListener::ConfigurationListener( ToolPanelViewShell_Impl& i_rShellImpl ) + :m_pShellImpl( &i_rShellImpl ) +{ + ::boost::shared_ptr< FrameworkHelper > pFrameworkHelper( FrameworkHelper::Instance( i_rShellImpl.GetAntiImpl().GetViewShellBase() ) ); + Reference< XConfigurationControllerBroadcaster > xBroadcaster; + if ( pFrameworkHelper.get() ) + xBroadcaster.set( pFrameworkHelper->GetConfigurationController().get() ); + ENSURE_OR_THROW( pFrameworkHelper.get(), "no access to the config controller" ); + + osl_incrementInterlockedCount( &m_refCount ); + { + xBroadcaster->addConfigurationChangeListener( this, ::rtl::OUString(), Any() ); + } + osl_decrementInterlockedCount( &m_refCount ); +} + +// --------------------------------------------------------------------------------------------------------------------- +ConfigurationListener::~ConfigurationListener() +{ +} + +// --------------------------------------------------------------------------------------------------------------------- +void SAL_CALL ConfigurationListener::notifyConfigurationChange( const ConfigurationChangeEvent& i_rEvent ) throw (RuntimeException) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + + // is this an event we're interested in? + if ( i_rEvent.Type != FrameworkHelper::msResourceActivationEvent ) + return; + + // is this a resource we're interested in? Must be anchored in the task pane ... + Reference< XResourceId > xAnchorId; + if ( i_rEvent.ResourceId.is() ) + xAnchorId = i_rEvent.ResourceId->getAnchor(); + if ( !xAnchorId.is() ) + return; + const ::rtl::OUString sAnchorURL( xAnchorId->getResourceURL() ); + if ( sAnchorURL != FrameworkHelper::msTaskPaneURL ) + return; + + m_pShellImpl->ActivatePanelByResource( i_rEvent.ResourceId->getResourceURL() ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void SAL_CALL ConfigurationListener::disposing( const EventObject& i_rEvent ) throw (RuntimeException) +{ + (void)i_rEvent; + { + ::osl::MutexGuard aGuard( m_aMutex ); + impl_checkDisposed_throw(); + } + + dispose(); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ConfigurationListener::dispose() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_pShellImpl = NULL; +} + +// ===================================================================================================================== +// = ToolPanelViewShell +// ===================================================================================================================== +// --------------------------------------------------------------------------------------------------------------------- +SFX_IMPL_INTERFACE(ToolPanelViewShell, SfxShell, SdResId(STR_TASKPANEVIEWSHELL)) +{ +} + +// --------------------------------------------------------------------------------------------------------------------- +TYPEINIT1(ToolPanelViewShell, ViewShell); + +// --------------------------------------------------------------------------------------------------------------------- +ToolPanelViewShell_Impl::InitialPanel ToolPanelViewShell_Impl::impl_determineInitialPanel() +{ + InitialPanel aPanelToActivate; + if ( GetAntiImpl().GetViewShellBase().GetDocShell()->GetDocumentType() == DOCUMENT_TYPE_DRAW ) + // for Draw, rely on SFX's default handling, which is to activate the previously active panel + return aPanelToActivate; + + // Default to Layout panel, but check whether the requested configuration already contains a tool panel, in this case, + // use that one. + aPanelToActivate.sPanelResourceURL = FrameworkHelper::msLayoutTaskPanelURL; + aPanelToActivate.bActivateDirectly = false; + try + { + ::boost::shared_ptr< FrameworkHelper > pFrameworkHelper( FrameworkHelper::Instance( m_rPanelViewShell.GetViewShellBase() ) ); + const Reference< XResourceId > xToolPanelId( pFrameworkHelper->CreateResourceId( FrameworkHelper::msTaskPaneURL, FrameworkHelper::msRightPaneURL ) ); + Reference< XConfigurationController > xCC( pFrameworkHelper->GetConfigurationController(), UNO_QUERY_THROW ); + Reference< XConfiguration > xConfiguration( xCC->getRequestedConfiguration(), UNO_QUERY_THROW ); + Sequence< Reference< XResourceId > > aViewIds( xConfiguration->getResources( + FrameworkHelper::CreateResourceId( FrameworkHelper::msTaskPaneURL, FrameworkHelper::msRightPaneURL ), + FrameworkHelper::msTaskPanelURLPrefix, AnchorBindingMode_DIRECT ) ); + + if ( aViewIds.getLength() > 0 ) + { + const ::rtl::OUString sResourceURL( aViewIds[0]->getResourceURL() ); + PanelId nRequestedPanel = GetStandardPanelId( sResourceURL ); + if ( nRequestedPanel != PID_UNKNOWN ) + { + aPanelToActivate.sPanelResourceURL = sResourceURL; + aPanelToActivate.bActivateDirectly = true; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return aPanelToActivate; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::Setup() +{ + if ( m_bInitialized ) + return; + m_bInitialized = true; + + // initially activate a panel + const InitialPanel aInitialPanel = impl_determineInitialPanel(); + if ( aInitialPanel.sPanelResourceURL.getLength() ) + { + if ( aInitialPanel.bActivateDirectly ) + { + ActivatePanelByResource( aInitialPanel.sPanelResourceURL ); + } + else + { + ::boost::shared_ptr< FrameworkHelper > pFrameworkHelper( FrameworkHelper::Instance( GetAntiImpl().GetViewShellBase() ) ); + pFrameworkHelper->RequestTaskPanel( aInitialPanel.sPanelResourceURL ); + } + } + + // listen at the configuration + m_pConfigListener.set( new ConfigurationListener( *this ) ); + + m_pTaskPane->Show(); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::Cleanup() +{ + if ( m_bInitialized ) + { + if ( m_pConfigListener.is() ) + m_pConfigListener->dispose(); + } + GetToolPanelDeck().RemoveListener( *this ); + m_pTaskPaneController.reset(); + m_pTaskPane.reset(); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::ActivatePanelByResource( const ::rtl::OUString& i_rResourceURL ) +{ + // determine position of the requested panel + ::boost::optional< size_t > aPanelPos = GetTaskPane().GetPanelPos( i_rResourceURL ); + OSL_ENSURE( !!aPanelPos, "ToolPanelViewShell_Impl::ActivatePanelByResource: illegal panel resource, or illegal panel deck setup!" ); + if ( !!aPanelPos ) + GetToolPanelDeck().ActivatePanel( *aPanelPos ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::DeactivatePanelByResource( const ::rtl::OUString& i_rPanelResourceURL ) +{ + // determine position of the requested panel + ::boost::optional< size_t > aPanelPos = GetTaskPane().GetPanelPos( i_rPanelResourceURL ); + OSL_ENSURE( !!aPanelPos, "ToolPanelViewShell_Impl::DeactivatePanelByResource: illegal panel resource, or illegal panel deck setup!" ); + if ( !!aPanelPos ) + { + if ( GetToolPanelDeck().GetActivePanel() == *aPanelPos ) + GetToolPanelDeck().ActivatePanel( ::boost::optional< size_t >() ); + } +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::Initialize() +{ + mpImpl->Setup(); +} + +// --------------------------------------------------------------------------------------------------------------------- +ToolPanelViewShell::ToolPanelViewShell( SfxViewFrame* pFrame, ViewShellBase& rViewShellBase, ::Window* pParentWindow, + FrameView* pFrameViewArgument ) + :ViewShell(pFrame, pParentWindow, rViewShellBase) + ,mpImpl( new ToolPanelViewShell_Impl( *this, *mpContentWindow.get() ) ) + ,mpSubShellManager() + ,mnMenuId(0) +{ + meShellType = ST_TASK_PANE; + + mpContentWindow->SetCenterAllowed( false ); + pParentWindow->SetStyle( pParentWindow->GetStyle() | WB_DIALOGCONTROL ); + + GetParentWindow()->SetBackground( Wallpaper() ); + mpContentWindow->SetBackground( Wallpaper() ); + + GetParentWindow()->SetHelpId(HID_SD_TASK_PANE); + + mpImpl->ConnectToDockingWindow(); + + SetPool( &GetDoc()->GetPool() ); + + if ( pFrameViewArgument ) + mpFrameView = pFrameViewArgument; + else + mpFrameView = new FrameView( GetDoc() ); + GetFrameView()->Connect(); + + // Hide or delete unused controls that we have inherited from the + // ViewShell base class. + mpHorizontalScrollBar.reset(); + mpVerticalScrollBar.reset(); + mpScrollBarBox.reset(); + mpHorizontalRuler.reset(); + mpVerticalRuler.reset(); + + SetName( String( RTL_CONSTASCII_USTRINGPARAM( "ToolPanelViewShell" ) ) ); + + // Some recent changes to the toolpanel make it necessary to create the + // accessibility object now. Creating it on demand would lead to a + // pointer cycle in the tree of accessibility objects and would lead + // e.g. the accerciser AT tool into an infinite loop. + // It would be nice to get rid of this workaround in the future. + if (mpContentWindow.get()) + mpContentWindow->SetAccessible(mpImpl->CreateAccessible(*mpContentWindow)); + + // For accessibility we have to shortly hide the content window. This + // triggers the construction of a new accessibility object for the new + // view shell. (One is created earlier while the construtor of the base + // class is executed. At that time the correct accessibility object can + // not be constructed.) + if (mpContentWindow.get()) + { + mpContentWindow->Hide(); + mpContentWindow->Show(); + } + + // Register the shell manager as factory at the ViewShellManager. + mpSubShellManager.reset( new TaskPaneShellManager( + GetViewShellBase().GetViewShellManager(), + *this + ) ); + GetViewShellBase().GetViewShellManager()->AddSubShellFactory( this, mpSubShellManager ); +} + +// --------------------------------------------------------------------------------------------------------------------- +ToolPanelViewShell::~ToolPanelViewShell() +{ + mpImpl->Cleanup(); + + // reset our impl before destroying the panel deck, to ensure the hidden panels are properly + // disposed/destroyed, too + mpImpl.reset(); + GetViewShellBase().GetViewShellManager()->RemoveSubShellFactory(this, mpSubShellManager); +} + +// --------------------------------------------------------------------------------------------------------------------- +// static +void ToolPanelViewShell::RegisterControls() +{ + SfxModule* pModule = SD_MOD(); + controls::MasterPagesSelector::RegisterInterface( pModule ); + LayoutMenu::RegisterInterface( pModule ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::ArrangeGUIElements() +{ + ViewShell::ArrangeGUIElements(); + + Initialize(); + + mpImpl->GetTaskPane().SetPosSizePixel( Point(), maViewSize ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::GetFocus() +{ + Invalidate(); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::LoseFocus() +{ + Invalidate(); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::KeyInput( const KeyEvent& i_rKeyEvent ) +{ + const KeyCode nCode = i_rKeyEvent.GetKeyCode(); + if ( nCode == KEY_RETURN ) + { + if ( !mpImpl->GetTaskPane().HasChildPathFocus() ) + mpImpl->GetTaskPane().GrabFocus(); + } + else + ViewShell::KeyInput( i_rKeyEvent, NULL ); +} + +// --------------------------------------------------------------------------------------------------------------------- +SdPage* ToolPanelViewShell::GetActualPage() +{ + return NULL; +} + +// --------------------------------------------------------------------------------------------------------------------- +SdPage* ToolPanelViewShell::getCurrentPage() const +{ + return NULL; +} + +// --------------------------------------------------------------------------------------------------------------------- +TaskPaneShellManager& ToolPanelViewShell::GetSubShellManager() const +{ + return *mpSubShellManager.get(); +} + +// --------------------------------------------------------------------------------------------------------------------- +DockingWindow* ToolPanelViewShell::GetDockingWindow() +{ + ::Window* pParentWindow = GetParentWindow(); + DockingWindow* pDockingWindow = NULL; + while (pParentWindow!=NULL && pDockingWindow==NULL) + { + pDockingWindow = dynamic_cast<DockingWindow*>(pParentWindow); + pParentWindow = pParentWindow->GetParent(); + } + return pDockingWindow; +} + +// --------------------------------------------------------------------------------------------------------------------- +Reference< XAccessible > ToolPanelViewShell::CreateAccessibleDocumentView( ::sd::Window* i_pWindow ) +{ + ENSURE_OR_RETURN( i_pWindow, "ToolPanelViewShell::CreateAccessibleDocumentView: illegal window!", NULL ); + // As said above, we have to create the accessibility object + // (unconditionally) in the constructor, not here on demand, or + // otherwise we would create a cycle in the tree of accessible objects + // which could lead to infinite loops in AT tools. + // return mpImpl->CreateAccessible( *i_pWindow ); + return Reference<XAccessible>(); +} + +// --------------------------------------------------------------------------------------------------------------------- +Reference< XDrawSubController > ToolPanelViewShell::CreateSubController() +{ + // This view shell is not designed to be the main view shell and thus + // does not support a UNO sub controller. + return Reference< XDrawSubController >(); +} + +// --------------------------------------------------------------------------------------------------------------------- +bool ToolPanelViewShell::RelocateToParentWindow( ::Window* pParentWindow ) +{ + ::Window* pOldParentWindow = GetParentWindow(); + FocusManager::Instance().RemoveLinks( pOldParentWindow, &mpImpl->GetTaskPane() ); + FocusManager::Instance().RemoveLinks( &mpImpl->GetTaskPane(), pOldParentWindow ); + + PaneDockingWindow* pDockingWindow = dynamic_cast< PaneDockingWindow* >( GetDockingWindow() ); + if ( pDockingWindow != NULL ) + { + pDockingWindow->SetEndDockingHdl( Link() ); + } + + ViewShell::RelocateToParentWindow(pParentWindow); + + mpImpl->ConnectToDockingWindow(); + + Resize(); + + return true; +} + +//--------------------------------------------------------------------------------------------------------------------- +bool ToolPanelViewShell::IsPanelAnchorWindow( const ::Window& i_rWindow ) const +{ + return &mpImpl->GetToolPanelDeck().GetPanelWindowAnchor() == &i_rWindow; +} + +//--------------------------------------------------------------------------------------------------------------------- +namespace +{ + typedef std::auto_ptr< ControlFactory > (*ControlFactoryFactory)( ToolPanelViewShell& i_rToolPanelShell ); + + struct PanelFactory + { + ControlFactoryFactory pFactory; + ULONG nHelpID; + PanelFactory( const ControlFactoryFactory i_pFactory, const ULONG i_nHelpID ) + :pFactory( i_pFactory ) + ,nHelpID( i_nHelpID ) + { + } + }; + + const PanelFactory lcl_describePanel( const PanelId i_ePanelId ) + { + switch ( i_ePanelId ) + { + case PID_MASTER_PAGES: + return PanelFactory( &controls::MasterPagesPanel::CreateControlFactory, HID_SD_SLIDE_DESIGNS ); + case PID_LAYOUT: + return PanelFactory( &LayoutMenu::CreateControlFactory, HID_SD_SLIDE_LAYOUTS ); + case PID_TABLE_DESIGN: + return PanelFactory( &controls::TableDesignPanel::CreateControlFactory, HID_SD_TABLE_DESIGN ); + case PID_CUSTOM_ANIMATION: + return PanelFactory( &controls::CustomAnimationPanel::CreateControlFactory, HID_SD_CUSTOM_ANIMATIONS ); + case PID_SLIDE_TRANSITION: + return PanelFactory( &controls::SlideTransitionPanel::CreateControlFactory, HID_SD_SLIDE_TRANSITIONS ); + default: + break; + } + throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal panel ID" ) ), NULL ); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +Reference< XUIElement > ToolPanelViewShell::CreatePanelUIElement( const Reference< XFrame >& i_rDocFrame, const ::rtl::OUString& i_rPanelResourceURL ) +{ + const PanelId ePanelId( GetStandardPanelId( i_rPanelResourceURL ) ); + ENSURE_OR_RETURN( ePanelId != PID_UNKNOWN, "ToolPanelViewShell::CreatePanelUIElement: illegal panel URL!", NULL ); + + // a TreeNode which will resemble the panel + const PanelFactory aPanelFactory( lcl_describePanel( ePanelId ) ); + ::std::auto_ptr< ControlFactory > pControlFactory( (*aPanelFactory.pFactory)( *this ) ); + ::std::auto_ptr< TreeNode > pNode( pControlFactory->CreateControl( mpImpl->GetToolPanelDeck().GetPanelWindowAnchor() ) ); + ENSURE_OR_THROW( ( pNode.get() != NULL ) && ( pNode->GetWindow() != NULL ), + "illegal node returned by the control factory" ); + pNode->GetWindow()->SetHelpId( aPanelFactory.nHelpID ); + + // create an XToolPanel + Reference< XToolPanel > xPanel( new ToolPanel( pNode ) ); + + // create an XUIElement providing this panel + const Reference< XUIElement > xUIElement( new ToolPanelUIElement( i_rDocFrame, i_rPanelResourceURL, xPanel ) ); + + return xUIElement; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::ActivatePanel( const ::rtl::OUString& i_rPanelResourceURL ) +{ + OSL_ENSURE( i_rPanelResourceURL.indexOf( FrameworkHelper::msTaskPanelURLPrefix ) < 0, + "ToolPanelViewShell::ActivatePanel: for drawing-framework-controller panels, please use FrameworkHelper::RequestTaskPanel!" ); + mpImpl->ActivatePanelByResource( i_rPanelResourceURL ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell::DeactivatePanel( const ::rtl::OUString& i_rPanelResourceURL ) +{ + mpImpl->DeactivatePanelByResource( i_rPanelResourceURL ); +} + +// ===================================================================================================================== +// = ToolPanelViewShell_Impl - implementation +// ===================================================================================================================== +// --------------------------------------------------------------------------------------------------------------------- +ToolPanelViewShell_Impl::ToolPanelViewShell_Impl( ToolPanelViewShell& i_rPanelViewShell, ::Window& i_rPanelDeckParent ) + :m_rPanelViewShell( i_rPanelViewShell ) + ,m_pTaskPane( new ::sfx2::ModuleTaskPane( i_rPanelDeckParent, i_rPanelViewShell.GetViewShellBase().GetViewFrame()->GetFrame().GetFrameInterface(), *this ) ) + ,m_bInitialized( false ) +{ + const String sPaneTitle( SdResId( STR_RIGHT_PANE_TITLE ) ); + GetToolPanelDeck().SetAccessibleName( sPaneTitle ); + GetToolPanelDeck().SetAccessibleDescription( sPaneTitle ); + + GetToolPanelDeck().AddListener( *this ); +} + +// --------------------------------------------------------------------------------------------------------------------- +ToolPanelViewShell_Impl::~ToolPanelViewShell_Impl() +{ +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition ) +{ + // not interested in + (void)i_pPanel; + (void)i_nPosition; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::PanelRemoved( const size_t i_nPosition ) +{ + // not interested in + (void)i_nPosition; +} + +// --------------------------------------------------------------------------------------------------------------------- +::rtl::OUString ToolPanelViewShell_Impl::impl_getPanelURL( const ::boost::optional< size_t >& i_rPanel ) +{ + ::rtl::OUString sPanelURL; + if ( !!i_rPanel ) + { + sPanelURL = GetTaskPane().GetPanelResourceURL( *i_rPanel ); + const PanelId ePanelId( GetStandardPanelId( sPanelURL, true ) ); + if ( ePanelId == PID_UNKNOWN ) + sPanelURL = ::rtl::OUString(); + } + return sPanelURL; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive ) +{ + // update the configuration controller, since this change in the active panel might have been triggered by means other + // than the drawing framework, so it does not yet know about it. + + const ::rtl::OUString sOldPanelURL( impl_getPanelURL( i_rOldActive ) ); + const ::rtl::OUString sNewPanelURL( impl_getPanelURL( i_rNewActive ) ); + + const ::boost::shared_ptr< FrameworkHelper > pFrameworkHelper( FrameworkHelper::Instance( GetAntiImpl().GetViewShellBase() ) ); + if ( sNewPanelURL.getLength() ) + { + // activate the resource belonging to the new panel. This will automatically de-activate the previously active + // panel resource (since ResourceActivationMode_REPLACE is used) + pFrameworkHelper->RequestTaskPanel( sNewPanelURL ); + } + else if ( sOldPanelURL.getLength() ) + { + // there is no new active panel, or it is not one of our standard panels, i.e. it is not covered by the + // resource framework. => Deactivate the old resource. + try + { + Reference< XConfigurationController > xConfigController( pFrameworkHelper->GetConfigurationController(), UNO_QUERY_THROW ); + xConfigController->requestResourceDeactivation( + pFrameworkHelper->CreateResourceId( + sOldPanelURL, + FrameworkHelper::msTaskPaneURL, + FrameworkHelper::msRightPaneURL + ) + ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter ) +{ + // not interested in + (void)i_rNewLayouter; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::Dying() +{ + // not interested in +} + +// --------------------------------------------------------------------------------------------------------------------- +short ToolPanelViewShell_Impl::compareToolPanelsURLs( const ::rtl::OUString& i_rLHS, const ::rtl::OUString& i_rRHS ) const +{ + const PanelId eLHS( GetStandardPanelId( i_rLHS, true ) ); + const PanelId eRHS( GetStandardPanelId( i_rRHS, true ) ); + if ( eLHS < eRHS ) + return -1; + if ( eLHS == eRHS ) + return 0; + return 1; +} + +// --------------------------------------------------------------------------------------------------------------------- +void ToolPanelViewShell_Impl::ConnectToDockingWindow() +{ + m_pTaskPaneController.reset(); + DockingWindow* pDockingWindow( GetAntiImpl().GetDockingWindow() ); + if ( pDockingWindow ) + { + PaneDockingWindow* pPaneDockingWindow = dynamic_cast< PaneDockingWindow* >( pDockingWindow ); + OSL_ENSURE( pPaneDockingWindow, "ToolPanelViewShell_Impl::ConnectToDockingWindow: unsupported docking window type!" ); + if ( pPaneDockingWindow != NULL ) + m_pTaskPaneController.reset( new ::sfx2::TaskPaneController( GetTaskPane(), *pPaneDockingWindow ) ); + } + + // Tell the focus manager that we want to pass the focus to our + // child. + FocusManager::Instance().RegisterDownLink( GetAntiImpl().GetParentWindow(), &GetTaskPane() ); +} + +// --------------------------------------------------------------------------------------------------------------------- +Reference< XAccessible > ToolPanelViewShell_Impl::CreateAccessible( ::sd::Window& i_rWindow ) +{ + Reference< XAccessible > xAccessible( GetToolPanelDeck().GetAccessible( FALSE ) ); + if ( !xAccessible.is() ) + { + // determine the XAccessible which is the parent of the to-be-created object + ::Window* pAccessibleParent = i_rWindow.GetAccessibleParentWindow(); + OSL_ENSURE( pAccessibleParent, "ToolPanelViewShell_Impl::CreateAccessible: illegal accessible parent provided by the sd::Window!" ); + GetToolPanelDeck().SetAccessibleParentWindow( pAccessibleParent ); + + xAccessible = GetToolPanelDeck().GetAccessible( TRUE ); + ENSURE_OR_RETURN( xAccessible.is(), "ToolPanelViewShell_Impl::CreateAccessible: illegal ToolPanelDeck accessible!", NULL ); + OSL_ENSURE( xAccessible->getAccessibleContext().is() + && xAccessible->getAccessibleContext()->getAccessibleParent() == pAccessibleParent->GetAccessible(), + "ToolPanelViewShell_Impl::CreateAccessible: illegal parenthood!" ); + } + return xAccessible; +} + +} } // end of namespace ::sd::toolpanel diff --git a/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.cxx b/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.cxx new file mode 100644 index 000000000000..86abd44e3a83 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.cxx @@ -0,0 +1,208 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "AllMasterPagesSelector.hxx" +#include "PreviewValueSet.hxx" +#include "app.hrc" +#include "MasterPageContainer.hxx" +#include "MasterPageDescriptor.hxx" +#include <tools/link.hxx> +#include <set> + +namespace { + +using namespace sd::toolpanel::controls; + +int GetURLPriority (const SharedMasterPageDescriptor& rpDescriptor) +{ + int nPriority (0); + switch (rpDescriptor->GetURLClassification()) + { + case MasterPageDescriptor::URLCLASS_USER: nPriority = 0; break; + case MasterPageDescriptor::URLCLASS_LAYOUT: nPriority = 1; break; + case MasterPageDescriptor::URLCLASS_PRESENTATION: nPriority = 2; break; + case MasterPageDescriptor::URLCLASS_OTHER: nPriority = 3; break; + case MasterPageDescriptor::URLCLASS_UNKNOWN: nPriority = 4; break; + default: + case MasterPageDescriptor::URLCLASS_UNDETERMINED: nPriority = 5; break; + } + return nPriority; +} + + +class MasterPageDescriptorOrder +{ +public: + bool operator() (const sd::toolpanel::controls::SharedMasterPageDescriptor& rp1, + const sd::toolpanel::controls::SharedMasterPageDescriptor& rp2) + { + if (rp1->meOrigin == MasterPageContainer::DEFAULT) + return true; + else if (rp2->meOrigin == MasterPageContainer::DEFAULT) + return false; + else if (rp1->GetURLClassification() == rp2->GetURLClassification()) + return rp1->mnTemplateIndex < rp2->mnTemplateIndex; + else + return GetURLPriority(rp1) < GetURLPriority(rp2); + } +}; + +} // end of anonymous namespace + + + +namespace sd { namespace toolpanel { namespace controls { + +class AllMasterPagesSelector::SortedMasterPageDescriptorList + : public ::std::set<SharedMasterPageDescriptor,MasterPageDescriptorOrder> +{ +public: + SortedMasterPageDescriptorList (void) {} +}; + + + + +AllMasterPagesSelector::AllMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + DrawViewShell& rViewShell, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer) + : MasterPagesSelector(pParent, rDocument, rBase, rpContainer), + mrViewShell(rViewShell), + mpSortedMasterPages(new SortedMasterPageDescriptorList()) +{ + SetName (String(RTL_CONSTASCII_USTRINGPARAM("AllMasterPagesSelector"))); + MasterPagesSelector::Fill(); +} + + + + +AllMasterPagesSelector::~AllMasterPagesSelector (void) +{ +} + + + + +void AllMasterPagesSelector::Fill (ItemList& rItemList) +{ + if (mpSortedMasterPages->empty()) + UpdateMasterPageList(); + UpdatePageSet(rItemList); +} + + + + +void AllMasterPagesSelector::NotifyContainerChangeEvent ( + const MasterPageContainerChangeEvent& rEvent) +{ + switch (rEvent.meEventType) + { + case MasterPageContainerChangeEvent::CHILD_ADDED: + AddItem(rEvent.maChildToken); + MasterPagesSelector::Fill(); + break; + + case MasterPageContainerChangeEvent::INDEX_CHANGED: + case MasterPageContainerChangeEvent::INDEXES_CHANGED: + mpSortedMasterPages->clear(); + MasterPagesSelector::Fill(); + break; + + default: + MasterPagesSelector::NotifyContainerChangeEvent(rEvent); + break; + } +} + + + + +void AllMasterPagesSelector::UpdateMasterPageList (void) +{ + mpSortedMasterPages->clear(); + int nTokenCount = mpContainer->GetTokenCount(); + for (int i=0; i<nTokenCount; i++) + AddItem(mpContainer->GetTokenForIndex(i)); +} + + + + +void AllMasterPagesSelector::AddItem (MasterPageContainer::Token aToken) +{ + switch (mpContainer->GetOriginForToken(aToken)) + { + case MasterPageContainer::DEFAULT: + case MasterPageContainer::TEMPLATE: + // Templates are added only when coming from the + // MasterPageContainerFiller so that they have an id which + // defines their place in the list. Templates (pre) loaded from + // RecentlyUsedMasterPages are ignored (they will be loaded + // later by the MasterPageContainerFiller.) + if (mpContainer->GetTemplateIndexForToken(aToken) >= 0) + mpSortedMasterPages->insert(mpContainer->GetDescriptorForToken(aToken)); + break; + + default: + break; + } +} + + + + +void AllMasterPagesSelector::UpdatePageSet (ItemList& rItemList) +{ + SortedMasterPageDescriptorList::const_iterator iDescriptor; + SortedMasterPageDescriptorList::const_iterator iEnd (mpSortedMasterPages->end()); + for (iDescriptor=mpSortedMasterPages->begin(); iDescriptor!=iEnd; ++iDescriptor) + rItemList.push_back((*iDescriptor)->maToken); +} + + + + +void AllMasterPagesSelector::GetState (SfxItemSet& rItemSet) +{ + MasterPagesSelector::GetState(rItemSet); + + if (rItemSet.GetItemState(SID_TP_EDIT_MASTER) == SFX_ITEM_AVAILABLE) + rItemSet.DisableItem(SID_TP_EDIT_MASTER); +} + + + + +} } } // end of namespace ::sd::toolpanel::control diff --git a/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.hxx b/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.hxx new file mode 100644 index 000000000000..e937958dbbf0 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/AllMasterPagesSelector.hxx @@ -0,0 +1,94 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_ALL_MASTER_PAGES_SELECTOR_HXX +#define SD_TOOLPANEL_CONTROLS_ALL_MASTER_PAGES_SELECTOR_HXX + +#include "MasterPagesSelector.hxx" + +#include <memory> + +namespace sd { namespace toolpanel { namespace controls { + + +/** Show a list of all available master pages so that the user can assign + them to the document. +*/ +class AllMasterPagesSelector + : public MasterPagesSelector +{ +public: + AllMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + DrawViewShell& rViewShell, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer); + virtual ~AllMasterPagesSelector (void); + + /** Scan the set of templates for the ones whose first master pages are + shown by this control and store them in the MasterPageContainer. + */ + virtual void Fill (ItemList& rItemList); + + virtual void GetState (SfxItemSet& rItemSet); + +protected: + virtual void NotifyContainerChangeEvent (const MasterPageContainerChangeEvent& rEvent); + +private: + DrawViewShell& mrViewShell; + + /** The list of master pages displayed by this class. + */ + class SortedMasterPageDescriptorList; + ::std::auto_ptr<SortedMasterPageDescriptorList> mpSortedMasterPages; + + void AddTemplate (const TemplateEntry& rEntry); + + /** This filter returns <TRUE/> when the master page specified by the + given file name belongs to the set of Impress master pages. + */ + bool FileFilter (const String& sFileName); + + void AddItem (MasterPageContainer::Token aToken); + + /** Add all items in the internal master page list into the given list. + */ + void UpdatePageSet (ItemList& rItemList); + + /** Update the internal list of master pages that are to show in the + control. + */ + void UpdateMasterPageList (void); + + using sd::toolpanel::controls::MasterPagesSelector::Fill; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.cxx b/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.cxx new file mode 100755 index 000000000000..730fc74795f2 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.cxx @@ -0,0 +1,170 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +/************************************************************************* + * + * 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: AnimationSchemesPanel.cxx,v $ + * $Revision: 1.6 $ + * + * 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_sd.hxx" +#include "AnimationSchemesPanel.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" +#include <com/sun/star/frame/XModel.hpp> + +namespace sd +{ + + class ViewShellBase; + extern ::Window * createAnimationSchemesPanel( ::Window* pParent, ViewShellBase& rBase ); + +namespace toolpanel { namespace controls { + + +AnimationSchemesPanel::AnimationSchemesPanel(TreeNode* pParent, ViewShellBase& rBase) + : SubToolPanel (pParent), + maPreferredSize( 100, 200 ) +{ + mpWrappedControl = createAnimationSchemesPanel( pParent->GetWindow(), rBase ); + mpWrappedControl->Show(); +} + +AnimationSchemesPanel::~AnimationSchemesPanel() +{ + delete mpWrappedControl; +} + +Size AnimationSchemesPanel::GetPreferredSize() +{ + return maPreferredSize; +} +sal_Int32 AnimationSchemesPanel::GetPreferredWidth(sal_Int32 ) +{ + return maPreferredSize.Width(); +} +sal_Int32 AnimationSchemesPanel::GetPreferredHeight(sal_Int32 ) +{ + return maPreferredSize.Height(); +} +::Window* AnimationSchemesPanel::GetWindow() +{ + return mpWrappedControl; +} +bool AnimationSchemesPanel::IsResizable() +{ + return true; +} +bool AnimationSchemesPanel::IsExpandable() const +{ + return true; +} + + +} } } // end of namespace ::sd::toolpanel::controls +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include "AnimationSchemesPanel.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" +#include <com/sun/star/frame/XModel.hpp> + +namespace sd +{ + + class ViewShellBase; + extern ::Window * createAnimationSchemesPanel( ::Window* pParent, ViewShellBase& rBase ); + +namespace toolpanel { namespace controls { + + +AnimationSchemesPanel::AnimationSchemesPanel(TreeNode* pParent, ViewShellBase& rBase) + : SubToolPanel (pParent), + maPreferredSize( 100, 200 ) +{ + mpWrappedControl = createAnimationSchemesPanel( pParent->GetWindow(), rBase ); + mpWrappedControl->Show(); +} + +AnimationSchemesPanel::~AnimationSchemesPanel() +{ + delete mpWrappedControl; +} + +Size AnimationSchemesPanel::GetPreferredSize() +{ + return maPreferredSize; +} +sal_Int32 AnimationSchemesPanel::GetPreferredWidth(sal_Int32 ) +{ + return maPreferredSize.Width(); +} +sal_Int32 AnimationSchemesPanel::GetPreferredHeight(sal_Int32 ) +{ + return maPreferredSize.Height(); +} +::Window* AnimationSchemesPanel::GetWindow() +{ + return mpWrappedControl; +} +bool AnimationSchemesPanel::IsResizable() +{ + return true; +} +bool AnimationSchemesPanel::IsExpandable() const +{ + return true; +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.hxx b/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.hxx new file mode 100755 index 000000000000..dd3388fb0342 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/AnimationSchemesPanel.hxx @@ -0,0 +1,138 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ +/************************************************************************* + * + * 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: AnimationSchemesPanel.hxx,v $ + * $Revision: 1.6 $ + * + * 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 SD_TASKPANE_CONTROLS_ANIMATION_SCHEMES_PANEL_HXX +#define SD_TASKPANE_CONTROLS_ANIMATION_SCHEMES_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class TreeNode; +} } + +namespace sd { namespace toolpanel { namespace controls { + +class AnimationSchemesPanel + : public SubToolPanel +{ +public: + AnimationSchemesPanel ( + TreeNode* pParent, + ViewShellBase& rBase); + virtual ~AnimationSchemesPanel (void); + + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeigh); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual ::Window* GetWindow (void); + virtual bool IsResizable (void); + virtual bool IsExpandable (void) const; + + using Window::GetWindow; + +private: + Size maPreferredSize; + ::Window* mpWrappedControl; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif +#ifndef SD_TASKPANE_CONTROLS_ANIMATION_SCHEMES_PANEL_HXX +#define SD_TASKPANE_CONTROLS_ANIMATION_SCHEMES_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class TreeNode; +} } + +namespace sd { namespace toolpanel { namespace controls { + +class AnimationSchemesPanel + : public SubToolPanel +{ +public: + AnimationSchemesPanel ( + TreeNode* pParent, + ViewShellBase& rBase); + virtual ~AnimationSchemesPanel (void); + + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeigh); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual ::Window* GetWindow (void); + virtual bool IsResizable (void); + virtual bool IsExpandable (void) const; + + using Window::GetWindow; + +private: + Size maPreferredSize; + ::Window* mpWrappedControl; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.cxx b/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.cxx new file mode 100644 index 000000000000..7f4149d7e6fd --- /dev/null +++ b/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.cxx @@ -0,0 +1,343 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "CurrentMasterPagesSelector.hxx" +#include "PreviewValueSet.hxx" +#include "ViewShellBase.hxx" +#include "DrawViewShell.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "MasterPageContainer.hxx" +#include "MasterPageDescriptor.hxx" +#include "EventMultiplexer.hxx" +#include "app.hrc" +#include "DrawDocShell.hxx" +#include "DrawViewShell.hxx" +#include "res_bmp.hrc" +#include "sdresid.hxx" + +#include <vcl/image.hxx> +#include <svx/svdmodel.hxx> +#include <sfx2/request.hxx> + +#include <set> + + +using namespace ::com::sun::star; + +namespace sd { namespace toolpanel { namespace controls { + + +CurrentMasterPagesSelector::CurrentMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer) + : MasterPagesSelector (pParent, rDocument, rBase, rpContainer) +{ + SetName(String(RTL_CONSTASCII_USTRINGPARAM("CurrentMasterPagesSelector"))); + + // For this master page selector only we change the default action for + // left clicks. + mnDefaultClickAction = SID_TP_APPLY_TO_SELECTED_SLIDES; + + Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener)); + rBase.GetEventMultiplexer()->AddEventListener(aLink, + sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE + | sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL + | sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER + | sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER + | sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED + | sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED + | sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED); +} + + + + +CurrentMasterPagesSelector::~CurrentMasterPagesSelector (void) +{ + if (mrDocument.GetDocSh() != NULL) + { + EndListening(*mrDocument.GetDocSh()); + } + else + { + OSL_ASSERT(mrDocument.GetDocSh() != NULL); + } + + Link aLink (LINK(this,CurrentMasterPagesSelector,EventMultiplexerListener)); + mrBase.GetEventMultiplexer()->RemoveEventListener(aLink); +} + + + + +void CurrentMasterPagesSelector::LateInit (void) +{ + MasterPagesSelector::LateInit(); + MasterPagesSelector::Fill(); + if (mrDocument.GetDocSh() != NULL) + { + StartListening(*mrDocument.GetDocSh()); + } + else + { + OSL_ASSERT(mrDocument.GetDocSh() != NULL); + } +} + + + + +void CurrentMasterPagesSelector::Fill (ItemList& rItemList) +{ + USHORT nPageCount = mrDocument.GetMasterSdPageCount(PK_STANDARD); + SdPage* pMasterPage; + // Remember the names of the master pages that have been inserted to + // avoid double insertion. + ::std::set<String> aMasterPageNames; + for (USHORT nIndex=0; nIndex<nPageCount; nIndex++) + { + pMasterPage = mrDocument.GetMasterSdPage (nIndex, PK_STANDARD); + if (pMasterPage == NULL) + continue; + + // Use the name of the master page to avoid duplicate entries. + String sName (pMasterPage->GetName()); + if (aMasterPageNames.find(sName)!=aMasterPageNames.end()) + continue; + aMasterPageNames.insert (sName); + + // Look up the master page in the container and, when it is not yet + // in it, insert it. + MasterPageContainer::Token aToken = mpContainer->GetTokenForPageObject(pMasterPage); + if (aToken == MasterPageContainer::NIL_TOKEN) + { + SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( + MasterPageContainer::MASTERPAGE, + nIndex, + String(), + pMasterPage->GetName(), + String(), + pMasterPage->IsPrecious(), + ::boost::shared_ptr<PageObjectProvider>(new ExistingPageProvider(pMasterPage)), + ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider()))); + aToken = mpContainer->PutMasterPage(pDescriptor); + } + + rItemList.push_back(aToken); + } +} + + + + +ResId CurrentMasterPagesSelector::GetContextMenuResId (void) const +{ + return SdResId(RID_TASKPANE_CURRENT_MASTERPAGESSELECTOR_POPUP); +} + + + + +void CurrentMasterPagesSelector::UpdateSelection (void) +{ + // Iterate over all pages and for the selected ones put the name of + // their master page into a set. + USHORT nPageCount = mrDocument.GetSdPageCount(PK_STANDARD); + SdPage* pPage; + ::std::set<String> aNames; + USHORT nIndex; + bool bLoop (true); + for (nIndex=0; nIndex<nPageCount && bLoop; nIndex++) + { + pPage = mrDocument.GetSdPage (nIndex, PK_STANDARD); + if (pPage != NULL && pPage->IsSelected()) + { + if ( ! pPage->TRG_HasMasterPage()) + { + // One of the pages has no master page. This is an + // indicator for that this method is called in the middle of + // a document change and that the model is not in a valid + // state. Therefore we stop update the selection and wait + // for another call to UpdateSelection when the model is + // valid again. + bLoop = false; + } + else + { + SdrPage& rMasterPage (pPage->TRG_GetMasterPage()); + SdPage* pMasterPage = static_cast<SdPage*>(&rMasterPage); + if (pMasterPage != NULL) + aNames.insert (pMasterPage->GetName()); + } + } + } + + // Find the items for the master pages in the set. + USHORT nItemCount (mpPageSet->GetItemCount()); + for (nIndex=1; nIndex<=nItemCount && bLoop; nIndex++) + { + String sName (mpPageSet->GetItemText (nIndex)); + if (aNames.find(sName) != aNames.end()) + { + mpPageSet->SelectItem (nIndex); + } + } +} + + + + +void CurrentMasterPagesSelector::Execute (SfxRequest& rRequest) +{ + switch (rRequest.GetSlot()) + { + case SID_DELETE_MASTER_PAGE: + { + // Check once again that the master page can safely be deleted, + // i.e. is not used. + SdPage* pMasterPage = GetSelectedMasterPage(); + if (pMasterPage != NULL + && mrDocument.GetMasterPageUserCount(pMasterPage) > 0) + { + // Removing the precious flag so that the following call to + // RemoveUnnessesaryMasterPages() will remove this master page. + pMasterPage->SetPrecious(false); + mrDocument.RemoveUnnecessaryMasterPages(pMasterPage, FALSE, TRUE); + } + } + break; + + default: + MasterPagesSelector::Execute(rRequest); + break; + } +} + + + + +void CurrentMasterPagesSelector::GetState (SfxItemSet& rItemSet) +{ + // Disable the SID_DELTE_MASTER slot when there is only one master page. + if (rItemSet.GetItemState(SID_DELETE_MASTER_PAGE) == SFX_ITEM_AVAILABLE + && mrDocument.GetMasterPageUserCount(GetSelectedMasterPage()) > 0) + { + rItemSet.DisableItem(SID_DELETE_MASTER_PAGE); + } + + ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( + ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell())); + if (rItemSet.GetItemState(SID_TP_EDIT_MASTER) == SFX_ITEM_AVAILABLE + && pDrawViewShell + && pDrawViewShell->GetEditMode() == EM_MASTERPAGE) + { + rItemSet.DisableItem (SID_TP_EDIT_MASTER); + } + + MasterPagesSelector::GetState(rItemSet); +} + + + + + + +IMPL_LINK(CurrentMasterPagesSelector,EventMultiplexerListener, + sd::tools::EventMultiplexerEvent*,pEvent) +{ + if (pEvent != NULL) + { + switch (pEvent->meEventId) + { + case sd::tools::EventMultiplexerEvent::EID_CURRENT_PAGE: + case sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_NORMAL: + case sd::tools::EventMultiplexerEvent::EID_EDIT_MODE_MASTER: + case sd::tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION: + UpdateSelection(); + break; + + case sd::tools::EventMultiplexerEvent::EID_PAGE_ORDER: + // This is tricky. If a master page is removed, moved, or + // added we have to wait until both the notes master page + // and the standard master page have been removed, moved, + // or added. We do this by looking at the number of master + // pages which has to be odd in the consistent state (the + // handout master page is always present). If the number is + // even we ignore the hint. + if (mrBase.GetDocument()->GetMasterPageCount()%2 == 1) + MasterPagesSelector::Fill(); + break; + + case sd::tools::EventMultiplexerEvent::EID_SHAPE_CHANGED: + case sd::tools::EventMultiplexerEvent::EID_SHAPE_INSERTED: + case sd::tools::EventMultiplexerEvent::EID_SHAPE_REMOVED: + InvalidatePreview((const SdPage*)pEvent->mpUserData); + break; + } + } + + return 0; +} + + + + +void CurrentMasterPagesSelector::Notify (SfxBroadcaster&, const SfxHint& rHint) +{ + const SfxSimpleHint* pSimpleHint = dynamic_cast<const SfxSimpleHint*>(&rHint); + if (pSimpleHint != NULL) + { + if (pSimpleHint->GetId() == SFX_HINT_DOCCHANGED) + { + // Is the edit view visible in the center pane? + ::boost::shared_ptr<DrawViewShell> pDrawViewShell ( + ::boost::dynamic_pointer_cast<DrawViewShell>(mrBase.GetMainViewShell())); + if (pDrawViewShell.get() != NULL) + { + // Is the edit view in master page mode? + if (pDrawViewShell->GetEditMode() == EM_MASTERPAGE) + { + // Mark the currently edited master page as precious. + SdPage* pCurrentMasterPage = pDrawViewShell->getCurrentPage(); + if (pCurrentMasterPage != NULL) + pCurrentMasterPage->SetPrecious(true); + } + } + } + } +} + + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.hxx b/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.hxx new file mode 100644 index 000000000000..ee3503d9787d --- /dev/null +++ b/sd/source/ui/toolpanel/controls/CurrentMasterPagesSelector.hxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_CURRENT_MASTER_PAGES_SELECTOR_HXX +#define SD_TOOLPANEL_CONTROLS_CURRENT_MASTER_PAGES_SELECTOR_HXX + +#include "MasterPagesSelector.hxx" +#include <com/sun/star/lang/XComponent.hpp> + +namespace sd { namespace tools { class EventMultiplexerEvent; } } + + +namespace sd { namespace toolpanel { namespace controls { + + +/** Show the master pages currently used by a SdDrawDocument. +*/ +class CurrentMasterPagesSelector + : public MasterPagesSelector, + public SfxListener +{ +public: + CurrentMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer); + virtual ~CurrentMasterPagesSelector (void); + + virtual void LateInit (void); + + /** Set the selection so that the master page is selected that is + used by the currently selected page of the document in the + center pane. + */ + virtual void UpdateSelection (void); + + /** Copy all master pages that are to be shown into the given list. + */ + virtual void Fill (ItemList& rItemList); + + using sd::toolpanel::controls::MasterPagesSelector::Fill; + +protected: + virtual ResId GetContextMenuResId (void) const; + virtual void Execute (SfxRequest& rRequest); + virtual void GetState (SfxItemSet& rItemSet); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> + mxListener; + + DECL_LINK(EventMultiplexerListener,sd::tools::EventMultiplexerEvent*); + void Notify (SfxBroadcaster&, const SfxHint& rHint); +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/CustomAnimationPanel.cxx b/sd/source/ui/toolpanel/controls/CustomAnimationPanel.cxx new file mode 100755 index 000000000000..e7edf109cffd --- /dev/null +++ b/sd/source/ui/toolpanel/controls/CustomAnimationPanel.cxx @@ -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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "CustomAnimationPanel.hxx" + +#include "taskpane/TaskPaneControlFactory.hxx" +#include "taskpane/ToolPanelViewShell.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" + +namespace sd +{ + + class ViewShellBase; + extern ::Window * createCustomAnimationPanel( ::Window* pParent, ViewShellBase& rBase ); + +namespace toolpanel { namespace controls { + + +CustomAnimationPanel::CustomAnimationPanel(Window& i_rParentWindow, ToolPanelViewShell& i_rPanelViewShell) + :SubToolPanel( i_rParentWindow ) + ,m_pPanelViewShell( &i_rPanelViewShell ) +{ + mpWrappedControl = createCustomAnimationPanel( &i_rParentWindow, i_rPanelViewShell.GetViewShellBase() ); + mpWrappedControl->Show(); +} + +CustomAnimationPanel::~CustomAnimationPanel() +{ + delete mpWrappedControl; +} + +std::auto_ptr< ControlFactory > CustomAnimationPanel::CreateControlFactory( ToolPanelViewShell& i_rToolPanelShell ) +{ + return std::auto_ptr< ControlFactory >( + new RootControlFactoryWithArg< CustomAnimationPanel, ToolPanelViewShell >( i_rToolPanelShell ) ); +} + +TaskPaneShellManager* CustomAnimationPanel::GetShellManager() +{ + if ( m_pPanelViewShell ) + return &m_pPanelViewShell->GetSubShellManager(); + return SubToolPanel::GetShellManager(); +} + +Size CustomAnimationPanel::GetPreferredSize() +{ + return maPreferredSize; +} +sal_Int32 CustomAnimationPanel::GetPreferredWidth(sal_Int32 ) +{ + return maPreferredSize.Width(); +} +sal_Int32 CustomAnimationPanel::GetPreferredHeight(sal_Int32 ) +{ + return maPreferredSize.Height(); +} +::Window* CustomAnimationPanel::GetWindow() +{ + return mpWrappedControl; +} +bool CustomAnimationPanel::IsResizable() +{ + return true; +} +bool CustomAnimationPanel::IsExpandable() const +{ + return true; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> CustomAnimationPanel::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + if (GetWindow() != NULL) + return GetWindow()->GetAccessible(); + else + return NULL; +} + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/CustomAnimationPanel.hxx b/sd/source/ui/toolpanel/controls/CustomAnimationPanel.hxx new file mode 100755 index 000000000000..864ba637b94d --- /dev/null +++ b/sd/source/ui/toolpanel/controls/CustomAnimationPanel.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_CUSTOM_ANIMATION_PANEL_HXX +#define SD_TOOLPANEL_CONTROLS_CUSTOM_ANIMATION_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class TreeNode; +class ControlFactory; +class ToolPanelViewShell; +} } + +namespace sd { namespace toolpanel { namespace controls { + +class CustomAnimationPanel + : public SubToolPanel +{ +public: + CustomAnimationPanel ( + Window& i_rParentWindow, + ToolPanelViewShell& i_rPanelViewShell); + virtual ~CustomAnimationPanel (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory (ToolPanelViewShell& i_rPanelViewShell); + + // TreeNode overridables + virtual TaskPaneShellManager* GetShellManager(); + + // ILayoutableWindow overridables + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeigh); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual ::Window* GetWindow (void); + virtual bool IsResizable (void); + virtual bool IsExpandable (void) const; + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& rxParent); + + using Window::GetWindow; +private: + Size maPreferredSize; + ::Window* mpWrappedControl; + ToolPanelViewShell* m_pPanelViewShell; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/DocumentHelper.cxx b/sd/source/ui/toolpanel/controls/DocumentHelper.cxx new file mode 100755 index 000000000000..c5919b7aa7ee --- /dev/null +++ b/sd/source/ui/toolpanel/controls/DocumentHelper.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "DocumentHelper.hxx" + +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "sdpage.hxx" +#include "glob.hxx" +#include "unmovss.hxx" +#include "strings.hrc" +#include "sdresid.hxx" +#include "undoback.hxx" +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include "stlpool.hxx" +#include <svx/xfillit0.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; + +namespace sd { namespace toolpanel { namespace controls { + +SdPage* DocumentHelper::CopyMasterPageToLocalDocument ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage) +{ + SdPage* pNewMasterPage = NULL; + + do + { + if (pMasterPage == NULL) + break; + + // Check the presence of the source document. + SdDrawDocument* pSourceDocument = static_cast<SdDrawDocument*>( + pMasterPage->GetModel()); + if (pSourceDocument == NULL) + break; + + // When the given master page already belongs to the target document + // then there is nothing more to do. + if (pSourceDocument == &rTargetDocument) + { + pNewMasterPage = pMasterPage; + break; + } + + // Test if the master pages of both the slide and its notes page are + // present. This is not the case when we are called during the + // creation of the slide master page because then the notes master + // page is not there. + USHORT nSourceMasterPageCount = pSourceDocument->GetMasterPageCount(); + if (nSourceMasterPageCount%2 == 0) + // There should be 1 handout page + n slide masters + n notes + // masters = 2*n+1. An even value indicates that a new slide + // master but not yet the notes master has been inserted. + break; + USHORT nIndex = pMasterPage->GetPageNum(); + if (nSourceMasterPageCount <= nIndex+1) + break; + // Get the slide master page. + if (pMasterPage != static_cast<SdPage*>( + pSourceDocument->GetMasterPage(nIndex))) + break; + // Get the notes master page. + SdPage* pNotesMasterPage = static_cast<SdPage*>( + pSourceDocument->GetMasterPage(nIndex+1)); + if (pNotesMasterPage == NULL) + break; + + + // Check if a master page with the same name as that of the given + // master page already exists. + bool bPageExists (false); + USHORT nMasterPageCount(rTargetDocument.GetMasterSdPageCount(PK_STANDARD)); + for (USHORT nMaster=0; nMaster<nMasterPageCount; nMaster++) + { + SdPage* pCandidate = static_cast<SdPage*>( + rTargetDocument.GetMasterSdPage (nMaster, PK_STANDARD)); + if (pMasterPage!=NULL + && pCandidate->GetName().CompareTo(pMasterPage->GetName())==0) + { + bPageExists = true; + pNewMasterPage = pCandidate; + break; + } + } + if (bPageExists) + break; + + // Create a new slide (and its notes page.) + uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier ( + rTargetDocument.getUnoModel(), uno::UNO_QUERY); + if ( ! xSlideSupplier.is()) + break; + uno::Reference<drawing::XDrawPages> xSlides ( + xSlideSupplier->getDrawPages(), uno::UNO_QUERY); + if ( ! xSlides.is()) + break; + xSlides->insertNewByIndex (xSlides->getCount()); + + // Set a layout. + SdPage* pSlide = rTargetDocument.GetSdPage( + rTargetDocument.GetSdPageCount(PK_STANDARD)-1, + PK_STANDARD); + if (pSlide == NULL) + break; + pSlide->SetAutoLayout(AUTOLAYOUT_TITLE, TRUE); + + // Create a copy of the master page and the associated notes + // master page and insert them into our document. + pNewMasterPage = AddMasterPage(rTargetDocument, pMasterPage); + if (pNewMasterPage==NULL) + break; + SdPage* pNewNotesMasterPage + = AddMasterPage(rTargetDocument, pNotesMasterPage); + if (pNewNotesMasterPage==NULL) + break; + + // Make the connection from the new slide to the master page + // (and do the same for the notes page.) + rTargetDocument.SetMasterPage ( + rTargetDocument.GetSdPageCount(PK_STANDARD)-1, + pNewMasterPage->GetName(), + &rTargetDocument, + FALSE, // Connect the new master page with the new slide but + // do not modify other (master) pages. + TRUE); + } + while (false); + + // We are not interested in any automatisms for our modified internal + // document. + rTargetDocument.SetChanged (sal_False); + + return pNewMasterPage; +} + + + + +SdPage* DocumentHelper::GetSlideForMasterPage (SdPage* pMasterPage) +{ + SdPage* pCandidate = NULL; + + SdDrawDocument* pDocument = NULL; + if (pMasterPage != NULL) + pDocument = dynamic_cast<SdDrawDocument*>(pMasterPage->GetModel()); + + // Iterate over all pages and check if it references the given master + // page. + if (pDocument!=NULL && pDocument->GetSdPageCount(PK_STANDARD) > 0) + { + // In most cases a new slide has just been inserted so start with + // the last page. + USHORT nPageIndex (pDocument->GetSdPageCount(PK_STANDARD)-1); + bool bFound (false); + while ( ! bFound) + { + pCandidate = pDocument->GetSdPage( + nPageIndex, + PK_STANDARD); + if (pCandidate != NULL) + { + if (static_cast<SdPage*>(&pCandidate->TRG_GetMasterPage()) + == pMasterPage) + { + bFound = true; + break; + } + } + + if (nPageIndex == 0) + break; + else + nPageIndex --; + } + + // If no page was found that refernced the given master page reset + // the pointer that is returned. + if ( ! bFound) + pCandidate = NULL; + } + + return pCandidate; +} + + + + +SdPage* DocumentHelper::AddMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage) +{ + SdPage* pClonedMasterPage = NULL; + + if (pMasterPage!=NULL) + { + try + { + // Duplicate the master page. + pClonedMasterPage = static_cast<SdPage*>(pMasterPage->Clone()); + + // Copy the necessary styles. + SdDrawDocument* pSourceDocument + = static_cast<SdDrawDocument*>(pMasterPage->GetModel()); + if (pSourceDocument != NULL) + ProvideStyles (*pSourceDocument, rTargetDocument, pClonedMasterPage); + + // Copy the precious flag. + pClonedMasterPage->SetPrecious(pMasterPage->IsPrecious()); + + // Now that the styles are available we can insert the cloned + // master page. + rTargetDocument.InsertMasterPage (pClonedMasterPage); + } + catch (uno::Exception& rException) + { + pClonedMasterPage = NULL; + DBG_UNHANDLED_EXCEPTION(); + } + catch (::std::exception rException) + { + pClonedMasterPage = NULL; + OSL_TRACE ("caught general exception"); + } + catch (...) + { + pClonedMasterPage = NULL; + OSL_TRACE ("caught general exception"); + } + } + + return pClonedMasterPage; +} + + + + +void DocumentHelper::ProvideStyles ( + SdDrawDocument& rSourceDocument, + SdDrawDocument& rTargetDocument, + SdPage* pPage) +{ + // Get the layout name of the given page. + String sLayoutName (pPage->GetLayoutName()); + sLayoutName.Erase (sLayoutName.SearchAscii (SD_LT_SEPARATOR)); + + // Copy the style sheet from source to target document. + SdStyleSheetPool* pSourceStyleSheetPool = + static_cast<SdStyleSheetPool*>(rSourceDocument.GetStyleSheetPool()); + SdStyleSheetPool* pTargetStyleSheetPool = + static_cast<SdStyleSheetPool*>(rTargetDocument.GetStyleSheetPool()); + SdStyleSheetVector aCreatedStyles; + pTargetStyleSheetPool->CopyLayoutSheets ( + sLayoutName, + *pSourceStyleSheetPool, + aCreatedStyles); + + // Add an undo action for the copied style sheets. + if( !aCreatedStyles.empty() ) + { + SfxUndoManager* pUndoManager = rTargetDocument.GetDocSh()->GetUndoManager(); + if (pUndoManager != NULL) + { + SdMoveStyleSheetsUndoAction* pMovStyles = + new SdMoveStyleSheetsUndoAction ( + &rTargetDocument, + aCreatedStyles, + TRUE); + pUndoManager->AddUndoAction (pMovStyles); + } + } +} + + + + +void DocumentHelper::AssignMasterPageToPageList ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList) +{ + do + { + if (pMasterPage == NULL && pMasterPage->IsMasterPage()) + break; + + // Make the layout name by stripping ouf the layout postfix from the + // layout name of the given master page. + String sFullLayoutName (pMasterPage->GetLayoutName()); + String sBaseLayoutName (sFullLayoutName); + sBaseLayoutName.Erase (sBaseLayoutName.SearchAscii (SD_LT_SEPARATOR)); + + if (rpPageList->empty()) + break; + + // Create a second list that contains only the valid pointers to + // pages for which an assignment is necessary. + ::std::vector<SdPage*>::const_iterator iPage; + ::std::vector<SdPage*> aCleanedList; + for (iPage=rpPageList->begin(); iPage!=rpPageList->end(); ++iPage) + { + OSL_ASSERT(*iPage!=NULL && (*iPage)->GetModel() == &rTargetDocument); + if (*iPage != NULL + && (*iPage)->GetLayoutName().CompareTo(sFullLayoutName)!=0) + { + aCleanedList.push_back(*iPage); + } + } + if (aCleanedList.size() == 0) + break; + + SfxUndoManager* pUndoMgr = rTargetDocument.GetDocSh()->GetUndoManager(); + if( pUndoMgr ) + pUndoMgr->EnterListAction(String(SdResId(STR_UNDO_SET_PRESLAYOUT)), String()); + + SdPage* pMasterPageInDocument = ProvideMasterPage(rTargetDocument,pMasterPage,rpPageList); + if (pMasterPageInDocument == NULL) + break; + + // Assign the master pages to the given list of pages. + for (iPage=aCleanedList.begin(); + iPage!=aCleanedList.end(); + ++iPage) + { + AssignMasterPageToPage ( + pMasterPageInDocument, + sBaseLayoutName, + *iPage); + } + + if( pUndoMgr ) + pUndoMgr->LeaveListAction(); + } + while (false); +} + + + + +SdPage* DocumentHelper::AddMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + USHORT nInsertionIndex) +{ + SdPage* pClonedMasterPage = NULL; + + if (pMasterPage!=NULL) + { + // Duplicate the master page. + pClonedMasterPage = static_cast<SdPage*>(pMasterPage->Clone()); + + // Copy the precious flag. + pClonedMasterPage->SetPrecious(pMasterPage->IsPrecious()); + + // Copy the necessary styles. + SdDrawDocument* pSourceDocument + = static_cast<SdDrawDocument*>(pMasterPage->GetModel()); + if (pSourceDocument != NULL) + { + ProvideStyles (*pSourceDocument, rTargetDocument, pClonedMasterPage); + + // Now that the styles are available we can insert the cloned + // master page. + rTargetDocument.InsertMasterPage (pClonedMasterPage, nInsertionIndex); + + // Adapt the size of the new master page to that of the pages in + // the document. + Size aNewSize (rTargetDocument.GetSdPage(0, pMasterPage->GetPageKind())->GetSize()); + Rectangle aBorders ( + pClonedMasterPage->GetLftBorder(), + pClonedMasterPage->GetUppBorder(), + pClonedMasterPage->GetRgtBorder(), + pClonedMasterPage->GetLwrBorder()); + pClonedMasterPage->ScaleObjects(aNewSize, aBorders, TRUE); + pClonedMasterPage->SetSize(aNewSize); + pClonedMasterPage->CreateTitleAndLayout(TRUE); + } + } + + return pClonedMasterPage; +} + + + + +/** In here we have to handle three cases: + 1. pPage is a normal slide. We can use SetMasterPage to assign the + master pages to it. + 2. pPage is a master page that is used by at least one slide. We can + assign the master page to these slides. + 3. pPage is a master page that is currently not used by any slide. + We can delete that page and add copies of the given master pages + instead. + + For points 2 and 3 where one master page A is assigned to another B we have + to keep in mind that the master page that page A has already been + inserted into the target document. +*/ +void DocumentHelper::AssignMasterPageToPage ( + SdPage* pMasterPage, + const String& rsBaseLayoutName, + SdPage* pPage) +{ + // Leave early when the parameters are invalid. + if (pPage == NULL || pMasterPage == NULL) + return; + SdDrawDocument* pDocument = dynamic_cast<SdDrawDocument*>(pPage->GetModel()); + if (pDocument == NULL) + return; + + if ( ! pPage->IsMasterPage()) + { + // 1. Remove the background object (so that that, if it exists, does + // not override the new master page) and assign the master page to + // the regular slide. + pDocument->GetDocSh()->GetUndoManager()->AddUndoAction( + new SdBackgroundObjUndoAction( + *pDocument, *pPage, pPage->getSdrPageProperties().GetItemSet()), + TRUE); + pPage->getSdrPageProperties().PutItem(XFillStyleItem(XFILL_NONE)); + + pDocument->SetMasterPage ( + (pPage->GetPageNum()-1)/2, + rsBaseLayoutName, + pDocument, + FALSE, + FALSE); + } + else + { + // Find first slide that uses the master page. + SdPage* pSlide = NULL; + USHORT nPageCount = pDocument->GetSdPageCount(PK_STANDARD); + for (USHORT nPage=0; nPage<nPageCount&&pSlide==NULL; nPage++) + { + SdrPage* pCandidate = pDocument->GetSdPage(nPage,PK_STANDARD); + if (pCandidate != NULL + && pCandidate->TRG_HasMasterPage() + && &(pCandidate->TRG_GetMasterPage()) == pPage) + { + pSlide = static_cast<SdPage*>(pCandidate); + } + } + + if (pSlide != NULL) + { + // 2. Assign the given master pages to the first slide that was + // found above that uses the master page. + pDocument->SetMasterPage ( + (pSlide->GetPageNum()-1)/2, + rsBaseLayoutName, + pDocument, + FALSE, + FALSE); + } + else + { + // 3. Replace the master page A by a copy of the given master + // page B. + pDocument->RemoveUnnecessaryMasterPages ( + pPage, FALSE); + } + } +} + + + + +SdPage* DocumentHelper::ProvideMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList) +{ + // Make sure that both the master page and its notes master exist + // in the source document. If one is missing then return without + // making any changes. + if (pMasterPage == NULL) + { + // The caller should make sure that the master page is valid. + OSL_ASSERT(pMasterPage != NULL); + return NULL; + } + SdDrawDocument* pSourceDocument = static_cast<SdDrawDocument*>(pMasterPage->GetModel()); + if (pSourceDocument == NULL) + return NULL; + SdPage* pNotesMasterPage = static_cast<SdPage*>( + pSourceDocument->GetMasterPage(pMasterPage->GetPageNum()+1)); + if (pNotesMasterPage == NULL) + { + // The model is not in a valid state. Maybe a new master page + // is being (not finished yet) created? Return without making + // any changes. + return NULL; + } + + SdPage* pMasterPageInDocument = NULL; + // Search for a master page with the same name as the given one in + // the target document. + const XubString sMasterPageLayoutName (pMasterPage->GetLayoutName()); + for (USHORT nIndex=0,nCount=rTargetDocument.GetMasterPageCount(); nIndex<nCount; ++nIndex) + { + SdPage* pCandidate = static_cast<SdPage*>(rTargetDocument.GetMasterPage(nIndex)); + if (pCandidate!=NULL + && sMasterPageLayoutName==pCandidate->GetLayoutName()) + { + // The requested master page does already exist in the + // target document, return it. + return pCandidate; + } + } + + // The given master page does not already belong to the target + // document so we have to create copies and insert them into the + // targer document. + + // Determine the position where the new master pages are inserted. + // By default they are inserted at the end. When we assign to a + // master page then insert after the last of the (selected) pages. + USHORT nInsertionIndex = rTargetDocument.GetMasterPageCount(); + if (rpPageList->front()->IsMasterPage()) + { + nInsertionIndex = rpPageList->back()->GetPageNum(); + } + + // Clone the master page. + if (pMasterPage->GetModel() != &rTargetDocument) + { + pMasterPageInDocument = AddMasterPage (rTargetDocument, pMasterPage, nInsertionIndex); + if( rTargetDocument.IsUndoEnabled() ) + rTargetDocument.AddUndo( + rTargetDocument.GetSdrUndoFactory().CreateUndoNewPage(*pMasterPageInDocument)); + } + else + pMasterPageInDocument = pMasterPage; + + // Clone the notes master. + if (pNotesMasterPage->GetModel() != &rTargetDocument) + { + SdPage* pClonedNotesMasterPage + = AddMasterPage (rTargetDocument, pNotesMasterPage, nInsertionIndex+1); + if( rTargetDocument.IsUndoEnabled() ) + rTargetDocument.AddUndo( + rTargetDocument.GetSdrUndoFactory().CreateUndoNewPage(*pClonedNotesMasterPage)); + } + + return pMasterPageInDocument; +} + + + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/DocumentHelper.hxx b/sd/source/ui/toolpanel/controls/DocumentHelper.hxx new file mode 100644 index 000000000000..2ff1c8aa575a --- /dev/null +++ b/sd/source/ui/toolpanel/controls/DocumentHelper.hxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_DCUMENT_HELPER_HXX +#define SD_TOOLPANEL_CONTROLS_DCUMENT_HELPER_HXX + +#include <tools/solar.h> +#include <boost/shared_ptr.hpp> +#include <vector> + +class SdDrawDocument; +class SdPage; +class String; + +namespace sd { namespace toolpanel { namespace controls { + +/** A collection of methods supporting the handling of master pages. +*/ +class DocumentHelper +{ +public: + /** Return a copy of the given master page in the given document. + */ + static SdPage* CopyMasterPageToLocalDocument ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage); + + /** Return and, when not yet present, create a slide that uses the given + masster page. + */ + static SdPage* GetSlideForMasterPage (SdPage* pMasterPage); + + /** Copy the styles used by the given page from the source document to + the target document. + */ + static void ProvideStyles ( + SdDrawDocument& rSourceDocument, + SdDrawDocument& rTargetDocument, + SdPage* pPage); + + /** Assign the given master page to the list of pages. + @param rTargetDocument + The document that is the owner of the pages in rPageList. + @param pMasterPage + This master page will usually be a member of the list of all + available master pages as provided by the MasterPageContainer. + @param rPageList + The pages to which to assign the master page. These pages may + be slides or master pages themselves. + */ + static void AssignMasterPageToPageList ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rPageList); + +private: + static SdPage* AddMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage); + static SdPage* AddMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + USHORT nInsertionIndex); + static SdPage* ProvideMasterPage ( + SdDrawDocument& rTargetDocument, + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList); + + /** Assign the given master page to the given page. + @param pMasterPage + In contrast to AssignMasterPageToPageList() this page is assumed + to be in the target document, i.e. the same document that pPage + is in. The caller will usually call AddMasterPage() to create a + clone of a master page in a another document to create it. + @param rsBaseLayoutName + The layout name of the given master page. It is given so that + it has not to be created on every call. It could be generated + from the given master page, though. + @param pPage + The page to which to assign the master page. It can be a slide + or a master page itself. + */ + static void AssignMasterPageToPage ( + SdPage* pMasterPage, + const String& rsBaseLayoutName, + SdPage* pPage); +}; + + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainer.cxx b/sd/source/ui/toolpanel/controls/MasterPageContainer.cxx new file mode 100755 index 000000000000..80a094ec1a66 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainer.cxx @@ -0,0 +1,1220 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageContainer.hxx" + +#include "MasterPageDescriptor.hxx" +#include "MasterPageContainerFiller.hxx" +#include "MasterPageContainerQueue.hxx" +#include "TemplateScanner.hxx" +#include "tools/AsynchronousTask.hxx" +#include "strings.hrc" +#include <algorithm> +#include <list> +#include <set> + +#include "unomodel.hxx" +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/io/XStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/util/XCloseable.hpp> +#include <comphelper/processfactory.hxx> +#include <tools/urlobj.hxx> +#include <sfx2/app.hxx> +#include <svx/svdpage.hxx> +#include "DrawDocShell.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include "sdresid.hxx" +#include "tools/TimerBasedTaskExecution.hxx" +#include "pres.hxx" +#include <osl/mutex.hxx> +#include <boost/weak_ptr.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sd::toolpanel::controls; + +namespace { + +typedef ::std::vector<SharedMasterPageDescriptor> MasterPageContainerType; + +} // end of anonymous namespace + + +namespace sd { namespace toolpanel { namespace controls { + + +/** Inner implementation class of the MasterPageContainer. +*/ +class MasterPageContainer::Implementation + : public SdGlobalResource, + public MasterPageContainerFiller::ContainerAdapter, + public MasterPageContainerQueue::ContainerAdapter +{ +public: + mutable ::osl::Mutex maMutex; + + static ::boost::weak_ptr<Implementation> mpInstance; + MasterPageContainerType maContainer; + + static ::boost::shared_ptr<Implementation> Instance (void); + + void LateInit (void); + void AddChangeListener (const Link& rLink); + void RemoveChangeListener (const Link& rLink); + void UpdatePreviewSizePixel (void); + Size GetPreviewSizePixel (PreviewSize eSize) const; + + bool HasToken (Token aToken) const; + const SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken) const; + SharedMasterPageDescriptor GetDescriptor (MasterPageContainer::Token aToken); + virtual Token PutMasterPage (const SharedMasterPageDescriptor& rDescriptor); + void InvalidatePreview (Token aToken); + Image GetPreviewForToken ( + Token aToken, + PreviewSize ePreviewSize); + PreviewState GetPreviewState (Token aToken) const; + bool RequestPreview (Token aToken); + + Reference<frame::XModel> GetModel (void); + SdDrawDocument* GetDocument (void); + + void FireContainerChange ( + MasterPageContainerChangeEvent::EventType eType, + Token aToken, + bool bNotifyAsynchronously = false); + + virtual bool UpdateDescriptor ( + const SharedMasterPageDescriptor& rpDescriptor, + bool bForcePageObject, + bool bForcePreview, + bool bSendEvents); + + void ReleaseDescriptor (Token aToken); + + /** Called by the MasterPageContainerFiller to notify that all master + pages from template documents have been added. + */ + virtual void FillingDone (void); + +private: + Implementation (void); + virtual ~Implementation (void); + + class Deleter { public: + void operator() (Implementation* pObject) { delete pObject; } + }; + friend class Deleter; + + enum InitializationState { NOT_INITIALIZED, INITIALIZING, INITIALIZED } meInitializationState; + + ::boost::scoped_ptr<MasterPageContainerQueue> mpRequestQueue; + ::com::sun::star::uno::Reference<com::sun::star::frame::XModel> mxModel; + SdDrawDocument* mpDocument; + PreviewRenderer maPreviewRenderer; + /** Remember whether the first page object has already been used to + determine the correct size ratio. + */ + bool mbFirstPageObjectSeen; + + // The widths for the previews contain two pixels for the border that is + // painted arround the preview. + static const int SMALL_PREVIEW_WIDTH = 72 + 2; + static const int LARGE_PREVIEW_WIDTH = 2*72 + 2; + + /** This substition of page preview shows "Preparing preview" and is + shown as long as the actual previews are not being present. + */ + Image maLargePreviewBeingCreated; + Image maSmallPreviewBeingCreated; + + /** This substition of page preview is shown when a preview can not be + created and thus is not available. + */ + Image maLargePreviewNotAvailable; + Image maSmallPreviewNotAvailable; + + ::std::vector<Link> maChangeListeners; + + // We have to remember the tasks for initialization and filling in case + // a MasterPageContainer object is destroyed before these tasks have + // been completed. + ::boost::weak_ptr<sd::tools::TimerBasedTaskExecution> mpFillerTask; + + Size maSmallPreviewSizePixel; + Size maLargePreviewSizePixel; + bool mbPageRatioKnown; + + bool mbContainerCleaningPending; + + typedef ::std::pair<MasterPageContainerChangeEvent::EventType,Token> EventData; + DECL_LINK(AsynchronousNotifyCallback, EventData*); + ::sd::DrawDocShell* LoadDocument ( + const String& sFileName, + SfxObjectShellLock& rxDocumentShell); + + Image GetPreviewSubstitution (USHORT nId, PreviewSize ePreviewSize); + + void CleanContainer (void); +}; + + + + +//===== MasterPageContainer =================================================== + +::boost::weak_ptr<MasterPageContainer::Implementation> + MasterPageContainer::Implementation::mpInstance; +static const MasterPageContainer::Token NIL_TOKEN (-1); + + + + +::boost::shared_ptr<MasterPageContainer::Implementation> + MasterPageContainer::Implementation::Instance (void) +{ + ::boost::shared_ptr<MasterPageContainer::Implementation> pInstance; + + if (Implementation::mpInstance.expired()) + { + ::osl::GetGlobalMutex aMutexFunctor; + ::osl::MutexGuard aGuard (aMutexFunctor()); + if (Implementation::mpInstance.expired()) + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( + new MasterPageContainer::Implementation(), + MasterPageContainer::Implementation::Deleter()); + SdGlobalResourceContainer::Instance().AddResource(pInstance); + Implementation::mpInstance = pInstance; + } + else + pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( + Implementation::mpInstance); + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + pInstance = ::boost::shared_ptr<MasterPageContainer::Implementation>( + Implementation::mpInstance); + } + + DBG_ASSERT (pInstance.get()!=NULL, + "MasterPageContainer::Implementation::Instance(): instance is NULL"); + return pInstance; +} + + + + +MasterPageContainer::MasterPageContainer (void) + : mpImpl(Implementation::Instance()), + mePreviewSize(SMALL) +{ + mpImpl->LateInit(); +} + + + + +MasterPageContainer::~MasterPageContainer (void) +{ +} + + + + +void MasterPageContainer::AddChangeListener (const Link& rLink) +{ + mpImpl->AddChangeListener(rLink); +} + + + + +void MasterPageContainer::RemoveChangeListener (const Link& rLink) +{ + mpImpl->RemoveChangeListener(rLink); +} + + + + +void MasterPageContainer::SetPreviewSize (PreviewSize eSize) +{ + mePreviewSize = eSize; + mpImpl->FireContainerChange( + MasterPageContainerChangeEvent::SIZE_CHANGED, + NIL_TOKEN); +} + + + + +MasterPageContainer::PreviewSize MasterPageContainer::GetPreviewSize (void) const +{ + return mePreviewSize; +} + + + + +Size MasterPageContainer::GetPreviewSizePixel (void) const +{ + return mpImpl->GetPreviewSizePixel(mePreviewSize); +} + + + + +MasterPageContainer::Token MasterPageContainer::PutMasterPage ( + const SharedMasterPageDescriptor& rDescriptor) +{ + return mpImpl->PutMasterPage(rDescriptor); +} + + + + +void MasterPageContainer::AcquireToken (Token aToken) +{ + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + { + ++pDescriptor->mnUseCount; + } +} + + + + +void MasterPageContainer::ReleaseToken (Token aToken) +{ + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + { + OSL_ASSERT(pDescriptor->mnUseCount>0); + --pDescriptor->mnUseCount; + if (pDescriptor->mnUseCount <= 0) + { + switch (pDescriptor->meOrigin) + { + case DEFAULT: + case TEMPLATE: + default: + break; + + case MASTERPAGE: + mpImpl->ReleaseDescriptor(aToken); + break; + } + } + } +} + + + + +int MasterPageContainer::GetTokenCount (void) const +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + return mpImpl->maContainer.size(); +} + + + + +bool MasterPageContainer::HasToken (Token aToken) const +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + return mpImpl->HasToken(aToken); +} + + + + +MasterPageContainer::Token MasterPageContainer::GetTokenForIndex (int nIndex) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + Token aResult (NIL_TOKEN); + if (HasToken(nIndex)) + aResult = mpImpl->maContainer[nIndex]->maToken; + return aResult; +} + + + + +MasterPageContainer::Token MasterPageContainer::GetTokenForURL ( + const String& sURL) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + Token aResult (NIL_TOKEN); + if (sURL.Len() > 0) + { + MasterPageContainerType::iterator iEntry ( + ::std::find_if ( + mpImpl->maContainer.begin(), + mpImpl->maContainer.end(), + MasterPageDescriptor::URLComparator(sURL))); + if (iEntry != mpImpl->maContainer.end()) + aResult = (*iEntry)->maToken; + } + return aResult; +} + + + + +MasterPageContainer::Token MasterPageContainer::GetTokenForStyleName (const String& sStyleName) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + Token aResult (NIL_TOKEN); + if (sStyleName.Len() > 0) + { + MasterPageContainerType::iterator iEntry ( + ::std::find_if ( + mpImpl->maContainer.begin(), + mpImpl->maContainer.end(), + MasterPageDescriptor::StyleNameComparator(sStyleName))); + if (iEntry != mpImpl->maContainer.end()) + aResult = (*iEntry)->maToken; + } + return aResult; +} + + + + +MasterPageContainer::Token MasterPageContainer::GetTokenForPageObject ( + const SdPage* pPage) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + Token aResult (NIL_TOKEN); + if (pPage != NULL) + { + MasterPageContainerType::iterator iEntry ( + ::std::find_if ( + mpImpl->maContainer.begin(), + mpImpl->maContainer.end(), + MasterPageDescriptor::PageObjectComparator(pPage))); + if (iEntry != mpImpl->maContainer.end()) + aResult = (*iEntry)->maToken; + } + return aResult; +} + + + + +String MasterPageContainer::GetURLForToken ( + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return pDescriptor->msURL; + else + return String(); +} + + + + +String MasterPageContainer::GetPageNameForToken ( + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return pDescriptor->msPageName; + else + return String(); +} + + + + +String MasterPageContainer::GetStyleNameForToken ( + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return pDescriptor->msStyleName; + else + return String(); +} + + + + +SdPage* MasterPageContainer::GetPageObjectForToken ( + MasterPageContainer::Token aToken, + bool bLoad) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SdPage* pPageObject = NULL; + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + { + pPageObject = pDescriptor->mpMasterPage; + if (pPageObject == NULL) + { + // The page object is not (yet) present. Call + // UpdateDescriptor() to trigger the PageObjectProvider() to + // provide it. + if (bLoad) + mpImpl->GetModel(); + if (mpImpl->UpdateDescriptor(pDescriptor,bLoad,false, true)) + pPageObject = pDescriptor->mpMasterPage; + } + } + return pPageObject; +} + + + + +MasterPageContainer::Origin MasterPageContainer::GetOriginForToken (Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return pDescriptor->meOrigin; + else + return UNKNOWN; +} + + + + +sal_Int32 MasterPageContainer::GetTemplateIndexForToken (Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + SharedMasterPageDescriptor pDescriptor = mpImpl->GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return pDescriptor->mnTemplateIndex; + else + return -1; +} + + + + +SharedMasterPageDescriptor MasterPageContainer::GetDescriptorForToken ( + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (mpImpl->maMutex); + + return mpImpl->GetDescriptor(aToken); +} + + + +void MasterPageContainer::InvalidatePreview (MasterPageContainer::Token aToken) +{ + mpImpl->InvalidatePreview(aToken); +} + + + + +Image MasterPageContainer::GetPreviewForToken (MasterPageContainer::Token aToken) +{ + return mpImpl->GetPreviewForToken(aToken,mePreviewSize); +} + + + + +MasterPageContainer::PreviewState MasterPageContainer::GetPreviewState (Token aToken) +{ + return mpImpl->GetPreviewState(aToken); +} + + + + +bool MasterPageContainer::RequestPreview (Token aToken) +{ + return mpImpl->RequestPreview(aToken); +} + + + + +//==== Implementation ================================================ + +MasterPageContainer::Implementation::Implementation (void) + : maMutex(), + maContainer(), + meInitializationState(NOT_INITIALIZED), + mpRequestQueue(NULL), + mxModel(NULL), + mpDocument(NULL), + maPreviewRenderer(), + mbFirstPageObjectSeen(false), + maLargePreviewBeingCreated(), + maSmallPreviewBeingCreated(), + maLargePreviewNotAvailable(), + maSmallPreviewNotAvailable(), + maChangeListeners(), + maSmallPreviewSizePixel(), + maLargePreviewSizePixel(), + mbPageRatioKnown(false), + mbContainerCleaningPending(true) + +{ + UpdatePreviewSizePixel(); +} + + + + +MasterPageContainer::Implementation::~Implementation (void) +{ + // When the initializer or filler tasks are still running then we have + // to stop them now in order to prevent them from calling us back. + tools::TimerBasedTaskExecution::ReleaseTask(mpFillerTask); + + mpRequestQueue.reset(); + + uno::Reference<util::XCloseable> xCloseable (mxModel, uno::UNO_QUERY); + if (xCloseable.is()) + { + try + { + xCloseable->close(true); + } + catch (::com::sun::star::util::CloseVetoException aException) + { + } + } + mxModel = NULL; +} + + + + +void MasterPageContainer::Implementation::LateInit (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + if (meInitializationState == NOT_INITIALIZED) + { + meInitializationState = INITIALIZING; + + OSL_ASSERT(Instance().get()==this); + mpRequestQueue.reset(MasterPageContainerQueue::Create( + ::boost::shared_ptr<MasterPageContainerQueue::ContainerAdapter>(Instance()))); + + mpFillerTask = ::sd::tools::TimerBasedTaskExecution::Create( + ::boost::shared_ptr<tools::AsynchronousTask>(new MasterPageContainerFiller(*this)), + 5, + 50); + + meInitializationState = INITIALIZED; + } +} + + + + +void MasterPageContainer::Implementation::AddChangeListener (const Link& rLink) +{ + const ::osl::MutexGuard aGuard (maMutex); + + ::std::vector<Link>::iterator iListener ( + ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); + if (iListener == maChangeListeners.end()) + maChangeListeners.push_back(rLink); + +} + + + + +void MasterPageContainer::Implementation::RemoveChangeListener (const Link& rLink) +{ + const ::osl::MutexGuard aGuard (maMutex); + + ::std::vector<Link>::iterator iListener ( + ::std::find(maChangeListeners.begin(),maChangeListeners.end(),rLink)); + if (iListener != maChangeListeners.end()) + maChangeListeners.erase(iListener); +} + + + + +void MasterPageContainer::Implementation::UpdatePreviewSizePixel (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + // The default aspect ratio is 4:3 + int nWidth (4); + int nHeight (3); + + // Search for the first entry with an existing master page. + MasterPageContainerType::const_iterator iDescriptor; + MasterPageContainerType::const_iterator iContainerEnd(maContainer.end()); + for (iDescriptor=maContainer.begin(); iDescriptor!=iContainerEnd; ++iDescriptor) + if (*iDescriptor!=NULL && (*iDescriptor)->mpMasterPage != NULL) + { + Size aPageSize ((*iDescriptor)->mpMasterPage->GetSize()); + nWidth = aPageSize.Width(); + nHeight = aPageSize.Height(); + mbFirstPageObjectSeen = true; + break; + } + + maSmallPreviewSizePixel.Width() = SMALL_PREVIEW_WIDTH; + maLargePreviewSizePixel.Width() = LARGE_PREVIEW_WIDTH; + + int nNewSmallHeight ((maSmallPreviewSizePixel.Width()-2) * nHeight / nWidth + 2); + int nNewLargeHeight ((maLargePreviewSizePixel.Width()-2) * nHeight / nWidth + 2); + + if (nNewSmallHeight!=maSmallPreviewSizePixel.Height() + || nNewLargeHeight!=maLargePreviewSizePixel.Height()) + { + maSmallPreviewSizePixel.Height() = nNewSmallHeight; + maLargePreviewSizePixel.Height() = nNewLargeHeight; + FireContainerChange( + MasterPageContainerChangeEvent::SIZE_CHANGED, + NIL_TOKEN); + } +} + + + + +Size MasterPageContainer::Implementation::GetPreviewSizePixel (PreviewSize eSize) const +{ + if (eSize == SMALL) + return maSmallPreviewSizePixel; + else + return maLargePreviewSizePixel; +} + + + + +IMPL_LINK(MasterPageContainer::Implementation,AsynchronousNotifyCallback, EventData*, pData) +{ + const ::osl::MutexGuard aGuard (maMutex); + + if (pData != NULL) + { + FireContainerChange(pData->first, pData->second, false); + delete pData; + } + + return 0; +} + + + + +MasterPageContainer::Token MasterPageContainer::Implementation::PutMasterPage ( + const SharedMasterPageDescriptor& rpDescriptor) +{ + const ::osl::MutexGuard aGuard (maMutex); + + Token aResult (NIL_TOKEN); + + // Get page object and preview when that is inexpensive. + UpdateDescriptor(rpDescriptor,false,false, false); + + // Look up the new MasterPageDescriptor and either insert it or update + // an already existing one. + MasterPageContainerType::iterator aEntry ( + ::std::find_if ( + maContainer.begin(), + maContainer.end(), + MasterPageDescriptor::AllComparator(rpDescriptor))); + if (aEntry == maContainer.end()) + { + // Insert a new MasterPageDescriptor. + bool bIgnore (rpDescriptor->mpPageObjectProvider.get()==NULL + && rpDescriptor->msURL.getLength()==0); + + if ( ! bIgnore) + { + if (mbContainerCleaningPending) + CleanContainer(); + + aResult = maContainer.size(); + rpDescriptor->SetToken(aResult); + + // Templates are precious, i.e. we lock them so that they will + // not be destroyed when (temporarily) no one references them. + // They will only be deleted when the container is destroyed. + switch (rpDescriptor->meOrigin) + { + case TEMPLATE: + case DEFAULT: + ++rpDescriptor->mnUseCount; + break; + + default: + break; + } + + maContainer.push_back(rpDescriptor); + aEntry = maContainer.end()-1; + + FireContainerChange(MasterPageContainerChangeEvent::CHILD_ADDED,aResult); + } + } + else + { + // Update an existing MasterPageDescriptor. + aResult = (*aEntry)->maToken; + ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pEventTypes( + (*aEntry)->Update(*rpDescriptor)); + if (pEventTypes.get()!=NULL && pEventTypes->size()>0) + { + // One or more aspects of the descriptor have changed. Send + // appropriate events to the listeners. + UpdateDescriptor(*aEntry,false,false, true); + + std::vector<MasterPageContainerChangeEvent::EventType>::const_iterator iEventType; + for (iEventType=pEventTypes->begin(); iEventType!=pEventTypes->end(); ++iEventType) + { + FireContainerChange( + *iEventType, + (*aEntry)->maToken, + false); + } + } + } + + return aResult; +} + + + + +bool MasterPageContainer::Implementation::HasToken (Token aToken) const +{ + return aToken>=0 + && (unsigned)aToken<maContainer.size() + && maContainer[aToken].get()!=NULL; +} + + + + +const SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor ( + Token aToken) const +{ + if (aToken>=0 && (unsigned)aToken<maContainer.size()) + return maContainer[aToken]; + else + return SharedMasterPageDescriptor(); +} + + + + +SharedMasterPageDescriptor MasterPageContainer::Implementation::GetDescriptor (Token aToken) +{ + if (aToken>=0 && (unsigned)aToken<maContainer.size()) + return maContainer[aToken]; + else + return SharedMasterPageDescriptor(); +} + + + + +void MasterPageContainer::Implementation::InvalidatePreview (Token aToken) +{ + const ::osl::MutexGuard aGuard (maMutex); + + SharedMasterPageDescriptor pDescriptor (GetDescriptor(aToken)); + if (pDescriptor.get() != NULL) + { + pDescriptor->maSmallPreview = Image(); + pDescriptor->maLargePreview = Image(); + RequestPreview(aToken); + } +} + + + + +Image MasterPageContainer::Implementation::GetPreviewForToken ( + MasterPageContainer::Token aToken, + PreviewSize ePreviewSize) +{ + const ::osl::MutexGuard aGuard (maMutex); + + Image aPreview; + PreviewState ePreviewState (GetPreviewState(aToken)); + + SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); + + // When the preview is missing but inexpensively creatable then do that + // now. + if (pDescriptor.get()!=NULL) + { + if (ePreviewState == PS_CREATABLE) + if (UpdateDescriptor(pDescriptor, false,false, true)) + if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) + ePreviewState = PS_AVAILABLE; + + switch (ePreviewState) + { + case PS_AVAILABLE: + aPreview = pDescriptor->GetPreview(ePreviewSize); + break; + + case PS_PREPARING: + aPreview = GetPreviewSubstitution( + STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, + ePreviewSize); + break; + + case PS_CREATABLE: + aPreview = GetPreviewSubstitution( + STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION, + ePreviewSize); + break; + + case PS_NOT_AVAILABLE: + aPreview = GetPreviewSubstitution( + STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION, + ePreviewSize); + if (ePreviewSize == SMALL) + pDescriptor->maSmallPreview = aPreview; + else + pDescriptor->maLargePreview = aPreview; + break; + } + } + + return aPreview; +} + + + + +MasterPageContainer::PreviewState MasterPageContainer::Implementation::GetPreviewState ( + Token aToken) const +{ + const ::osl::MutexGuard aGuard (maMutex); + + PreviewState eState (PS_NOT_AVAILABLE); + + SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + { + if (pDescriptor->maLargePreview.GetSizePixel().Width() != 0) + eState = PS_AVAILABLE; + else if (pDescriptor->mpPreviewProvider.get() != NULL) + { + // The preview does not exist but can be created. When that is + // not expensive then do it at once. + if (mpRequestQueue->HasRequest(aToken)) + eState = PS_PREPARING; + else + eState = PS_CREATABLE; + } + else + eState = PS_NOT_AVAILABLE; + } + + return eState; +} + + + + +bool MasterPageContainer::Implementation::RequestPreview (Token aToken) +{ + SharedMasterPageDescriptor pDescriptor = GetDescriptor(aToken); + if (pDescriptor.get() != NULL) + return mpRequestQueue->RequestPreview(pDescriptor); + else + return false; +} + + + + +Reference<frame::XModel> MasterPageContainer::Implementation::GetModel (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + if ( ! mxModel.is()) + { + // Get the desktop a s service factory. + ::rtl::OUString sDesktopServiceName ( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")); + uno::Reference<frame::XComponentLoader> xDesktop ( + ::comphelper::getProcessServiceFactory()->createInstance( + sDesktopServiceName), + uno::UNO_QUERY); + + // Create a new model. + ::rtl::OUString sModelServiceName ( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.presentation.PresentationDocument")); + mxModel = uno::Reference<frame::XModel>( + ::comphelper::getProcessServiceFactory()->createInstance( + sModelServiceName), + uno::UNO_QUERY); + + // Initialize the model. + uno::Reference<frame::XLoadable> xLoadable (mxModel,uno::UNO_QUERY); + if (xLoadable.is()) + xLoadable->initNew(); + + // Use its tunnel to get a pointer to its core implementation. + uno::Reference<lang::XUnoTunnel> xUnoTunnel (mxModel, uno::UNO_QUERY); + if (xUnoTunnel.is()) + { + mpDocument = reinterpret_cast<SdXImpressDocument*>( + xUnoTunnel->getSomething( + SdXImpressDocument::getUnoTunnelId()))->GetDoc(); + } + + // Create a default page. + uno::Reference<drawing::XDrawPagesSupplier> xSlideSupplier (mxModel, uno::UNO_QUERY); + if (xSlideSupplier.is()) + { + uno::Reference<drawing::XDrawPages> xSlides ( + xSlideSupplier->getDrawPages(), uno::UNO_QUERY); + if (xSlides.is()) + { + sal_Int32 nIndex (0); + uno::Reference<drawing::XDrawPage> xNewPage (xSlides->insertNewByIndex(nIndex)); + uno::Reference<beans::XPropertySet> xProperties(xNewPage, uno::UNO_QUERY); + if (xProperties.is()) + xProperties->setPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Layout")), + makeAny((sal_Int16)AUTOLAYOUT_TITLE)); + } + } + } + return mxModel; +} + + + + +SdDrawDocument* MasterPageContainer::Implementation::GetDocument (void) +{ + GetModel(); + return mpDocument; +} + + + + +Image MasterPageContainer::Implementation::GetPreviewSubstitution ( + USHORT nId, + PreviewSize ePreviewSize) +{ + const ::osl::MutexGuard aGuard (maMutex); + + Image aPreview; + + switch (nId) + { + case STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION: + { + Image& rPreview (ePreviewSize==SMALL + ? maSmallPreviewBeingCreated + : maLargePreviewBeingCreated); + if (rPreview.GetSizePixel().Width() == 0) + { + rPreview = maPreviewRenderer.RenderSubstitution( + ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, + SdResId(STR_TASKPANEL_PREPARING_PREVIEW_SUBSTITUTION)); + } + aPreview = rPreview; + } + break; + + case STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION: + { + Image& rPreview (ePreviewSize==SMALL + ? maSmallPreviewNotAvailable + : maLargePreviewNotAvailable); + if (rPreview.GetSizePixel().Width() == 0) + { + rPreview = maPreviewRenderer.RenderSubstitution( + ePreviewSize==SMALL ? maSmallPreviewSizePixel : maLargePreviewSizePixel, + SdResId(STR_TASKPANEL_NOT_AVAILABLE_SUBSTITUTION)); + } + aPreview = rPreview; + } + break; + } + + return aPreview; +} + + + + +void MasterPageContainer::Implementation::CleanContainer (void) +{ + // Remove the empty elements at the end of the container. The empty + // elements in the middle can not be removed because that would + // invalidate the references still held by others. + int nIndex (maContainer.size()-1); + while (nIndex>=0 && maContainer[nIndex].get()==NULL) + --nIndex; + maContainer.resize(++nIndex); +} + + + + +void MasterPageContainer::Implementation::FireContainerChange ( + MasterPageContainerChangeEvent::EventType eType, + Token aToken, + bool bNotifyAsynchronously) +{ + if (bNotifyAsynchronously) + { + Application::PostUserEvent( + LINK(this,Implementation,AsynchronousNotifyCallback), + new EventData(eType,aToken)); + } + else + { + ::std::vector<Link> aCopy(maChangeListeners.begin(),maChangeListeners.end()); + ::std::vector<Link>::iterator iListener; + MasterPageContainerChangeEvent aEvent; + aEvent.meEventType = eType; + aEvent.maChildToken = aToken; + for (iListener=aCopy.begin(); iListener!=aCopy.end(); ++iListener) + iListener->Call(&aEvent); + } +} + + + + +bool MasterPageContainer::Implementation::UpdateDescriptor ( + const SharedMasterPageDescriptor& rpDescriptor, + bool bForcePageObject, + bool bForcePreview, + bool bSendEvents) +{ + const ::osl::MutexGuard aGuard (maMutex); + + // We have to create the page object when the preview provider needs it + // and the caller needs the preview. + bForcePageObject |= (bForcePreview + && rpDescriptor->mpPreviewProvider->NeedsPageObject() + && rpDescriptor->mpMasterPage==NULL); + + // Define a cost threshold so that an update or page object or preview + // that is at least this cost are made at once. Updates with higher cost + // are scheduled for later. + sal_Int32 nCostThreshold (mpRequestQueue->IsEmpty() ? 5 : 0); + + // Update the page object (which may be used for the preview update). + if (bForcePageObject) + GetDocument(); + bool bPageObjectModified (rpDescriptor->UpdatePageObject( + (bForcePageObject ? -1 : nCostThreshold), + mpDocument)); + if (bPageObjectModified && bSendEvents) + FireContainerChange( + MasterPageContainerChangeEvent::DATA_CHANGED, + rpDescriptor->maToken); + if (bPageObjectModified && ! mbFirstPageObjectSeen) + UpdatePreviewSizePixel(); + + // Update the preview. + bool bPreviewModified (rpDescriptor->UpdatePreview( + (bForcePreview ? -1 : nCostThreshold), + maSmallPreviewSizePixel, + maLargePreviewSizePixel, + maPreviewRenderer)); + + if (bPreviewModified && bSendEvents) + FireContainerChange( + MasterPageContainerChangeEvent::PREVIEW_CHANGED, + rpDescriptor->maToken); + + return bPageObjectModified || bPreviewModified; +} + + + + +void MasterPageContainer::Implementation::ReleaseDescriptor (Token aToken) +{ + if (aToken>=0 && (unsigned)aToken<maContainer.size()) + { + maContainer[aToken].reset(); + mbContainerCleaningPending = true; + } +} + + + + +void MasterPageContainer::Implementation::FillingDone (void) +{ + mpRequestQueue->ProcessAllRequests(); +} + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainer.hxx b/sd/source/ui/toolpanel/controls/MasterPageContainer.hxx new file mode 100755 index 000000000000..60f760f63e34 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainer.hxx @@ -0,0 +1,220 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_HXX +#define SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_HXX + +#include "MasterPageContainerProviders.hxx" + +#include <osl/mutex.hxx> +#include <tools/string.hxx> +#include <vcl/image.hxx> +#include <memory> +#include "PreviewRenderer.hxx" +#include <com/sun/star/frame/XModel.hpp> +#include <vcl/timer.hxx> +#include "tools/SdGlobalResourceContainer.hxx" + +#include <boost/shared_ptr.hpp> + +class SdPage; +class SdDrawDocument; +class SfxObjectShellLock; + +namespace sd { +class DrawDocShell; +} + +namespace sd { namespace toolpanel { namespace controls { + +class MasterPageDescriptor; + +/** This container manages the master pages used by the MasterPagesSelector + controls. It uses internally a singleton implementation object. + Therefore, all MasterPageContainer object operator on the same set of + master pages. Each MasterPageContainer, however, has its own + PreviewSize value and thus can independantly switch between large and + small previews. + + The container maintains its own document to store master page objects. + + For each master page container stores its URL, preview bitmap, page + name, and, if available, the page object. + + Entries are accessed via a Token, which is mostly a numerical index but + whose values do not neccessarily have to be consecutive. +*/ +class MasterPageContainer +{ +public: + typedef int Token; + static const Token NIL_TOKEN = -1; + + MasterPageContainer (void); + virtual ~MasterPageContainer (void); + + void AddChangeListener (const Link& rLink); + void RemoveChangeListener (const Link& rLink); + + enum PreviewSize { SMALL, LARGE }; + /** There are two different preview sizes, a small one and a large one. + Which one is used by the called container can be changed with this + method. + When the preview size is changed then all change listeners are + notified of this. + */ + void SetPreviewSize (PreviewSize eSize); + + /** Returns the preview size. + */ + PreviewSize GetPreviewSize (void) const; + + /** Return the preview size in pixels. + */ + Size GetPreviewSizePixel (void) const; + + enum PreviewState { PS_AVAILABLE, PS_CREATABLE, PS_PREPARING, PS_NOT_AVAILABLE }; + PreviewState GetPreviewState (Token aToken); + + /** This method is typically called for entries in the container for + which GetPreviewState() returns OS_CREATABLE. The creation of the + preview is then scheduled to be executed asynchronously at a later + point in time. When the preview is available the change listeners + will be notified. + */ + bool RequestPreview (Token aToken); + + /** Each entry of the container is either the first page of a template + document or is a master page of an Impress document. + */ + enum Origin { + MASTERPAGE, // Master page of a document. + TEMPLATE, // First page of a template file. + DEFAULT, // Empty master page with default style. + UNKNOWN + }; + + /** Put the master page identified and described by the given parameters + into the container. When there already is a master page with the + given URL, page name, or object pointer (when that is not NULL) then + the existing entry is replaced/updated by the given one. Otherwise + a new entry is inserted. + */ + Token PutMasterPage (const ::boost::shared_ptr<MasterPageDescriptor>& rDescriptor); + void AcquireToken (Token aToken); + void ReleaseToken (Token aToken); + + /** This and the GetTokenForIndex() methods can be used to iterate over + all members of the container. + */ + int GetTokenCount (void) const; + + /** Determine whether the container has a member for the given token. + */ + bool HasToken (Token aToken) const; + + /** Return a token for an index in the range + 0 <= index < GetTokenCount(). + */ + Token GetTokenForIndex (int nIndex); + + Token GetTokenForURL (const String& sURL); + Token GetTokenForStyleName (const String& sStyleName); + Token GetTokenForPageObject (const SdPage* pPage); + + String GetURLForToken (Token aToken); + String GetPageNameForToken (Token aToken); + String GetStyleNameForToken (Token aToken); + SdPage* GetPageObjectForToken (Token aToken, bool bLoad=true); + Origin GetOriginForToken (Token aToken); + sal_Int32 GetTemplateIndexForToken (Token aToken); + ::boost::shared_ptr<MasterPageDescriptor> GetDescriptorForToken (Token aToken); + + void InvalidatePreview (Token aToken); + + /** Return a preview for the specified token. When the preview is not + present then the PreviewProvider associated with the token is + executed only when that is not expensive. It is the responsibility + of the caller to call RequestPreview() to do the same + (asynchronously) for expensive PreviewProviders. + Call GetPreviewState() to find out if that is necessary. + @param aToken + This token specifies for which master page to return the prview. + Tokens are returned for example by the GetTokenFor...() methods. + @return + The returned image is the requested preview or a substitution. + */ + Image GetPreviewForToken (Token aToken); + +private: + class Implementation; + ::boost::shared_ptr<Implementation> mpImpl; + PreviewSize mePreviewSize; + + /** Retrieve the preview of the document specified by the given URL. + */ + static BitmapEx LoadPreviewFromURL (const ::rtl::OUString& aURL); +}; + + + + +/** For some changes to the set of master pages in a MasterPageContainer or + to the data stored for each master page one or more events are sent to + registered listeners. + Each event has an event type and a token that tells the listener where + the change took place. +*/ +class MasterPageContainerChangeEvent +{ +public: + enum EventType { + // A master page was added to the container. + CHILD_ADDED, + // A master page was removed from the container. + CHILD_REMOVED, + // The preview of a master page has changed. + PREVIEW_CHANGED, + // The size of a preview has changed. + SIZE_CHANGED, + // Some of the data stored for a master page has changed. + DATA_CHANGED, + // The TemplateIndex of a master page has changed. + INDEX_CHANGED, + // More than one entries changed their TemplateIndex + INDEXES_CHANGED + } meEventType; + + // Token of the container entry whose data changed or which was added or + // removed. + MasterPageContainer::Token maChildToken; +}; + + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.cxx b/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.cxx new file mode 100644 index 000000000000..23663b4822ef --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.cxx @@ -0,0 +1,199 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageContainerFiller.hxx" + +#include "MasterPageDescriptor.hxx" +#include "MasterPageContainerProviders.hxx" +#include "TemplateScanner.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sd::toolpanel::controls; + + +namespace sd { namespace toolpanel { namespace controls { + +MasterPageContainerFiller::MasterPageContainerFiller (ContainerAdapter& rpAdapter) + : mrContainerAdapter(rpAdapter), + meState(INITIALIZE_TEMPLATE_SCANNER), + mpScannerTask(), + mpLastAddedEntry(NULL), + mnIndex(1) +{ + // Add one entry for the default master page. We use temporarily the + // DefaultPagePreviewProvider to prevent the rendering (and the + // expensive creation) of the default page. It is replaced later on by + // another. + SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( + MasterPageContainer::DEFAULT, + 0, + String(), + String(), + String(), + false, + ::boost::shared_ptr<PageObjectProvider>(new DefaultPageObjectProvider()), + ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider()))); + mrContainerAdapter.PutMasterPage(pDescriptor); +} + + + + +MasterPageContainerFiller::~MasterPageContainerFiller (void) +{ +} + + + + +void MasterPageContainerFiller::RunNextStep (void) +{ + switch (meState) + { + case INITIALIZE_TEMPLATE_SCANNER: + mpScannerTask.reset(new TemplateScanner()); + meState = SCAN_TEMPLATE; + break; + + case SCAN_TEMPLATE: + meState = ScanTemplate(); + break; + + case ADD_TEMPLATE: + meState = AddTemplate(); + break; + + case DONE: + case ERROR: + default: + break; + } + + // When the state has just been set to DONE or ERROR then tell the + // container that no more templates will be coming and stop the + // scanning. + switch (meState) + { + case DONE: + case ERROR: + if (mpScannerTask.get() != NULL) + { + mrContainerAdapter.FillingDone(); + mpScannerTask.reset(); + } + default: + break; + } +} + + + + +bool MasterPageContainerFiller::HasNextStep (void) +{ + switch (meState) + { + case DONE: + case ERROR: + return false; + + default: + return true; + } +} + + + + +MasterPageContainerFiller::State MasterPageContainerFiller::ScanTemplate (void) +{ + State eState (ERROR); + + if (mpScannerTask.get() != NULL) + { + if (mpScannerTask->HasNextStep()) + { + mpScannerTask->RunNextStep(); + if (mpScannerTask->GetLastAddedEntry() != mpLastAddedEntry) + { + mpLastAddedEntry = mpScannerTask->GetLastAddedEntry(); + if (mpLastAddedEntry != NULL) + eState = ADD_TEMPLATE; + else + eState = SCAN_TEMPLATE; + } + else + eState = SCAN_TEMPLATE; + } + else + eState = DONE; + } + + return eState; +} + + + + +MasterPageContainerFiller::State MasterPageContainerFiller::AddTemplate (void) +{ + if (mpLastAddedEntry != NULL) + { + SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( + MasterPageContainer::TEMPLATE, + mnIndex, + mpLastAddedEntry->msPath, + mpLastAddedEntry->msTitle, + String(), + false, + ::boost::shared_ptr<PageObjectProvider>( + new TemplatePageObjectProvider(mpLastAddedEntry->msPath)), + ::boost::shared_ptr<PreviewProvider>( + new TemplatePreviewProvider(mpLastAddedEntry->msPath)))); + // For user supplied templates we use a different preview provider: + // The preview in the document shows not only shapes on the master + // page but also shapes on the foreground. This is misleading and + // therefore these previews are discarded and created directly from + // the page objects. + if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER) + pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>( + new PagePreviewProvider()); + + mrContainerAdapter.PutMasterPage(pDescriptor); + ++mnIndex; + } + + return SCAN_TEMPLATE; +} + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.hxx b/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.hxx new file mode 100644 index 000000000000..c8ba61fef378 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerFiller.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_FILLER_HXX +#define SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_FILLER_HXX + +#include "MasterPageContainer.hxx" +#include "MasterPageDescriptor.hxx" +#include "tools/AsynchronousTask.hxx" + +namespace sd { +class TemplateScanner; +class TemplateEntry; +} + +namespace sd { namespace toolpanel { namespace controls { + +/** Fill a MasterPageContainer with information about the available master + pages. These are provided by one default page and from the existing + Impress templates. This is done asynchronously. +*/ +class MasterPageContainerFiller + : public ::sd::tools::AsynchronousTask +{ +public: + class ContainerAdapter + { + public: + virtual MasterPageContainer::Token PutMasterPage ( + const SharedMasterPageDescriptor& rpDescriptor) = 0; + /** This method is called when all Impress templates have been added + to the container via the PutMasterPage() method. + */ + virtual void FillingDone (void) = 0; + }; + + MasterPageContainerFiller (ContainerAdapter& rContainerAdapter); + virtual ~MasterPageContainerFiller (void); + + /** Run the next step of the task. After HasNextStep() returns false + this method should ignore further calls. + */ + virtual void RunNextStep (void); + + /** Return <TRUE/> when there is at least one more step to execute. + When the task has been executed completely then <FALSE/> is + returned. + */ + virtual bool HasNextStep (void); + +private: + ContainerAdapter& mrContainerAdapter; + // Remember what the next step has to do. + enum State { + INITIALIZE_TEMPLATE_SCANNER, + SCAN_TEMPLATE, + ADD_TEMPLATE, + ERROR, + DONE + } meState; + ::std::auto_ptr<TemplateScanner> mpScannerTask; + const TemplateEntry* mpLastAddedEntry; + int mnIndex; + + State ScanTemplate (void); + State AddTemplate (void); +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.cxx b/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.cxx new file mode 100755 index 000000000000..61483f278a4f --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.cxx @@ -0,0 +1,429 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageContainerProviders.hxx" + +#include "DrawDocShell.hxx" +#include "drawdoc.hxx" +#include "PreviewRenderer.hxx" +#include <comphelper/processfactory.hxx> +#include <sfx2/app.hxx> +#include <sfx2/sfxsids.hrc> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/image.hxx> +#include <vcl/pngread.hxx> +#include <com/sun/star/embed/ElementModes.hpp> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::sd::toolpanel::controls; + + +namespace sd { namespace toolpanel { namespace controls { + + +//===== PagePreviewProvider =================================================== + +PagePreviewProvider::PagePreviewProvider (void) +{ +} + + + + +Image PagePreviewProvider::operator () ( + int nWidth, + SdPage* pPage, + ::sd::PreviewRenderer& rRenderer) +{ + Image aPreview; + + if (pPage != NULL) + { + // Use the given renderer to create a preview of the given page + // object. + aPreview = rRenderer.RenderPage( + pPage, + nWidth, + String::CreateFromAscii(""), + false); + } + + return aPreview; +} + + + + +int PagePreviewProvider::GetCostIndex (void) +{ + return 5; +} + + + + +bool PagePreviewProvider::NeedsPageObject (void) +{ + return true; +} + + + + +//===== TemplatePreviewProvider =============================================== + +TemplatePreviewProvider::TemplatePreviewProvider (const ::rtl::OUString& rsURL) + : msURL(rsURL) +{ +} + + + + +Image TemplatePreviewProvider::operator() ( + int nWidth, + SdPage* pPage, + ::sd::PreviewRenderer& rRenderer) +{ + // Unused parameters. + (void)nWidth; + (void)pPage; + (void)rRenderer; + + // Load the thumbnail from a template document. + uno::Reference<io::XInputStream> xIStream; + + uno::Reference< lang::XMultiServiceFactory > xServiceManager ( + ::comphelper::getProcessServiceFactory()); + if (xServiceManager.is()) + { + try + { + uno::Reference<lang::XSingleServiceFactory> xStorageFactory( + xServiceManager->createInstance( + ::rtl::OUString::createFromAscii( + "com.sun.star.embed.StorageFactory")), + uno::UNO_QUERY); + + if (xStorageFactory.is()) + { + uno::Sequence<uno::Any> aArgs (2); + aArgs[0] <<= msURL; + aArgs[1] <<= embed::ElementModes::READ; + uno::Reference<embed::XStorage> xDocStorage ( + xStorageFactory->createInstanceWithArguments(aArgs), + uno::UNO_QUERY); + + try + { + if (xDocStorage.is()) + { + uno::Reference<embed::XStorage> xStorage ( + xDocStorage->openStorageElement( + ::rtl::OUString::createFromAscii("Thumbnails"), + embed::ElementModes::READ)); + if (xStorage.is()) + { + uno::Reference<io::XStream> xThumbnailCopy ( + xStorage->cloneStreamElement( + ::rtl::OUString::createFromAscii( + "thumbnail.png"))); + if (xThumbnailCopy.is()) + xIStream = xThumbnailCopy->getInputStream(); + } + } + } + catch (uno::Exception& rException) + { + OSL_TRACE ( + "caught exception while trying to access Thumbnail/thumbnail.png of %s: %s", + ::rtl::OUStringToOString(msURL, + RTL_TEXTENCODING_UTF8).getStr(), + ::rtl::OUStringToOString(rException.Message, + RTL_TEXTENCODING_UTF8).getStr()); + } + + try + { + // An (older) implementation had a bug - The storage + // name was "Thumbnail" instead of "Thumbnails". The + // old name is still used as fallback but this code can + // be removed soon. + if ( ! xIStream.is()) + { + uno::Reference<embed::XStorage> xStorage ( + xDocStorage->openStorageElement( + ::rtl::OUString::createFromAscii("Thumbnail"), + embed::ElementModes::READ)); + if (xStorage.is()) + { + uno::Reference<io::XStream> xThumbnailCopy ( + xStorage->cloneStreamElement( + ::rtl::OUString::createFromAscii( + "thumbnail.png"))); + if (xThumbnailCopy.is()) + xIStream = xThumbnailCopy->getInputStream(); + } + } + } + catch (uno::Exception& rException) + { + OSL_TRACE ( + "caught exception while trying to access Thumbnails/thumbnail.png of %s: %s", + ::rtl::OUStringToOString(msURL, + RTL_TEXTENCODING_UTF8).getStr(), + ::rtl::OUStringToOString(rException.Message, + RTL_TEXTENCODING_UTF8).getStr()); + } + } + } + catch (uno::Exception& rException) + { + OSL_TRACE ( + "caught exception while trying to access tuhmbnail of %s: %s", + ::rtl::OUStringToOString(msURL, + RTL_TEXTENCODING_UTF8).getStr(), + ::rtl::OUStringToOString(rException.Message, + RTL_TEXTENCODING_UTF8).getStr()); + } + } + + // Extract the image from the stream. + BitmapEx aThumbnail; + if (xIStream.is()) + { + ::std::auto_ptr<SvStream> pStream ( + ::utl::UcbStreamHelper::CreateStream (xIStream)); + ::vcl::PNGReader aReader (*pStream); + aThumbnail = aReader.Read (); + } + + // Note that the preview is returned without scaling it to the desired + // width. This gives the caller the chance to take advantage of a + // possibly larger resolution then was asked for. + return aThumbnail; +} + + + + +int TemplatePreviewProvider::GetCostIndex (void) +{ + return 10; +} + + + + +bool TemplatePreviewProvider::NeedsPageObject (void) +{ + return false; +} + + + + +//===== TemplatePageObjectProvider ============================================= + +TemplatePageObjectProvider::TemplatePageObjectProvider (const ::rtl::OUString& rsURL) + : msURL(rsURL), + mxDocumentShell() +{ +} + + + + +SdPage* TemplatePageObjectProvider::operator() (SdDrawDocument* pContainerDocument) +{ + // Unused parameters. + (void)pContainerDocument; + + SdPage* pPage = NULL; + + mxDocumentShell = NULL; + ::sd::DrawDocShell* pDocumentShell = NULL; + try + { + // Load the template document and return its first page. + pDocumentShell = LoadDocument (msURL); + if (pDocumentShell != NULL) + { + SdDrawDocument* pDocument = pDocumentShell->GetDoc(); + if (pDocument != NULL) + { + pPage = pDocument->GetMasterSdPage(0, PK_STANDARD); + // In order to make the newly loaded master page deletable + // when copied into documents it is marked as no "precious". + // When it is modified then it is marked as "precious". + if (pPage != NULL) + pPage->SetPrecious(false); + } + } + } + catch (uno::RuntimeException) + { + DBG_UNHANDLED_EXCEPTION(); + pPage = NULL; + } + + return pPage; +} + + + + +::sd::DrawDocShell* TemplatePageObjectProvider::LoadDocument (const ::rtl::OUString& sFileName) +{ + SfxApplication* pSfxApp = SFX_APP(); + SfxItemSet* pSet = new SfxAllItemSet (pSfxApp->GetPool()); + pSet->Put (SfxBoolItem (SID_TEMPLATE, TRUE)); + pSet->Put (SfxBoolItem (SID_PREVIEW, TRUE)); + if (pSfxApp->LoadTemplate (mxDocumentShell, sFileName, TRUE, pSet)) + { + mxDocumentShell = NULL; + } + SfxObjectShell* pShell = mxDocumentShell; + return PTR_CAST(::sd::DrawDocShell,pShell); +} + + + + +int TemplatePageObjectProvider::GetCostIndex (void) +{ + return 20; +} + + + + +bool TemplatePageObjectProvider::operator== (const PageObjectProvider& rProvider) +{ + const TemplatePageObjectProvider* pTemplatePageObjectProvider + = dynamic_cast<const TemplatePageObjectProvider*>(&rProvider); + if (pTemplatePageObjectProvider != NULL) + return (msURL == pTemplatePageObjectProvider->msURL); + else + return false; +} + + + + +//===== DefaultPageObjectProvider ============================================== + +DefaultPageObjectProvider::DefaultPageObjectProvider (void) +{ +} + + + + +SdPage* DefaultPageObjectProvider::operator () (SdDrawDocument* pContainerDocument) +{ + SdPage* pLocalMasterPage = NULL; + if (pContainerDocument != NULL) + { + sal_Int32 nIndex (0); + SdPage* pLocalSlide = pContainerDocument->GetSdPage((USHORT)nIndex, PK_STANDARD); + if (pLocalSlide!=NULL && pLocalSlide->TRG_HasMasterPage()) + pLocalMasterPage = dynamic_cast<SdPage*>(&pLocalSlide->TRG_GetMasterPage()); + } + + if (pLocalMasterPage == NULL) + { + DBG_ASSERT(false, "can not create master page for slide"); + } + + return pLocalMasterPage; +} + + + + +int DefaultPageObjectProvider::GetCostIndex (void) +{ + return 15; +} + + + + +bool DefaultPageObjectProvider::operator== (const PageObjectProvider& rProvider) +{ + return (dynamic_cast<const DefaultPageObjectProvider*>(&rProvider) != NULL); +} + + + + +//===== ExistingPageProvider ================================================== + +ExistingPageProvider::ExistingPageProvider (SdPage* pPage) + : mpPage(pPage) +{ +} + + + + +SdPage* ExistingPageProvider::operator() (SdDrawDocument* pDocument) +{ + (void)pDocument; // Unused parameter. + + return mpPage; +} + + + + +int ExistingPageProvider::GetCostIndex (void) +{ + return 0; +} + + + + +bool ExistingPageProvider::operator== (const PageObjectProvider& rProvider) +{ + const ExistingPageProvider* pExistingPageProvider + = dynamic_cast<const ExistingPageProvider*>(&rProvider); + if (pExistingPageProvider != NULL) + return (mpPage == pExistingPageProvider->mpPage); + else + return false; +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.hxx b/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.hxx new file mode 100755 index 000000000000..071b23cdbb16 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerProviders.hxx @@ -0,0 +1,189 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_PROVIDERS_HXX +#define SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_PROVIDERS_HXX + +#include <rtl/ustring.hxx> +#include <sfx2/objsh.hxx> + +class Image; +class SdDrawDocument; +class SdPage; +namespace sd { class PreviewRenderer; } +namespace sd { class DrawDocShell; } + + +namespace sd { namespace toolpanel { namespace controls { + + +/** Interface for a provider of page objects. It is used by the + MasterPageDescriptor to create master page objects on demand. +*/ +class PageObjectProvider +{ +public: + /** Return a master page either by returning an already existing one, by + creating a new page, or by loading a document. + @param pDocument + The document of the MasterPageContainer. It may be used to + create new pages. + */ + virtual SdPage* operator() (SdDrawDocument* pDocument) = 0; + + /** An abstract value for the expected cost of providing a master page + object. + @return + A value of 0 represents for the lowest cost, i.e. an almost + immediate return. Positive values stand for higher costs. + Negative values are not supported. + */ + virtual int GetCostIndex (void) = 0; + + virtual bool operator== (const PageObjectProvider& rProvider) = 0; +}; + + + + +class PreviewProvider +{ +public: + /** Create a preview image in the specified width. + @param nWidth + Requested width of the preview. The calling method can cope + with other sizes as well but the resulting image quality is + better when the returned image has the requested size. + @param pPage + Page object for which a preview is requested. This may be NULL + when the page object is expensive to get and the PreviewProvider + does not need this object (NeedsPageObject() returns false.) + @param rRenderer + This PreviewRenderer may be used by the PreviewProvider to + create a preview image. + */ + virtual Image operator() (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer) = 0; + + /** Return a value that indicates how expensive the creation of a + preview image is. The higher the returned value the more expensive + is the preview creation. Return 0 when the preview is already + present and can be returned immediately. + */ + virtual int GetCostIndex (void) = 0; + + /** Return whether the page object passed is necessary to create a + preview. + */ + virtual bool NeedsPageObject (void) = 0; +}; + + + + +/** Provide previews of existing page objects by rendering them. +*/ +class PagePreviewProvider : public PreviewProvider +{ +public: + PagePreviewProvider (void); + virtual Image operator () (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer); + virtual int GetCostIndex (void); + virtual bool NeedsPageObject (void); +private: +}; + + + + +/** Provide master page objects for template documents for which only the + URL is given. +*/ +class TemplatePageObjectProvider : public PageObjectProvider +{ +public: + TemplatePageObjectProvider (const ::rtl::OUString& rsURL); + virtual ~TemplatePageObjectProvider (void) {}; + virtual SdPage* operator () (SdDrawDocument* pDocument); + virtual int GetCostIndex (void); + virtual bool operator== (const PageObjectProvider& rProvider); +private: + ::rtl::OUString msURL; + SfxObjectShellLock mxDocumentShell; + ::sd::DrawDocShell* LoadDocument (const ::rtl::OUString& sFileName); +}; + + + + +/** Provide previews for template documents by loading the thumbnails from + the documents. +*/ +class TemplatePreviewProvider : public PreviewProvider +{ +public: + TemplatePreviewProvider (const ::rtl::OUString& rsURL); + virtual ~TemplatePreviewProvider (void) {}; + virtual Image operator() (int nWidth, SdPage* pPage, ::sd::PreviewRenderer& rRenderer); + virtual int GetCostIndex (void); + virtual bool NeedsPageObject (void); +private: + ::rtl::OUString msURL; +}; + + + + +/** Create an empty default master page. +*/ +class DefaultPageObjectProvider : public PageObjectProvider +{ +public: + DefaultPageObjectProvider (void); + virtual SdPage* operator () (SdDrawDocument* pDocument); + virtual int GetCostIndex (void); + virtual bool operator== (const PageObjectProvider& rProvider); +}; + + + +/** This implementation of the PageObjectProvider simply returns an already + existing master page object. +*/ +class ExistingPageProvider : public ::sd::toolpanel::controls::PageObjectProvider +{ +public: + ExistingPageProvider (SdPage* pPage); + virtual SdPage* operator() (SdDrawDocument* pDocument); + virtual int GetCostIndex (void); + virtual bool operator== (const PageObjectProvider& rProvider); +private: + SdPage* mpPage; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.cxx b/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.cxx new file mode 100755 index 000000000000..94940d19ebd1 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.cxx @@ -0,0 +1,304 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageContainerQueue.hxx" + +#include "tools/IdleDetection.hxx" + +#include <set> + +namespace sd { namespace toolpanel { namespace controls { + +const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeout (15); +const sal_Int32 MasterPageContainerQueue::snDelayedCreationTimeoutWhenNotIdle (100); +const sal_Int32 MasterPageContainerQueue::snMasterPagePriorityBoost (5); +const sal_Int32 MasterPageContainerQueue::snWaitForMoreRequestsPriorityThreshold (-10); +sal_uInt32 MasterPageContainerQueue::snWaitForMoreRequestsCount(15); + +//===== MasterPageContainerQueue::PreviewCreationRequest ====================== + +class MasterPageContainerQueue::PreviewCreationRequest +{ +public: + PreviewCreationRequest (const SharedMasterPageDescriptor& rpDescriptor, int nPriority) + : mpDescriptor(rpDescriptor), + mnPriority(nPriority) + {} + SharedMasterPageDescriptor mpDescriptor; + int mnPriority; + class Compare {public: + bool operator() (const PreviewCreationRequest& r1,const PreviewCreationRequest& r2) + { + if (r1.mnPriority != r2.mnPriority) + { + // Prefer requests with higher priority. + return r1.mnPriority > r2.mnPriority; + } + else + { + // Prefer tokens that have been earlier created (those with lower + // value). + return r1.mpDescriptor->maToken < r2.mpDescriptor->maToken; + } + } + }; + class CompareToken {public: + MasterPageContainer::Token maToken; + CompareToken(MasterPageContainer::Token aToken) : maToken(aToken) {} + bool operator() (const PreviewCreationRequest& rRequest) + { return maToken==rRequest.mpDescriptor->maToken; } + }; +}; + + + + +//===== MasterPageContainerQueue::RequestQueue ================================ + +class MasterPageContainerQueue::RequestQueue + : public ::std::set<PreviewCreationRequest,PreviewCreationRequest::Compare> +{ +public: + RequestQueue (void) {} +}; + + + + +//===== MasterPageContainerQueue ============================================== + +MasterPageContainerQueue* MasterPageContainerQueue::Create ( + const ::boost::weak_ptr<ContainerAdapter>& rpContainer) +{ + MasterPageContainerQueue* pQueue = new MasterPageContainerQueue(rpContainer); + pQueue->LateInit(); + return pQueue; +} + + + + +MasterPageContainerQueue::MasterPageContainerQueue ( + const ::boost::weak_ptr<ContainerAdapter>& rpContainer) + : mpWeakContainer(rpContainer), + mpRequestQueue(new RequestQueue()), + maDelayedPreviewCreationTimer(), + mnRequestsServedCount(0) +{ +} + + + + +MasterPageContainerQueue::~MasterPageContainerQueue (void) +{ + maDelayedPreviewCreationTimer.Stop(); + while ( ! mpRequestQueue->empty()) + mpRequestQueue->erase(mpRequestQueue->begin()); +} + + + + +void MasterPageContainerQueue::LateInit (void) +{ + // Set up the timer for the delayed creation of preview bitmaps. + maDelayedPreviewCreationTimer.SetTimeout (snDelayedCreationTimeout); + Link aLink (LINK(this,MasterPageContainerQueue,DelayedPreviewCreation)); + maDelayedPreviewCreationTimer.SetTimeoutHdl(aLink); +} + + + + +bool MasterPageContainerQueue::RequestPreview (const SharedMasterPageDescriptor& rpDescriptor) +{ + bool bSuccess (false); + if (rpDescriptor.get() != NULL + && rpDescriptor->maLargePreview.GetSizePixel().Width() == 0) + { + sal_Int32 nPriority (CalculatePriority(rpDescriptor)); + + // Add a new or replace an existing request. + RequestQueue::iterator iRequest (::std::find_if( + mpRequestQueue->begin(), + mpRequestQueue->end(), + PreviewCreationRequest::CompareToken(rpDescriptor->maToken))); + // When a request for the same token exists then the lowest of the + // two priorities is used. + if (iRequest != mpRequestQueue->end()) + if (iRequest->mnPriority < nPriority) + { + mpRequestQueue->erase(iRequest); + iRequest = mpRequestQueue->end(); + } + + // Add a new request when none exists (or has just been erased). + if (iRequest == mpRequestQueue->end()) + { + mpRequestQueue->insert(PreviewCreationRequest(rpDescriptor,nPriority)); + maDelayedPreviewCreationTimer.Start(); + bSuccess = true; + } + } + return bSuccess; +} + + + + +sal_Int32 MasterPageContainerQueue::CalculatePriority ( + const SharedMasterPageDescriptor& rpDescriptor) const +{ + sal_Int32 nPriority; + + // The cost is used as a starting value. + int nCost (0); + if (rpDescriptor->mpPreviewProvider.get() != NULL) + { + nCost = rpDescriptor->mpPreviewProvider->GetCostIndex(); + if (rpDescriptor->mpPreviewProvider->NeedsPageObject()) + if (rpDescriptor->mpPageObjectProvider.get() != NULL) + nCost += rpDescriptor->mpPageObjectProvider->GetCostIndex(); + } + + // Its negative value is used so that requests with a low cost are + // preferred over those with high costs. + nPriority = -nCost; + + // Add a term that introduces an order based on the appearance in the + // AllMasterPagesSelector. + nPriority -= rpDescriptor->maToken / 3; + + // Process requests for the CurrentMasterPagesSelector first. + if (rpDescriptor->meOrigin == MasterPageContainer::MASTERPAGE) + nPriority += snMasterPagePriorityBoost; + + return nPriority; +} + + + + +IMPL_LINK(MasterPageContainerQueue, DelayedPreviewCreation, Timer*, pTimer) +{ + bool bIsShowingFullScreenShow (false); + bool bWaitForMoreRequests (false); + + do + { + if (mpRequestQueue->size() == 0) + break; + + // First check whether the system is idle. + sal_Int32 nIdleState (tools::IdleDetection::GetIdleState()); + if (nIdleState != tools::IdleDetection::IDET_IDLE) + { + if ((nIdleState&tools::IdleDetection::IDET_FULL_SCREEN_SHOW_ACTIVE) != 0) + bIsShowingFullScreenShow = true; + break; + } + + PreviewCreationRequest aRequest (*mpRequestQueue->begin()); + + // Check if the request should really be processed right now. + // Reasons to not do it are when its cost is high and not many other + // requests have been inserted into the queue that would otherwise + // be processed first. + if (aRequest.mnPriority < snWaitForMoreRequestsPriorityThreshold + && (mnRequestsServedCount+mpRequestQueue->size() < snWaitForMoreRequestsCount)) + { + // Wait for more requests before this one is processed. Note + // that the queue processing is not started anew when this + // method is left. That is done when the next request is + // inserted. + bWaitForMoreRequests = true; + break; + } + + mpRequestQueue->erase(mpRequestQueue->begin()); + + if (aRequest.mpDescriptor.get() != NULL) + { + mnRequestsServedCount += 1; + if ( ! mpWeakContainer.expired()) + { + ::boost::shared_ptr<ContainerAdapter> pContainer (mpWeakContainer); + if (pContainer.get() != NULL) + pContainer->UpdateDescriptor(aRequest.mpDescriptor,false,true,true); + } + } + } + while (false); + + if (mpRequestQueue->size() > 0 && ! bWaitForMoreRequests) + { + int nTimeout (snDelayedCreationTimeout); + if (bIsShowingFullScreenShow) + nTimeout = snDelayedCreationTimeoutWhenNotIdle; + maDelayedPreviewCreationTimer.SetTimeout(nTimeout); + pTimer->Start(); + } + + return 0; +} + + + + +bool MasterPageContainerQueue::HasRequest (MasterPageContainer::Token aToken) const +{ + RequestQueue::iterator iRequest (::std::find_if( + mpRequestQueue->begin(), + mpRequestQueue->end(), + PreviewCreationRequest::CompareToken(aToken))); + return (iRequest != mpRequestQueue->end()); +} + + + + +bool MasterPageContainerQueue::IsEmpty (void) const +{ + return mpRequestQueue->empty(); +} + + + + +void MasterPageContainerQueue::ProcessAllRequests (void) +{ + snWaitForMoreRequestsCount = 0; + if (mpRequestQueue->size() > 0) + maDelayedPreviewCreationTimer.Start(); +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.hxx b/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.hxx new file mode 100644 index 000000000000..3e8d31e67c1b --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageContainerQueue.hxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_QUEUE_HXX +#define SD_TOOLPANEL_CONTROLS_MASTER_PAGE_CONTAINER_QUEUE_HXX + +#include "MasterPageContainer.hxx" +#include "MasterPageDescriptor.hxx" + +#include <boost/scoped_ptr.hpp> +#include <boost/weak_ptr.hpp> + +namespace sd { namespace toolpanel { namespace controls { + + +/** The queue stores and processes all requests from a MasterPageContainer + for the creation of previews. + The order of request processing and its timing is controlled by a + heuristic that uses values given with each request and which is + controlled by various parameters that are described below. +*/ +class MasterPageContainerQueue +{ +public: + class ContainerAdapter { public: + virtual bool UpdateDescriptor ( + const SharedMasterPageDescriptor& rpDescriptor, + bool bForcePageObject, + bool bForcePreview, + bool bSendEvents) = 0; + }; + + static MasterPageContainerQueue* Create ( + const ::boost::weak_ptr<ContainerAdapter>& rpContainer); + virtual ~MasterPageContainerQueue (void); + + /** This method is typically called for entries in the container for + which GetPreviewState() returns OS_CREATABLE. The creation of the + preview is then scheduled to be executed asynchronously at a later + point in time. When the preview is available the change listeners + will be notified. + */ + bool RequestPreview (const SharedMasterPageDescriptor& rDescriptor); + + /** Return <TRUE/> when there is a request currently in the queue for + the given token. + */ + bool HasRequest (MasterPageContainer::Token aToken) const; + + /** Return <TRUE/> when there is at least one request in the queue. + */ + bool IsEmpty (void) const; + + /** After this call the queue does not wait anymore for requests with + higher priority when only a small number of requests with lower + priority are present. This method should be called when all + templates are inserted into the MasterPageContainer. + */ + void ProcessAllRequests (void); + +private: + ::boost::weak_ptr<ContainerAdapter> mpWeakContainer; + class PreviewCreationRequest; + class RequestQueue; + ::boost::scoped_ptr<RequestQueue> mpRequestQueue; + Timer maDelayedPreviewCreationTimer; + sal_uInt32 mnRequestsServedCount; + + // There are a couple of values that define various aspects of the + // heuristic that defines the order and timing in which requests for + // preview creation are processed. + + /** The time to wait (in milliseconds) between the creation of previews. + */ + static const sal_Int32 snDelayedCreationTimeout; + + /** The time to wait when the system is not idle. + */ + static const sal_Int32 snDelayedCreationTimeoutWhenNotIdle; + + /** Requests for previews of master pages in a document have their + priority increased by this value. + */ + static const sal_Int32 snMasterPagePriorityBoost; + + /** When only requests which a priority lower than this threshold exist + and not many requests have been made yet then wait with processing + them until more requests are present. + */ + static const sal_Int32 snWaitForMoreRequestsPriorityThreshold; + + /** When only requests which a priority lower than a threshold exist + and not more requests than this number have been made or already + processed then wait with processing them until more requests are + present. + */ + static sal_uInt32 snWaitForMoreRequestsCount; + + MasterPageContainerQueue (const ::boost::weak_ptr<ContainerAdapter>& rpContainer); + void LateInit (void); + + /** Calculate the priority that defines the order in which requests + are processed. + */ + sal_Int32 CalculatePriority (const SharedMasterPageDescriptor& rDescriptor) const; + + DECL_LINK(DelayedPreviewCreation, Timer *); +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageDescriptor.cxx b/sd/source/ui/toolpanel/controls/MasterPageDescriptor.cxx new file mode 100755 index 000000000000..6871883d65f5 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageDescriptor.cxx @@ -0,0 +1,423 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageDescriptor.hxx" + +#include "DocumentHelper.hxx" +#include "sdpage.hxx" +#include <tools/urlobj.hxx> + +namespace sd { namespace toolpanel { namespace controls { + + +//===== MasterPageDescriptor ================================================== + +MasterPageDescriptor::MasterPageDescriptor ( + MasterPageContainer::Origin eOrigin, + const sal_Int32 nTemplateIndex, + const String& rsURL, + const String& rsPageName, + const String& rsStyleName, + const bool bIsPrecious, + const ::boost::shared_ptr<PageObjectProvider>& rpPageObjectProvider, + const ::boost::shared_ptr<PreviewProvider>& rpPreviewProvider) + : maToken(MasterPageContainer::NIL_TOKEN), + meOrigin(eOrigin), + msURL(INetURLObject(rsURL).GetMainURL(INetURLObject::DECODE_UNAMBIGUOUS)), + msPageName(rsPageName), + msStyleName(rsStyleName), + mbIsPrecious(bIsPrecious), + mpMasterPage(NULL), + mpSlide(NULL), + maSmallPreview(), + maLargePreview(), + mpPreviewProvider(rpPreviewProvider), + mpPageObjectProvider(rpPageObjectProvider), + mnTemplateIndex(nTemplateIndex), + meURLClassification(URLCLASS_UNDETERMINED), + mnUseCount(0) +{ +} + + + + +MasterPageDescriptor::MasterPageDescriptor (const MasterPageDescriptor& rDescriptor) + : maToken(rDescriptor.maToken), + meOrigin(rDescriptor.meOrigin), + msURL(rDescriptor.msURL), + msPageName(rDescriptor.msPageName), + msStyleName(rDescriptor.msStyleName), + mbIsPrecious(rDescriptor.mbIsPrecious), + mpMasterPage(rDescriptor.mpMasterPage), + mpSlide(rDescriptor.mpSlide), + maSmallPreview(rDescriptor.maSmallPreview), + maLargePreview(rDescriptor.maLargePreview), + mpPreviewProvider(rDescriptor.mpPreviewProvider), + mpPageObjectProvider(rDescriptor.mpPageObjectProvider), + mnTemplateIndex(rDescriptor.mnTemplateIndex), + meURLClassification(rDescriptor.meURLClassification), + mnUseCount(rDescriptor.mnUseCount) +{ +} + + + + +MasterPageDescriptor::~MasterPageDescriptor (void) +{ +} + + + + +void MasterPageDescriptor::SetToken (MasterPageContainer::Token aToken) +{ + maToken = aToken; +} + + + + +Image MasterPageDescriptor::GetPreview (MasterPageContainer::PreviewSize eSize) +{ + if (eSize == MasterPageContainer::SMALL) + return maSmallPreview; + else + return maLargePreview; +} + + + + +::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > + MasterPageDescriptor::Update ( + const MasterPageDescriptor& rDescriptor) +{ + bool bDataChanged (false); + bool bIndexChanged (false); + bool bPreviewChanged (false); + + if (meOrigin==MasterPageContainer::UNKNOWN + && rDescriptor.meOrigin!=MasterPageContainer::UNKNOWN) + { + meOrigin = rDescriptor.meOrigin; + bIndexChanged = true; + } + + if (msURL.getLength()==0 && rDescriptor.msURL.getLength()!=0) + { + msURL = rDescriptor.msURL; + bDataChanged = true; + } + + if (msPageName.getLength()==0 && rDescriptor.msPageName.getLength()!=0) + { + msPageName = rDescriptor.msPageName; + bDataChanged = true; + } + + if (msStyleName.getLength()==0 && rDescriptor.msStyleName.getLength()!=0) + { + msStyleName = rDescriptor.msStyleName; + bDataChanged = true; + } + + if (mpPageObjectProvider.get()==NULL && rDescriptor.mpPageObjectProvider.get()!=NULL) + { + mpPageObjectProvider = rDescriptor.mpPageObjectProvider; + bDataChanged = true; + } + + if (mpPreviewProvider.get()==NULL && rDescriptor.mpPreviewProvider.get()!=NULL) + { + mpPreviewProvider = rDescriptor.mpPreviewProvider; + bPreviewChanged = true; + } + + if (mnTemplateIndex<0 && rDescriptor.mnTemplateIndex>=0) + { + mnTemplateIndex = rDescriptor.mnTemplateIndex; + bIndexChanged = true; + } + + // Prepare the list of event types that will be returned. + ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > pResult; + if (bDataChanged || bIndexChanged || bPreviewChanged) + { + pResult.reset(new std::vector<MasterPageContainerChangeEvent::EventType>()); + if (bDataChanged) + pResult->push_back(MasterPageContainerChangeEvent::DATA_CHANGED); + if (bIndexChanged) + pResult->push_back(MasterPageContainerChangeEvent::INDEX_CHANGED); + if (bPreviewChanged) + pResult->push_back(MasterPageContainerChangeEvent::PREVIEW_CHANGED); + } + + return pResult; +} + + + + +bool MasterPageDescriptor::UpdatePageObject ( + sal_Int32 nCostThreshold, + SdDrawDocument* pDocument) +{ + bool bModified (false); + + // Update the page object when that is not yet known. + if (mpMasterPage == NULL + && mpPageObjectProvider.get()!=NULL + && (nCostThreshold<0 || mpPageObjectProvider->GetCostIndex()<=nCostThreshold)) + { + // Note that pDocument may be NULL. + + SdPage* pPage = (*mpPageObjectProvider)(pDocument); + if (meOrigin == MasterPageContainer::MASTERPAGE) + { + mpMasterPage = pPage; + if (mpMasterPage != NULL) + mpMasterPage->SetPrecious(mbIsPrecious); + } + else + { + // Master pages from templates are copied into the local document. + if (pDocument != NULL) + mpMasterPage = DocumentHelper::CopyMasterPageToLocalDocument(*pDocument,pPage); + mpSlide = DocumentHelper::GetSlideForMasterPage(mpMasterPage); + } + + if (mpMasterPage != NULL) + { + // Update page name and style name. + if (msPageName.getLength() == 0) + msPageName = mpMasterPage->GetName(); + msStyleName = mpMasterPage->GetName(); + + // Delete an existing substitution. The next request for a preview + // will create the real one. + maSmallPreview = Image(); + maLargePreview = Image(); + mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(new PagePreviewProvider()); + } + else + { + DBG_ASSERT(false, "UpdatePageObject: master page is NULL"); + } + + bModified = true; + } + + return bModified; +} + + + + +bool MasterPageDescriptor::UpdatePreview ( + sal_Int32 nCostThreshold, + const Size& rSmallSize, + const Size& rLargeSize, + ::sd::PreviewRenderer& rRenderer) +{ + bool bModified (false); + + // Update the preview when that is not yet known. + if (maLargePreview.GetSizePixel().Width()==0 + && mpPreviewProvider.get()!=NULL + && (nCostThreshold<0 || mpPreviewProvider->GetCostIndex()<=nCostThreshold)) + { + SdPage* pPage = mpSlide; + if (pPage == NULL) + { + pPage = mpMasterPage; + } + maLargePreview = (*mpPreviewProvider)( + rLargeSize.Width(), + pPage, + rRenderer); + if (maLargePreview.GetSizePixel().Width() > 0) + { + // Create the small preview by scaling the large one down. + maSmallPreview = rRenderer.ScaleBitmap( + maLargePreview.GetBitmapEx(), + rSmallSize.Width()); + // The large preview may not have the desired width. Scale it + // accrodingly. + if (maLargePreview.GetSizePixel().Width() != rLargeSize.Width()) + maLargePreview = rRenderer.ScaleBitmap( + maLargePreview.GetBitmapEx(), + rLargeSize.Width()); + bModified = true; + } + } + + return bModified; +} + + + + +MasterPageDescriptor::URLClassification MasterPageDescriptor::GetURLClassification (void) +{ + if (meURLClassification == URLCLASS_UNDETERMINED) + { + if (msURL.getLength() == 0) + meURLClassification = URLCLASS_UNKNOWN; + else if (msURL.indexOf(::rtl::OUString::createFromAscii("presnt"))>=0) + { + meURLClassification = URLCLASS_PRESENTATION; + } + else if (msURL.indexOf(::rtl::OUString::createFromAscii("layout"))>=0) + { + meURLClassification = URLCLASS_LAYOUT; + } + else if (msURL.indexOf(::rtl::OUString::createFromAscii("educate"))>=0) + { + meURLClassification = URLCLASS_OTHER; + } + else + { + meURLClassification = URLCLASS_USER; + } + } + + return meURLClassification; +} + + + +//===== URLComparator ========================================================= + +MasterPageDescriptor::URLComparator::URLComparator (const ::rtl::OUString& sURL) + : msURL(sURL) +{ +} + + + + +bool MasterPageDescriptor::URLComparator::operator() ( + const SharedMasterPageDescriptor& rDescriptor) +{ + if (rDescriptor.get() == NULL) + return false; + else + return rDescriptor->msURL.equals(msURL); +} + + + + +// ===== StyleNameComparator ================================================== + +MasterPageDescriptor::StyleNameComparator::StyleNameComparator (const ::rtl::OUString& sStyleName) + : msStyleName(sStyleName) +{ +} + + + + +bool MasterPageDescriptor::StyleNameComparator::operator() ( + const SharedMasterPageDescriptor& rDescriptor) +{ + if (rDescriptor.get() == NULL) + return false; + else + return rDescriptor->msStyleName.equals(msStyleName); +} + + + + +//===== PageObjectComparator ================================================== + +MasterPageDescriptor::PageObjectComparator::PageObjectComparator (const SdPage* pPageObject) + : mpMasterPage(pPageObject) +{ +} + + + + +bool MasterPageDescriptor::PageObjectComparator::operator() ( + const SharedMasterPageDescriptor& rDescriptor) +{ + if (rDescriptor.get() == NULL) + return false; + else + return rDescriptor->mpMasterPage==mpMasterPage; +} + + + + +//===== AllComparator ========================================================= + +MasterPageDescriptor::AllComparator::AllComparator(const SharedMasterPageDescriptor& rDescriptor) + : mpDescriptor(rDescriptor) +{ +} + + + + +bool MasterPageDescriptor::AllComparator::operator() (const SharedMasterPageDescriptor&rDescriptor) +{ + if (rDescriptor.get() == NULL) + return false; + else + { + // Take URL, page name, style name, and page object into account + // when comparing two descriptors. When two descriptors are + // identical in any of these values then their are thought of as + // equivalent. Only the Origin has to be the same in both + // descriptors. + return + mpDescriptor->meOrigin == rDescriptor->meOrigin + && ( + (mpDescriptor->msURL.getLength()>0 + && mpDescriptor->msURL.equals(rDescriptor->msURL)) + || (mpDescriptor->msPageName.getLength()>0 + && mpDescriptor->msPageName.equals(rDescriptor->msPageName)) + || (mpDescriptor->msStyleName.getLength()>0 + && mpDescriptor->msStyleName.equals(rDescriptor->msStyleName)) + || (mpDescriptor->mpMasterPage!=NULL + && mpDescriptor->mpMasterPage==rDescriptor->mpMasterPage) + || (mpDescriptor->mpPageObjectProvider.get()!=NULL + && rDescriptor->mpPageObjectProvider.get()!=NULL + && mpDescriptor->mpPageObjectProvider==rDescriptor->mpPageObjectProvider)); + } +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPageDescriptor.hxx b/sd/source/ui/toolpanel/controls/MasterPageDescriptor.hxx new file mode 100755 index 000000000000..0303989e3379 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageDescriptor.hxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_MASTER_PAGE_DESCRIPTOR_HXX +#define SD_TOOLPANEL_CONTROLS_MASTER_PAGE_DESCRIPTOR_HXX + +#include "MasterPageContainer.hxx" +#include <boost/shared_ptr.hpp> + +namespace sd { namespace toolpanel { namespace controls { + +class PageObjectProvider; +class PreviewProvider; + +class MasterPageDescriptor; +typedef ::boost::shared_ptr<MasterPageDescriptor> SharedMasterPageDescriptor; + +/** A collection of data that is stored for every master page in the + MasterpageContainer. +*/ +class MasterPageDescriptor +{ +public: + MasterPageDescriptor ( + MasterPageContainer::Origin eOrigin, + const sal_Int32 nTemplateIndex, + const String& rURL, + const String& rPageName, + const String& rStyleName, + const bool bIsPrecious, + const ::boost::shared_ptr<PageObjectProvider>& rpPageObjectProvider, + const ::boost::shared_ptr<PreviewProvider>& rpPreviewProvider); + MasterPageDescriptor (const MasterPageDescriptor& rDescriptor); + ~MasterPageDescriptor (void); + + void SetToken (MasterPageContainer::Token aToken); + + /** Update the called MasterPageDescriptor object with values from the + given one. Only those values are updated that have default values + in the called object and that have non-default values in the given + one. + @return + Returns a list of event types for which event notifications have + to be sent to listeners. The list may be empty or NULL. + */ + ::std::auto_ptr<std::vector<MasterPageContainerChangeEvent::EventType> > + Update ( + const MasterPageDescriptor& rDescriptor); + + /** This convenience method returns either a small or a large preview, + depending on the given size specifier. + Note that the previews are not created when they are not present. + @return + The returned preview may be empty. + */ + Image GetPreview (MasterPageContainer::PreviewSize ePreviewSize); + + /** Use the PreviewProvider to get access to a preview of the master + page. + + Note that this is only done, when either bForce is <TRUE/> or + the PreviewProvider::GetCostIndex() returns 0. + + The small preview is created by scaling the large one, not by + calling PreviewProvider::operator() a second time. + + It is the responsibility of the caller to call UpdatePageObject() + before calling this method when the PreviewProvider can only work + when the master page object is present, i.e. its NeedsPageObject() + method returns <TRUE/>. + + @param nCostThreshold + When this is zero or positive then the preview is created only + when the preview provider has a cost equal to or smaller than + this threshold. A negative value forces the preview to be + created, regardless of the cost. + @param rSmallSize + Size of the small preview. + @param rLargeSize + Size of the large preview. + @param rRenderer + A PreviewRenderer object that may be used to create a preview. + @return + When the previews are successfully provided then <TRUE/> is + returned. + */ + bool UpdatePreview ( + sal_Int32 nCostThreshold, + const Size& rSmallSize, + const Size& rLargeSize, + ::sd::PreviewRenderer& rRenderer); + + /** Use the PageObjectProvider to get access to the master page object. + + Note that this is only done, when either bForce is <TRUE/> or the + PreviewProvider::GetCostIndex() returns 0. + + @param nCostThreshold + When this is zero or positive then the page object is created + only when the page object provider has a cost equal to or + smaller than this threshold. A negative value forces the + page object be created, regardless of the cost. + @param pDocument + This document of the MasterPageContainer may be used to create + a page object with or store one in. + @return + When the master page object is successfully provided then + <TRUE/> is returned. + */ + bool UpdatePageObject ( + sal_Int32 nCostThreshold, + SdDrawDocument* pDocument); + + enum URLClassification { + URLCLASS_USER, + URLCLASS_LAYOUT, + URLCLASS_PRESENTATION, + URLCLASS_OTHER, + URLCLASS_UNKNOWN, + URLCLASS_UNDETERMINED + }; + + URLClassification GetURLClassification (void); + + /** The Token under which the MasterPageContainer gives access to the + object. + */ + MasterPageContainer::Token maToken; + + /** A rough specification of the origin of the master page. + */ + MasterPageContainer::Origin meOrigin; + + /** The URL is not empty for master pages loaded from a template + document. + */ + ::rtl::OUString msURL; + + /** Taken from the title of the template file. + */ + ::rtl::OUString msPageName; + + /** Taken from the master page object. + */ + ::rtl::OUString msStyleName; + + const bool mbIsPrecious; + + /** The actual master page. + */ + SdPage* mpMasterPage; + + /** A slide that uses the master page. + */ + SdPage* mpSlide; + + /** A small (the default size) preview of the master page. May be + empty. When this smaller preview is not empty then the larger one + is not empty, too. + */ + Image maSmallPreview; + + /** A large preview of the master page. May be empty. When this larger + preview is not empty then the smaller one is not empty, too. + */ + Image maLargePreview; + + /** The prewview provider. May be empty. May be replaced during the + lifetime of a MasterPageDescriptor object. + */ + ::boost::shared_ptr<PreviewProvider> mpPreviewProvider; + + /** The master page provider. May be empty. May be replaced during + the lifetime of a MasterPageDescriptor object. + */ + ::boost::shared_ptr<PageObjectProvider> mpPageObjectProvider; + + /** This index represents the order in which templates are provided via + the TemplateScanner. It defines the order in which the entries in + the AllMasterPagesSelector are displayed. The default value is -1. + */ + sal_Int32 mnTemplateIndex; + + URLClassification meURLClassification; + + sal_Int32 mnUseCount; + + class URLComparator { public: + ::rtl::OUString msURL; + URLComparator (const ::rtl::OUString& sURL); + bool operator() (const SharedMasterPageDescriptor& rDescriptor); + }; + class StyleNameComparator { public: + ::rtl::OUString msStyleName; + StyleNameComparator (const ::rtl::OUString& sStyleName); + bool operator() (const SharedMasterPageDescriptor& rDescriptor); + }; + class PageObjectComparator { public: + const SdPage* mpMasterPage; + PageObjectComparator (const SdPage* pPageObject); + bool operator() (const SharedMasterPageDescriptor& rDescriptor); + }; + class AllComparator { public: + AllComparator(const SharedMasterPageDescriptor& rDescriptor); + bool operator() (const SharedMasterPageDescriptor& rDescriptor); + private: + SharedMasterPageDescriptor mpDescriptor; + }; + + +}; + + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPageObserver.cxx b/sd/source/ui/toolpanel/controls/MasterPageObserver.cxx new file mode 100755 index 000000000000..2ba0cc678403 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPageObserver.cxx @@ -0,0 +1,426 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPageObserver.hxx" + +#include <algorithm> +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include <hash_map> +#include <set> +#include <vector> +#include <svl/lstner.hxx> +#include <osl/doublecheckedlocking.h> +#include <osl/getglobalmutex.hxx> + + +namespace sd { + +class MasterPageObserver::Implementation + : public SfxListener +{ +public: + /** The single instance of this class. It is created on demand when + Instance() is called for the first time. + */ + static MasterPageObserver* mpInstance; + + /** The master page observer will listen to events of this document and + detect changes of the use of master pages. + */ + void RegisterDocument (SdDrawDocument& rDocument); + + /** The master page observer will stop to listen to events of this + document. + */ + void UnregisterDocument (SdDrawDocument& rDocument); + + /** Add a listener that is informed of master pages that are newly + assigned to slides or become unassigned. + @param rEventListener + The event listener to call for future events. Call + RemoveEventListener() before the listener is destroyed. + */ + void AddEventListener (const Link& rEventListener); + + /** Remove the given listener from the list of listeners. + @param rEventListener + After this method returns the given listener is not called back + from this object. Passing a listener that has not + been registered before is safe and is silently ignored. + */ + void RemoveEventListener (const Link& rEventListener); + + /** Return a set of the names of master pages for the given document. + This convenience method exists because this set is part of the + internal data structure and thus takes no time to create. + */ + inline MasterPageObserver::MasterPageNameSet GetMasterPageNames ( + SdDrawDocument& rDocument); + +private: + ::std::vector<Link> maListeners; + + struct DrawDocHash { + size_t operator()(SdDrawDocument* argument) const + { return reinterpret_cast<unsigned long>(argument); } + }; + typedef ::std::hash_map<SdDrawDocument*, + MasterPageObserver::MasterPageNameSet, + DrawDocHash> + MasterPageContainer; + MasterPageContainer maUsedMasterPages; + + virtual void Notify( + SfxBroadcaster& rBroadcaster, + const SfxHint& rHint); + + void AnalyzeUsedMasterPages (SdDrawDocument& rDocument); + + void SendEvent (MasterPageObserverEvent& rEvent); +}; + +MasterPageObserver* MasterPageObserver::Implementation::mpInstance = NULL; + + + +//===== MasterPageObserver ==================================================== + +MasterPageObserver& MasterPageObserver::Instance (void) +{ + if (Implementation::mpInstance == NULL) + { + ::osl::GetGlobalMutex aMutexFunctor; + ::osl::MutexGuard aGuard (aMutexFunctor()); + if (Implementation::mpInstance == NULL) + { + MasterPageObserver* pInstance = new MasterPageObserver (); + SdGlobalResourceContainer::Instance().AddResource ( + ::std::auto_ptr<SdGlobalResource>(pInstance)); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + Implementation::mpInstance = pInstance; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + + DBG_ASSERT(Implementation::mpInstance!=NULL, + "MasterPageObserver::Instance(): instance is NULL"); + return *Implementation::mpInstance; +} + + + + +void MasterPageObserver::RegisterDocument (SdDrawDocument& rDocument) +{ + mpImpl->RegisterDocument (rDocument); +} + + + + +void MasterPageObserver::UnregisterDocument (SdDrawDocument& rDocument) +{ + mpImpl->UnregisterDocument (rDocument); +} + + + + +void MasterPageObserver::AddEventListener (const Link& rEventListener) +{ + + mpImpl->AddEventListener (rEventListener); +} + + + + +void MasterPageObserver::RemoveEventListener (const Link& rEventListener) +{ + mpImpl->RemoveEventListener (rEventListener); +} + + + + +MasterPageObserver::MasterPageObserver (void) + : mpImpl (new Implementation()) +{} + + + + +MasterPageObserver::~MasterPageObserver (void) +{} + + + + +//===== MasterPageObserver::Implementation ==================================== + +void MasterPageObserver::Implementation::RegisterDocument ( + SdDrawDocument& rDocument) +{ + // Gather the names of all the master pages in the given document. + MasterPageContainer::data_type aMasterPageSet; + USHORT nMasterPageCount = rDocument.GetMasterSdPageCount(PK_STANDARD); + for (USHORT nIndex=0; nIndex<nMasterPageCount; nIndex++) + { + SdPage* pMasterPage = rDocument.GetMasterSdPage (nIndex, PK_STANDARD); + if (pMasterPage != NULL) + aMasterPageSet.insert (pMasterPage->GetName()); + } + + maUsedMasterPages[&rDocument] = aMasterPageSet; + + StartListening (rDocument); +} + + + + +void MasterPageObserver::Implementation::UnregisterDocument ( + SdDrawDocument& rDocument) +{ + EndListening (rDocument); + + MasterPageContainer::iterator aMasterPageDescriptor(maUsedMasterPages.find(&rDocument)); + if(aMasterPageDescriptor != maUsedMasterPages.end()) + maUsedMasterPages.erase(aMasterPageDescriptor); +} + + + + +void MasterPageObserver::Implementation::AddEventListener ( + const Link& rEventListener) +{ + if (::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener) == maListeners.end()) + { + maListeners.push_back (rEventListener); + + // Tell the new listener about all the master pages that are + // currently in use. + typedef ::std::vector<String> StringList; + StringList aNewMasterPages; + StringList aRemovedMasterPages; + MasterPageContainer::iterator aDocumentIterator; + for (aDocumentIterator=maUsedMasterPages.begin(); + aDocumentIterator!=maUsedMasterPages.end(); + ++aDocumentIterator) + { + ::std::set<String>::reverse_iterator aNameIterator; + for (aNameIterator=aDocumentIterator->second.rbegin(); + aNameIterator!=aDocumentIterator->second.rend(); + ++aNameIterator) + { + MasterPageObserverEvent aEvent ( + MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS, + *aDocumentIterator->first, + *aNameIterator); + SendEvent (aEvent); + } + } + } +} + + + + +void MasterPageObserver::Implementation::RemoveEventListener ( + const Link& rEventListener) +{ + maListeners.erase ( + ::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener)); +} + + + + +MasterPageObserver::MasterPageNameSet + MasterPageObserver::Implementation::GetMasterPageNames ( + SdDrawDocument& rDocument) +{ + MasterPageContainer::iterator aMasterPageDescriptor ( + maUsedMasterPages.find(&rDocument)); + if (aMasterPageDescriptor != maUsedMasterPages.end()) + return aMasterPageDescriptor->second; + else + // Not found so return an empty set. + return MasterPageObserver::MasterPageNameSet(); +} + + + + +void MasterPageObserver::Implementation::Notify( + SfxBroadcaster& rBroadcaster, + const SfxHint& rHint) +{ + if (rHint.ISA(SdrHint)) + { + SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint)); + switch (rSdrHint.GetKind()) + { + case HINT_PAGEORDERCHG: + // Process the modified set of pages only when the number of + // standard and notes master pages are equal. This test + // filters out events that are sent in between the insertion + // of a new standard master page and a new notes master + // page. + if (rBroadcaster.ISA(SdDrawDocument)) + { + SdDrawDocument& rDocument ( + static_cast<SdDrawDocument&>(rBroadcaster)); + if (rDocument.GetMasterSdPageCount(PK_STANDARD) + == rDocument.GetMasterSdPageCount(PK_NOTES)) + { + AnalyzeUsedMasterPages (rDocument); + } + } + break; + + default: + break; + } + } +} + + + + +void MasterPageObserver::Implementation::AnalyzeUsedMasterPages ( + SdDrawDocument& rDocument) +{ + // Create a set of names of the master pages used by the given document. + USHORT nMasterPageCount = rDocument.GetMasterSdPageCount(PK_STANDARD); + ::std::set<String> aCurrentMasterPages; + for (USHORT nIndex=0; nIndex<nMasterPageCount; nIndex++) + { + SdPage* pMasterPage = rDocument.GetMasterSdPage (nIndex, PK_STANDARD); + if (pMasterPage != NULL) + aCurrentMasterPages.insert (pMasterPage->GetName()); + OSL_TRACE("currently used master page %d is %s", + nIndex, + ::rtl::OUStringToOString(pMasterPage->GetName(), + RTL_TEXTENCODING_UTF8).getStr()); + } + + typedef ::std::vector<String> StringList; + StringList aNewMasterPages; + StringList aRemovedMasterPages; + MasterPageContainer::iterator aOldMasterPagesDescriptor ( + maUsedMasterPages.find(&rDocument)); + if (aOldMasterPagesDescriptor != maUsedMasterPages.end()) + { + StringList::iterator I; + + ::std::set<String>::iterator J; + int i=0; + for (J=aOldMasterPagesDescriptor->second.begin(); + J!=aOldMasterPagesDescriptor->second.end(); + ++J) + OSL_TRACE("old used master page %d is %s", + i++, + ::rtl::OUStringToOString(*J, + RTL_TEXTENCODING_UTF8).getStr()); + + // Send events about the newly used master pages. + ::std::set_difference ( + aCurrentMasterPages.begin(), + aCurrentMasterPages.end(), + aOldMasterPagesDescriptor->second.begin(), + aOldMasterPagesDescriptor->second.end(), + ::std::back_insert_iterator<StringList>(aNewMasterPages)); + for (I=aNewMasterPages.begin(); I!=aNewMasterPages.end(); ++I) + { + OSL_TRACE(" added master page %s", + ::rtl::OUStringToOString(*I, + RTL_TEXTENCODING_UTF8).getStr()); + + MasterPageObserverEvent aEvent ( + MasterPageObserverEvent::ET_MASTER_PAGE_ADDED, + rDocument, + *I); + SendEvent (aEvent); + } + + // Send events about master pages that are not used any longer. + ::std::set_difference ( + aOldMasterPagesDescriptor->second.begin(), + aOldMasterPagesDescriptor->second.end(), + aCurrentMasterPages.begin(), + aCurrentMasterPages.end(), + ::std::back_insert_iterator<StringList>(aRemovedMasterPages)); + for (I=aRemovedMasterPages.begin(); I!=aRemovedMasterPages.end(); ++I) + { + OSL_TRACE(" removed master page %s", + ::rtl::OUStringToOString(*I, + RTL_TEXTENCODING_UTF8).getStr()); + + MasterPageObserverEvent aEvent ( + MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED, + rDocument, + *I); + SendEvent (aEvent); + } + + // Store the new list of master pages. + aOldMasterPagesDescriptor->second = aCurrentMasterPages; + } +} + + + + +void MasterPageObserver::Implementation::SendEvent ( + MasterPageObserverEvent& rEvent) +{ + ::std::vector<Link>::iterator aLink (maListeners.begin()); + ::std::vector<Link>::iterator aEnd (maListeners.end()); + while (aLink!=aEnd) + { + aLink->Call (&rEvent); + ++aLink; + } +} + + +} // end of namespace sd diff --git a/sd/source/ui/toolpanel/controls/MasterPagesPanel.cxx b/sd/source/ui/toolpanel/controls/MasterPagesPanel.cxx new file mode 100755 index 000000000000..8dab51e93a58 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPagesPanel.cxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPagesPanel.hxx" +#include "taskpane/ScrollPanel.hxx" +#include "CurrentMasterPagesSelector.hxx" +#include "RecentMasterPagesSelector.hxx" +#include "AllMasterPagesSelector.hxx" +#include "taskpane/ToolPanelViewShell.hxx" +#include "taskpane/TaskPaneControlFactory.hxx" +#include "taskpane/TitledControl.hxx" +#include "../TaskPaneShellManager.hxx" + +#include "DrawViewShell.hxx" +#include "ViewShellBase.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" +#include "helpids.h" +#include <svtools/valueset.hxx> + +namespace sd { namespace toolpanel { namespace controls { + + +MasterPagesPanel::MasterPagesPanel (::Window& i_rParentWindow, ToolPanelViewShell& i_rPanelViewShell) + :ScrollPanel (i_rParentWindow) + ,m_pPanelViewShell( &i_rPanelViewShell ) +{ + impl_construct( m_pPanelViewShell->GetViewShellBase() ); +} + +void MasterPagesPanel::impl_construct( ViewShellBase& rBase ) +{ + SdDrawDocument* pDocument = rBase.GetDocument(); + ::std::auto_ptr<controls::MasterPagesSelector> pSelector; + TitledControl* pTitledControl; + + ::boost::shared_ptr<MasterPageContainer> pContainer (new MasterPageContainer()); + + // Create a panel with the master pages that are in use by the currently + // edited document. + DrawViewShell* pDrawViewShell = dynamic_cast<DrawViewShell*>(rBase.GetMainViewShell().get()); + pSelector.reset(new controls::CurrentMasterPagesSelector ( + this, + *pDocument, + rBase, + pContainer)); + pSelector->LateInit(); + pSelector->SetSmartHelpId( SmartId(HID_SD_TASK_PANE_PREVIEW_CURRENT) ); + GetShellManager()->AddSubShell( + HID_SD_TASK_PANE_PREVIEW_CURRENT, + pSelector.get(), + pSelector->GetWindow()); + pTitledControl = AddControl ( + ::std::auto_ptr<TreeNode>(pSelector.release()), + SdResId(STR_TASKPANEL_CURRENT_MASTER_PAGES_TITLE), + HID_SD_CURRENT_MASTERS); + + // Create a panel with the most recently used master pages. + pSelector.reset(new controls::RecentMasterPagesSelector ( + this, + *pDocument, + rBase, + pContainer)); + pSelector->LateInit(); + pSelector->SetSmartHelpId( SmartId(HID_SD_TASK_PANE_PREVIEW_RECENT) ); + GetShellManager()->AddSubShell( + HID_SD_TASK_PANE_PREVIEW_RECENT, + pSelector.get(), + pSelector->GetWindow()); + pTitledControl = AddControl ( + ::std::auto_ptr<TreeNode>(pSelector.release()), + SdResId(STR_TASKPANEL_RECENT_MASTER_PAGES_TITLE), + HID_SD_RECENT_MASTERS); + + // Create a panel with all available master pages. + pSelector.reset(new controls::AllMasterPagesSelector ( + this, + *pDocument, + rBase, + *pDrawViewShell, + pContainer)); + pSelector->LateInit(); + pSelector->SetSmartHelpId( SmartId(HID_SD_TASK_PANE_PREVIEW_ALL) ); + GetShellManager()->AddSubShell( + HID_SD_TASK_PANE_PREVIEW_ALL, + pSelector.get(), + pSelector->GetWindow()); + pTitledControl = AddControl ( + ::std::auto_ptr<TreeNode>(pSelector.release()), + SdResId(STR_TASKPANEL_ALL_MASTER_PAGES_TITLE), + HID_SD_ALL_MASTERS); +} + + + + + +MasterPagesPanel::~MasterPagesPanel (void) +{ + TaskPaneShellManager* pShellManager( GetShellManager() ); + OSL_ENSURE( pShellManager, "MasterPagesPanel::~MasterPagesPanel: no shell manager anymore - cannot remove sub shells!" ); + if ( pShellManager ) + { + pShellManager->RemoveSubShell( HID_SD_TASK_PANE_PREVIEW_CURRENT ); + pShellManager->RemoveSubShell( HID_SD_TASK_PANE_PREVIEW_RECENT ); + pShellManager->RemoveSubShell( HID_SD_TASK_PANE_PREVIEW_ALL ); + } +} + + + + +TaskPaneShellManager* MasterPagesPanel::GetShellManager() +{ + if ( m_pPanelViewShell ) + return &m_pPanelViewShell->GetSubShellManager(); + return TreeNode::GetShellManager(); +} + + + + +std::auto_ptr< ControlFactory > MasterPagesPanel::CreateControlFactory( ToolPanelViewShell& i_rToolPanelShell ) +{ + return std::auto_ptr< ControlFactory >( + new RootControlFactoryWithArg< MasterPagesPanel, ToolPanelViewShell >( i_rToolPanelShell ) ); +} + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPagesPanel.hxx b/sd/source/ui/toolpanel/controls/MasterPagesPanel.hxx new file mode 100755 index 000000000000..932007802ebf --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPagesPanel.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 SD_TASKPANE_CONTROLS_MASTER_PAGES_PANEL_HXX +#define SD_TASKPANE_CONTROLS_MASTER_PAGES_PANEL_HXX + +#include "taskpane/ScrollPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class ControlFactory; +class TreeNode; +class ToolPanelViewShell; +} } + +namespace sd { namespace toolpanel { namespace controls { + +/** The master pages panel combines three master page related panels into + one. This has the benefit that creation of the task pane becomes a + little bit simpler and that common scroll bars can be displayed. +*/ +class MasterPagesPanel + : public ScrollPanel +{ +public: + MasterPagesPanel ( + ::Window& i_rParentWindow, + ToolPanelViewShell& i_rPanelViewShell); + virtual ~MasterPagesPanel (void); + + // TreeNode overridables + virtual TaskPaneShellManager* GetShellManager (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory (ToolPanelViewShell& i_rToolPanelShell); + +private: + void impl_construct( ViewShellBase& rBase ); + +private: + ToolPanelViewShell* m_pPanelViewShell; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/MasterPagesSelector.cxx b/sd/source/ui/toolpanel/controls/MasterPagesSelector.cxx new file mode 100755 index 000000000000..b321dbf8dd14 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPagesSelector.cxx @@ -0,0 +1,854 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "MasterPagesSelector.hxx" + +#include "MasterPageContainer.hxx" +#include "DocumentHelper.hxx" +#include "pres.hxx" +#include "drawdoc.hxx" +#include "DrawDocShell.hxx" +#include "sdpage.hxx" +#include "glob.hxx" +#include "glob.hrc" +#include "app.hrc" +#include "res_bmp.hrc" +#include "strings.hrc" +#include "DrawViewShell.hxx" +#include "DrawController.hxx" +#include "SlideSorterViewShell.hxx" +#include "PreviewValueSet.hxx" +#include "ViewShellBase.hxx" +#include "../TaskPaneShellManager.hxx" +#include "taskpane/TitledControl.hxx" +#include "taskpane/ControlContainer.hxx" +#include "controller/SlideSorterController.hxx" +#include "controller/SlsPageSelector.hxx" +#include <sfx2/objface.hxx> +#include "sdresid.hxx" +#include "TemplateScanner.hxx" +#ifndef _SD_DRAWVIEW_HXX +#include "drawview.hxx" +#endif +#include <vcl/image.hxx> +#include <svl/languageoptions.hxx> +#include <sfx2/app.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/mnumgr.hxx> +#include <svl/itemset.hxx> +#include <svl/eitem.hxx> +#include <svx/dlgutil.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svxids.hrc> +#include "FrameView.hxx" +#include "sdpage.hxx" +#include "stlpool.hxx" +#include "unmovss.hxx" +#include <sfx2/request.hxx> +#include <svl/itempool.hxx> + +using namespace ::sd::toolpanel::controls; +#define MasterPagesSelector +#include "sdslots.hxx" + +using namespace ::com::sun::star::text; + + + +namespace sd { namespace toolpanel { namespace controls { + + +SFX_IMPL_INTERFACE(MasterPagesSelector, SfxShell, + SdResId(STR_MASTERPAGESSELECTOR)) +{ + SFX_POPUPMENU_REGISTRATION( SdResId(RID_TASKPANE_MASTERPAGESSELECTOR_POPUP) ); +} + +TYPEINIT1(MasterPagesSelector, SfxShell); + + + +MasterPagesSelector::MasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer) + : TreeNode (pParent), + SfxShell(), + maMutex(), + mpContainer(rpContainer), + mrDocument(rDocument), + mpPageSet (new PreviewValueSet(pParent)), + mrBase(rBase), + mnDefaultClickAction(SID_TP_APPLY_TO_ALL_SLIDES), + maPreviewUpdateQueue(), + maCurrentItemList(), + maTokenToValueSetIndex(), + maLockedMasterPages() +{ + SetPool (&rDocument.GetPool()); + + mpPageSet->SetSelectHdl ( + LINK(this, MasterPagesSelector, ClickHandler)); + mpPageSet->SetRightMouseClickHandler ( + LINK(this, MasterPagesSelector, RightClickHandler)); + mpPageSet->SetContextMenuCallback ( + LINK(this, MasterPagesSelector, ContextMenuCallback)); + mpPageSet->SetStyle(mpPageSet->GetStyle() | WB_NO_DIRECTSELECT); + mpPageSet->SetPreviewSize(mpContainer->GetPreviewSizePixel()); + mpPageSet->Show(); + + Link aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener)); + mpContainer->AddChangeListener(aChangeListener); +} + + + + +MasterPagesSelector::~MasterPagesSelector (void) +{ + Clear(); + mpPageSet.reset(); + UpdateLocks(ItemList()); + + if (GetShellManager() != NULL) + GetShellManager()->RemoveSubShell (this); + + Link aChangeListener (LINK(this,MasterPagesSelector,ContainerChangeListener)); + mpContainer->RemoveChangeListener(aChangeListener); +} + + + + +void MasterPagesSelector::LateInit (void) +{ +} + + + + +sal_Int32 MasterPagesSelector::GetPreferredWidth (sal_Int32 nHeight) +{ + const ::osl::MutexGuard aGuard (maMutex); + + return mpPageSet->GetPreferredWidth (nHeight); +} + + + + +sal_Int32 MasterPagesSelector::GetPreferredHeight (sal_Int32 nWidth) +{ + const ::osl::MutexGuard aGuard (maMutex); + + return mpPageSet->GetPreferredHeight (nWidth); +} + + + + +Size MasterPagesSelector::GetPreferredSize (void) +{ + int nPreferredWidth = GetPreferredWidth( + mpPageSet->GetOutputSizePixel().Height()); + int nPreferredHeight = GetPreferredHeight(nPreferredWidth); + return Size (nPreferredWidth, nPreferredHeight); + +} + + + + +void MasterPagesSelector::UpdateLocks (const ItemList& rItemList) +{ + ItemList aNewLockList; + + // In here we first lock the master pages in the given list and then + // release the locks acquired in a previous call to this method. When + // this were done the other way round the lock count of some master + // pages might drop temporarily to 0 and would lead to unnecessary + // deletion and re-creation of MasterPageDescriptor objects. + + // Lock the master pages in the given list. + ItemList::const_iterator iItem; + for (iItem=rItemList.begin(); iItem!=rItemList.end(); ++iItem) + { + mpContainer->AcquireToken(*iItem); + aNewLockList.push_back(*iItem); + } + + // Release the previously locked master pages. + ItemList::const_iterator iPage; + ItemList::const_iterator iEnd (maLockedMasterPages.end()); + for (iPage=maLockedMasterPages.begin(); iPage!=iEnd; ++iPage) + mpContainer->ReleaseToken(*iPage); + + maLockedMasterPages.swap(aNewLockList); +} + + + + +void MasterPagesSelector::Fill (void) +{ + ::std::auto_ptr<ItemList> pItemList (new ItemList()); + + Fill(*pItemList); + + UpdateLocks(*pItemList); + UpdateItemList(pItemList); +} + + + + +ResId MasterPagesSelector::GetContextMenuResId (void) const +{ + return SdResId(RID_TASKPANE_MASTERPAGESSELECTOR_POPUP); +} + + + + +IMPL_LINK(MasterPagesSelector, ClickHandler, PreviewValueSet*, EMPTYARG) +{ + // We use the framework to assign the clicked-on master page because we + // so use the same mechanism as the context menu does (where we do not + // have the option to call the assignment method directly.) + if (GetShellManager() != NULL) + GetShellManager()->MoveToTop (this); + + SfxViewFrame* pViewFrame = mrBase.GetViewFrame(); + if (pViewFrame != NULL) + { + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + if (pDispatcher != NULL) + pDispatcher->Execute(mnDefaultClickAction); + } + + return 0; +} + + + + +IMPL_LINK(MasterPagesSelector, RightClickHandler, MouseEvent*, pEvent) +{ + // Here we only prepare the display of the context menu: the item under + // the mouse is selected. The actual display of the context menu is + // done in ContextMenuCallback which is called indirectly through + // PreviewValueSet::Command(). + mpPageSet->GrabFocus (); + mpPageSet->ReleaseMouse(); + if (GetDispatcher() != NULL && pEvent != NULL) + { + USHORT nIndex = mpPageSet->GetItemId (pEvent->GetPosPixel()); + if (nIndex > 0) + mpPageSet->SelectItem (nIndex); + } + return 0; +} + + + + +IMPL_LINK(MasterPagesSelector, ContextMenuCallback, CommandEvent*, pEvent) +{ + // Use the currently selected item and show the popup menu in its + // center. + if (GetShellManager() != NULL) + GetShellManager()->MoveToTop (this); + const USHORT nIndex = mpPageSet->GetSelectItemId(); + if (nIndex > 0 && pEvent!=NULL) + { + // The position of the upper left corner of the context menu is + // taken either from the mouse position (when the command was sent + // as reaction to a right click) or in the center of the selected + // item (when the command was sent as reaction to Shift+F10.) + Point aPosition (pEvent->GetMousePosPixel()); + if ( ! pEvent->IsMouseEvent()) + { + Rectangle aBBox (mpPageSet->GetItemRect(nIndex)); + aPosition = aBBox.Center(); + } + + const ResId aPopupResId (GetContextMenuResId()); + mrBase.GetViewFrame()->GetDispatcher()->ExecutePopup( + aPopupResId, + mpPageSet.get(), + &aPosition); + } + + return 0; +} + + + + +IMPL_LINK(MasterPagesSelector, ContainerChangeListener, MasterPageContainerChangeEvent*, pEvent) +{ + if (pEvent) + NotifyContainerChangeEvent(*pEvent); + return 0; +} + + + + +SdPage* MasterPagesSelector::GetSelectedMasterPage (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + SdPage* pMasterPage = NULL; + USHORT nIndex = mpPageSet->GetSelectItemId(); + UserData* pData = GetUserData(nIndex); + if (pData != NULL) + { + pMasterPage = mpContainer->GetPageObjectForToken(pData->second); + } + return pMasterPage; +} + + + + +/** Assemble a list of all slides of the document and pass it to + AssignMasterPageToPageList(). +*/ +void MasterPagesSelector::AssignMasterPageToAllSlides (SdPage* pMasterPage) +{ + do + { + if (pMasterPage == NULL) + break; + + USHORT nPageCount = mrDocument.GetSdPageCount(PK_STANDARD); + if (nPageCount == 0) + break; + + // Get a list of all pages. As a little optimization we only + // include pages that do not already have the given master page + // assigned. + String sFullLayoutName (pMasterPage->GetLayoutName()); + ::sd::slidesorter::SharedPageSelection pPageList ( + new ::sd::slidesorter::SlideSorterViewShell::PageSelection()); + for (USHORT nPageIndex=0; nPageIndex<nPageCount; nPageIndex++) + { + SdPage* pPage = mrDocument.GetSdPage (nPageIndex, PK_STANDARD); + if (pPage != NULL + && pPage->GetLayoutName().CompareTo(sFullLayoutName)!=0) + { + pPageList->push_back (pPage); + } + } + + AssignMasterPageToPageList(pMasterPage, pPageList); + } + while (false); +} + + + + +/** Assemble a list of the currently selected slides (selected in a visible + slide sorter) and pass it to AssignMasterPageToPageList(). +*/ +void MasterPagesSelector::AssignMasterPageToSelectedSlides ( + SdPage* pMasterPage) +{ + do + { + using namespace ::std; + using namespace ::sd::slidesorter; + using namespace ::sd::slidesorter::controller; + + if (pMasterPage == NULL) + break; + + // Find a visible slide sorter. + SlideSorterViewShell* pSlideSorter = SlideSorterViewShell::GetSlideSorter(mrBase); + if (pSlideSorter == NULL) + break; + + // Get a list of selected pages. + ::sd::slidesorter::SharedPageSelection pPageSelection = pSlideSorter->GetPageSelection(); + if (pPageSelection->empty()) + break; + + AssignMasterPageToPageList(pMasterPage, pPageSelection); + + // Restore the previous selection. + pSlideSorter->SetPageSelection(pPageSelection); + } + while (false); +} + + + + +void MasterPagesSelector::AssignMasterPageToPageList ( + SdPage* pMasterPage, + const ::sd::slidesorter::SharedPageSelection& rPageList) +{ + DocumentHelper::AssignMasterPageToPageList(mrDocument, pMasterPage, rPageList); +} + + + + +void MasterPagesSelector::NotifyContainerChangeEvent (const MasterPageContainerChangeEvent& rEvent) +{ + const ::osl::MutexGuard aGuard (maMutex); + + switch (rEvent.meEventType) + { + case MasterPageContainerChangeEvent::SIZE_CHANGED: + mpPageSet->SetPreviewSize(mpContainer->GetPreviewSizePixel()); + UpdateAllPreviews(); + break; + + case MasterPageContainerChangeEvent::PREVIEW_CHANGED: + { + int nIndex (GetIndexForToken(rEvent.maChildToken)); + if (nIndex >= 0) + { + mpPageSet->SetItemImage ( + (USHORT)nIndex, + mpContainer->GetPreviewForToken(rEvent.maChildToken)); + mpPageSet->Invalidate(mpPageSet->GetItemRect((USHORT)nIndex)); + } + } + break; + + case MasterPageContainerChangeEvent::DATA_CHANGED: + { + InvalidateItem(rEvent.maChildToken); + Fill(); + } + break; + + default: + break; + } +} + + + + +MasterPagesSelector::UserData* MasterPagesSelector::CreateUserData ( + int nIndex, + MasterPageContainer::Token aToken) const +{ + return new UserData(nIndex,aToken); +} + + + + +MasterPagesSelector::UserData* MasterPagesSelector::GetUserData (int nIndex) const +{ + const ::osl::MutexGuard aGuard (maMutex); + + if (nIndex>0 && nIndex<=mpPageSet->GetItemCount()) + return reinterpret_cast<UserData*>(mpPageSet->GetItemData((USHORT)nIndex)); + else + return NULL; +} + + + + +void MasterPagesSelector::SetUserData (int nIndex, UserData* pData) +{ + const ::osl::MutexGuard aGuard (maMutex); + + if (nIndex>0 && nIndex<=mpPageSet->GetItemCount()) + { + UserData* pOldData = GetUserData(nIndex); + if (pOldData!=NULL && pOldData!=pData) + delete pOldData; + mpPageSet->SetItemData((USHORT)nIndex, pData); + } +} + + + + +bool MasterPagesSelector::IsResizable (void) +{ + return false; +} + + + + +::Window* MasterPagesSelector::GetWindow (void) +{ + return mpPageSet.get(); +} + + + + +sal_Int32 MasterPagesSelector::GetMinimumWidth (void) +{ + return mpContainer->GetPreviewSizePixel().Width() + 2*3; +} + + + + +void MasterPagesSelector::UpdateSelection (void) +{ +} + + + + +void MasterPagesSelector::Execute (SfxRequest& rRequest) +{ + switch (rRequest.GetSlot()) + { + case SID_TP_APPLY_TO_ALL_SLIDES: + mrBase.SetBusyState (true); + AssignMasterPageToAllSlides (GetSelectedMasterPage()); + mrBase.SetBusyState (false); + break; + + case SID_TP_APPLY_TO_SELECTED_SLIDES: + mrBase.SetBusyState (true); + AssignMasterPageToSelectedSlides (GetSelectedMasterPage()); + mrBase.SetBusyState (false); + break; + + case SID_TP_USE_FOR_NEW_PRESENTATIONS: + DBG_ASSERT (false, + "Using slides as default for new presentations" + " is not yet implemented"); + break; + + case SID_TP_SHOW_SMALL_PREVIEW: + case SID_TP_SHOW_LARGE_PREVIEW: + { + mrBase.SetBusyState (true); + mpContainer->SetPreviewSize( + rRequest.GetSlot()==SID_TP_SHOW_SMALL_PREVIEW + ? MasterPageContainer::SMALL + : MasterPageContainer::LARGE); + mrBase.SetBusyState (false); + break; + } + + case SID_TP_EDIT_MASTER: + { + using namespace ::com::sun::star; + uno::Reference<drawing::XDrawPage> xSelectedMaster ( + GetSelectedMasterPage()->getUnoPage(), uno::UNO_QUERY); + SfxViewFrame* pViewFrame = mrBase.GetViewFrame(); + if (pViewFrame != NULL && xSelectedMaster.is()) + { + SfxDispatcher* pDispatcher = pViewFrame->GetDispatcher(); + if (pDispatcher != NULL) + { + USHORT nIndex = mpPageSet->GetSelectItemId(); + pDispatcher->Execute(SID_MASTERPAGE, SFX_CALLMODE_SYNCHRON); + mpPageSet->SelectItem (nIndex); + mrBase.GetDrawController().setCurrentPage(xSelectedMaster); + } + } + break; + } + + case SID_CUT: + case SID_COPY: + case SID_PASTE: + // Cut, copy, and paste are not supported and thus are ignored. + break; + } +} + + + + +void MasterPagesSelector::GetState (SfxItemSet& rItemSet) +{ + if (mpContainer->GetPreviewSize() == MasterPageContainer::SMALL) + rItemSet.DisableItem (SID_TP_SHOW_SMALL_PREVIEW); + else + rItemSet.DisableItem (SID_TP_SHOW_LARGE_PREVIEW); + + // Cut and paste is not supported so do not show the menu entries. + rItemSet.DisableItem (SID_CUT); + rItemSet.DisableItem (SID_COPY); + rItemSet.DisableItem (SID_PASTE); +} + + + + +void MasterPagesSelector::SetItem ( + USHORT nIndex, + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (maMutex); + + RemoveTokenToIndexEntry(nIndex,aToken); + + if (nIndex > 0) + { + if (aToken != MasterPageContainer::NIL_TOKEN) + { + Image aPreview (mpContainer->GetPreviewForToken(aToken)); + MasterPageContainer::PreviewState eState (mpContainer->GetPreviewState(aToken)); + + if (aPreview.GetSizePixel().Width()>0) + { + if (mpPageSet->GetItemPos(nIndex) != VALUESET_ITEM_NOTFOUND) + { + mpPageSet->SetItemImage(nIndex,aPreview); + mpPageSet->SetItemText(nIndex, mpContainer->GetPageNameForToken(aToken)); + } + else + { + mpPageSet->InsertItem ( + nIndex, + aPreview, + mpContainer->GetPageNameForToken(aToken), + nIndex); + } + SetUserData(nIndex, CreateUserData(nIndex,aToken)); + + AddTokenToIndexEntry(nIndex,aToken); + } + + if (eState == MasterPageContainer::PS_CREATABLE) + mpContainer->RequestPreview(aToken); + } + else + { + mpPageSet->RemoveItem(nIndex); + } + } + +} + + + + +void MasterPagesSelector::AddTokenToIndexEntry ( + USHORT nIndex, + MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (maMutex); + + maTokenToValueSetIndex[aToken] = nIndex; +} + + + + +void MasterPagesSelector::RemoveTokenToIndexEntry ( + USHORT nIndex, + MasterPageContainer::Token aNewToken) +{ + const ::osl::MutexGuard aGuard (maMutex); + + UserData* pData = GetUserData(nIndex); + if (pData != NULL) + { + // Get the token that the index pointed to previously. + MasterPageContainer::Token aOldToken (pData->second); + + if (aNewToken != aOldToken + && nIndex == GetIndexForToken(aOldToken)) + { + maTokenToValueSetIndex[aOldToken] = 0; + } + } +} + + + + +void MasterPagesSelector::InvalidatePreview (const SdPage* pPage) +{ + const ::osl::MutexGuard aGuard (maMutex); + + for (USHORT nIndex=1; nIndex<=mpPageSet->GetItemCount(); nIndex++) + { + UserData* pData = GetUserData(nIndex); + if (pData != NULL) + { + MasterPageContainer::Token aToken (pData->second); + if (pPage == mpContainer->GetPageObjectForToken(aToken,false)) + { + mpContainer->InvalidatePreview(aToken); + mpContainer->RequestPreview(aToken); + break; + } + } + } +} + +void MasterPagesSelector::UpdateAllPreviews (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + for (USHORT nIndex=1; nIndex<=mpPageSet->GetItemCount(); nIndex++) + { + UserData* pData = GetUserData(nIndex); + if (pData != NULL) + { + MasterPageContainer::Token aToken (pData->second); + mpPageSet->SetItemImage( + nIndex, + mpContainer->GetPreviewForToken(aToken)); + if (mpContainer->GetPreviewState(aToken) == MasterPageContainer::PS_CREATABLE) + mpContainer->RequestPreview(aToken); + } + } + mpPageSet->Rearrange(true); +} + + + + +void MasterPagesSelector::ClearPageSet (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + for (USHORT nIndex=1; nIndex<=mpPageSet->GetItemCount(); nIndex++) + { + UserData* pData = GetUserData(nIndex); + if (pData != NULL) + delete pData; + } + mpPageSet->Clear(); +} + + + + +void MasterPagesSelector::SetSmartHelpId( const SmartId& aId, SmartIdUpdateMode aMode ) +{ + const ::osl::MutexGuard aGuard (maMutex); + + mpPageSet->SetSmartHelpId( aId, aMode ); +} + + + + +sal_Int32 MasterPagesSelector::GetIndexForToken (MasterPageContainer::Token aToken) const +{ + const ::osl::MutexGuard aGuard (maMutex); + + TokenToValueSetIndex::const_iterator iIndex (maTokenToValueSetIndex.find(aToken)); + if (iIndex != maTokenToValueSetIndex.end()) + return iIndex->second; + else + return -1; +} + + + + +void MasterPagesSelector::Clear (void) +{ + const ::osl::MutexGuard aGuard (maMutex); + + ClearPageSet(); +} + + + + +void MasterPagesSelector::InvalidateItem (MasterPageContainer::Token aToken) +{ + const ::osl::MutexGuard aGuard (maMutex); + + ItemList::iterator iItem; + for (iItem=maCurrentItemList.begin(); iItem!=maCurrentItemList.end(); ++iItem) + { + if (*iItem == aToken) + { + *iItem = MasterPageContainer::NIL_TOKEN; + break; + } + } +} + + + + +void MasterPagesSelector::UpdateItemList (::std::auto_ptr<ItemList> pNewItemList) +{ + const ::osl::MutexGuard aGuard (maMutex); + + ItemList::const_iterator iNewItem (pNewItemList->begin()); + ItemList::const_iterator iCurrentItem (maCurrentItemList.begin()); + ItemList::const_iterator iNewEnd (pNewItemList->end()); + ItemList::const_iterator iCurrentEnd (maCurrentItemList.end()); + USHORT nIndex (1); + + // Update existing items. + for ( ; iNewItem!=iNewEnd && iCurrentItem!=iCurrentEnd; ++iNewItem, ++iCurrentItem,++nIndex) + { + if (*iNewItem != *iCurrentItem) + { + SetItem(nIndex,*iNewItem); + } + } + + // Append new items. + for ( ; iNewItem!=iNewEnd; ++iNewItem,++nIndex) + { + SetItem(nIndex,*iNewItem); + } + + // Remove trailing items. + for ( ; iCurrentItem!=iCurrentEnd; ++iCurrentItem,++nIndex) + { + SetItem(nIndex,MasterPageContainer::NIL_TOKEN); + } + + maCurrentItemList.swap(*pNewItemList); + + mpPageSet->Rearrange(); + if (GetParentNode() != NULL) + GetParentNode()->RequestResize(); +} + + + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/MasterPagesSelector.hxx b/sd/source/ui/toolpanel/controls/MasterPagesSelector.hxx new file mode 100755 index 000000000000..a2df51f2bd4b --- /dev/null +++ b/sd/source/ui/toolpanel/controls/MasterPagesSelector.hxx @@ -0,0 +1,235 @@ +/************************************************************************* + * + * 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 SD_TASKPANE_CONTROLS_MASTER_PAGES_SELECTOR_HXX +#define SD_TASKPANE_CONTROLS_MASTER_PAGES_SELECTOR_HXX + +#include "taskpane/TaskPaneTreeNode.hxx" +#include "MasterPageContainer.hxx" +#include "SlideSorterViewShell.hxx" + +#include "pres.hxx" +#include <sfx2/shell.hxx> +#include <vcl/image.hxx> +#include "glob.hxx" +#include <osl/mutex.hxx> + +#include <queue> + +class MouseEvent; +class SdDrawDocument; +class SdPage; +class SfxModule; + +namespace sd { +class DrawViewShell; +class TemplateEntry; +class TemplateDir; +class ViewShellBase; +} + +namespace sd { namespace toolpanel { namespace controls { + +class PreviewValueSet; + +/** Base class of a menu that lets the user select from a list of + templates or designs that are loaded from files. +*/ +class MasterPagesSelector + : public TreeNode, + public SfxShell +{ +public: + TYPEINFO(); + SFX_DECL_INTERFACE(SD_IF_SDMASTERPAGESSELECTOR) + + MasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer); + virtual ~MasterPagesSelector (void); + + virtual void LateInit (void); + + /** Return the height that this control needs to show all of its lines. + */ + long GetRequiredHeight (int nWidth) const; + + /** The given master page, either the master page of a slide or a notes + page, is cloned and inserted into mrDocument. The necessary styles + are copied as well. + */ + static SdPage* AddMasterPage ( + SdDrawDocument* pTargetDocument, + SdPage* pMasterPage, + USHORT nInsertionIndex); + + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeight); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual bool IsResizable (void); + virtual ::Window* GetWindow (void); + virtual sal_Int32 GetMinimumWidth (void); + + virtual void Execute (SfxRequest& rRequest); + virtual void GetState (SfxItemSet& rItemSet); + + /** Update the selection of previews according to whatever + influences them appart from mouse and keyboard. If, for + example, the current page of the main pane changes, then call + this method at the CurrentMasterPagesSelector to select the + previews of the master pages that are assigned to the new + current page. + + The default implementation of this method ignores the call. This is + used by e.g. the RecentMasterPagesSelector because it does not show + the currently used master pages by default and thus is not + influenced by its changes. + */ + virtual void UpdateSelection (void); + + void FillPageSet (void); + + /** Make the selector empty. This method clear the value set from any + entries. Overload this method to add functionality, especially to + destroy objects set as data items at the value set. + */ + void ClearPageSet (void); + + void SetSmartHelpId( const SmartId& aId, SmartIdUpdateMode aMode = SMART_SET_SMART ); + + /** Mark the preview that belongs to the given index as not up-to-date + anymore with respect to page content or preview size. + The implementation of this method will either sunchronously or + asynchronously call UpdatePreview(). + @param nIndex + Index into the value set control that is used for displaying the + previews. + */ + void InvalidatePreview (const SdPage* pPage); + + void UpdateAllPreviews (void); + +protected: + mutable ::osl::Mutex maMutex; + ::boost::shared_ptr<MasterPageContainer> mpContainer; + + SdDrawDocument& mrDocument; + ::std::auto_ptr<PreviewValueSet> mpPageSet; + bool mbSmallPreviewSize; + ViewShellBase& mrBase; + /** Slot that is executed as default action when the left mouse button is + clicked over a master page. + */ + sal_uInt16 mnDefaultClickAction; + /** Pages with pointers in this queue have their previews updated + eventually. Filled by InvalidatePreview() and operated upon by + UpdatePreviews(). + */ + ::std::queue<USHORT> maPreviewUpdateQueue; + + virtual SdPage* GetSelectedMasterPage (void); + + /** Assign the given master page to all slides of the document. + @param pMasterPage + The master page to assign to all slides. + */ + void AssignMasterPageToAllSlides (SdPage* pMasterPage); + + /** Assign the given master page to all slides that are selected in a + slide sorter that is displayed in the lef or center pane. When both + panes display a slide sorter then the one in the center pane is + used. + */ + void AssignMasterPageToSelectedSlides (SdPage* pMasterPage); + + virtual void AssignMasterPageToPageList ( + SdPage* pMasterPage, + const ::sd::slidesorter::SharedPageSelection& rPageList); + + virtual void NotifyContainerChangeEvent (const MasterPageContainerChangeEvent& rEvent); + + typedef ::std::pair<int, MasterPageContainer::Token> UserData; + UserData* CreateUserData (int nIndex, MasterPageContainer::Token aToken) const; + UserData* GetUserData (int nIndex) const; + void SetUserData (int nIndex, UserData* pData); + + virtual sal_Int32 GetIndexForToken (MasterPageContainer::Token aToken) const; + typedef ::std::vector<MasterPageContainer::Token> ItemList; + void UpdateItemList (::std::auto_ptr<ItemList> pList); + void Clear (void); + /** Invalidate the specified item so that on the next Fill() this item + is updated. + */ + void InvalidateItem (MasterPageContainer::Token aToken); + + // For every item in the ValueSet we store its associated token. This + // allows a faster access and easier change tracking. + ItemList maCurrentItemList; + typedef ::std::map<MasterPageContainer::Token,sal_Int32> TokenToValueSetIndex; + TokenToValueSetIndex maTokenToValueSetIndex; + + ItemList maLockedMasterPages; + /** Lock master pages in the given list and release locks that where + previously aquired. + */ + void UpdateLocks (const ItemList& rItemList); + + void Fill (void); + virtual void Fill (ItemList& rItemList) = 0; + + /** Give derived classes the oportunity to provide their own context + menu. If they do then they probably have to provide their own + Execute() and GetState() methods as well. + */ + virtual ResId GetContextMenuResId (void) const; + +private: + /** The offset between ValueSet index and MasterPageContainer::Token + last seen. This value is used heuristically to speed up the lookup + of an index for a token. + */ + DECL_LINK(ClickHandler, PreviewValueSet*); + DECL_LINK(RightClickHandler, MouseEvent*); + DECL_LINK(ContextMenuCallback, CommandEvent*); + DECL_LINK(ContainerChangeListener, MasterPageContainerChangeEvent*); + + void SetItem ( + USHORT nIndex, + MasterPageContainer::Token aToken); + void AddTokenToIndexEntry ( + USHORT nIndex, + MasterPageContainer::Token aToken); + void RemoveTokenToIndexEntry ( + USHORT nIndex, + MasterPageContainer::Token aToken); +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/PreviewValueSet.cxx b/sd/source/ui/toolpanel/controls/PreviewValueSet.cxx new file mode 100644 index 000000000000..a1f29dfee044 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/PreviewValueSet.cxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "PreviewValueSet.hxx" +#include <vcl/image.hxx> +#include "taskpane/TaskPaneTreeNode.hxx" + +namespace sd { namespace toolpanel { namespace controls { + + +PreviewValueSet::PreviewValueSet (TreeNode* pParent) + : ValueSet (pParent->GetWindow(), WB_TABSTOP), + mpParent(pParent), + maPreviewSize(10,10), + mnBorderWidth(3), + mnBorderHeight(3), + mnMaxColumnCount(-1) +{ + SetStyle ( + GetStyle() + & ~(WB_ITEMBORDER)// | WB_MENUSTYLEVALUESET) + // | WB_FLATVALUESET); + ); + + SetColCount(2); + // SetLineCount(1); + SetExtraSpacing (2); +} + + + + +PreviewValueSet::~PreviewValueSet (void) +{ +} + + + + +void PreviewValueSet::SetPreviewSize (const Size& rSize) +{ + maPreviewSize = rSize; +} + + + + +void PreviewValueSet::SetRightMouseClickHandler (const Link& rLink) +{ + maRightMouseClickHandler = rLink; +} + + + + +void PreviewValueSet::MouseButtonDown (const MouseEvent& rEvent) +{ + if (rEvent.IsRight()) + maRightMouseClickHandler.Call(reinterpret_cast<void*>( + &const_cast<MouseEvent&>(rEvent))); + else + ValueSet::MouseButtonDown (rEvent); + +} + + + + +void PreviewValueSet::Paint (const Rectangle& rRect) +{ + SetBackground (GetSettings().GetStyleSettings().GetWindowColor()); + + ValueSet::Paint (rRect); + + SetBackground (Wallpaper()); +} + + + + +void PreviewValueSet::Resize (void) +{ + ValueSet::Resize (); + + Size aWindowSize (GetOutputSizePixel()); + if (aWindowSize.Width()>0 && aWindowSize.Height()>0) + { + Rearrange(); + } +} + + + + +void PreviewValueSet::Command (const CommandEvent& rEvent) +{ + switch (rEvent.GetCommand()) + { + case COMMAND_CONTEXTMENU: + { + CommandEvent aNonConstEventCopy (rEvent); + maContextMenuCallback.Call(&aNonConstEventCopy); + } + break; + + default: + ValueSet::Command(rEvent); + break; + } +} + + + + +void PreviewValueSet::Rearrange (bool bForceRequestResize) +{ + USHORT nOldColumnCount (GetColCount()); + USHORT nOldRowCount (GetLineCount()); + + USHORT nNewColumnCount (CalculateColumnCount ( + GetOutputSizePixel().Width())); + USHORT nNewRowCount (CalculateRowCount (nNewColumnCount)); + + SetColCount(nNewColumnCount); + SetLineCount(nNewRowCount); + + if (bForceRequestResize + || nOldColumnCount != nNewColumnCount + || nOldRowCount != nNewRowCount) + mpParent->RequestResize(); +} + + + + +void PreviewValueSet::SetContextMenuCallback (const Link& rLink) +{ + maContextMenuCallback = rLink; +} + + + + +USHORT PreviewValueSet::CalculateColumnCount (int nWidth) const +{ + int nColumnCount = 0; + if (nWidth > 0) + { + nColumnCount = nWidth / (maPreviewSize.Width() + 2*mnBorderWidth); + if (nColumnCount < 1) + nColumnCount = 1; + else if (mnMaxColumnCount>0 && nColumnCount>mnMaxColumnCount) + nColumnCount = mnMaxColumnCount; + } + return (USHORT)nColumnCount; +} + + + + +USHORT PreviewValueSet::CalculateRowCount (USHORT nColumnCount) const +{ + int nRowCount = 0; + int nItemCount = GetItemCount(); + if (nColumnCount > 0) + { + nRowCount = (nItemCount+nColumnCount-1) / nColumnCount; + if (nRowCount < 1) + nRowCount = 1; + } + + return (USHORT)nRowCount; +} + + + + +sal_Int32 PreviewValueSet::GetPreferredWidth (sal_Int32 nHeight) +{ + int nPreferredWidth (maPreviewSize.Width() + 2*mnBorderWidth); + + // Get height of each row. + int nItemHeight (maPreviewSize.Height() + 2*mnBorderHeight); + + // Calculate the row- and column count and from the later the preferred + // width. + int nRowCount = nHeight / nItemHeight; + if (nRowCount > 0) + { + int nColumnCount = (GetItemCount()+nRowCount-1) / nRowCount; + if (nColumnCount > 0) + nPreferredWidth = (maPreviewSize.Width() + 2*mnBorderWidth) + * nColumnCount; + } + + return nPreferredWidth; +} + + + + +sal_Int32 PreviewValueSet::GetPreferredHeight (sal_Int32 nWidth) +{ + int nRowCount (CalculateRowCount(CalculateColumnCount(nWidth))); + int nItemHeight (maPreviewSize.Height()); + + return nRowCount * (nItemHeight + 2*mnBorderHeight); +} + + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/PreviewValueSet.hxx b/sd/source/ui/toolpanel/controls/PreviewValueSet.hxx new file mode 100644 index 000000000000..69fa7e272330 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/PreviewValueSet.hxx @@ -0,0 +1,96 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_PREVIEW_VALUE_SET_HXX +#define SD_TOOLPANEL_PREVIEW_VALUE_SET_HXX + +#include <svtools/valueset.hxx> + + +namespace sd { namespace toolpanel { +class TreeNode; +} } + +namespace sd { namespace toolpanel { namespace controls { + + +/** Adapt the svtools valueset to the needs of the master page controlls. +*/ +class PreviewValueSet + : public ValueSet +{ +public: + PreviewValueSet (TreeNode* pParent); + ~PreviewValueSet (void); + + void SetRightMouseClickHandler (const Link& rLink); + virtual void Paint (const Rectangle& rRect); + virtual void Resize (void); + + /** When a request for the display of a context menu is made to this + method then that request is forwarded via the ContextMenuCallback. + This way the owning class can handle the context menu without having + to be derived from this class. + Use SetContextMenuCallback to set or rest the handler. + */ + virtual void Command (const CommandEvent& rEvent); + + void SetPreviewSize (const Size& rSize); + + sal_Int32 GetPreferredWidth (sal_Int32 nHeight); + sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + + /** Set the number of rows and columns according to the current number + of items. Call this method when new items have been inserted. + */ + void Rearrange (bool bForceRequestResize = false); + + /** Set the callback function to which requests for context menus are + forewarded. Call with an empty Link to reset the callback + function. + */ + void SetContextMenuCallback (const Link& rLink); + +protected: + virtual void MouseButtonDown (const MouseEvent& rEvent); + +private: + Link maRightMouseClickHandler; + Link maContextMenuCallback; + TreeNode* mpParent; + Size maPreviewSize; + const int mnBorderWidth; + const int mnBorderHeight; + const int mnMaxColumnCount; + + USHORT CalculateColumnCount (int nWidth) const; + USHORT CalculateRowCount (USHORT nColumnCount) const; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.cxx b/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.cxx new file mode 100644 index 000000000000..2f2789216b8d --- /dev/null +++ b/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.cxx @@ -0,0 +1,159 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "RecentMasterPagesSelector.hxx" +#include "PreviewValueSet.hxx" + +#include "RecentlyUsedMasterPages.hxx" +#include "MasterPageContainerProviders.hxx" +#include "MasterPageObserver.hxx" +#include "sdpage.hxx" +#include "drawdoc.hxx" +#include "app.hrc" +#include <vcl/bitmap.hxx> +#include <tools/color.hxx> + +namespace sd { namespace toolpanel { namespace controls { + + +RecentMasterPagesSelector::RecentMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer) + : MasterPagesSelector (pParent, rDocument, rBase, rpContainer) +{ + SetName (String(RTL_CONSTASCII_USTRINGPARAM("RecentMasterPagesSelector"))); +} + + + + +RecentMasterPagesSelector::~RecentMasterPagesSelector (void) +{ + RecentlyUsedMasterPages::Instance().RemoveEventListener ( + LINK(this,RecentMasterPagesSelector,MasterPageListListener)); +} + + + + +void RecentMasterPagesSelector::LateInit (void) +{ + MasterPagesSelector::LateInit(); + + MasterPagesSelector::Fill(); + RecentlyUsedMasterPages::Instance().AddEventListener ( + LINK(this,RecentMasterPagesSelector,MasterPageListListener)); +} + + + + +IMPL_LINK(RecentMasterPagesSelector,MasterPageListListener, void*, EMPTYARG) +{ + MasterPagesSelector::Fill(); + return 0; +} + + + + +void RecentMasterPagesSelector::Fill (ItemList& rItemList) +{ + // Create a set of names of the master pages used by the document. + MasterPageObserver::MasterPageNameSet aCurrentNames; + USHORT nMasterPageCount = mrDocument.GetMasterSdPageCount(PK_STANDARD); + USHORT nIndex; + for (nIndex=0; nIndex<nMasterPageCount; nIndex++) + { + SdPage* pMasterPage = mrDocument.GetMasterSdPage (nIndex, PK_STANDARD); + if (pMasterPage != NULL) + aCurrentNames.insert (pMasterPage->GetName()); + } + MasterPageObserver::MasterPageNameSet::iterator aI; + + // Insert the recently used master pages that are currently not used. + RecentlyUsedMasterPages& rInstance (RecentlyUsedMasterPages::Instance()); + int nPageCount = rInstance.GetMasterPageCount(); + for (nIndex=0; nIndex<nPageCount; nIndex++) + { + // Add an entry when a) the page is already known to the + // MasterPageContainer, b) the style name is empty, i.e. it has not yet + // been loaded (and thus can not be in use) or otherwise c) the + // style name is not currently in use. + MasterPageContainer::Token aToken (rInstance.GetTokenForIndex(nIndex)); + if (aToken != MasterPageContainer::NIL_TOKEN) + { + String sStyleName (mpContainer->GetStyleNameForToken(aToken)); + if (sStyleName.Len()==0 + || aCurrentNames.find(sStyleName) == aCurrentNames.end()) + { + rItemList.push_back(aToken); + } + } + } +} + + + + +void RecentMasterPagesSelector::AssignMasterPageToPageList ( + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList) +{ + USHORT nSelectedItemId = mpPageSet->GetSelectItemId(); + + MasterPagesSelector::AssignMasterPageToPageList(pMasterPage, rpPageList); + + // Restore the selection. + if (mpPageSet->GetItemCount() > 0) + { + if (mpPageSet->GetItemCount() >= nSelectedItemId) + mpPageSet->SelectItem(nSelectedItemId); + else + mpPageSet->SelectItem(mpPageSet->GetItemCount()); + } +} + + + + +void RecentMasterPagesSelector::GetState (SfxItemSet& rItemSet) +{ + MasterPagesSelector::GetState (rItemSet); + if (rItemSet.GetItemState(SID_TP_EDIT_MASTER) == SFX_ITEM_AVAILABLE) + rItemSet.DisableItem (SID_TP_EDIT_MASTER); +} + + + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.hxx b/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.hxx new file mode 100644 index 000000000000..adac66187b71 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/RecentMasterPagesSelector.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_RECENT_MASTER_PAGES_SELECTOR_HXX +#define SD_TOOLPANEL_CONTROLS_RECENT_MASTER_PAGES_SELECTOR_HXX + +#include "MasterPagesSelector.hxx" + +namespace sd { namespace toolpanel { namespace controls { + + +/** Show the recently used master pages (that are not currently used). +*/ +class RecentMasterPagesSelector + : public MasterPagesSelector +{ +public: + RecentMasterPagesSelector ( + TreeNode* pParent, + SdDrawDocument& rDocument, + ViewShellBase& rBase, + const ::boost::shared_ptr<MasterPageContainer>& rpContainer); + virtual ~RecentMasterPagesSelector (void); + + virtual void LateInit (void); + + virtual void GetState (SfxItemSet& rItemSet); + +protected: + DECL_LINK(MasterPageListListener, void*); + virtual void Fill (ItemList& rItemList); + + using sd::toolpanel::controls::MasterPagesSelector::Fill; + + /** Forward this call to the base class but save and restore the + currently selected item. + Assign the given master page to the list of pages. + @param pMasterPage + This master page will usually be a member of the list of all + available master pages as provided by the MasterPageContainer. + @param rPageList + The pages to which to assign the master page. These pages may + be slides or master pages themselves. + */ + virtual void AssignMasterPageToPageList ( + SdPage* pMasterPage, + const ::boost::shared_ptr<std::vector<SdPage*> >& rpPageList); +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.cxx b/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.cxx new file mode 100644 index 000000000000..63d7f72e2903 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.cxx @@ -0,0 +1,501 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "RecentlyUsedMasterPages.hxx" +#include "MasterPageObserver.hxx" +#include "MasterPagesSelector.hxx" +#include "MasterPageDescriptor.hxx" +#include "tools/ConfigurationAccess.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" + +#include <algorithm> +#include <vector> + +#include <comphelper/processfactory.hxx> +#include "unomodel.hxx" +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/drawing/XDrawPages.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/PropertyState.hpp> +#include <tools/urlobj.hxx> +#include <unotools/confignode.hxx> +#include <osl/doublecheckedlocking.h> +#include <osl/getglobalmutex.hxx> + +using namespace ::std; +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +namespace { + +static const OUString& GetPathToImpressConfigurationRoot (void) +{ + static const OUString sPathToImpressConfigurationRoot ( + RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/")); + return sPathToImpressConfigurationRoot; +} +static const OUString& GetPathToSetNode (void) +{ + static const OUString sPathToSetNode( + RTL_CONSTASCII_USTRINGPARAM( + "MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages")); + return sPathToSetNode; +} + + +class Descriptor +{ +public: + ::rtl::OUString msURL; + ::rtl::OUString msName; + ::sd::toolpanel::controls::MasterPageContainer::Token maToken; + Descriptor (const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName) + : msURL(rsURL), + msName(rsName), + maToken(::sd::toolpanel::controls::MasterPageContainer::NIL_TOKEN) + {} + Descriptor (::sd::toolpanel::controls::MasterPageContainer::Token aToken, + const ::rtl::OUString& rsURL, const ::rtl::OUString& rsName) + : msURL(rsURL), + msName(rsName), + maToken(aToken) + {} + class TokenComparator + { public: + TokenComparator(::sd::toolpanel::controls::MasterPageContainer::Token aToken) + : maToken(aToken) {} + bool operator () (const Descriptor& rDescriptor) + { return maToken==rDescriptor.maToken; } + private: ::sd::toolpanel::controls::MasterPageContainer::Token maToken; + }; +}; + +} // end of anonymous namespace + + + + +namespace sd { namespace toolpanel { namespace controls { + +class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor> +{ +public: + MasterPageList (void) {} +}; + + +RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL; + + +RecentlyUsedMasterPages& RecentlyUsedMasterPages::Instance (void) +{ + if (mpInstance == NULL) + { + ::osl::GetGlobalMutex aMutexFunctor; + ::osl::MutexGuard aGuard (aMutexFunctor()); + if (mpInstance == NULL) + { + RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages(); + pInstance->LateInit(); + SdGlobalResourceContainer::Instance().AddResource ( + ::std::auto_ptr<SdGlobalResource>(pInstance)); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + mpInstance = pInstance; + } + } + else { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + + return *mpInstance; +} + + + + +RecentlyUsedMasterPages::RecentlyUsedMasterPages (void) + : maListeners(), + mpMasterPages(new MasterPageList()), + mnMaxListSize(8), + mpContainer(new MasterPageContainer()) +{ +} + + + + +RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void) +{ + Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); + mpContainer->RemoveChangeListener(aLink); + + MasterPageObserver::Instance().RemoveEventListener( + LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); +} + + + + +void RecentlyUsedMasterPages::LateInit (void) +{ + Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener)); + mpContainer->AddChangeListener(aLink); + + LoadPersistentValues (); + MasterPageObserver::Instance().AddEventListener( + LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener)); +} + + + + +void RecentlyUsedMasterPages::LoadPersistentValues (void) +{ + try + { + do + { + tools::ConfigurationAccess aConfiguration ( + GetPathToImpressConfigurationRoot(), + tools::ConfigurationAccess::READ_ONLY); + Reference<container::XNameAccess> xSet ( + aConfiguration.GetConfigurationNode(GetPathToSetNode()), + UNO_QUERY); + if ( ! xSet.is()) + break; + + const String sURLMemberName (OUString::createFromAscii("URL")); + const String sNameMemberName (OUString::createFromAscii("Name")); + OUString sURL; + OUString sName; + + // Read the names and URLs of the master pages. + Sequence<OUString> aKeys (xSet->getElementNames()); + mpMasterPages->clear(); + mpMasterPages->reserve(aKeys.getLength()); + for (int i=0; i<aKeys.getLength(); i++) + { + Reference<container::XNameAccess> xSetItem ( + xSet->getByName(aKeys[i]), UNO_QUERY); + if (xSetItem.is()) + { + Any aURL (xSetItem->getByName(sURLMemberName)); + Any aName (xSetItem->getByName(sNameMemberName)); + aURL >>= sURL; + aName >>= sName; + SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor( + MasterPageContainer::TEMPLATE, + -1, + sURL, + String(), + sName, + false, + ::boost::shared_ptr<PageObjectProvider>( + new TemplatePageObjectProvider(sURL)), + ::boost::shared_ptr<PreviewProvider>( + new TemplatePreviewProvider(sURL)))); + // For user supplied templates we use a different + // preview provider: The preview in the document shows + // not only shapes on the master page but also shapes on + // the foreground. This is misleading and therefore + // these previews are discarded and created directly + // from the page objects. + if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER) + pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>( + new PagePreviewProvider()); + MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor)); + mpMasterPages->push_back(Descriptor(aToken,sURL,sName)); + } + } + + ResolveList(); + } + while (false); + } + catch (Exception&) + { + // Ignore exception. + } +} + + + + +void RecentlyUsedMasterPages::SavePersistentValues (void) +{ + try + { + do + { + tools::ConfigurationAccess aConfiguration ( + GetPathToImpressConfigurationRoot(), + tools::ConfigurationAccess::READ_WRITE); + Reference<container::XNameContainer> xSet ( + aConfiguration.GetConfigurationNode(GetPathToSetNode()), + UNO_QUERY); + if ( ! xSet.is()) + break; + + // Clear the set. + Sequence<OUString> aKeys (xSet->getElementNames()); + sal_Int32 i; + for (i=0; i<aKeys.getLength(); i++) + xSet->removeByName (aKeys[i]); + + // Fill it with the URLs of this object. + const String sURLMemberName (OUString::createFromAscii("URL")); + const String sNameMemberName (OUString::createFromAscii("Name")); + Any aValue; + Reference<lang::XSingleServiceFactory> xChildFactory ( + xSet, UNO_QUERY); + if ( ! xChildFactory.is()) + break; + MasterPageList::const_iterator iDescriptor; + sal_Int32 nIndex(0); + for (iDescriptor=mpMasterPages->begin(); + iDescriptor!=mpMasterPages->end(); + ++iDescriptor,++nIndex) + { + // Create new child. + OUString sKey (OUString::createFromAscii("index_")); + sKey += OUString::valueOf(nIndex); + Reference<container::XNameReplace> xChild( + xChildFactory->createInstance(), UNO_QUERY); + if (xChild.is()) + { + xSet->insertByName (sKey, makeAny(xChild)); + + aValue <<= OUString(iDescriptor->msURL); + xChild->replaceByName (sURLMemberName, aValue); + + aValue <<= OUString(iDescriptor->msName); + xChild->replaceByName (sNameMemberName, aValue); + } + } + + // Write the data back to disk. + aConfiguration.CommitChanges(); + } + while (false); + } + catch (Exception&) + { + // Ignore exception. + } +} + + + + +void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener) +{ + if (::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener) == maListeners.end()) + { + maListeners.push_back (rEventListener); + } +} + + + + +void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener) +{ + maListeners.erase ( + ::std::find ( + maListeners.begin(), + maListeners.end(), + rEventListener)); +} + + + + +int RecentlyUsedMasterPages::GetMasterPageCount (void) const +{ + return mpMasterPages->size(); +} + + + + +MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const +{ + if(nIndex<mpMasterPages->size()) + return (*mpMasterPages)[nIndex].maToken; + else + return MasterPageContainer::NIL_TOKEN; +} + + + + +void RecentlyUsedMasterPages::SendEvent (void) +{ + ::std::vector<Link>::iterator aLink (maListeners.begin()); + ::std::vector<Link>::iterator aEnd (maListeners.end()); + while (aLink!=aEnd) + { + aLink->Call (NULL); + ++aLink; + } +} + + + + +IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener, + MasterPageObserverEvent*, pEvent) +{ + switch (pEvent->meType) + { + case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED: + case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS: + AddMasterPage( + mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName)); + break; + + case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED: + // Do not change the list of recently master pages (the deleted + // page was recently used) but tell the listeners. They may want + // to update their lists. + SendEvent(); + break; + } + return 0; +} + + + + +IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener, + MasterPageContainerChangeEvent*, pEvent) +{ + if (pEvent != NULL) + switch (pEvent->meEventType) + { + case MasterPageContainerChangeEvent::CHILD_ADDED: + case MasterPageContainerChangeEvent::CHILD_REMOVED: + case MasterPageContainerChangeEvent::INDEX_CHANGED: + case MasterPageContainerChangeEvent::INDEXES_CHANGED: + ResolveList(); + break; + + default: + // Ignored. + break; + } + return 0; +} + + + + +void RecentlyUsedMasterPages::AddMasterPage ( + MasterPageContainer::Token aToken, + bool bMakePersistent) +{ + // For the page to be inserted the token has to be valid and the page + // has to have a valid URL. This excludes master pages that do not come + // from template files. + if (aToken != MasterPageContainer::NIL_TOKEN + && mpContainer->GetURLForToken(aToken).Len()>0) + { + + MasterPageList::iterator aIterator ( + ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(), + Descriptor::TokenComparator(aToken))); + if (aIterator != mpMasterPages->end()) + { + // When an entry for the given token already exists then remove + // it now and insert it later at the head of the list. + mpMasterPages->erase (aIterator); + } + + mpMasterPages->insert(mpMasterPages->begin(), + Descriptor( + aToken, + mpContainer->GetURLForToken(aToken), + mpContainer->GetStyleNameForToken(aToken))); + + // Shorten list to maximal size. + while (mpMasterPages->size() > mnMaxListSize) + { + mpMasterPages->pop_back (); + } + + if (bMakePersistent) + SavePersistentValues (); + SendEvent(); + } +} + + + + +void RecentlyUsedMasterPages::ResolveList (void) +{ + bool bNotify (false); + + MasterPageList::iterator iDescriptor; + for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor) + { + if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN) + { + MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL)); + iDescriptor->maToken = aToken; + if (aToken != MasterPageContainer::NIL_TOKEN) + bNotify = true; + } + else + { + if ( ! mpContainer->HasToken(iDescriptor->maToken)) + { + iDescriptor->maToken = MasterPageContainer::NIL_TOKEN; + bNotify = true; + } + } + } + + if (bNotify) + SendEvent(); +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.hxx b/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.hxx new file mode 100644 index 000000000000..1f16d31b95d5 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/RecentlyUsedMasterPages.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX +#define SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX + +#include "tools/SdGlobalResourceContainer.hxx" +#include <osl/mutex.hxx> +#include <tools/link.hxx> +#include <vcl/image.hxx> +#include <vector> +#include <tools/string.hxx> + +#include "DrawDocShell.hxx" +#include "MasterPageContainer.hxx" +#include <com/sun/star/uno/XInterface.hpp> + +class SdPage; + +namespace sd { +class MasterPageObserverEvent; +} + + +namespace sd { namespace toolpanel { namespace controls { + +/** This singleton holds a list of the most recently used master pages. +*/ +class RecentlyUsedMasterPages + : public SdGlobalResource +{ +public: + /** Return the single instance of this class. + */ + static RecentlyUsedMasterPages& Instance (void); + + void AddEventListener (const Link& rEventListener); + void RemoveEventListener (const Link& rEventListener); + + int GetMasterPageCount (void) const; + MasterPageContainer::Token GetTokenForIndex (sal_uInt32 nIndex) const; + +private: + /** The single instance of this class. It is created on demand when + Instance() is called for the first time. + */ + static RecentlyUsedMasterPages* mpInstance; + + ::std::vector<Link> maListeners; + + class MasterPageList; + ::std::auto_ptr<MasterPageList> mpMasterPages; + unsigned long int mnMaxListSize; + ::boost::shared_ptr<MasterPageContainer> mpContainer; + + RecentlyUsedMasterPages (void); + virtual ~RecentlyUsedMasterPages (void); + + /** Call this method after a new object has been created. + */ + void LateInit (void); + + /// The copy constructor is not implemented. Do not use! + RecentlyUsedMasterPages (const RecentlyUsedMasterPages&); + + /// The assignment operator is not implemented. Do not use! + RecentlyUsedMasterPages& operator= (const RecentlyUsedMasterPages&); + + void SendEvent (void); + DECL_LINK(MasterPageChangeListener, MasterPageObserverEvent*); + DECL_LINK(MasterPageContainerChangeListener, MasterPageContainerChangeEvent*); + + /** Add a descriptor for the specified master page to the end of the + list of most recently used master pages. When the page is already a + member of that list the associated descriptor is moved to the end of + the list to make it the most recently used entry. + @param bMakePersistent + When <TRUE/> is given then the new list of recently used master + pages is written back into the configuration to make it + persistent. Giving <FALSE/> to ommit this is used while loading + the persistent list from the configuration. + */ + void AddMasterPage ( + MasterPageContainer::Token aToken, + bool bMakePersistent = true); + + /** Load the list of recently used master pages from the registry where + it was saved to make it persistent. + */ + void LoadPersistentValues (void); + + /** Save the list of recently used master pages to the registry to make + it presistent. + */ + void SavePersistentValues (void); + + void ResolveList (void); +}; + + + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/SlideTransitionPanel.cxx b/sd/source/ui/toolpanel/controls/SlideTransitionPanel.cxx new file mode 100755 index 000000000000..4ad67b876983 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/SlideTransitionPanel.cxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * 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_sd.hxx" +#include "SlideTransitionPanel.hxx" + +#include "taskpane/TaskPaneControlFactory.hxx" +#include "taskpane/ToolPanelViewShell.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" +#include <com/sun/star/frame/XModel.hpp> + +namespace sd +{ + + class ViewShellBase; + extern ::Window * createSlideTransitionPanel( ::Window* pParent, ViewShellBase& rBase ); + +namespace toolpanel { namespace controls { + + + +SlideTransitionPanel::SlideTransitionPanel(Window& i_rParentWindow, ToolPanelViewShell& i_rToolPanelShell) + :SubToolPanel( i_rParentWindow ) + ,maPreferredSize( 100, 200 ) + ,m_pPanelViewShell( &i_rToolPanelShell ) +{ + mpWrappedControl = createSlideTransitionPanel( &i_rParentWindow, i_rToolPanelShell.GetViewShellBase() ); + mpWrappedControl->Show(); +} + +SlideTransitionPanel::~SlideTransitionPanel() +{ + delete mpWrappedControl; +} + +std::auto_ptr< ControlFactory > SlideTransitionPanel::CreateControlFactory( ToolPanelViewShell& i_rToolPanelShell ) +{ + return std::auto_ptr< ControlFactory >( + new RootControlFactoryWithArg< SlideTransitionPanel, ToolPanelViewShell >( i_rToolPanelShell ) ); +} + +TaskPaneShellManager* SlideTransitionPanel::GetShellManager() +{ + if ( m_pPanelViewShell ) + return &m_pPanelViewShell->GetSubShellManager(); + return SubToolPanel::GetShellManager(); +} + +Size SlideTransitionPanel::GetPreferredSize() +{ + return maPreferredSize; +} +sal_Int32 SlideTransitionPanel::GetPreferredWidth(sal_Int32 ) +{ + return maPreferredSize.Width(); +} +sal_Int32 SlideTransitionPanel::GetPreferredHeight(sal_Int32 ) +{ + return maPreferredSize.Height(); +} +::Window* SlideTransitionPanel::GetWindow() +{ + return mpWrappedControl; +} +bool SlideTransitionPanel::IsResizable() +{ + return true; +} +bool SlideTransitionPanel::IsExpandable() const +{ + return true; +} + + + + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> SlideTransitionPanel::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + if (GetWindow() != NULL) + return GetWindow()->GetAccessible(); + else + return NULL; +} + + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/SlideTransitionPanel.hxx b/sd/source/ui/toolpanel/controls/SlideTransitionPanel.hxx new file mode 100755 index 000000000000..f62cb918806b --- /dev/null +++ b/sd/source/ui/toolpanel/controls/SlideTransitionPanel.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_SLIDE_TRANSITION_PANEL_HXX +#define SD_TOOLPANEL_CONTROLS_SLIDE_TRANSITION_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class ControlFactory; +class TreeNode; +class ToolPanelViewShell; +} } + +namespace sd { namespace toolpanel { namespace controls { + +class SlideTransitionPanel + : public SubToolPanel +{ +public: + SlideTransitionPanel ( + Window& i_rParentWindow, + ToolPanelViewShell& i_rToolPanelShell); + virtual ~SlideTransitionPanel (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory (ToolPanelViewShell& i_rToolPanelShell); + + // TreeNode overridables + virtual TaskPaneShellManager* GetShellManager(); + + // ILayoutableWindow overridables + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeigh); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual ::Window* GetWindow (void); + virtual bool IsResizable (void); + virtual bool IsExpandable (void) const; + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& rxParent); + + using Window::GetWindow; + +private: + Size maPreferredSize; + ::Window* mpWrappedControl; + ToolPanelViewShell* m_pPanelViewShell; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/TableDesignPanel.cxx b/sd/source/ui/toolpanel/controls/TableDesignPanel.cxx new file mode 100755 index 000000000000..d6507a25c11f --- /dev/null +++ b/sd/source/ui/toolpanel/controls/TableDesignPanel.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * 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_sd.hxx" + +#include "TableDesignPanel.hxx" + +#include "taskpane/TaskPaneControlFactory.hxx" +#include "taskpane/ToolPanelViewShell.hxx" + +#include "strings.hrc" +#include "sdresid.hxx" + +namespace sd +{ + + class ViewShellBase; + extern ::Window * createTableDesignPanel( ::Window* pParent, ViewShellBase& rBase ); + +namespace toolpanel { namespace controls { + + +TableDesignPanel::TableDesignPanel( ::Window& i_rParentWindow, ToolPanelViewShell& i_rPanelViewShell ) + :SubToolPanel( i_rParentWindow ) + ,m_pPanelViewShell( &i_rPanelViewShell ) +{ + mpWrappedControl = createTableDesignPanel( &i_rParentWindow, i_rPanelViewShell.GetViewShellBase() ); + mpWrappedControl->Show(); +} + +TableDesignPanel::~TableDesignPanel() +{ + delete mpWrappedControl; +} + +std::auto_ptr< ControlFactory > TableDesignPanel::CreateControlFactory( ToolPanelViewShell& i_rToolPanelShell ) +{ + return std::auto_ptr< ControlFactory >( + new RootControlFactoryWithArg< TableDesignPanel, ToolPanelViewShell >( i_rToolPanelShell ) ); +} + +TaskPaneShellManager* TableDesignPanel::GetShellManager() +{ + if ( m_pPanelViewShell ) + return &m_pPanelViewShell->GetSubShellManager(); + return SubToolPanel::GetShellManager(); +} + +Size TableDesignPanel::GetPreferredSize() +{ + return maPreferredSize; +} +sal_Int32 TableDesignPanel::GetPreferredWidth(sal_Int32 ) +{ + return maPreferredSize.Width(); +} +sal_Int32 TableDesignPanel::GetPreferredHeight(sal_Int32 ) +{ + return maPreferredSize.Height(); +} +::Window* TableDesignPanel::GetWindow() +{ + return mpWrappedControl; +} +bool TableDesignPanel::IsResizable() +{ + return true; +} +bool TableDesignPanel::IsExpandable() const +{ + return true; +} + +::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible> TableDesignPanel::CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& ) +{ + if (GetWindow() != NULL) + return GetWindow()->GetAccessible(); + else + return NULL; +} + +} } } // end of namespace ::sd::toolpanel::controls diff --git a/sd/source/ui/toolpanel/controls/TableDesignPanel.hxx b/sd/source/ui/toolpanel/controls/TableDesignPanel.hxx new file mode 100755 index 000000000000..a3620df2ef68 --- /dev/null +++ b/sd/source/ui/toolpanel/controls/TableDesignPanel.hxx @@ -0,0 +1,81 @@ +/************************************************************************* + * + * 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 SD_TOOLPANEL_CONTROLS_TABLE_DESIGN_PANEL_HXX +#define SD_TOOLPANEL_CONTROLS_TABLE_DESIGN_PANEL_HXX + +#include "taskpane/SubToolPanel.hxx" + +namespace sd { +class ViewShellBase; +} + +namespace sd { namespace toolpanel { +class TreeNode; +class ControlFactory; +class ToolPanelViewShell; +} } + +namespace sd { namespace toolpanel { namespace controls { + +class TableDesignPanel + : public SubToolPanel +{ +public: + TableDesignPanel ( + ::Window& i_rParentWindow, + ToolPanelViewShell& i_rPanelViewShell); + virtual ~TableDesignPanel (void); + + static std::auto_ptr<ControlFactory> CreateControlFactory (ToolPanelViewShell& i_rToolPanelShell); + + // TreeNode overridables + virtual TaskPaneShellManager* GetShellManager(); + + // ILayoutableWindow overridables + virtual Size GetPreferredSize (void); + virtual sal_Int32 GetPreferredWidth (sal_Int32 nHeigh); + virtual sal_Int32 GetPreferredHeight (sal_Int32 nWidth); + virtual ::Window* GetWindow (void); + virtual bool IsResizable (void); + virtual bool IsExpandable (void) const; + + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > CreateAccessibleObject ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible>& rxParent); + + using Window::GetWindow; +private: + Size maPreferredSize; + ::Window* mpWrappedControl; + ToolPanelViewShell* m_pPanelViewShell; +}; + +} } } // end of namespace ::sd::toolpanel::controls + +#endif diff --git a/sd/source/ui/toolpanel/controls/makefile.mk b/sd/source/ui/toolpanel/controls/makefile.mk new file mode 100755 index 000000000000..b2218e55008c --- /dev/null +++ b/sd/source/ui/toolpanel/controls/makefile.mk @@ -0,0 +1,67 @@ +#************************************************************************* +# +# 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=..$/..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=tpcontrols +ENABLE_EXCEPTIONS=TRUE +AUTOSEG=true +PRJINC=..$/..$/ ..$/..$/slidesorter + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/AllMasterPagesSelector.obj \ + $(SLO)$/CurrentMasterPagesSelector.obj \ + $(SLO)$/DocumentHelper.obj \ + $(SLO)$/MasterPageObserver.obj \ + $(SLO)$/MasterPagesPanel.obj \ + $(SLO)$/MasterPagesSelector.obj \ + $(SLO)$/MasterPageContainer.obj \ + $(SLO)$/MasterPageContainerFiller.obj \ + $(SLO)$/MasterPageContainerProviders.obj\ + $(SLO)$/MasterPageContainerQueue.obj \ + $(SLO)$/MasterPageDescriptor.obj \ + $(SLO)$/PreviewValueSet.obj \ + $(SLO)$/RecentlyUsedMasterPages.obj \ + $(SLO)$/RecentMasterPagesSelector.obj \ + $(SLO)$/CustomAnimationPanel.obj \ + $(SLO)$/SlideTransitionPanel.obj \ + $(SLO)$/TableDesignPanel.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sd/source/ui/toolpanel/makefile.mk b/sd/source/ui/toolpanel/makefile.mk new file mode 100755 index 000000000000..262b32535ef3 --- /dev/null +++ b/sd/source/ui/toolpanel/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=toolpanel +ENABLE_EXCEPTIONS=TRUE +AUTOSEG=true +PRJINC=..$/slidesorter + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/ControlContainer.obj \ + $(SLO)$/ScrollPanel.obj \ + $(SLO)$/SubToolPanel.obj \ + $(SLO)$/TitleBar.obj \ + $(SLO)$/TitledControl.obj \ + $(SLO)$/TaskPaneControlFactory.obj \ + $(SLO)$/TaskPaneFocusManager.obj \ + $(SLO)$/TaskPaneShellManager.obj \ + $(SLO)$/TaskPaneTreeNode.obj \ + $(SLO)$/ToolPanel.obj \ + $(SLO)$/ToolPanelViewShell.obj \ + $(SLO)$/ToolPanelFactory.obj \ + $(SLO)$/ToolPanelUIElement.obj \ + \ + $(SLO)$/LayoutMenu.obj \ + $(SLO)$/TestMenu.obj \ + $(SLO)$/TestPanel.obj \ + $(SLO)$/SlideSorterCacheDisplay.obj + +EXCEPTIONSFILES= + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + |