diff options
author | Rafael Dominguez <venccsralph@gmail.com> | 2012-07-06 05:23:43 -0430 |
---|---|---|
committer | Rafael Dominguez <venccsralph@gmail.com> | 2012-07-06 05:23:43 -0430 |
commit | 5eb74b1fcad83c605cc00e377460e0ae313d7277 (patch) | |
tree | dae1a098290f55460e0da0a024105c1e28e19410 /sfx2/source | |
parent | dafa1f576482bc7a0086c353ffff0dbd594a7915 (diff) | |
parent | fa99c1ea4f6d450cc12998d4513ed8cf77bafcc9 (diff) |
Merge branch 'feature/template-dialog'
Conflicts:
sfx2/Library_sfx.mk
sfx2/inc/sfx2/sfxcommands.h
sfx2/inc/sfx2/sfxsids.hrc
sfx2/source/appl/appserv.cxx
svtools/Library_svt.mk
Change-Id: I4305d81cb5fd6f5192a29f85835c78f31310b0d6
Diffstat (limited to 'sfx2/source')
21 files changed, 5166 insertions, 0 deletions
diff --git a/sfx2/source/appl/appserv.cxx b/sfx2/source/appl/appserv.cxx index 084a2d65ccd0..fadf7ea7a35a 100644 --- a/sfx2/source/appl/appserv.cxx +++ b/sfx2/source/appl/appserv.cxx @@ -53,6 +53,7 @@ #include "comphelper/configurationhelper.hxx" #include <svtools/addresstemplate.hxx> +#include <svtools/miscopt.hxx> #include <svl/visitem.hxx> #include <unotools/intlwrapper.hxx> @@ -125,6 +126,7 @@ #include "sorgitm.hxx" #include "sfx2/sfxhelp.hxx" #include <sfx2/zoomitem.hxx> +#include "templatedlg.hxx" using namespace ::com::sun::star; using namespace ::com::sun::star::beans; @@ -547,6 +549,14 @@ void SfxApplication::MiscExec_Impl( SfxRequest& rReq ) break; } + case SID_TEMPLATE_MANAGER: + { + SfxTemplateManagerDlg dlg; + dlg.Execute(); + bDone = true; + break; + } + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case SID_ORGANIZER: { @@ -814,6 +824,17 @@ void SfxApplication::MiscState_Impl(SfxItemSet &rSet) rSet.DisableItem(SID_SHOW_IME_STATUS_WINDOW); break; + case SID_TEMPLATE_MANAGER: + { + SvtMiscOptions aMiscOptions; + if ( !aMiscOptions.IsExperimentalMode() ) + { + rSet.DisableItem( nWhich ); + rSet.Put( SfxVisibilityItem( nWhich, sal_False ) ); + } + } + break; + default: break; } diff --git a/sfx2/source/control/templatefolderview.cxx b/sfx2/source/control/templatefolderview.cxx new file mode 100644 index 000000000000..c66148d5bbfe --- /dev/null +++ b/sfx2/source/control/templatefolderview.cxx @@ -0,0 +1,707 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/templatefolderview.hxx> + +#include <comphelper/processfactory.hxx> +#include <sfx2/doctempl.hxx> +#include <sfx2/templateview.hxx> +#include <sfx2/templateviewitem.hxx> +#include <sfx2/templatefolderviewitem.hxx> +#include <svl/inettype.hxx> +#include <svtools/imagemgr.hxx> +#include <tools/urlobj.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/pngread.hxx> + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#define ITEM_MAX_WIDTH 192 +#define ITEM_MAX_HEIGHT 192 +#define ITEM_PADDING 5 +#define ITEM_SPACE 20 +#define THUMBNAIL_MAX_HEIGHT 128 - 2*ITEM_PADDING +#define THUMBNAIL_MAX_WIDTH ITEM_MAX_WIDTH - 2*ITEM_PADDING + +#define INIT_VIEW_COLS 3 +#define INIT_VIEW_LINES 1 + +void lcl_updateThumbnails (TemplateFolderViewItem *pItem); + +BitmapEx lcl_ScaleImg (const BitmapEx &rImg, long width, long height) +{ + BitmapEx aImg = rImg; + + int sWidth = std::min(aImg.GetSizePixel().getWidth(),width); + int sHeight = std::min(aImg.GetSizePixel().getHeight(),height); + + aImg.Scale(Size(sWidth,sHeight),BMP_SCALE_INTERPOLATE); + + return aImg; +} + +BitmapEx lcl_fetchThumbnail (const rtl::OUString &msURL, long width, long height) +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + + // 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( "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( + "Thumbnails", + embed::ElementModes::READ)); + if (xStorage.is()) + { + uno::Reference<io::XStream> xThumbnailCopy ( + xStorage->cloneStreamElement("thumbnail.png")); + if (xThumbnailCopy.is()) + xIStream = xThumbnailCopy->getInputStream(); + } + } + } + catch (const 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( "Thumbnail", + embed::ElementModes::READ)); + if (xStorage.is()) + { + uno::Reference<io::XStream> xThumbnailCopy ( + xStorage->cloneStreamElement("thumbnail.png")); + if (xThumbnailCopy.is()) + xIStream = xThumbnailCopy->getInputStream(); + } + } + } + catch (const 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 (const 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 (); + } + + return lcl_ScaleImg(aThumbnail,width,height); +} + +// Display template items depending on the generator application +class ViewFilter_Application +{ +public: + + ViewFilter_Application (SfxDocumentTemplates *pDocTemplates, FILTER_APPLICATION App) + : mApp(App), mpDocTemplates(pDocTemplates) + {} + + bool operator () (const ThumbnailViewItem *pItem) + { + const TemplateViewItem *pTempItem = static_cast<const TemplateViewItem*>(pItem); + + if (mApp == FILTER_APP_WRITER) + { + return pTempItem->getFileType() == "OpenDocument Text" || + pTempItem->getFileType() == "OpenDocument Text Template"; + } + else if (mApp == FILTER_APP_CALC) + { + return pTempItem->getFileType() == "OpenDocument Spreadsheet" || + pTempItem->getFileType() == "OpenDocument Spreadsheet Template"; + } + else if (mApp == FILTER_APP_IMPRESS) + { + return pTempItem->getFileType() == "OpenDocument Presentation" || + pTempItem->getFileType() == "OpenDocument Presentation Template"; + } + else if (mApp == FILTER_APP_DRAW) + { + return pTempItem->getFileType() == "OpenDocument Drawing" || + pTempItem->getFileType() == "OpenDocument Drawing Template"; + } + + return true; + } + +private: + + FILTER_APPLICATION mApp; + SfxDocumentTemplates *mpDocTemplates; +}; + +class FolderFilter_Application +{ +public: + + FolderFilter_Application ( SfxDocumentTemplates *pDocTemplates, FILTER_APPLICATION eApp) + : meApp(eApp) + { + maFilterFunc = ViewFilter_Application(pDocTemplates,eApp); + } + + bool operator () (const ThumbnailViewItem *pItem) + { + TemplateFolderViewItem *pFolderItem = (TemplateFolderViewItem*)pItem; + + std::vector<TemplateViewItem*> &rTemplates = pFolderItem->maTemplates; + + size_t nVisCount = 0; + ThumbnailViewItem *pTemplateItem; + + // Clear thumbnails + pFolderItem->maPreview1.Clear(); + pFolderItem->maPreview2.Clear(); + + for (size_t i = 0, n = rTemplates.size(); i < n; ++i) + { + pTemplateItem = rTemplates[i]; + + if (maFilterFunc(pTemplateItem)) + { + ++nVisCount; + + // Update the thumbnails + if (nVisCount == 1) + pFolderItem->maPreview1 = pTemplateItem->maPreview1; + else if (nVisCount == 2) + pFolderItem->maPreview2 = pTemplateItem->maPreview1; + } + } + + return nVisCount; + } + +private: + + FILTER_APPLICATION meApp; + boost::function<bool (const ThumbnailViewItem*)> maFilterFunc; +}; + +TemplateFolderView::TemplateFolderView ( Window* pParent, const ResId& rResId, bool bDisableTransientChildren) + : ThumbnailView(pParent,rResId,bDisableTransientChildren), + mbFilteredResults(false), + meFilterOption(FILTER_APP_NONE), + mpDocTemplates(new SfxDocumentTemplates), + mpItemView(new TemplateView(this,mpDocTemplates)) +{ + Size aViewSize = mpItemView->CalcWindowSizePixel(INIT_VIEW_COLS,INIT_VIEW_LINES, + ITEM_MAX_WIDTH,ITEM_MAX_HEIGHT,ITEM_SPACE); + + mpItemView->SetColor(Color(COL_WHITE)); + mpItemView->SetSizePixel(aViewSize); + mpItemView->setItemDimensions(ITEM_MAX_WIDTH,THUMBNAIL_MAX_HEIGHT, + ITEM_MAX_HEIGHT-THUMBNAIL_MAX_HEIGHT, + ITEM_PADDING); + + mpItemView->setItemStateHdl(LINK(this,TemplateFolderView,TVTemplateStateHdl)); + mpItemView->setChangeNameHdl(LINK(this,TemplateFolderView,ChangeNameHdl)); + mpItemView->setCloseHdl(LINK(this,TemplateFolderView,OverlayCloseHdl)); +} + +TemplateFolderView::~TemplateFolderView() +{ + delete mpItemView; + delete mpDocTemplates; +} + +void TemplateFolderView::Populate () +{ + sal_uInt16 nCount = mpDocTemplates->GetRegionCount(); + for (sal_uInt16 i = 0; i < nCount; ++i) + { + rtl::OUString aRegionName(mpDocTemplates->GetFullRegionName(i)); + + if ((sal_uInt32)aRegionName.getLength() > mpItemAttrs->nMaxTextLenght) + { + aRegionName = aRegionName.copy(0,mpItemAttrs->nMaxTextLenght-3); + aRegionName += "..."; + } + + TemplateFolderViewItem* pItem = new TemplateFolderViewItem( *this, this ); + pItem->mnId = i+1; + pItem->maText = aRegionName; + pItem->setSelectClickHdl(LINK(this,ThumbnailView,OnFolderSelected)); + + sal_uInt16 nEntries = mpDocTemplates->GetCount(i); + + for (sal_uInt16 j = 0; j < nEntries; ++j) + { + rtl::OUString aName = mpDocTemplates->GetName(i,j); + rtl::OUString aURL = mpDocTemplates->GetPath(i,j); + rtl::OUString aType = SvFileInformationManager::GetDescription(INetURLObject(aURL)); + + if ((sal_uInt32)aName.getLength() > mpItemAttrs->nMaxTextLenght) + { + aName = aName.copy(0,mpItemAttrs->nMaxTextLenght-3); + aName += "..."; + } + + TemplateViewItem *pTemplateItem = new TemplateViewItem(*mpItemView,mpItemView); + pTemplateItem->mnId = j+1; + pTemplateItem->maText = aName; + pTemplateItem->setPath(aURL); + pTemplateItem->setFileType(aType); + pTemplateItem->maPreview1 = lcl_fetchThumbnail(aURL,THUMBNAIL_MAX_WIDTH,THUMBNAIL_MAX_HEIGHT); + + pItem->maTemplates.push_back(pTemplateItem); + } + + lcl_updateThumbnails(pItem); + + mItemList.push_back(pItem); + } + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +std::vector<rtl::OUString> TemplateFolderView::getFolderNames() +{ + size_t n = mItemList.size(); + std::vector<rtl::OUString> ret(n); + + for (size_t i = 0; i < n; ++i) + ret[i] = mItemList[i]->maText; + + return ret; +} + +bool TemplateFolderView::isOverlayVisible () const +{ + return mpItemView->IsVisible(); +} + +void TemplateFolderView::showOverlay (bool bVisible) +{ + mbActive = !bVisible; + mpItemView->Show(bVisible); + + // Clear items is the overlay is closed. + if (!bVisible) + { + // Check if the folder view needs to be filtered + if (mbFilteredResults) + { + filterItems(FolderFilter_Application(mpDocTemplates,meFilterOption)); + + mbFilteredResults = false; + meFilterOption = FILTER_APP_NONE; + } + + mpItemView->Clear(); + + setSelectionMode(mbSelectionMode); + } +} + +void TemplateFolderView::setOverlayDblClickHdl(const Link &rLink) +{ + mpItemView->setDblClickHdl(rLink); +} + +void TemplateFolderView::filterTemplatesByApp (const FILTER_APPLICATION &eApp) +{ + meFilterOption = eApp; + + if (mpItemView->IsVisible()) + { + mbFilteredResults = true; + mpItemView->filterItems(ViewFilter_Application(mpDocTemplates,eApp)); + } + else + { + filterItems(FolderFilter_Application(mpDocTemplates,eApp)); + } +} + +std::vector<std::pair<sal_uInt16,std::vector<ThumbnailViewItem*> > > +TemplateFolderView::getFilteredItems(const boost::function<bool (const ThumbnailViewItem*) > &rFunc) const +{ + std::vector<ThumbnailViewItem*> aRegionItems; + std::vector<std::pair<sal_uInt16,std::vector<ThumbnailViewItem*> > > aItems; + + for (size_t i = 0; i < mItemList.size(); ++i) + { + TemplateFolderViewItem *pFolderItem = static_cast<TemplateFolderViewItem*>(mItemList[i]); + + sal_uInt16 nRegionId = pFolderItem->mnId-1; + + for (size_t j = 0; j < pFolderItem->maTemplates.size(); ++j) + { + if (rFunc(pFolderItem->maTemplates[j])) + aRegionItems.push_back(pFolderItem->maTemplates[j]); + } + + aItems.push_back(std::make_pair(nRegionId,aRegionItems)); + aRegionItems.clear(); + } + + return aItems; +} + +void TemplateFolderView::sortOverlayItems(const boost::function<bool (const ThumbnailViewItem*, + const ThumbnailViewItem*) > &func) +{ + mpItemView->sortItems(func); +} + +sal_uInt16 TemplateFolderView::createRegion(const rtl::OUString &rName) +{ + sal_uInt16 nRegionId = mpDocTemplates->GetRegionCount(); // Next regionId + + if (!mpDocTemplates->InsertDir(rName,nRegionId)) + return false; + + rtl::OUString aRegionName = rName; + + if ((sal_uInt32)aRegionName.getLength() > mpItemAttrs->nMaxTextLenght) + { + aRegionName = aRegionName.copy(0,mpItemAttrs->nMaxTextLenght-3); + aRegionName += "..."; + } + + TemplateFolderViewItem* pItem = new TemplateFolderViewItem( *this, this ); + pItem->mnId = nRegionId+1; + pItem->maText = aRegionName; + pItem->setSelectClickHdl(LINK(this,ThumbnailView,OnFolderSelected)); + + mItemList.push_back(pItem); + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + + return true; +} + +bool TemplateFolderView::removeTemplate (const sal_uInt16 nItemId) +{ + sal_uInt16 nRegionId = mpItemView->getRegionId(); + sal_uInt16 nItemRegionId = nRegionId + 1; + sal_uInt16 nTemplateId = nItemId - 1; + + if (!mpDocTemplates->Delete(nRegionId,nTemplateId)) + return false; + + for (size_t i = 0, n = mItemList.size(); i < n; ++i) + { + if (mItemList[i]->mnId == nItemRegionId) + { + + TemplateFolderViewItem *pItem = static_cast<TemplateFolderViewItem*>(mItemList[i]); + std::vector<TemplateViewItem*>::iterator pIter; + for (pIter = pItem->maTemplates.begin(); pIter != pItem->maTemplates.end(); ++pIter) + { + if ((*pIter)->mnId == nItemId) + { + delete *pIter; + + pItem->maTemplates.erase(pIter); + + mpItemView->RemoveItem(nItemId); + + break; + } + } + + lcl_updateThumbnails(pItem); + + CalculateItemPositions(); + + break; + } + } + + return true; +} + +bool TemplateFolderView::moveTemplates(std::set<const ThumbnailViewItem *> &rItems, + const sal_uInt16 nTargetItem, bool bCopy) +{ + bool ret = true; + bool refresh = false; + + sal_uInt16 nSrcRegionId = mpItemView->getRegionId(); + sal_uInt16 nSrcRegionItemId = nSrcRegionId + 1; + + TemplateFolderViewItem *pTarget = NULL; + TemplateFolderViewItem *pSrc = NULL; + + for (size_t i = 0, n = mItemList.size(); i < n; ++i) + { + if (mItemList[i]->mnId == nTargetItem) + pTarget = static_cast<TemplateFolderViewItem*>(mItemList[i]); + else if (mItemList[i]->mnId == nSrcRegionItemId) + pSrc = static_cast<TemplateFolderViewItem*>(mItemList[i]); + } + + if (pTarget && pSrc) + { + sal_uInt16 nTargetRegion = pTarget->mnId-1; + sal_uInt16 nTargetIdx = mpDocTemplates->GetCount(nTargetRegion); // Next Idx + + std::set<const ThumbnailViewItem*>::iterator aSelIter; + for ( aSelIter = rItems.begin(); aSelIter != rItems.end(); ++aSelIter, ++nTargetIdx ) + { + const TemplateViewItem *pViewItem = static_cast<const TemplateViewItem*>(*aSelIter); + + bool bOK; + + if (bCopy) + bOK = mpDocTemplates->Copy(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnId-1); + else + bOK = mpDocTemplates->Move(nTargetRegion,nTargetIdx,nSrcRegionId,pViewItem->mnId-1); + + if (!bOK) + { + ret = false; + continue; + } + + // move template to destination + + TemplateViewItem *pTemplateItem = new TemplateViewItem(*mpItemView,mpItemView); + pTemplateItem->mnId = nTargetIdx + 1; + pTemplateItem->maText = pViewItem->maText; + pTemplateItem->setPath(pViewItem->getPath()); + pTemplateItem->setFileType(pViewItem->getFileType()); + pTemplateItem->maPreview1 = pViewItem->maPreview1; + + pTarget->maTemplates.push_back(pTemplateItem); + + if (!bCopy) + { + // remove template for overlay and from cached data + + std::vector<TemplateViewItem*>::iterator pIter; + for (pIter = pSrc->maTemplates.begin(); pIter != pSrc->maTemplates.end(); ++pIter) + { + if ((*pIter)->mnId == pViewItem->mnId) + { + delete *pIter; + + pSrc->maTemplates.erase(pIter); + + mpItemView->RemoveItem(pViewItem->mnId); + break; + } + } + } + + refresh = true; + } + } + else + ret = false; + + if (refresh) + { + lcl_updateThumbnails(pSrc); + lcl_updateThumbnails(pTarget); + + CalculateItemPositions(); + + Invalidate(); + mpItemView->Invalidate(); + } + + return ret; +} + +void TemplateFolderView::copyFrom (TemplateFolderViewItem *pItem, const rtl::OUString &rPath) +{ + sal_uInt16 nId = 0; + sal_uInt16 nRegionId = pItem->mnId - 1; + String aPath(rPath); + + if (!mItemList.empty()) + nId = (mItemList.back())->mnId+1; + + if (mpDocTemplates->CopyFrom(nRegionId,nId,aPath)) + { + TemplateViewItem *pTemplate = new TemplateViewItem(*mpItemView,mpItemView); + pTemplate->mnId = nId; + pTemplate->maText = mpDocTemplates->GetName(nRegionId,nId); + pTemplate->maPreview1 = lcl_fetchThumbnail(rPath,128,128); + pTemplate->setPath(rPath); + pTemplate->setFileType(SvFileInformationManager::GetDescription(INetURLObject(rPath))); + + pItem->maTemplates.push_back(pTemplate); + + lcl_updateThumbnails(pItem); + + CalculateItemPositions(); + } +} + +void TemplateFolderView::Resize() +{ + Size aWinSize = GetOutputSize(); + Size aViewSize = mpItemView->GetSizePixel(); + + Point aPos; + aPos.setX((aWinSize.getWidth() - aViewSize.getWidth())/2); + + mpItemView->SetPosPixel(aPos); +} + +void TemplateFolderView::OnSelectionMode (bool bMode) +{ + if (mpItemView->IsVisible()) + { + mbSelectionMode = bMode; + mpItemView->setSelectionMode(bMode); + } + else + ThumbnailView::OnSelectionMode(bMode); +} + +void TemplateFolderView::OnItemDblClicked (ThumbnailViewItem *pRegionItem) +{ + // Fill templates + sal_uInt16 nRegionId = pRegionItem->mnId-1; + + mpItemView->setRegionId(nRegionId); + mpItemView->InsertItems(static_cast<TemplateFolderViewItem*>(pRegionItem)->maTemplates); + + if (mbSelectionMode) + mpItemView->setSelectionMode(true); + + if (meFilterOption != FILTER_APP_NONE) + mpItemView->filterItems(ViewFilter_Application(mpDocTemplates,meFilterOption)); + + mbActive = false; + mpItemView->Show(); +} + +IMPL_LINK(TemplateFolderView, TVTemplateStateHdl, const ThumbnailViewItem*, pItem) +{ + maTemplateStateHdl.Call((void*)pItem); + return 0; +} + +IMPL_LINK(TemplateFolderView, ChangeNameHdl, TemplateView*, pView) +{ + sal_uInt16 nRegionId = pView->getRegionId(); + sal_uInt16 nItemId = nRegionId + 1; + + if (!mpDocTemplates->SetName(pView->getRegionName(),nRegionId,USHRT_MAX)) + return false; + + for (size_t i = 0; i < mItemList.size(); ++i) + { + if (mItemList[i]->mnId == nItemId) + { + mItemList[i]->maText = pView->getRegionName(); + mItemList[i]->calculateItemsPosition(mpItemAttrs->nMaxTextLenght); + Invalidate(); + break; + } + } + + return true; +} + +IMPL_LINK_NOARG(TemplateFolderView, OverlayCloseHdl) +{ + showOverlay(false); + return 0; +} + +void lcl_updateThumbnails (TemplateFolderViewItem *pItem) +{ + // Update folder thumbnails + for (size_t i = 0, n = pItem->maTemplates.size(); i < 2 && i < n; ++i) + { + if (i == 0) + { + pItem->maPreview1 = lcl_ScaleImg(pItem->maTemplates[i]->maPreview1, + THUMBNAIL_MAX_WIDTH*0.75, + THUMBNAIL_MAX_HEIGHT*0.75); + } + else + { + pItem->maPreview2 = lcl_ScaleImg(pItem->maTemplates[i]->maPreview1, + THUMBNAIL_MAX_WIDTH*0.75, + THUMBNAIL_MAX_HEIGHT*0.75); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/control/templatefolderviewitem.cxx b/sfx2/source/control/templatefolderviewitem.cxx new file mode 100644 index 000000000000..7c5459b173e4 --- /dev/null +++ b/sfx2/source/control/templatefolderviewitem.cxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/templatefolderviewitem.hxx> + +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/attribute/fillbitmapattribute.hxx> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <sfx2/templateviewitem.hxx> +#include <vcl/button.hxx> + +using namespace basegfx; +using namespace basegfx::tools; +using namespace drawinglayer::attribute; +using namespace drawinglayer::primitive2d; + +TemplateFolderViewItem::TemplateFolderViewItem (ThumbnailView &rView, Window *pParent) + : ThumbnailViewItem(rView,pParent) +{ +} + +TemplateFolderViewItem::~TemplateFolderViewItem () +{ + for (size_t i = 0; i < maTemplates.size(); ++i) + delete maTemplates[i]; +} + +void TemplateFolderViewItem::calculateItemsPosition (sal_uInt32 nMaxTextLenght) +{ + ThumbnailViewItem::calculateItemsPosition(nMaxTextLenght); +} + +void TemplateFolderViewItem::Paint (drawinglayer::processor2d::BaseProcessor2D *pProcessor, + const ThumbnailItemAttributes *pAttrs) +{ + int nCount = 0; + int nSeqSize = 3; + + if (!maPreview2.IsEmpty()) + ++nSeqSize; + + BColor aFillColor = pAttrs->aFillColor; + Primitive2DSequence aSeq(nSeqSize); + + // Draw background + if ( mbSelected || mbHover ) + aFillColor = pAttrs->aHighlightColor; + + aSeq[nCount++] = Primitive2DReference( new PolyPolygonColorPrimitive2D( + B2DPolyPolygon(Polygon(maDrawArea,5,5).getB2DPolygon()), + aFillColor)); + + // Draw thumbnail + Point aPos = maPrev1Pos; + Size aImageSize = maPreview1.GetSizePixel(); + + float fScaleX = 1.0f; + float fScaleY = 1.0f; + + if (!maPreview2.IsEmpty()) + { + fScaleX = 0.8; + fScaleY = 0.8; + + aSeq[nCount++] = Primitive2DReference( new FillBitmapPrimitive2D( + createScaleTranslateB2DHomMatrix(fScaleX,fScaleY,aPos.X(),aPos.Y()), + FillBitmapAttribute(maPreview2, + B2DPoint(35,20), + B2DVector(aImageSize.Width(),aImageSize.Height()), + false) + )); + } + + aSeq[nCount++] = Primitive2DReference( new FillBitmapPrimitive2D( + createScaleTranslateB2DHomMatrix(fScaleX,fScaleY,aPos.X(),aPos.Y()), + FillBitmapAttribute(maPreview1, + B2DPoint(0,0), + B2DVector(aImageSize.Width(),aImageSize.Height()), + false) + )); + + // Draw centered text below thumbnail + aPos = maTextPos; + + // Create the text primitive + basegfx::B2DHomMatrix aTextMatrix( createScaleTranslateB2DHomMatrix( + pAttrs->aFontSize.getX(), pAttrs->aFontSize.getY(), + double( aPos.X() ), double( aPos.Y() ) ) ); + + aSeq[nCount++] = Primitive2DReference( + new TextSimplePortionPrimitive2D(aTextMatrix, + maText,0,maText.getLength(), + std::vector< double >( ), + pAttrs->aFontAttr, + com::sun::star::lang::Locale(), + Color(COL_BLACK).getBColor() ) ); + + pProcessor->process(aSeq); + + if (mbMode || mbHover || mbSelected) + mpSelectBox->Paint(maDrawArea); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/templatesearchview.cxx b/sfx2/source/control/templatesearchview.cxx new file mode 100644 index 000000000000..fa6eabcbd1c3 --- /dev/null +++ b/sfx2/source/control/templatesearchview.cxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "templatesearchview.hxx" + +#include <sfx2/templateviewitem.hxx> + +struct TemplateSearchViewItem : public TemplateViewItem +{ + TemplateSearchViewItem (ThumbnailView &rView, Window *pParent) + : TemplateViewItem(rView,pParent) + {} + + virtual ~TemplateSearchViewItem () + {} + + sal_uInt16 mnIdx; // Template associated Index + sal_uInt16 mnRegionId; // Template associated Region id +}; + +TemplateSearchView::TemplateSearchView (Window *pParent, WinBits nWinStyle) + : ThumbnailView(pParent,nWinStyle) +{ +} + +TemplateSearchView::~TemplateSearchView () +{ +} + +void TemplateSearchView::AppendItem(sal_uInt16 nItemId, sal_uInt16 nRegionId, sal_uInt16 nIdx, + const rtl::OUString &rStr, const rtl::OUString &rPath, + const BitmapEx &rImage) +{ + TemplateSearchViewItem *pItem = new TemplateSearchViewItem(*this,this); + pItem->mnId = nItemId; + pItem->mnIdx = nIdx; + pItem->mnRegionId = nRegionId; + pItem->maPreview1 = rImage; + pItem->maText = rStr; + pItem->setPath(rPath); + pItem->setSelectClickHdl(LINK(this,ThumbnailView,OnFolderSelected)); + + mItemList.push_back(pItem); + + CalculateItemPositions(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/templateview.cxx b/sfx2/source/control/templateview.cxx new file mode 100644 index 000000000000..1ffd1c89802b --- /dev/null +++ b/sfx2/source/control/templateview.cxx @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/templateview.hxx> + +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <drawinglayer/attribute/fillbitmapattribute.hxx> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <sfx2/doctempl.hxx> +#include <sfx2/sfxresid.hxx> +#include <sfx2/templateviewitem.hxx> +#include <vcl/edit.hxx> + +#include "templateview.hrc" + +#define EDIT_HEIGHT 20 + +using namespace basegfx; +using namespace basegfx::tools; +using namespace drawinglayer::attribute; +using namespace drawinglayer::primitive2d; + +TemplateView::TemplateView (Window *pParent, SfxDocumentTemplates *pTemplates) + : ThumbnailView(pParent,WB_VSCROLL), + maCloseImg(SfxResId(IMG_TEMPLATE_VIEW_CLOSE)), + mbRenderTitle(true), + mnRegionId(0), + mpDocTemplates(pTemplates), + mpEditName(new Edit(this, WB_BORDER | WB_HIDE)) +{ + mnHeaderHeight = 30; +} + +TemplateView::~TemplateView () +{ +} + +void TemplateView::setRegionId (const sal_uInt16 nRegionId) +{ + mnRegionId = nRegionId; + maFolderName = mpDocTemplates->GetRegionName(nRegionId); + mpEditName->SetText(rtl::OUString()); +} + +void TemplateView::Paint (const Rectangle &rRect) +{ + ThumbnailView::Paint(rRect); + + int nCount = 0; + int nMaxCount = 1; + + if (mbRenderTitle) + ++nMaxCount; + + Primitive2DSequence aSeq(nMaxCount); + TextLayouterDevice aTextDev; + + // Draw centered region name + Point aPos; + Size aWinSize = GetOutputSizePixel(); + + if (mbRenderTitle) + { + aPos.X() = (aWinSize.getWidth() - aTextDev.getTextWidth(maFolderName,0,maFolderName.getLength()))/2; + aPos.Y() = aTextDev.getTextHeight() + (mnHeaderHeight - aTextDev.getTextHeight())/2; + + basegfx::B2DHomMatrix aTextMatrix( createScaleTranslateB2DHomMatrix( + mpItemAttrs->aFontSize.getX(), mpItemAttrs->aFontSize.getY(), + double( aPos.X() ), double( aPos.Y() ) ) ); + + aSeq[nCount++] = Primitive2DReference( + new TextSimplePortionPrimitive2D(aTextMatrix, + maFolderName,0,maFolderName.getLength(), + std::vector< double >( ), + mpItemAttrs->aFontAttr, + com::sun::star::lang::Locale(), + Color(COL_BLACK).getBColor() ) ); + } + + // Draw close icon + Size aImageSize = maCloseImg.GetSizePixel(); + + aPos.Y() = (mnHeaderHeight - aImageSize.Height())/2; + aPos.X() = aWinSize.Width() - aImageSize.Width() - aPos.Y(); + + aSeq[nCount] = Primitive2DReference( new FillBitmapPrimitive2D( + createTranslateB2DHomMatrix(aPos.X(),aPos.Y()), + FillBitmapAttribute(maCloseImg.GetBitmapEx(), + B2DPoint(0,0), + B2DVector(aImageSize.Width(),aImageSize.Height()), + false) + )); + + mpProcessor->process(aSeq); +} + +void TemplateView::InsertItems (const std::vector<TemplateViewItem*> &rTemplates) +{ + for (size_t i = 0, n = rTemplates.size(); i < n; ++i ) + { + TemplateViewItem *pItem = new TemplateViewItem(*this,this); + TemplateViewItem *pCur = rTemplates[i]; + + pItem->mnId = pCur->mnId; + pItem->maText = pCur->maText; + pItem->setPath(pCur->getPath()); + pItem->setFileType(pCur->getFileType()); + pItem->maPreview1 = pCur->maPreview1; + pItem->setSelectClickHdl(LINK(this,ThumbnailView,OnFolderSelected)); + + mItemList.push_back(pItem); + } + + CalculateItemPositions(); + + Invalidate(); +} + +void TemplateView::Resize() +{ + // Set editbox size and position + Size aWinSize = GetOutputSize(); + + Size aEditSize(aWinSize.getWidth()/2,EDIT_HEIGHT); + + Point aPos; + aPos.X() = (aWinSize.getWidth() - aEditSize.getWidth())/2; + aPos.Y() = (mnHeaderHeight - aEditSize.getHeight())/2; + + mpEditName->SetPosSizePixel(aPos,aEditSize); + + ThumbnailView::Resize(); +} + +void TemplateView::MouseButtonDown (const MouseEvent &rMEvt) +{ + if (rMEvt.IsLeft()) + { + // Check if we are editing title + if (mpEditName->IsVisible()) + { + mpEditName->Show(false); + mbRenderTitle = true; + + // Update name if its not empty + rtl::OUString aTmp = mpEditName->GetText(); + + if (!aTmp.isEmpty()) + { + PostUserEvent(LINK(this,TemplateView,ChangeNameHdl)); + } + else + { + mpEditName->SetText(rtl::OUString()); + Invalidate(); + } + + return; + } + + Size aWinSize = GetOutputSizePixel(); + Size aImageSize = maCloseImg.GetSizePixel(); + + Point aPos; + aPos.Y() = (mnHeaderHeight - aImageSize.Height())/2; + aPos.X() = aWinSize.Width() - aImageSize.Width() - aPos.Y(); + + Rectangle aImgRect(aPos,aImageSize); + + if (aImgRect.IsInside(rMEvt.GetPosPixel())) + { + maCloseHdl.Call(this); + } + else + { + drawinglayer::primitive2d::TextLayouterDevice aTextDev; + + float fTextWidth = aTextDev.getTextWidth(maFolderName,0,maFolderName.getLength()); + + aPos.X() = (aWinSize.getWidth() - fTextWidth)/2; + aPos.Y() = (mnHeaderHeight - aTextDev.getTextHeight())/2; + + Rectangle aTitleRect(aPos,Size(fTextWidth,aTextDev.getTextHeight())); + + if (aTitleRect.IsInside(rMEvt.GetPosPixel())) + { + mbRenderTitle = false; + + Invalidate(); + mpEditName->Show(); + } + } + } + + ThumbnailView::MouseButtonDown(rMEvt); +} + +void TemplateView::OnItemDblClicked(ThumbnailViewItem *pItem) +{ + maDblClickHdl.Call(pItem); +} + +IMPL_LINK_NOARG(TemplateView, ChangeNameHdl) +{ + rtl::OUString aTmp = maFolderName; + maFolderName = mpEditName->GetText(); + + if (!maChangeNameHdl.Call(this)) + maFolderName = aTmp; + + mpEditName->SetText(rtl::OUString()); + + Invalidate(); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/templateview.hrc b/sfx2/source/control/templateview.hrc new file mode 100644 index 000000000000..cc26a18784bf --- /dev/null +++ b/sfx2/source/control/templateview.hrc @@ -0,0 +1,9 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#define IMG_TEMPLATE_VIEW_CLOSE 1 diff --git a/sfx2/source/control/templateview.src b/sfx2/source/control/templateview.src new file mode 100644 index 000000000000..8252ee9a590b --- /dev/null +++ b/sfx2/source/control/templateview.src @@ -0,0 +1,17 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "templateview.hrc" + +Image IMG_TEMPLATE_VIEW_CLOSE +{ + ImageBitmap = Bitmap + { + File = "closedoc.png"; + }; +}; diff --git a/sfx2/source/control/templateviewitem.cxx b/sfx2/source/control/templateviewitem.cxx new file mode 100644 index 000000000000..156f8eae7b39 --- /dev/null +++ b/sfx2/source/control/templateviewitem.cxx @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/templateviewitem.hxx> + +TemplateViewItem::TemplateViewItem (ThumbnailView &rView, Window *pParent) + : ThumbnailViewItem(rView,pParent) +{ +} + +TemplateViewItem::~TemplateViewItem () +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/thumbnailview.cxx b/sfx2/source/control/thumbnailview.cxx new file mode 100644 index 000000000000..92938eb888e0 --- /dev/null +++ b/sfx2/source/control/thumbnailview.cxx @@ -0,0 +1,1157 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sfx2/thumbnailview.hxx> +#include <sfx2/thumbnailviewitem.hxx> + +#include "thumbnailviewacc.hxx" + +#include <basegfx/color/bcolortools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/vector/b2dsize.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <drawinglayer/attribute/fillbitmapattribute.hxx> +#include <drawinglayer/attribute/fontattribute.hxx> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <rtl/ustring.hxx> +#include <vcl/decoview.hxx> +#include <vcl/svapp.hxx> +#include <vcl/scrbar.hxx> +#include <vcl/help.hxx> + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +using namespace basegfx; +using namespace basegfx::tools; +using namespace drawinglayer::attribute; +using namespace drawinglayer::primitive2d; + +enum +{ + ITEM_OFFSET = 4, + ITEM_OFFSET_DOUBLE = 6, + NAME_LINE_OFF_X = 2, + NAME_LINE_OFF_Y = 2, + NAME_LINE_HEIGHT = 2, + NAME_OFFSET = 2, + SCROLL_OFFSET = 4 +}; + +ThumbnailView::ThumbnailView (Window *pParent, WinBits nWinStyle, bool bDisableTransientChildren) + : Control( pParent, nWinStyle ), + maColor( pParent->GetBackground().GetColor() ) +{ + ImplInit(); + mbIsTransientChildrenDisabled = bDisableTransientChildren; +} + +ThumbnailView::ThumbnailView (Window *pParent, const ResId &rResId, bool bDisableTransientChildren) + : Control( pParent, rResId ) +{ + ImplInit(); + mbIsTransientChildrenDisabled = bDisableTransientChildren; +} + +ThumbnailView::~ThumbnailView() +{ + com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> + xComponent(GetAccessible(sal_False), + com::sun::star::uno::UNO_QUERY); + + if (xComponent.is()) + xComponent->dispose (); + + delete mpScrBar; + delete mpItemAttrs; + + ImplDeleteItems(); +} + +void ThumbnailView::ImplInit() +{ + mpScrBar = NULL; + mnHeaderHeight = 0; + mnItemWidth = 0; + mnItemHeight = 0; + mnItemPadding = 0; + mnVisLines = 0; + mnLines = 0; + mnUserItemWidth = 0; + mnUserItemHeight = 0; + mnFirstLine = 0; + mnScrBarOffset = 1; + mnSelItemId = 0; + mnHighItemId = 0; + mnCols = 0; + mnCurCol = 0; + mnUserCols = 0; + mnUserVisLines = 0; + mnSpacing = 0; + mbScroll = false; + mbHasVisibleItems = false; + mbSelectionMode = false; + mbActive = true; + maFilterFunc = ViewFilterAll(); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + mpProcessor = drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos ); + + ImplInitSettings( true, true, true ); +} + +void ThumbnailView::ImplDeleteItems() +{ + const size_t n = mItemList.size(); + + for ( size_t i = 0; i < n; ++i ) + { + ThumbnailViewItem *const pItem = mItemList[i]; + if ( pItem->isVisible() && ImplHasAccessibleListeners() ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + + aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled ); + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny ); + } + + delete pItem; + } + + mItemList.clear(); +} + +void ThumbnailView::ImplInitSettings( bool bFont, bool bForeground, bool bBackground ) +{ + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + + if ( bFont ) + { + Font aFont; + aFont = rStyleSettings.GetAppFont(); + if ( IsControlFont() ) + aFont.Merge( GetControlFont() ); + SetZoomedPointFont( aFont ); + } + + if ( bForeground || bFont ) + { + Color aColor; + if ( IsControlForeground() ) + aColor = GetControlForeground(); + else + aColor = rStyleSettings.GetButtonTextColor(); + SetTextColor( aColor ); + SetTextFillColor(); + } + + if ( bBackground ) + { + Color aColor; + if ( IsControlBackground() ) + aColor = GetControlBackground(); + else + aColor = rStyleSettings.GetFaceColor(); + SetBackground( aColor ); + } + + mpItemAttrs = new ThumbnailItemAttributes; + mpItemAttrs->aFillColor = maColor.getBColor(); + mpItemAttrs->aHighlightColor = rStyleSettings.GetHighlightColor().getBColor(); + mpItemAttrs->aFontAttr = getFontAttributeFromVclFont(mpItemAttrs->aFontSize,GetFont(),false,true); + mpItemAttrs->nMaxTextLenght = -1; +} + +void ThumbnailView::ImplInitScrollBar() +{ + if ( GetStyle() & WB_VSCROLL ) + { + if ( !mpScrBar ) + { + mpScrBar = new ScrollBar( this, WB_VSCROLL | WB_DRAG ); + mpScrBar->SetScrollHdl( LINK( this, ThumbnailView, ImplScrollHdl ) ); + } + else + { + // adapt the width because of the changed settings + long nScrBarWidth = GetSettings().GetStyleSettings().GetScrollBarSize(); + mpScrBar->SetPosSizePixel( 0, 0, nScrBarWidth, 0, WINDOW_POSSIZE_WIDTH ); + } + } +} + +void ThumbnailView::DrawItem (ThumbnailViewItem *pItem) +{ + if (mbActive && pItem->isVisible()) + { + Rectangle aRect = pItem->getDrawArea(); + + if ( (aRect.GetHeight() > 0) && (aRect.GetWidth() > 0) ) + pItem->Paint(mpProcessor,mpItemAttrs); + } +} + +void ThumbnailView::OnSelectionMode (bool bMode) +{ + for (size_t i = 0, n = mItemList.size(); i < n; ++i) + { + mItemList[i]->setSelectionMode(bMode); + + if (mItemList[i]->isVisible()) + DrawItem(mItemList[i]); + } +} + +void ThumbnailView::OnItemDblClicked (ThumbnailViewItem*) +{ +} + +::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > ThumbnailView::CreateAccessible() +{ + return new ThumbnailViewAcc( this, mbIsTransientChildrenDisabled ); +} + +void ThumbnailView::CalculateItemPositions () +{ + if (!mnItemHeight || !mnItemWidth) + return; + + Size aWinSize = GetOutputSizePixel(); + size_t nItemCount = mItemList.size(); + WinBits nStyle = GetStyle(); + ScrollBar* pDelScrBar = NULL; + + // consider the scrolling + if ( nStyle & WB_VSCROLL ) + ImplInitScrollBar(); + else + { + if ( mpScrBar ) + { + // delete ScrollBar not until later, to prevent recursive calls + pDelScrBar = mpScrBar; + mpScrBar = NULL; + } + } + + // calculate ScrollBar width + long nScrBarWidth = 0; + if ( mpScrBar ) + nScrBarWidth = mpScrBar->GetSizePixel().Width()+mnScrBarOffset; + + // calculate maximum number of visible columns + mnCols = (sal_uInt16)((aWinSize.Width()-nScrBarWidth) / (mnItemWidth)); + + if ( mnUserCols && mnUserCols < mnCols ) + mnCols = mnUserCols; + + // calculate maximum number of visible rows + mnVisLines = (sal_uInt16)((aWinSize.Height()-mnHeaderHeight) / (mnItemHeight)); + + if ( mnUserVisLines && mnUserVisLines < mnVisLines ) + mnVisLines = mnUserVisLines; + + // calculate empty space + long nHSpace = aWinSize.Width()-nScrBarWidth - mnCols*mnItemWidth; + long nVSpace = aWinSize.Height()-mnHeaderHeight - mnVisLines*mnItemHeight; + long nHItemSpace = nHSpace / (mnCols+1); + long nVItemSpace = nVSpace / (mnVisLines+1); + + // calculate maximum number of rows + // Floor( (M+N-1)/N )==Ceiling( M/N ) + mnLines = (static_cast<long>(nItemCount)+mnCols-1) / mnCols; + + if ( !mnLines ) + mnLines = 1; + + // check if scroll is needed + mbScroll = mnLines > mnVisLines; + + if ( mnLines <= mnVisLines ) + mnFirstLine = 0; + else + { + if ( mnFirstLine > (sal_uInt16)(mnLines-mnVisLines) ) + mnFirstLine = (sal_uInt16)(mnLines-mnVisLines); + } + + mbHasVisibleItems = true; + + // calculate offsets + long nStartX = nHItemSpace; + long nStartY = nVItemSpace + mnHeaderHeight; + + // calculate and draw items + long x = nStartX; + long y = nStartY; + + // draw items + size_t nFirstItem = mnFirstLine * mnCols; + size_t nLastItem = nFirstItem + (mnVisLines * mnCols); + size_t nTotalItems = mnFirstLine*mnCols + mnVisLines*mnCols; + + maItemListRect.Left() = x; + maItemListRect.Top() = y; + maItemListRect.Right() = x + mnCols*(mnItemWidth+nHItemSpace) - nHItemSpace - 1; + maItemListRect.Bottom() = y + mnVisLines*(mnItemHeight+nVItemSpace) - nVItemSpace - 1; + + // If want also draw parts of items in the last line, + // then we add one more line if parts of these line are + // visible + if ( y+(mnVisLines*(mnItemHeight+nVItemSpace)) < aWinSize.Height() ) + nTotalItems += mnCols; + + size_t nCurCount = 0; + for ( size_t i = 0; i < nItemCount; i++ ) + { + ThumbnailViewItem *const pItem = mItemList[i]; + + if ((i >= nFirstItem) && (i < nLastItem) && maFilterFunc(pItem) && nCurCount < nTotalItems) + { + if( !pItem->isVisible() && ImplHasAccessibleListeners() ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + + aNewAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled ); + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny ); + } + + if (!mItemList[i]->isVisible()) + maItemStateHdl.Call(mItemList[i]); + + pItem->show(true); + pItem->setDrawArea(Rectangle( Point(x,y), Size(mnItemWidth, mnItemHeight) )); + pItem->calculateItemsPosition(mpItemAttrs->nMaxTextLenght); + + if ( !((nCurCount+1) % mnCols) ) + { + x = nStartX; + y += mnItemHeight+nVItemSpace; + } + else + x += mnItemWidth+nHItemSpace; + + ++nCurCount; + } + else + { + if( pItem->isVisible() && ImplHasAccessibleListeners() ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + + aOldAny <<= pItem->GetAccessible( mbIsTransientChildrenDisabled ); + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::CHILD, aOldAny, aNewAny ); + } + + if (mItemList[i]->isVisible()) + maItemStateHdl.Call(mItemList[i]); + + pItem->show(false); + } + } + + // arrange ScrollBar, set values and show it + if ( mpScrBar ) + { + Point aPos( aWinSize.Width() - nScrBarWidth - mnScrBarOffset, mnHeaderHeight ); + Size aSize( nScrBarWidth - mnScrBarOffset, aWinSize.Height() - mnHeaderHeight ); + + mpScrBar->SetPosSizePixel( aPos, aSize ); + mpScrBar->SetRangeMax( mnLines ); + mpScrBar->SetVisibleSize( mnVisLines ); + mpScrBar->SetThumbPos( (long)mnFirstLine ); + long nPageSize = mnVisLines; + if ( nPageSize < 1 ) + nPageSize = 1; + mpScrBar->SetPageSize( nPageSize ); + mpScrBar->Show(mbScroll); + } + + // delete ScrollBar + delete pDelScrBar; +} + +bool ThumbnailView::ImplScroll( const Point& rPos ) +{ + if ( !mbScroll || !maItemListRect.IsInside(rPos) ) + return false; + + const long nScrollOffset = (mnItemHeight <= 16) ? SCROLL_OFFSET/2 : SCROLL_OFFSET; + bool bScroll = false; + + if ( rPos.Y() <= maItemListRect.Top()+nScrollOffset ) + { + if ( mnFirstLine > 0 ) + { + --mnFirstLine; + bScroll = true; + } + } + else if ( rPos.Y() >= maItemListRect.Bottom()-nScrollOffset ) + { + if ( mnFirstLine < static_cast<sal_uInt16>(mnLines-mnVisLines) ) + { + ++mnFirstLine; + bScroll = true; + } + } + + if ( !bScroll ) + return false; + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + + return true; +} + +size_t ThumbnailView::ImplGetItem( const Point& rPos, bool bMove ) const +{ + if ( !mbHasVisibleItems ) + { + return THUMBNAILVIEW_ITEM_NOTFOUND; + } + + if ( maItemListRect.IsInside( rPos ) ) + { + for (size_t i = 0; i < mItemList.size(); ++i) + { + if (mItemList[i]->isVisible() && mItemList[i]->getDrawArea().IsInside(rPos)) + return i; + } + + // return the previously selected item if spacing is set and + // the mouse hasn't left the window yet + if ( bMove && mnSpacing && mnHighItemId ) + { + return GetItemPos( mnHighItemId ); + } + } + + return THUMBNAILVIEW_ITEM_NOTFOUND; +} + +ThumbnailViewItem* ThumbnailView::ImplGetItem( size_t nPos ) +{ + return ( nPos < mItemList.size() ) ? mItemList[nPos] : NULL; +} + +ThumbnailViewItem* ThumbnailView::ImplGetFirstItem() +{ + return mItemList.empty() ? NULL : mItemList[0]; +} + +sal_uInt16 ThumbnailView::ImplGetVisibleItemCount() const +{ + sal_uInt16 nRet = 0; + const size_t nItemCount = mItemList.size(); + + for ( size_t n = 0; n < nItemCount; ++n ) + { + if ( mItemList[n]->isVisible() ) + ++nRet; + } + + return nRet; +} + +ThumbnailViewItem* ThumbnailView::ImplGetVisibleItem( sal_uInt16 nVisiblePos ) +{ + const size_t nItemCount = mItemList.size(); + + for ( size_t n = 0; n < nItemCount; ++n ) + { + ThumbnailViewItem *const pItem = mItemList[n]; + + if ( pItem->isVisible() && !nVisiblePos-- ) + return pItem; + } + + return NULL; +} + +void ThumbnailView::ImplFireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ) +{ + ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) ); + + if( pAcc ) + pAcc->FireAccessibleEvent( nEventId, rOldValue, rNewValue ); +} + +bool ThumbnailView::ImplHasAccessibleListeners() +{ + ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) ); + return( pAcc && pAcc->HasAccessibleListeners() ); +} + +IMPL_LINK( ThumbnailView,ImplScrollHdl, ScrollBar*, pScrollBar ) +{ + sal_uInt16 nNewFirstLine = mnFirstLine; + + if (pScrollBar->GetDelta() > 0) + nNewFirstLine += 1; + else + nNewFirstLine -= 1; + + if ( nNewFirstLine != mnFirstLine ) + { + mnFirstLine = nNewFirstLine; + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } + return 0; +} + +IMPL_LINK_NOARG(ThumbnailView, ImplTimerHdl) +{ + ImplTracking( GetPointerPosPixel(), true ); + return 0; +} + +void ThumbnailView::ImplTracking( const Point& rPos, bool bRepeat ) +{ + if ( bRepeat ) + { + if ( ImplScroll( rPos ) ) + { + } + } +} + +void ThumbnailView::ImplEndTracking( const Point& rPos, bool bCancel ) +{ +} + +IMPL_LINK (ThumbnailView, OnFolderSelected, ThumbnailViewItem*, pItem) +{ + maItemStateHdl.Call(pItem); + return 0; +} + +void ThumbnailView::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeft() ) + { + ThumbnailViewItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) ); + + if (pItem && pItem->isVisible()) + { + if ( !rMEvt.IsMod2() ) + { + if ( rMEvt.GetClicks() == 1 ) + { + if (mbSelectionMode) + { + pItem->setSelection(!pItem->isSelected()); + + if (!pItem->isHighlighted()) + DrawItem(pItem); + + maItemStateHdl.Call(pItem); + } + else + { + if (pItem->isInsideTitle(rMEvt.GetPosPixel())) + { + pItem->setSelection(!pItem->isSelected()); + + if (!pItem->isHighlighted()) + DrawItem(pItem); + + maItemStateHdl.Call(pItem); + } + + //StartTracking( STARTTRACK_SCROLLREPEAT ); + } + } + else if ( rMEvt.GetClicks() == 2 ) + OnItemDblClicked(pItem); + } + + return; + } + } + + Control::MouseButtonDown( rMEvt ); +} + +void ThumbnailView::MouseButtonUp( const MouseEvent& rMEvt ) +{ + Control::MouseButtonUp( rMEvt ); +} + +void ThumbnailView::MouseMove( const MouseEvent& rMEvt ) +{ + ThumbnailViewItem* pItem = ImplGetItem( ImplGetItem( rMEvt.GetPosPixel() ) ); + + if (pItem && mbActive) + { + if (mnHighItemId != pItem->mnId && pItem->isVisible()) + { + size_t nPos = GetItemPos(mnHighItemId); + + if (nPos != THUMBNAILVIEW_ITEM_NOTFOUND) + { + ThumbnailViewItem *pOld = mItemList[nPos]; + + pOld->setHighlight(false); + + if (!pOld->isSelected()) + DrawItem(pOld); + } + + mnHighItemId = pItem->mnId; + pItem->setHighlight(true); + + if (!pItem->isSelected()) + DrawItem(pItem); + } + } + else + { + if (mnHighItemId) + { + size_t nPos = GetItemPos(mnHighItemId); + + if (nPos != THUMBNAILVIEW_ITEM_NOTFOUND) + { + ThumbnailViewItem *pOld = mItemList[nPos]; + + pOld->setHighlight(false); + + if (!pOld->isSelected()) + DrawItem(pOld); + } + + mnHighItemId = 0; + } + } + + Control::MouseMove( rMEvt ); +} + +void ThumbnailView::Tracking( const TrackingEvent& rTEvt ) +{ + Point aMousePos = rTEvt.GetMouseEvent().GetPosPixel(); + + if ( rTEvt.IsTrackingEnded() ) + ImplEndTracking( aMousePos, rTEvt.IsTrackingCanceled() ); + else + ImplTracking( aMousePos, rTEvt.IsTrackingRepeat() ); +} + +void ThumbnailView::Command( const CommandEvent& rCEvt ) +{ + if ( (rCEvt.GetCommand() == COMMAND_WHEEL) || + (rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL) || + (rCEvt.GetCommand() == COMMAND_AUTOSCROLL) ) + { + if ( HandleScrollCommand( rCEvt, NULL, mpScrBar ) ) + return; + } + + Control::Command( rCEvt ); +} + +void ThumbnailView::Paint( const Rectangle &aRect) +{ + size_t nItemCount = mItemList.size(); + + // Draw background + Primitive2DSequence aSeq(1); + aSeq[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D( + B2DPolyPolygon(Polygon(aRect,5,5).getB2DPolygon()), + maColor.getBColor())); + + mpProcessor->process(aSeq); + + // draw items + for ( size_t i = 0; i < nItemCount; i++ ) + { + ThumbnailViewItem *const pItem = mItemList[i]; + + if ( pItem->isVisible() ) + DrawItem(pItem); + } + + if ( mpScrBar && mpScrBar->IsVisible() ) + mpScrBar->Paint(aRect); +} + +void ThumbnailView::GetFocus() +{ + Control::GetFocus(); + + // Tell the accessible object that we got the focus. + ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) ); + if( pAcc ) + pAcc->GetFocus(); +} + +void ThumbnailView::LoseFocus() +{ + if (mnHighItemId) + { + size_t nPos = GetItemPos(mnHighItemId); + + if (nPos != THUMBNAILVIEW_ITEM_NOTFOUND) + { + ThumbnailViewItem *pOld = mItemList[nPos]; + + pOld->setHighlight(false); + + if (!pOld->isSelected()) + DrawItem(pOld); + } + + mnHighItemId = 0; + } + + Control::LoseFocus(); + + // Tell the accessible object that we lost the focus. + ThumbnailViewAcc* pAcc = ThumbnailViewAcc::getImplementation( GetAccessible( sal_False ) ); + if( pAcc ) + pAcc->LoseFocus(); +} + +void ThumbnailView::Resize() +{ + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + Control::Resize(); +} + +void ThumbnailView::StateChanged( StateChangedType nType ) +{ + Control::StateChanged( nType ); + + if ( nType == STATE_CHANGE_INITSHOW ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_UPDATEMODE ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } + else if ( nType == STATE_CHANGE_TEXT ) + { + } + else if ( (nType == STATE_CHANGE_ZOOM) || + (nType == STATE_CHANGE_CONTROLFONT) ) + { + ImplInitSettings( true, false, false ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLFOREGROUND ) + { + ImplInitSettings( false, true, false ); + Invalidate(); + } + else if ( nType == STATE_CHANGE_CONTROLBACKGROUND ) + { + ImplInitSettings( false, false, true ); + Invalidate(); + } + else if ( (nType == STATE_CHANGE_STYLE) || (nType == STATE_CHANGE_ENABLE) ) + { + ImplInitSettings( false, false, true ); + Invalidate(); + } +} + +void ThumbnailView::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Control::DataChanged( rDCEvt ); + + if ( (rDCEvt.GetType() == DATACHANGED_FONTS) || + (rDCEvt.GetType() == DATACHANGED_DISPLAY) || + (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) || + ((rDCEvt.GetType() == DATACHANGED_SETTINGS) && + (rDCEvt.GetFlags() & SETTINGS_STYLE)) ) + { + ImplInitSettings( true, true, true ); + Invalidate(); + } +} + +void ThumbnailView::InsertItem( sal_uInt16 nItemId, const BitmapEx& rImage, + const rtl::OUString& rText, size_t nPos ) +{ + ThumbnailViewItem* pItem = new ThumbnailViewItem( *this, this ); + pItem->mnId = nItemId; + pItem->maPreview1 = rImage; + pItem->maText = rText; + pItem->setSelectClickHdl(LINK(this,ThumbnailView,OnFolderSelected)); + ImplInsertItem( pItem, nPos ); +} + +void ThumbnailView::ImplInsertItem( ThumbnailViewItem *const pItem, const size_t nPos ) +{ + assert(pItem->mnId); // "ItemId == 0" + assert(GetItemPos( pItem->mnId ) == THUMBNAILVIEW_ITEM_NOTFOUND); // ItemId already exists + + if ( nPos < mItemList.size() ) { + ValueItemList::iterator it = mItemList.begin(); + ::std::advance( it, nPos ); + mItemList.insert( it, pItem ); + } else { + mItemList.push_back( pItem ); + } + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +void ThumbnailView::RemoveItem( sal_uInt16 nItemId ) +{ + size_t nPos = GetItemPos( nItemId ); + + if ( nPos == THUMBNAILVIEW_ITEM_NOTFOUND ) + return; + + if ( nPos < mItemList.size() ) { + ValueItemList::iterator it = mItemList.begin(); + ::std::advance( it, nPos ); + delete *it; + mItemList.erase( it ); + } + + // reset variables + if ( (mnHighItemId == nItemId) || (mnSelItemId == nItemId) ) + { + mnCurCol = 0; + mnHighItemId = 0; + mnSelItemId = 0; + } + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +void ThumbnailView::Clear() +{ + ImplDeleteItems(); + + // reset variables + mnFirstLine = 0; + mnCurCol = 0; + mnHighItemId = 0; + mnSelItemId = 0; + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +size_t ThumbnailView::GetItemCount() const +{ + return mItemList.size(); +} + +size_t ThumbnailView::GetItemPos( sal_uInt16 nItemId ) const +{ + for ( size_t i = 0, n = mItemList.size(); i < n; ++i ) { + if ( mItemList[i]->mnId == nItemId ) { + return i; + } + } + return THUMBNAILVIEW_ITEM_NOTFOUND; +} + +sal_uInt16 ThumbnailView::GetItemId( size_t nPos ) const +{ + return ( nPos < mItemList.size() ) ? mItemList[nPos]->mnId : 0 ; +} + +sal_uInt16 ThumbnailView::GetItemId( const Point& rPos ) const +{ + size_t nItemPos = ImplGetItem( rPos ); + if ( nItemPos != THUMBNAILVIEW_ITEM_NOTFOUND ) + return GetItemId( nItemPos ); + + return 0; +} + +void ThumbnailView::SetColCount( sal_uInt16 nNewCols ) +{ + if ( mnUserCols != nNewCols ) + { + mnUserCols = nNewCols; + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +void ThumbnailView::SetLineCount( sal_uInt16 nNewLines ) +{ + if ( mnUserVisLines != nNewLines ) + { + mnUserVisLines = nNewLines; + + CalculateItemPositions(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } +} + +void ThumbnailView::setItemMaxTextLength(sal_uInt32 nLength) +{ + mpItemAttrs->nMaxTextLenght = nLength; +} + +void ThumbnailView::setItemDimensions(long itemWidth, long thumbnailHeight, long displayHeight, int itemPadding) +{ + mnItemWidth = itemWidth + 2*itemPadding; + mnThumbnailHeight = thumbnailHeight; + mnDisplayHeight = displayHeight; + mnItemPadding = itemPadding; + mnItemHeight = mnDisplayHeight + mnThumbnailHeight + 2*itemPadding; +} + +void ThumbnailView::SelectItem( sal_uInt16 nItemId ) +{ + size_t nItemPos = 0; + + if ( nItemId ) + { + nItemPos = GetItemPos( nItemId ); + if ( nItemPos == THUMBNAILVIEW_ITEM_NOTFOUND ) + return; + } + + if ( mnSelItemId != nItemId) + { + sal_uInt16 nOldItem = mnSelItemId ? mnSelItemId : 1; + mnSelItemId = nItemId; + + bool bNewOut = IsReallyVisible() && IsUpdateMode(); + bool bNewLine = false; + + // if necessary scroll to the visible area + if ( mbScroll && nItemId ) + { + sal_uInt16 nNewLine = (sal_uInt16)(nItemPos / mnCols); + if ( nNewLine < mnFirstLine ) + { + mnFirstLine = nNewLine; + bNewLine = true; + } + else if ( nNewLine > (sal_uInt16)(mnFirstLine+mnVisLines-1) ) + { + mnFirstLine = (sal_uInt16)(nNewLine-mnVisLines+1); + bNewLine = true; + } + } + + if ( bNewOut ) + { + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); + } + + if( ImplHasAccessibleListeners() ) + { + // focus event (deselect) + if( nOldItem ) + { + const size_t nPos = GetItemPos( nItemId ); + + if( nPos != THUMBNAILVIEW_ITEM_NOTFOUND ) + { + ThumbnailViewAcc* pItemAcc = ThumbnailViewAcc::getImplementation( + mItemList[nPos]->GetAccessible( mbIsTransientChildrenDisabled ) ); + + if( pItemAcc ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + if( !mbIsTransientChildrenDisabled ) + { + aOldAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( + static_cast< ::cppu::OWeakObject* >( pItemAcc )); + ImplFireAccessibleEvent (::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); + } + else + { + aOldAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); + } + } + } + } + + // focus event (select) + const size_t nPos = GetItemPos( mnSelItemId ); + + ThumbnailViewItem* pItem = NULL; + if( nPos != THUMBNAILVIEW_ITEM_NOTFOUND ) + pItem = mItemList[nPos]; + + ThumbnailViewAcc* pItemAcc = NULL; + if (pItem != NULL) + pItemAcc = ThumbnailViewAcc::getImplementation( pItem->GetAccessible( mbIsTransientChildrenDisabled ) ); + + if( pItemAcc ) + { + ::com::sun::star::uno::Any aOldAny, aNewAny; + if( !mbIsTransientChildrenDisabled ) + { + aNewAny <<= ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >( + static_cast< ::cppu::OWeakObject* >( pItemAcc )); + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldAny, aNewAny ); + } + else + { + aNewAny <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + pItemAcc->FireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, aOldAny, aNewAny ); + } + } + + // selection event + ::com::sun::star::uno::Any aOldAny, aNewAny; + ImplFireAccessibleEvent( ::com::sun::star::accessibility::AccessibleEventId::SELECTION_CHANGED, aOldAny, aNewAny ); + } + } +} + +rtl::OUString ThumbnailView::GetItemText( sal_uInt16 nItemId ) const +{ + size_t nPos = GetItemPos( nItemId ); + + if ( nPos != THUMBNAILVIEW_ITEM_NOTFOUND ) + return mItemList[nPos]->maText; + + return rtl::OUString(); +} + +void ThumbnailView::SetColor( const Color& rColor ) +{ + maColor = rColor; + mpItemAttrs->aFillColor = rColor.getBColor(); + + if ( IsReallyVisible() && IsUpdateMode() ) + Invalidate(); +} + +bool ThumbnailView::StartDrag( const CommandEvent& rCEvt, Region& rRegion ) +{ + if ( rCEvt.GetCommand() != COMMAND_STARTDRAG ) + return false; + + // if necessary abort an existing action + + // Check out if the the clicked on page is selected. If this is not the + // case set it as the current item. We only check mouse actions since + // drag-and-drop can also be triggered by the keyboard + sal_uInt16 nSelId; + if ( rCEvt.IsMouseEvent() ) + nSelId = GetItemId( rCEvt.GetMousePosPixel() ); + else + nSelId = mnSelItemId; + + // don't activate dragging if no item was clicked on + if ( !nSelId ) + return false; + + // Check out if the page was selected. If not set as current page and + // call select. + if ( nSelId != mnSelItemId ) + { + SelectItem( nSelId ); + Update(); + } + + Region aRegion; + + // assign region + rRegion = aRegion; + + return true; +} + +Size ThumbnailView::CalcWindowSizePixel (sal_uInt16 nCols, sal_uInt16 nLines, + sal_uInt16 nItemWidth, sal_uInt16 nItemHeight, + sal_uInt16 nItemSpace) +{ + Size aSize(nItemWidth*nCols, nItemHeight*nLines); + + aSize.Width() += nItemSpace*(nCols+1); + aSize.Height() += nItemSpace*(nLines+1); + + aSize.Height() += mnHeaderHeight; + + // sum possible ScrollBar width + aSize.Width() += GetScrollWidth(); + + return aSize; +} + +long ThumbnailView::GetScrollWidth() const +{ + if ( GetStyle() & WB_VSCROLL ) + { + ((ThumbnailView*)this)->ImplInitScrollBar(); + return mpScrBar->GetSizePixel().Width()+mnScrBarOffset; + } + else + return 0; +} + +void ThumbnailView::setSelectionMode (bool mode) +{ + mbSelectionMode = mode; + + OnSelectionMode(mode); +} + +void ThumbnailView::filterItems (const boost::function<bool (const ThumbnailViewItem*) > &func) +{ + maFilterFunc = func; + + CalculateItemPositions(); + + Invalidate(); +} + +void ThumbnailView::sortItems (const boost::function<bool (const ThumbnailViewItem*, const ThumbnailViewItem*) > &func) +{ + std::sort(mItemList.begin(),mItemList.end(),func); + + CalculateItemPositions(); + + Invalidate(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/thumbnailviewacc.cxx b/sfx2/source/control/thumbnailviewacc.cxx new file mode 100644 index 000000000000..680a4699ec5b --- /dev/null +++ b/sfx2/source/control/thumbnailviewacc.cxx @@ -0,0 +1,1009 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 "thumbnailviewacc.hxx" + +#include <comphelper/servicehelper.hxx> +#include <sfx2/thumbnailview.hxx> +#include <sfx2/thumbnailviewitem.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <vcl/svapp.hxx> + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +using namespace ::com::sun::star; + +ThumbnailViewAcc::ThumbnailViewAcc( ThumbnailView* pParent, bool bIsTransientChildrenDisabled ) : + ValueSetAccComponentBase (m_aMutex), + mpParent( pParent ), + mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ), + mbIsFocused(false) +{ +} + +ThumbnailViewAcc::~ThumbnailViewAcc() +{ +} + +void ThumbnailViewAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue ) +{ + if( nEventId ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners ); + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() ); + accessibility::AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<uno::XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + try + { + (*aIter)->notifyEvent( aEvtObject ); + } + catch(const uno::Exception&) + { + } + + aIter++; + } + } +} + +namespace +{ + class theValueSetAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theValueSetAccUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 >& ThumbnailViewAcc::getUnoTunnelId() +{ + return theValueSetAccUnoTunnelId::get().getSeq(); +} + +ThumbnailViewAcc* ThumbnailViewAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData ) + throw() +{ + try + { + uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY ); + return( xUnoTunnel.is() ? reinterpret_cast<ThumbnailViewAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ThumbnailViewAcc::getUnoTunnelId() ))) : NULL ); + } + catch(const ::com::sun::star::uno::Exception&) + { + return NULL; + } +} + +void ThumbnailViewAcc::GetFocus (void) +{ + mbIsFocused = true; + + // Boradcast the state change. + ::com::sun::star::uno::Any aOldState, aNewState; + aNewState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( + ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, + aOldState, aNewState); +} + +void ThumbnailViewAcc::LoseFocus (void) +{ + mbIsFocused = false; + + // Boradcast the state change. + ::com::sun::star::uno::Any aOldState, aNewState; + aOldState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED; + FireAccessibleEvent( + ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED, + aOldState, aNewState); +} + +uno::Reference< accessibility::XAccessibleContext > SAL_CALL ThumbnailViewAcc::getAccessibleContext() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + return this; +} + +sal_Int32 SAL_CALL ThumbnailViewAcc::getAccessibleChildCount() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + ThrowIfDisposed(); + + sal_Int32 nCount = mpParent->ImplGetVisibleItemCount(); + return nCount; +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewAcc::getAccessibleChild( sal_Int32 i ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xRet; + ThumbnailViewItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i)); + + if( pItem ) + xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled ); + else + throw lang::IndexOutOfBoundsException(); + + return xRet; +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewAcc::getAccessibleParent() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + Window* pParent = mpParent->GetParent(); + uno::Reference< accessibility::XAccessible > xRet; + + if( pParent ) + xRet = pParent->GetAccessible(); + + return xRet; +} + +sal_Int32 SAL_CALL ThumbnailViewAcc::getAccessibleIndexInParent() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + Window* pParent = mpParent->GetParent(); + sal_Int32 nRet = 0; + + if( pParent ) + { + sal_Bool bFound = sal_False; + + for( sal_uInt16 i = 0, nCount = pParent->GetChildCount(); ( i < nCount ) && !bFound; i++ ) + { + if( pParent->GetChild( i ) == mpParent ) + { + nRet = i; + bFound = sal_True; + } + } + } + + return nRet; +} + +sal_Int16 SAL_CALL ThumbnailViewAcc::getAccessibleRole() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + // #i73746# As the Java Access Bridge (v 2.0.1) uses "managesDescendants" + // always if the role is LIST, we need a different role in this case + return (mbIsTransientChildrenDisabled + ? accessibility::AccessibleRole::PANEL + : accessibility::AccessibleRole::LIST ); +} + +::rtl::OUString SAL_CALL ThumbnailViewAcc::getAccessibleDescription() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + return rtl::OUString("ThumbnailView"); +} + +::rtl::OUString SAL_CALL ThumbnailViewAcc::getAccessibleName() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + rtl::OUString aRet; + + if ( mpParent ) + aRet = mpParent->GetAccessibleName(); + + if ( aRet.isEmpty() ) + { + Window* pLabel = mpParent->GetAccessibleRelationLabeledBy(); + if ( pLabel && pLabel != mpParent ) + aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() ); + } + + return aRet; +} + +uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ThumbnailViewAcc::getAccessibleRelationSet() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + return uno::Reference< accessibility::XAccessibleRelationSet >(); +} + +uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ThumbnailViewAcc::getAccessibleStateSet() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper(); + + // Set some states. + pStateSet->AddState (accessibility::AccessibleStateType::ENABLED); + pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE); + pStateSet->AddState (accessibility::AccessibleStateType::SHOWING); + pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE); + if ( !mbIsTransientChildrenDisabled ) + pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS); + pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE); + if (mbIsFocused) + pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED); + + return pStateSet; +} + +lang::Locale SAL_CALL ThumbnailViewAcc::getLocale() + throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const ::rtl::OUString aEmptyStr; + uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() ); + lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + if( xParent.is() ) + { + uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale (); + } + + return aRet; +} + +void SAL_CALL ThumbnailViewAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (m_aMutex); + + if( rxListener.is() ) + { + std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = true; + else + ++aIter; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +void SAL_CALL ThumbnailViewAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + ::osl::MutexGuard aGuard (m_aMutex); + + if( rxListener.is() ) + { + std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin(); + bool bFound = false; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = true; + } + else + ++aIter; + } + } +} + +sal_Bool SAL_CALL ThumbnailViewAcc::containsPoint( const awt::Point& aPoint ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewAcc::getAccessibleAtPoint( const awt::Point& aPoint ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const sal_uInt16 nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) ); + uno::Reference< accessibility::XAccessible > xRet; + + if ( nItemId ) + { + const size_t nItemPos = mpParent->GetItemPos( nItemId ); + + if( THUMBNAILVIEW_ITEM_NONEITEM != nItemPos ) + { + ThumbnailViewItem *const pItem = mpParent->mItemList[nItemPos]; + xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled ); + } + } + + return xRet; +} + +awt::Rectangle SAL_CALL ThumbnailViewAcc::getBounds() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const Point aOutPos( mpParent->GetPosPixel() ); + const Size aOutSize( mpParent->GetOutputSizePixel() ); + awt::Rectangle aRet; + + aRet.X = aOutPos.X(); + aRet.Y = aOutPos.Y(); + aRet.Width = aOutSize.Width(); + aRet.Height = aOutSize.Height(); + + return aRet; +} + +awt::Point SAL_CALL ThumbnailViewAcc::getLocation() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + awt::Point aRet; + + aRet.X = aRect.X; + aRet.Y = aRect.Y; + + return aRet; +} + +awt::Point SAL_CALL ThumbnailViewAcc::getLocationOnScreen() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + const Point aScreenPos( mpParent->OutputToAbsoluteScreenPixel( Point() ) ); + awt::Point aRet; + + aRet.X = aScreenPos.X(); + aRet.Y = aScreenPos.Y(); + + return aRet; +} + +awt::Size SAL_CALL ThumbnailViewAcc::getSize() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +void SAL_CALL ThumbnailViewAcc::grabFocus() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + mpParent->GrabFocus(); +} + +uno::Any SAL_CALL ThumbnailViewAcc::getAccessibleKeyBinding() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + return uno::Any(); +} + +sal_Int32 SAL_CALL ThumbnailViewAcc::getForeground( ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor(); + return static_cast<sal_Int32>(nColor); +} + +sal_Int32 SAL_CALL ThumbnailViewAcc::getBackground( ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor(); + return static_cast<sal_Int32>(nColor); +} + +void SAL_CALL ThumbnailViewAcc::selectAccessibleChild( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + ThumbnailViewItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex)); + + if(pItem != NULL) + { + mpParent->SelectItem( pItem->mnId ); + } + else + throw lang::IndexOutOfBoundsException(); +} + +sal_Bool SAL_CALL ThumbnailViewAcc::isAccessibleChildSelected( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + ThumbnailViewItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex)); + sal_Bool bRet = sal_False; + + if (pItem != NULL) + bRet = mpParent->IsItemSelected( pItem->mnId ); + else + throw lang::IndexOutOfBoundsException(); + + return bRet; +} + +void SAL_CALL ThumbnailViewAcc::clearAccessibleSelection() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; +} + +void SAL_CALL ThumbnailViewAcc::selectAllAccessibleChildren() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + // unsupported due to single selection only +} + +sal_Int32 SAL_CALL ThumbnailViewAcc::getSelectedAccessibleChildCount() + throw (uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + sal_Int32 nRet = 0; + + for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ ) + { + ThumbnailViewItem* pItem = getItem (i); + + if( pItem && mpParent->IsItemSelected( pItem->mnId ) ) + ++nRet; + } + + return nRet; +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xRet; + + for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ ) + { + ThumbnailViewItem* pItem = getItem(i); + + if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) ) + xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled ); + } + + return xRet; +} + +void SAL_CALL ThumbnailViewAcc::deselectAccessibleChild( sal_Int32 nChildIndex ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ThrowIfDisposed(); + const SolarMutexGuard aSolarGuard; + // Because of the single selection we can reset the whole selection when + // the specified child is currently selected. + if (isAccessibleChildSelected(nChildIndex)) + ; +} + +sal_Int64 SAL_CALL ThumbnailViewAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException ) +{ + sal_Int64 nRet; + + if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ThumbnailViewAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) + nRet = reinterpret_cast< sal_Int64 >( this ); + else + nRet = 0; + + return nRet; +} + +void SAL_CALL ThumbnailViewAcc::disposing (void) +{ + ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy; + + { + // Make a copy of the list and clear the original. + const SolarMutexGuard aSolarGuard; + ::osl::MutexGuard aGuard (m_aMutex); + aListenerListCopy = mxEventListeners; + mxEventListeners.clear(); + + // Reset the pointer to the parent. It has to be the one who has + // disposed us because he is dying. + mpParent = NULL; + } + + // Inform all listeners that this objects is disposing. + ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> >::const_iterator + aListenerIterator (aListenerListCopy.begin()); + lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this)); + while (aListenerIterator != aListenerListCopy.end()) + { + try + { + (*aListenerIterator)->disposing (aEvent); + } + catch(const uno::Exception&) + { + // Ignore exceptions. + } + + ++aListenerIterator; + } +} + +sal_uInt16 ThumbnailViewAcc::getItemCount (void) const +{ + return mpParent->ImplGetVisibleItemCount(); +} + +ThumbnailViewItem* ThumbnailViewAcc::getItem (sal_uInt16 nIndex) const +{ + return mpParent->ImplGetVisibleItem (static_cast<sal_uInt16>(nIndex)); +} + +void ThumbnailViewAcc::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + OSL_TRACE ("Calling disposed object. Throwing exception:"); + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), + static_cast<uno::XWeak*>(this)); + } + else + { + DBG_ASSERT (mpParent!=NULL, "ValueSetAcc not disposed but mpParent == NULL"); + } +} + +ThumbnailViewItemAcc::ThumbnailViewItemAcc( ThumbnailViewItem* pParent, bool bIsTransientChildrenDisabled ) : + mpParent( pParent ), + mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ) +{ +} + +ThumbnailViewItemAcc::~ThumbnailViewItemAcc() +{ +} + +void ThumbnailViewItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue ) +{ + if( nEventId ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > > aTmpListeners( mxEventListeners ); + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter( aTmpListeners.begin() ); + accessibility::AccessibleEventObject aEvtObject; + + aEvtObject.EventId = nEventId; + aEvtObject.Source = static_cast<uno::XWeak*>(this); + aEvtObject.NewValue = rNewValue; + aEvtObject.OldValue = rOldValue; + + while( aIter != aTmpListeners.end() ) + { + (*aIter)->notifyEvent( aEvtObject ); + aIter++; + } + } +} + +void ThumbnailViewItemAcc::ParentDestroyed() +{ + const ::osl::MutexGuard aGuard( maMutex ); + mpParent = NULL; +} + +namespace +{ + class theValueItemAccUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theValueItemAccUnoTunnelId > {}; +} + +const uno::Sequence< sal_Int8 >& ThumbnailViewItemAcc::getUnoTunnelId() +{ + return theValueItemAccUnoTunnelId::get().getSeq(); +} + +ThumbnailViewItemAcc* ThumbnailViewItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData ) + throw() +{ + try + { + uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY ); + return( xUnoTunnel.is() ? reinterpret_cast<ThumbnailViewItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ThumbnailViewItemAcc::getUnoTunnelId() ))) : NULL ); + } + catch(const ::com::sun::star::uno::Exception&) + { + return NULL; + } +} + +uno::Reference< accessibility::XAccessibleContext > SAL_CALL ThumbnailViewItemAcc::getAccessibleContext() + throw (uno::RuntimeException) +{ + return this; +} + +sal_Int32 SAL_CALL ThumbnailViewItemAcc::getAccessibleChildCount() + throw (uno::RuntimeException) +{ + return 0; +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewItemAcc::getAccessibleChild( sal_Int32 ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + throw lang::IndexOutOfBoundsException(); +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewItemAcc::getAccessibleParent() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + uno::Reference< accessibility::XAccessible > xRet; + + if( mpParent ) + xRet = mpParent->mrParent.GetAccessible(); + + return xRet; +} + +sal_Int32 SAL_CALL ThumbnailViewItemAcc::getAccessibleIndexInParent() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + // The index defaults to -1 to indicate the child does not belong to its + // parent. + sal_Int32 nIndexInParent = -1; + + if( mpParent ) + { + bool bDone = false; + + sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount(); + ThumbnailViewItem* pItem; + for (sal_uInt16 i=0; i<nCount && !bDone; i++) + { + // Guard the retrieval of the i-th child with a try/catch block + // just in case the number of children changes in the mean time. + try + { + pItem = mpParent->mrParent.ImplGetVisibleItem (i); + } + catch (const lang::IndexOutOfBoundsException&) + { + pItem = NULL; + } + + // Do not create an accessible object for the test. + if (pItem != NULL && pItem->mpxAcc != NULL) + if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this ) + { + nIndexInParent = i; + bDone = true; + } + } + } + + return nIndexInParent; +} + +sal_Int16 SAL_CALL ThumbnailViewItemAcc::getAccessibleRole() + throw (uno::RuntimeException) +{ + return accessibility::AccessibleRole::LIST_ITEM; +} + +::rtl::OUString SAL_CALL ThumbnailViewItemAcc::getAccessibleDescription() + throw (uno::RuntimeException) +{ + return ::rtl::OUString(); +} + +::rtl::OUString SAL_CALL ThumbnailViewItemAcc::getAccessibleName() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + rtl::OUString aRet; + + if( mpParent ) + { + aRet = mpParent->maText; + + if( aRet.isEmpty() ) + { + rtl::OUStringBuffer aBuffer("Item "); + aBuffer.append(static_cast<sal_Int32>(mpParent->mnId)); + aRet = aBuffer.makeStringAndClear(); + } + } + + return aRet; +} + +uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ThumbnailViewItemAcc::getAccessibleRelationSet() + throw (uno::RuntimeException) +{ + return uno::Reference< accessibility::XAccessibleRelationSet >(); +} + +uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ThumbnailViewItemAcc::getAccessibleStateSet() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper; + + if( mpParent ) + { + pStateSet->AddState (accessibility::AccessibleStateType::ENABLED); + pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE); + pStateSet->AddState (accessibility::AccessibleStateType::SHOWING); + pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE); + if ( !mbIsTransientChildrenDisabled ) + pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT); + + // SELECTABLE + pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE ); + // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE ); + + // SELECTED + if( mpParent->mrParent.GetSelectItemId() == mpParent->mnId ) + { + pStateSet->AddState( accessibility::AccessibleStateType::SELECTED ); + // pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED ); + } + } + + return pStateSet; +} + +lang::Locale SAL_CALL ThumbnailViewItemAcc::getLocale() + throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + const ::rtl::OUString aEmptyStr; + uno::Reference< accessibility::XAccessible > xParent( getAccessibleParent() ); + lang::Locale aRet( aEmptyStr, aEmptyStr, aEmptyStr ); + + if( xParent.is() ) + { + uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() ); + + if( xParentContext.is() ) + aRet = xParentContext->getLocale(); + } + + return aRet; +} + +void SAL_CALL ThumbnailViewItemAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + const ::osl::MutexGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin(); + sal_Bool bFound = sal_False; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + bFound = sal_True; + else + ++aIter; + } + + if (!bFound) + mxEventListeners.push_back( rxListener ); + } +} + +void SAL_CALL ThumbnailViewItemAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + const ::osl::MutexGuard aGuard( maMutex ); + + if( rxListener.is() ) + { + ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin(); + sal_Bool bFound = sal_False; + + while( !bFound && ( aIter != mxEventListeners.end() ) ) + { + if( *aIter == rxListener ) + { + mxEventListeners.erase( aIter ); + bFound = sal_True; + } + else + ++aIter; + } + } +} + +sal_Bool SAL_CALL ThumbnailViewItemAcc::containsPoint( const awt::Point& aPoint ) + throw (uno::RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + const Point aSize( aRect.Width, aRect.Height ); + const Point aNullPoint, aTestPoint( aPoint.X, aPoint.Y ); + + return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint ); +} + +uno::Reference< accessibility::XAccessible > SAL_CALL ThumbnailViewItemAcc::getAccessibleAtPoint( const awt::Point& ) + throw (uno::RuntimeException) +{ + uno::Reference< accessibility::XAccessible > xRet; + return xRet; +} + +awt::Rectangle SAL_CALL ThumbnailViewItemAcc::getBounds() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + awt::Rectangle aRet; + + if( mpParent ) + { + Rectangle aRect( mpParent->getDrawArea() ); + Point aOrigin; + Rectangle aParentRect( aOrigin, mpParent->mrParent.GetOutputSizePixel() ); + + aRect.Intersection( aParentRect ); + + aRet.X = aRect.Left(); + aRet.Y = aRect.Top(); + aRet.Width = aRect.GetWidth(); + aRet.Height = aRect.GetHeight(); + } + + return aRet; +} + +awt::Point SAL_CALL ThumbnailViewItemAcc::getLocation() + throw (uno::RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + awt::Point aRet; + + aRet.X = aRect.X; + aRet.Y = aRect.Y; + + return aRet; +} + +awt::Point SAL_CALL ThumbnailViewItemAcc::getLocationOnScreen() + throw (uno::RuntimeException) +{ + const SolarMutexGuard aSolarGuard; + awt::Point aRet; + + if( mpParent ) + { + const Point aPos = mpParent->getDrawArea().TopLeft(); + const Point aScreenPos( mpParent->mrParent.OutputToAbsoluteScreenPixel( aPos ) ); + + aRet.X = aScreenPos.X(); + aRet.Y = aScreenPos.Y(); + } + + return aRet; +} + +awt::Size SAL_CALL ThumbnailViewItemAcc::getSize() + throw (uno::RuntimeException) +{ + const awt::Rectangle aRect( getBounds() ); + awt::Size aRet; + + aRet.Width = aRect.Width; + aRet.Height = aRect.Height; + + return aRet; +} + +void SAL_CALL ThumbnailViewItemAcc::grabFocus() + throw (uno::RuntimeException) +{ + // nothing to do +} + +uno::Any SAL_CALL ThumbnailViewItemAcc::getAccessibleKeyBinding() + throw (uno::RuntimeException) +{ + return uno::Any(); +} + +sal_Int32 SAL_CALL ThumbnailViewItemAcc::getForeground( ) + throw (uno::RuntimeException) +{ + sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor(); + return static_cast<sal_Int32>(nColor); +} + +sal_Int32 SAL_CALL ThumbnailViewItemAcc::getBackground( ) + throw (uno::RuntimeException) +{ + return static_cast<sal_Int32>(Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor()); +} + +sal_Int64 SAL_CALL ThumbnailViewItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException ) +{ + sal_Int64 nRet; + + if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ThumbnailViewItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) ) + nRet = reinterpret_cast< sal_Int64 >( this ); + else + nRet = 0; + + return nRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/control/thumbnailviewacc.hxx b/sfx2/source/control/thumbnailviewacc.hxx new file mode 100644 index 000000000000..f74cadd6ab5a --- /dev/null +++ b/sfx2/source/control/thumbnailviewacc.hxx @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 THUMBNAILVIEWACC_HXX +#define THUMBNAILVIEWACC_HXX + +#include <osl/mutex.hxx> +#include <cppuhelper/implbase5.hxx> +#include <cppuhelper/compbase6.hxx> +#include <comphelper/broadcasthelper.hxx> + +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleSelection.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include <com/sun/star/lang/DisposedException.hpp> + +#include <vector> + +class ThumbnailView; +struct ThumbnailViewItem; + +typedef ::cppu::PartialWeakComponentImplHelper6< + ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleSelection, + ::com::sun::star::lang::XUnoTunnel > + ValueSetAccComponentBase; + +class ThumbnailViewAcc : + public ::comphelper::OBaseMutex, + public ValueSetAccComponentBase +{ +public: + + ThumbnailViewAcc( ThumbnailView* pParent, bool bIsTransientChildrenDisabled ); + ~ThumbnailViewAcc(); + + void FireAccessibleEvent( short nEventId, + const ::com::sun::star::uno::Any& rOldValue, + const ::com::sun::star::uno::Any& rNewValue ); + + sal_Bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + + static ThumbnailViewAcc* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxData ) throw(); + +public: + + /** Called by the corresponding ValueSet when it gets the focus. + Stores the new focus state and broadcasts a state change event. + */ + void GetFocus (void); + + /** Called by the corresponding ValueSet when it loses the focus. + Stores the new focus state and broadcasts a state change event. + */ + void LoseFocus (void); + + // XComponent + virtual void SAL_CALL dispose()throw (::com::sun::star::uno::RuntimeException) + { WeakComponentImplHelperBase::dispose(); } + virtual void SAL_CALL addEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (::com::sun::star::uno::RuntimeException) + { WeakComponentImplHelperBase::addEventListener(xListener); } + virtual void SAL_CALL removeEventListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XEventListener > & xListener)throw (::com::sun::star::uno::RuntimeException) + { WeakComponentImplHelperBase::removeEventListener(xListener); } + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleSelection + virtual void SAL_CALL selectAccessibleChild( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL clearAccessibleSelection( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL selectAllAccessibleChildren( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectedAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( ::com::sun::star::uno::RuntimeException ); + +private: + ::std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessibleEventListener > > mxEventListeners; + ThumbnailView* mpParent; + bool mbIsTransientChildrenDisabled; + /// The current FOCUSED state. + bool mbIsFocused; + + static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + + /** Tell all listeners that the object is dying. This callback is + usually called from the WeakComponentImplHelper class. + */ + virtual void SAL_CALL disposing (void); + + /** Return the number of items. This takes the None-Item into account. + */ + sal_uInt16 getItemCount (void) const; + + /** Return the item associated with the given index. The None-Item is + taken into account which, when present, is taken to be the first + (with index 0) item. + @param nIndex + Index of the item to return. The index 0 denotes the None-Item + when present. + @return + Returns NULL when the given index is out of range. + */ + ThumbnailViewItem* getItem (sal_uInt16 nIndex) const; + + /** Check whether or not the object has been disposed (or is in the + state of beeing disposed). If that is the case then + DisposedException is thrown to inform the (indirect) caller of the + foul deed. + */ + void ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException); +}; + +class ThumbnailViewItemAcc : public ::cppu::WeakImplHelper5< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::lang::XUnoTunnel > +{ +private: + + ::std::vector< ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessibleEventListener > > mxEventListeners; + ::osl::Mutex maMutex; + ThumbnailViewItem* mpParent; + bool mbIsTransientChildrenDisabled; + + static const ::com::sun::star::uno::Sequence< sal_Int8 >& getUnoTunnelId(); + +public: + + ThumbnailViewItemAcc( ThumbnailViewItem* pParent, bool bIsTransientChildrenDisabled ); + ~ThumbnailViewItemAcc(); + + void ParentDestroyed(); + + void FireAccessibleEvent( short nEventId, const ::com::sun::star::uno::Any& rOldValue, const ::com::sun::star::uno::Any& rNewValue ); + sal_Bool HasAccessibleListeners() const { return( mxEventListeners.size() > 0 ); } + + static ThumbnailViewItemAcc* getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxData ) throw(); + +public: + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleDescription( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale( ) throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getAccessibleKeyBinding( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XUnoTunnel + virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( ::com::sun::star::uno::RuntimeException ); +}; + +#endif // THUMBNAILVIEWACC_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/control/thumbnailviewitem.cxx b/sfx2/source/control/thumbnailviewitem.cxx new file mode 100644 index 000000000000..dbbbcb79ac3c --- /dev/null +++ b/sfx2/source/control/thumbnailviewitem.cxx @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * 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 <sfx2/thumbnailviewitem.hxx> + +#include "thumbnailviewacc.hxx" + +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/vector/b2dsize.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/attribute/fillbitmapattribute.hxx> +#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <vcl/button.hxx> +#include <vcl/svapp.hxx> + +using namespace basegfx; +using namespace basegfx::tools; +using namespace ::com::sun::star; +using namespace drawinglayer::attribute; +using namespace drawinglayer::primitive2d; + +ThumbnailViewItem::ThumbnailViewItem(ThumbnailView &rView, Window *pParent) + : mrParent(rView) + , mnId(0) + , mbVisible(true) + , mbSelected(false) + , mbHover(false) + , mpxAcc(NULL) + , mbMode(false) + , mpSelectBox(new CheckBox(pParent,WB_HIDE | WB_NOPOINTERFOCUS)) +{ + mpSelectBox->SetSizePixel(Size(20,20)); + mpSelectBox->SetClickHdl(LINK(this,ThumbnailViewItem,OnClick)); +} + +ThumbnailViewItem::~ThumbnailViewItem() +{ + if( mpxAcc ) + { + static_cast< ThumbnailViewItemAcc* >( mpxAcc->get() )->ParentDestroyed(); + delete mpxAcc; + } + + delete mpSelectBox; +} + +void ThumbnailViewItem::show (bool bVisible) +{ + mbVisible = bVisible; + + if (mbMode) + mpSelectBox->Show(bVisible); + else if (!bVisible) + mpSelectBox->Show(bVisible); + else if (mbSelected) + mpSelectBox->Show(bVisible); +} + +void ThumbnailViewItem::setSelection (bool state) +{ + mbSelected = state; + mpSelectBox->SetState(state ? STATE_CHECK : STATE_NOCHECK); + + if (!isHighlighted()) + mpSelectBox->Show(state); +} + +void ThumbnailViewItem::setHighlight (bool state) +{ + mbHover = state; + + if (!isSelected()) + mpSelectBox->Show(state); +} + +uno::Reference< accessibility::XAccessible > ThumbnailViewItem::GetAccessible( bool bIsTransientChildrenDisabled ) +{ + if( !mpxAcc ) + mpxAcc = new uno::Reference< accessibility::XAccessible >( new ThumbnailViewItemAcc( this, bIsTransientChildrenDisabled ) ); + + return *mpxAcc; +} + +void ThumbnailViewItem::setDrawArea (const Rectangle &area) +{ + maDrawArea = area; +} + +void ThumbnailViewItem::calculateItemsPosition (sal_uInt32 nMaxTextLenght) +{ + drawinglayer::primitive2d::TextLayouterDevice aTextDev; + + Size aRectSize = maDrawArea.GetSize(); + Size aImageSize = maPreview1.GetSizePixel(); + + // Calculate thumbnail position + Point aPos = maDrawArea.TopLeft(); + aPos.X() = maDrawArea.Left() + (aRectSize.Width()-aImageSize.Width())/2; + aPos.Y() = maDrawArea.Top() + (aRectSize.Height()-aImageSize.Height())/2; + maPrev1Pos = aPos; + + // Calculate text position + aPos.Y() += aImageSize.Height(); + aPos.Y() = aPos.Y() + aTextDev.getTextHeight() + (maDrawArea.Bottom() - aPos.Y() - aTextDev.getTextHeight())/2; + aPos.X() = maDrawArea.Left() + (aRectSize.Width() - aTextDev.getTextWidth(maText,0,nMaxTextLenght))/2; + maTextPos = aPos; + + // Calculate checkbox position + aPos.Y() -= aTextDev.getTextHeight(); + aPos.X() = maDrawArea.Left() + 15; + + mpSelectBox->SetPosPixel(aPos); +} + +void ThumbnailViewItem::setSelectionMode (bool mode) +{ + mbMode = mode; + + if (!mbHover && !mbSelected && mbVisible) + mpSelectBox->Show(mode); +} + +void ThumbnailViewItem::setSelectClickHdl (const Link &link) +{ + maClickHdl = link; +} + +bool ThumbnailViewItem::isInsideTitle (const Point &pt) const +{ + Rectangle aRect(Point(maTextPos.X(),mpSelectBox->GetPosPixel().Y()), + Point(maDrawArea.Right(),maDrawArea.Bottom())); + + return aRect.IsInside(pt); +} + +void ThumbnailViewItem::Paint (drawinglayer::processor2d::BaseProcessor2D *pProcessor, + const ThumbnailItemAttributes *pAttrs) +{ + BColor aFillColor = pAttrs->aFillColor; + Primitive2DSequence aSeq(3); + + // Draw background + if ( mbSelected || mbHover ) + aFillColor = pAttrs->aHighlightColor; + + aSeq[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D( + B2DPolyPolygon(Polygon(maDrawArea,5,5).getB2DPolygon()), + aFillColor)); + + // Draw thumbnail + Point aPos = maPrev1Pos; + Size aImageSize = maPreview1.GetSizePixel(); + + aSeq[1] = Primitive2DReference( new FillBitmapPrimitive2D( + createTranslateB2DHomMatrix(aPos.X(),aPos.Y()), + FillBitmapAttribute(maPreview1, + B2DPoint(0,0), + B2DVector(aImageSize.Width(),aImageSize.Height()), + false) + )); + + // Draw centered text below thumbnail + aPos = maTextPos; + + // Create the text primitive + basegfx::B2DHomMatrix aTextMatrix( createScaleTranslateB2DHomMatrix( + pAttrs->aFontSize.getX(), pAttrs->aFontSize.getY(), + double( aPos.X() ), double( aPos.Y() ) ) ); + + aSeq[2] = Primitive2DReference( + new TextSimplePortionPrimitive2D(aTextMatrix, + maText,0,pAttrs->nMaxTextLenght, + std::vector< double >( ), + pAttrs->aFontAttr, + com::sun::star::lang::Locale(), + Color(COL_BLACK).getBColor() ) ); + + pProcessor->process(aSeq); + + if (mbMode || mbHover || mbSelected) + mpSelectBox->Paint(maDrawArea); +} + +IMPL_LINK (ThumbnailViewItem, OnClick, CheckBox*, ) +{ + mbSelected = mpSelectBox->GetState() == STATE_CHECK; + mpSelectBox->Invalidate(); + maClickHdl.Call(this); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/dialog/inputdlg.cxx b/sfx2/source/dialog/inputdlg.cxx new file mode 100644 index 000000000000..c1bd5055a0a5 --- /dev/null +++ b/sfx2/source/dialog/inputdlg.cxx @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "inputdlg.hxx" + +#include "inputdlg.hrc" + +#include <sfx2/sfxresid.hxx> +#include <vcl/button.hxx> +#include <vcl/edit.hxx> +#include <vcl/fixed.hxx> + +#define LABEL_TEXT_SPACE 5 + +InputDialog::InputDialog (const rtl::OUString &rLabelText, Window *pParent) + : ModalDialog(pParent,SfxResId(DLG_INPUT_BOX)), + mpEntry(new Edit(this,SfxResId(EDT_INPUT_FIELD))), + mpLabel(new FixedText(this,SfxResId(LABEL_INPUT_TEXT))), + mpOK(new PushButton(this,SfxResId(BTN_INPUT_OK))), + mpCancel(new PushButton(this,SfxResId(BTN_INPUT_CANCEL))) +{ + SetStyle(GetStyle() | WB_CENTER | WB_VCENTER); + + mpLabel->SetText(rLabelText); + + // Fit label size to text and reposition edit box + Size aLabelSize = mpLabel->CalcMinimumSize(); + Size aEditSize = mpEntry->GetSizePixel(); + Size aBtnSize = mpOK->GetSizePixel(); + + Point aLabelPos = mpLabel->GetPosPixel(); + Point aEditPos = mpEntry->GetPosPixel(); + + aEditPos.setX(aLabelPos.getX() + aLabelSize.getWidth() + LABEL_TEXT_SPACE); + + mpLabel->SetPosSizePixel(aLabelPos,aLabelSize); + mpEntry->SetPosSizePixel(aEditPos,aEditSize); + + // Resize window if needed + Size aWinSize = GetOutputSize(); + aWinSize.setWidth(aEditPos.getX() + aEditSize.getWidth() + LABEL_TEXT_SPACE); + SetSizePixel(aWinSize); + + // Align buttons + Point aBtnPos = mpCancel->GetPosPixel(); + + aBtnPos.setX(aWinSize.getWidth() - aBtnSize.getWidth() - LABEL_TEXT_SPACE); + mpCancel->SetPosPixel(aBtnPos); + + aBtnPos.setX(aBtnPos.getX() - aBtnSize.getWidth() - LABEL_TEXT_SPACE); + mpOK->SetPosPixel(aBtnPos); + + mpOK->SetClickHdl(LINK(this,InputDialog,ClickHdl)); + mpCancel->SetClickHdl(LINK(this,InputDialog,ClickHdl)); +} + +InputDialog::~InputDialog() +{ + delete mpEntry; + delete mpLabel; + delete mpOK; + delete mpCancel; +} + +rtl::OUString InputDialog::getEntryText () const +{ + return mpEntry->GetText(); +} + +IMPL_LINK(InputDialog,ClickHdl,PushButton*, pButton) +{ + EndDialog(pButton == mpOK ? true : false); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + + diff --git a/sfx2/source/dialog/inputdlg.hrc b/sfx2/source/dialog/inputdlg.hrc new file mode 100644 index 000000000000..bb9edd8cb11a --- /dev/null +++ b/sfx2/source/dialog/inputdlg.hrc @@ -0,0 +1,13 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#define DLG_INPUT_BOX 256 +#define LABEL_INPUT_TEXT 2 +#define EDT_INPUT_FIELD 3 +#define BTN_INPUT_OK 4 +#define BTN_INPUT_CANCEL 5 diff --git a/sfx2/source/dialog/inputdlg.src b/sfx2/source/dialog/inputdlg.src new file mode 100644 index 000000000000..edd16d698001 --- /dev/null +++ b/sfx2/source/dialog/inputdlg.src @@ -0,0 +1,48 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "inputdlg.hrc" + +ModalDialog DLG_INPUT_BOX +{ + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Size = MAP_APPFONT ( 215, 40 ); + + FixedText LABEL_INPUT_TEXT + { + Pos = MAP_APPFONT(5,6); + Size = MAP_APPFONT(80,10); + }; + + Edit EDT_INPUT_FIELD + { + Border = TRUE; + Pos = MAP_APPFONT(90,5); + Size = MAP_APPFONT(120,10); + }; + + PushButton BTN_INPUT_OK + { + Pos = MAP_APPFONT(125,20); + Size = MAP_APPFONT(40,15); + TabStop = TRUE; + DefButton = TRUE; + Text [en-US] = "Accept"; + }; + + PushButton BTN_INPUT_CANCEL + { + Pos = MAP_APPFONT(170,20); + Size = MAP_APPFONT(40,15); + TabStop = TRUE; + Text [en-US] = "Cancel"; + }; +}; diff --git a/sfx2/source/doc/doc.hrc b/sfx2/source/doc/doc.hrc index a55337b9f377..f3edfa7390d2 100644 --- a/sfx2/source/doc/doc.hrc +++ b/sfx2/source/doc/doc.hrc @@ -38,6 +38,7 @@ #define DLG_NEW_FILE (RID_SFX_DOC_START+1) #define DLG_DOC_TEMPLATE (RID_SFX_DOC_START+2) #define DLG_ORGANIZE (RID_SFX_DOC_START+3) +#define DLG_TEMPLATE_MANAGER (RID_SFX_DOC_START+4) #define BMP_STYLES_CLOSED (RID_SFX_DOC_START+ 0) #define BMP_STYLES_OPENED (RID_SFX_DOC_START+ 1) diff --git a/sfx2/source/doc/templatedlg.cxx b/sfx2/source/doc/templatedlg.cxx new file mode 100644 index 000000000000..77f903240a7b --- /dev/null +++ b/sfx2/source/doc/templatedlg.cxx @@ -0,0 +1,790 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "templatedlg.hxx" + +#include "inputdlg.hxx" +#include "templatesearchview.hxx" + +#include <comphelper/processfactory.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/sfxresid.hxx> +#include <sfx2/templatefolderview.hxx> +#include <sfx2/templatefolderviewitem.hxx> +#include <sfx2/templateviewitem.hxx> +#include <sfx2/thumbnailviewitem.hxx> +#include <tools/urlobj.hxx> +#include <unotools/moduleoptions.hxx> +#include <vcl/edit.hxx> +#include <vcl/toolbox.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> + +#include "doc.hrc" +#include "templatedlg.hrc" + +#define ITEM_MAX_WIDTH 192 +#define ITEM_MAX_HEIGHT 192 +#define ITEM_PADDING 5 +#define ITEM_SPACE 30 +#define ITEM_MAX_TEXT_LENGTH 20 +#define THUMBNAIL_MAX_HEIGHT 128 + +#define INIT_FOLDER_COLS 3 +#define INIT_FOLDER_LINES 2 + +#define PADDING_TOOLBAR_VIEW 15 +#define PADDING_DLG_BORDER 10 + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +void lcl_createTemplate(uno::Reference<XComponentLoader> xDesktop, const FILTER_APPLICATION eApp); + +// Sort by name in ascending order +class SortView_Name +{ +public: + + bool operator() (const ThumbnailViewItem *pItem1, const ThumbnailViewItem *pItem2) + { + return (pItem1->maText.compareTo(pItem2->maText) < 0); + } +}; + +class SearchView_Keyword +{ +public: + + SearchView_Keyword (const rtl::OUString &rKeyword) + : maKeyword(rKeyword) + {} + + bool operator() (const ThumbnailViewItem *pItem) + { + return pItem->maText.indexOf(maKeyword) != -1; + } + +private: + + rtl::OUString maKeyword; +}; + +SfxTemplateManagerDlg::SfxTemplateManagerDlg (Window *parent) + : ModalDialog(parent, SfxResId(DLG_TEMPLATE_MANAGER)), + aButtonAll(this,SfxResId(BTN_SELECT_ALL)), + aButtonDocs(this,SfxResId(BTN_SELECT_DOCS)), + aButtonPresents(this,SfxResId(BTN_SELECT_PRESENTATIONS)), + aButtonSheets(this,SfxResId(BTN_SELECT_SHEETS)), + aButtonDraws(this,SfxResId(BTN_SELECT_DRAWS)), + maButtonClose(this,SfxResId(BTN_TEMPLATE_CLOSE)), + maButtonSelMode(this,SfxResId(BTN_SELECTION_MODE)), + mpSearchEdit(new Edit(this,WB_HIDE | WB_BORDER)), + mpViewBar( new ToolBox(this, SfxResId(TBX_ACTION_VIEW))), + mpActionBar( new ToolBox(this, SfxResId(TBX_ACTION_ACTION))), + mpTemplateBar( new ToolBox(this, SfxResId(TBX_ACTION_TEMPLATES))), + mpSearchView(new TemplateSearchView(this)), + maView(new TemplateFolderView(this,SfxResId(TEMPLATE_VIEW))), + mnSelectionCount(0), + mxDesktop(comphelper::getProcessServiceFactory()->createInstance( "com.sun.star.frame.Desktop" ),uno::UNO_QUERY ) +{ + maButtonSelMode.SetStyle(maButtonSelMode.GetStyle() | WB_TOGGLE); + + // Create popup menus + mpCreateMenu = new PopupMenu; + mpCreateMenu->InsertItem(MNI_CREATE_TEXT,SfxResId(STR_CREATE_TEXT).toString(),SfxResId(IMG_CREATE_TEXT)); + mpCreateMenu->InsertItem(MNI_CREATE_SHEET,SfxResId(STR_CREATE_SHEET).toString(),SfxResId(IMG_CREATE_SHEET)); + mpCreateMenu->InsertItem(MNI_CREATE_PRESENT,SfxResId(STR_CREATE_PRESENT).toString(),SfxResId(IMG_CREATE_PRESENT)); + mpCreateMenu->InsertItem(MNI_CREATE_DRAW,SfxResId(STR_CREATE_DRAW).toString(),SfxResId(IMG_CREATE_DRAW)); + mpCreateMenu->SetSelectHdl(LINK(this, SfxTemplateManagerDlg, MenuSelectHdl)); + + mpActionMenu = new PopupMenu; + mpActionMenu->InsertItem(MNI_ACTION_SORT_NAME,SfxResId(STR_ACTION_SORT_NAME).toString(),SfxResId(IMG_ACTION_SORT)); + mpActionMenu->SetSelectHdl(LINK(this,SfxTemplateManagerDlg,MenuSelectHdl)); + + Size aWinSize = GetOutputSize(); + + // Calculate thumbnail view minimum size + Size aThumbSize = maView->CalcWindowSizePixel(INIT_FOLDER_COLS,INIT_FOLDER_LINES, + ITEM_MAX_WIDTH,ITEM_MAX_HEIGHT,ITEM_SPACE); + + if (aWinSize.getWidth() < aThumbSize.getWidth() + 2*PADDING_DLG_BORDER) + aWinSize.setWidth(aThumbSize.getWidth() + 2*PADDING_DLG_BORDER); + + // Calculate toolboxs size and positions + Size aViewSize = mpViewBar->CalcMinimumWindowSizePixel(); + Size aActionSize = mpActionBar->CalcMinimumWindowSizePixel(); + Size aTemplateSize = mpTemplateBar->CalcMinimumWindowSizePixel(); + + aActionSize.setWidth(2*aActionSize.getWidth()); + aViewSize.setWidth(aWinSize.getWidth()-aActionSize.getWidth()-mpViewBar->GetPosPixel().X()); + aTemplateSize.setWidth(aWinSize.getWidth()); + + Point aActionPos = mpActionBar->GetPosPixel(); + aActionPos.setX(aWinSize.getWidth() - aActionSize.getWidth()); + + mpViewBar->SetSizePixel(aViewSize); + mpActionBar->SetPosSizePixel(aActionPos,aActionSize); + mpTemplateBar->SetSizePixel(aTemplateSize); + + // Set toolbox styles + mpViewBar->SetButtonType(BUTTON_SYMBOLTEXT); + mpTemplateBar->SetButtonType(BUTTON_SYMBOLTEXT); + + // Set toolbox button bits + mpViewBar->EnableItem(TBI_TEMPLATE_IMPORT,false); + mpViewBar->SetItemBits(TBI_TEMPLATE_CREATE, TIB_DROPDOWNONLY); + mpActionBar->SetItemBits(TBI_TEMPLATE_ACTION, TIB_DROPDOWNONLY); + mpTemplateBar->SetItemBits(TBI_TEMPLATE_MOVE,TIB_DROPDOWNONLY); + + // Set toolbox handlers + mpViewBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXViewHdl)); + mpViewBar->SetDropdownClickHdl(LINK(this,SfxTemplateManagerDlg,TBXDropdownHdl)); + mpActionBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXActionHdl)); + mpActionBar->SetDropdownClickHdl(LINK(this,SfxTemplateManagerDlg,TBXDropdownHdl)); + mpTemplateBar->SetClickHdl(LINK(this,SfxTemplateManagerDlg,TBXTemplateHdl)); + mpTemplateBar->SetDropdownClickHdl(LINK(this,SfxTemplateManagerDlg,TBXDropdownHdl)); + + // Set view position below toolbox + Point aViewPos = maView->GetPosPixel(); + aViewPos.setY(aActionPos.Y() + aActionSize.getHeight() + PADDING_TOOLBAR_VIEW); + aViewPos.setX((aWinSize.getWidth() - aThumbSize.getWidth())/2); // Center the view + maView->SetPosPixel(aViewPos); + + if (aWinSize.getHeight() < aViewPos.getY() + aThumbSize.getHeight() + PADDING_DLG_BORDER) + aWinSize.setHeight(aViewPos.getY() + aThumbSize.getHeight() + PADDING_DLG_BORDER); + + // Set search box position and size + Size aSearchSize = mpSearchEdit->CalcMinimumSize(); + aSearchSize.setWidth(aWinSize.getWidth() - 2*PADDING_DLG_BORDER); + + mpSearchEdit->SetSizePixel(aSearchSize); + mpSearchEdit->SetPosPixel(Point(PADDING_DLG_BORDER,aActionPos.Y()+aActionSize.getHeight())); + mpSearchEdit->SetUpdateDataHdl(LINK(this,SfxTemplateManagerDlg,SearchUpdateHdl)); + mpSearchEdit->EnableUpdateData(); + + maView->SetStyle(WB_VSCROLL); + maView->SetColor(GetBackground().GetColor()); + maView->SetSizePixel(aThumbSize); + maView->setItemMaxTextLength(ITEM_MAX_TEXT_LENGTH); + + maView->setItemDimensions(ITEM_MAX_WIDTH,THUMBNAIL_MAX_HEIGHT, + ITEM_MAX_HEIGHT-THUMBNAIL_MAX_HEIGHT, + ITEM_PADDING); + + maView->setItemStateHdl(LINK(this,SfxTemplateManagerDlg,TVFolderStateHdl)); + maView->setTemplateStateHdl(LINK(this,SfxTemplateManagerDlg,TVTemplateStateHdl)); + maView->setOverlayDblClickHdl(LINK(this,SfxTemplateManagerDlg,OpenTemplateHdl)); + + mpSearchView->SetSizePixel(aThumbSize); + mpSearchView->setItemMaxTextLength(ITEM_MAX_TEXT_LENGTH); + + mpSearchView->setItemDimensions(ITEM_MAX_WIDTH,THUMBNAIL_MAX_HEIGHT, + ITEM_MAX_HEIGHT-THUMBNAIL_MAX_HEIGHT, + ITEM_PADDING); + + // Set OK button position + Point aBtnPos; + Size aBtnSize = maButtonClose.GetSizePixel(); + aBtnPos.setX(aWinSize.getWidth() - PADDING_DLG_BORDER - aBtnSize.getWidth()); + aBtnPos.setY(aViewPos.getY()+aThumbSize.getHeight() + PADDING_TOOLBAR_VIEW); + maButtonClose.SetPosPixel(aBtnPos); + + if (aWinSize.getHeight() != aBtnPos.getY() + aBtnSize.getHeight() + PADDING_DLG_BORDER ) + aWinSize.setHeight(aBtnPos.getY() + aBtnSize.getHeight() + PADDING_DLG_BORDER); + + aButtonAll.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewAllHdl)); + aButtonDocs.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDocsHdl)); + aButtonPresents.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewPresentsHdl)); + aButtonSheets.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewSheetsHdl)); + aButtonDraws.SetClickHdl(LINK(this,SfxTemplateManagerDlg,ViewDrawsHdl)); + maButtonClose.SetClickHdl(LINK(this,SfxTemplateManagerDlg,CloseHdl)); + maButtonSelMode.SetClickHdl(LINK(this,SfxTemplateManagerDlg,OnClickSelectionMode)); + + // Set dialog to correct dimensions + SetSizePixel(aWinSize); + + mpViewBar->Show(); + mpActionBar->Show(); + + maView->Populate(); + maView->Show(); + + FreeResource(); +} + +SfxTemplateManagerDlg::~SfxTemplateManagerDlg () +{ + delete mpSearchEdit; + delete mpViewBar; + delete mpActionBar; + delete mpTemplateBar; + delete mpSearchView; + delete maView; + delete mpCreateMenu; + delete mpActionMenu; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewAllHdl) +{ + maView->filterTemplatesByApp(FILTER_APP_NONE); + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDocsHdl) +{ + maView->filterTemplatesByApp(FILTER_APP_WRITER); + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewPresentsHdl) +{ + maView->filterTemplatesByApp(FILTER_APP_IMPRESS); + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewSheetsHdl) +{ + maView->filterTemplatesByApp(FILTER_APP_CALC); + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,ViewDrawsHdl) +{ + maView->filterTemplatesByApp(FILTER_APP_DRAW); + return 0; +} + +void SfxTemplateManagerDlg::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (!maView->GetActiveClipRegion().IsInside(rMEvt.GetPosPixel()) && maView->isOverlayVisible()) + maView->showOverlay(false); +} + +IMPL_LINK_NOARG (SfxTemplateManagerDlg, CloseHdl) +{ + Close(); + return 0; +} + +IMPL_LINK (SfxTemplateManagerDlg, OnClickSelectionMode, ImageButton*, pButton) +{ + maView->setSelectionMode(pButton->GetState() == STATE_CHECK); + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXViewHdl) +{ + switch(mpViewBar->GetCurItemId()) + { + case TBI_TEMPLATE_IMPORT: + OnTemplateImport(); + break; + default: + break; + } + + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXActionHdl) +{ + switch(mpActionBar->GetCurItemId()) + { + case TBI_TEMPLATE_SEARCH: + OnTemplateSearch(); + break; + default: + break; + } + + return 0; +} + +IMPL_LINK_NOARG(SfxTemplateManagerDlg,TBXTemplateHdl) +{ + switch(mpTemplateBar->GetCurItemId()) + { + case TBI_TEMPLATE_EDIT: + OnTemplateEdit(); + break; + case TBI_TEMPLATE_PROPERTIES: + OnTemplateProperties(); + break; + case TBI_TEMPLATE_DELETE: + OnTemplateDelete(); + break; + default: + break; + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, TBXDropdownHdl, ToolBox*, pBox) +{ + const sal_uInt16 nCurItemId = pBox->GetCurItemId(); + + switch(nCurItemId) + { + case TBI_TEMPLATE_CREATE: + pBox->SetItemDown( nCurItemId, true ); + + mpCreateMenu->Execute(pBox,pBox->GetItemRect(TBI_TEMPLATE_CREATE), + POPUPMENU_EXECUTE_DOWN); + + pBox->SetItemDown( nCurItemId, false ); + pBox->EndSelection(); + pBox->Invalidate(); + break; + case TBI_TEMPLATE_ACTION: + pBox->SetItemDown( nCurItemId, true ); + + mpActionMenu->Execute(pBox,pBox->GetItemRect(TBI_TEMPLATE_ACTION), + POPUPMENU_EXECUTE_DOWN); + + pBox->SetItemDown( nCurItemId, false ); + pBox->EndSelection(); + pBox->Invalidate(); + break; + case TBI_TEMPLATE_MOVE: + { + pBox->SetItemDown( nCurItemId, true ); + + std::vector<rtl::OUString> aNames = maView->getFolderNames(); + + PopupMenu *pMoveMenu = new PopupMenu; + pMoveMenu->SetSelectHdl(LINK(this,SfxTemplateManagerDlg,MoveMenuSelectHdl)); + + if (!aNames.empty()) + { + for (size_t i = 0, n = aNames.size(); i < n; ++i) + pMoveMenu->InsertItem(MNI_MOVE_FOLDER_BASE+i,aNames[i]); + } + + pMoveMenu->InsertSeparator(); + + pMoveMenu->InsertItem(MNI_MOVE_NEW,SfxResId(STR_MOVE_NEW).toString()); + pMoveMenu->InsertItem(MNI_MOVE_DELETE,SfxResId(STR_MOVE_DELETE).toString()); + + pMoveMenu->Execute(pBox,pBox->GetItemRect(TBI_TEMPLATE_MOVE), + POPUPMENU_EXECUTE_DOWN); + + delete pMoveMenu; + + pBox->SetItemDown( nCurItemId, false ); + pBox->EndSelection(); + pBox->Invalidate(); + break; + } + default: + break; + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, TVFolderStateHdl, const ThumbnailViewItem*, pItem) +{ + if (pItem->isSelected()) + { + if (maSelFolders.empty()) + mpViewBar->EnableItem(TBI_TEMPLATE_IMPORT,true); + + maSelFolders.insert(pItem); + } + else + { + maSelFolders.erase(pItem); + + if (maSelFolders.empty()) + mpViewBar->EnableItem(TBI_TEMPLATE_IMPORT,false); + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, TVTemplateStateHdl, const ThumbnailViewItem*, pItem) +{ + if (pItem->isSelected()) + { + if (maSelTemplates.empty()) + { + mpViewBar->Show(false); + mpActionBar->Show(false); + mpTemplateBar->Show(); + } + + maSelTemplates.insert(pItem); + } + else + { + if (maSelTemplates.find(pItem) != maSelTemplates.end()) + { + maSelTemplates.erase(pItem); + + if (maSelTemplates.empty()) + { + mpTemplateBar->Show(false); + mpViewBar->Show(); + mpActionBar->Show(); + } + } + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, MenuSelectHdl, Menu*, pMenu) +{ + sal_uInt16 nMenuId = pMenu->GetCurItemId(); + + switch(nMenuId) + { + case MNI_CREATE_TEXT: + lcl_createTemplate(mxDesktop,FILTER_APP_WRITER); + Close( ); + break; + case MNI_CREATE_SHEET: + lcl_createTemplate(mxDesktop,FILTER_APP_CALC); + Close( ); + break; + case MNI_CREATE_PRESENT: + lcl_createTemplate(mxDesktop,FILTER_APP_IMPRESS); + Close( ); + break; + case MNI_CREATE_DRAW: + lcl_createTemplate(mxDesktop,FILTER_APP_DRAW); + Close( ); + break; + case MNI_ACTION_SORT_NAME: + if (maView->isOverlayVisible()) + maView->sortOverlayItems(SortView_Name()); + else + maView->sortItems(SortView_Name()); + break; + default: + break; + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, MoveMenuSelectHdl, Menu*, pMenu) +{ + sal_uInt16 nMenuId = pMenu->GetCurItemId(); + + if (nMenuId == MNI_MOVE_NEW) + { + InputDialog dlg(SfxResId(STR_INPUT_NEW).toString(),this); + + int ret = dlg.Execute(); + + if (ret) + { + rtl::OUString aName = dlg.getEntryText(); + + if (!aName.isEmpty()) + { + sal_uInt16 nNewRegionId = maView->createRegion(aName); + + if (nNewRegionId) + { + // Move templates to desired folder if for some reason move fails + // try copying them. + if (!maView->moveTemplates(maSelTemplates,nNewRegionId,false) && + !maView->moveTemplates(maSelTemplates,nNewRegionId,true)) + { + } + } + } + } + } + else if (nMenuId == MNI_MOVE_DELETE) + { + std::set<const ThumbnailViewItem*>::const_iterator pIter; + for (pIter = maSelTemplates.begin(); pIter != maSelTemplates.end();) + { + if (maView->removeTemplate((*pIter)->mnId)) + maSelTemplates.erase(pIter++); + else + ++pIter; + } + } + else + { + // Try to move the template, if isnt possible try to copy it. + + sal_uInt16 nItemId = maView->GetItemId(nMenuId-MNI_MOVE_FOLDER_BASE); + + if (!maView->moveTemplates(maSelTemplates,nItemId,false) && + !maView->moveTemplates(maSelTemplates,nItemId,true)) + { + } + } + + return 0; +} + +IMPL_LINK(SfxTemplateManagerDlg, OpenTemplateHdl, ThumbnailViewItem*, pItem) +{ + uno::Sequence< PropertyValue > aArgs(1); + aArgs[0].Name = "AsTemplate"; + aArgs[0].Value <<= sal_True; + + TemplateViewItem *pTemplateItem = static_cast<TemplateViewItem*>(pItem); + + try + { + mxDesktop->loadComponentFromURL(pTemplateItem->getPath(),rtl::OUString("_blank"), 0, aArgs ); + } + catch( const uno::Exception& ) + { + } + + Close(); + + return 0; +} + +IMPL_LINK (SfxTemplateManagerDlg, SearchUpdateHdl, Edit*, pEdit) +{ + // if the search view is hidden, hide the folder view and display search one + if (!mpSearchView->IsVisible()) + { + mpSearchView->Clear(); + mpSearchView->Show(); + maView->Hide(); + } + + rtl::OUString aKeyword = mpSearchEdit->GetText(); + + if (!aKeyword.isEmpty()) + { + mpSearchView->Clear(); + + std::vector<std::pair<sal_uInt16,std::vector<ThumbnailViewItem*> > > aItems = + maView->getFilteredItems(SearchView_Keyword(aKeyword)); + + size_t nCounter = 0; + for (size_t i = 0; i < aItems.size(); ++i) + { + sal_uInt16 nRegionId = aItems[i].first; + std::vector<ThumbnailViewItem*> &rRegionItems = aItems[i].second; + + for (size_t j = 0; j < rRegionItems.size(); ++j) + { + TemplateViewItem *pItem = static_cast<TemplateViewItem*>(rRegionItems[j]); + + mpSearchView->AppendItem(++nCounter,nRegionId, + pItem->mnId-1, + pItem->maText, + pItem->getPath(), + pItem->maPreview1); + } + } + + mpSearchView->Invalidate(); + } + + return 0; +} + +void SfxTemplateManagerDlg::OnTemplateImport () +{ + sal_Int16 nDialogType = + com::sun::star::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE; + + sfx2::FileDialogHelper aFileDlg(nDialogType, SFXWB_MULTISELECTION); + + // add "All" filter + aFileDlg.AddFilter( String(SfxResId( STR_SFX_FILTERNAME_ALL) ), + DEFINE_CONST_UNICODE(FILEDIALOG_FILTER_ALL) ); + + // add template filter + rtl::OUString sFilterExt; + rtl::OUString sFilterName( SfxResId( STR_TEMPLATE_FILTER ).toString() ); + + // add filters of modules which are installed + SvtModuleOptions aModuleOpt; + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) ) + sFilterExt += "*.ott;*.stw;*.oth"; + + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) ) + { + if ( !sFilterExt.isEmpty() ) + sFilterExt += ";"; + + sFilterExt += "*.ots;*.stc"; + } + + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) ) + { + if ( !sFilterExt.isEmpty() ) + sFilterExt += ";"; + + sFilterExt += "*.otp;*.sti"; + } + + if ( aModuleOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) ) + { + if ( !sFilterExt.isEmpty() ) + sFilterExt += ";"; + + sFilterExt += "*.otg;*.std"; + } + + if ( !sFilterExt.isEmpty() ) + sFilterExt += ";"; + + sFilterExt += "*.vor"; + + sFilterName += " ("; + sFilterName += sFilterExt; + sFilterName += ")"; + + aFileDlg.AddFilter( sFilterName, sFilterExt ); + aFileDlg.SetCurrentFilter( sFilterName ); + + ErrCode nCode = aFileDlg.Execute(); + + if ( nCode == ERRCODE_NONE ) + { + com::sun::star::uno::Sequence< ::rtl::OUString > aFiles = aFileDlg.GetSelectedFiles(); + + if (aFiles.hasElements()) + { + std::set<const ThumbnailViewItem*>::const_iterator pIter; + for (pIter = maSelFolders.begin(); pIter != maSelFolders.end(); ++pIter) + { + TemplateFolderViewItem *pFolder = (TemplateFolderViewItem*)(*pIter); + + for (size_t i = 0, n = aFiles.getLength(); i < n; ++i) + maView->copyFrom(pFolder,aFiles[i]); + } + } + } +} + +void SfxTemplateManagerDlg::OnTemplateSearch () +{ + Point aPos = maView->GetPosPixel(); + Point aClosePos = maButtonClose.GetPosPixel(); + bool bVisible = mpSearchEdit->IsVisible(); + Size aWinSize = GetSizePixel(); + long nEditHeight = mpSearchEdit->GetSizePixel().getHeight(); + + if (bVisible) + { + aWinSize.setHeight(aWinSize.getHeight() - nEditHeight ); + aPos.setY(aPos.getY() - nEditHeight ); + aClosePos.setY(aClosePos.getY() - nEditHeight ); + mpActionBar->SetItemState(TBI_TEMPLATE_SEARCH,STATE_NOCHECK); + } + else + { + aWinSize.setHeight(aWinSize.getHeight() + nEditHeight ); + aPos.setY(aPos.getY() + nEditHeight ); + aClosePos.setY(aClosePos.getY() + nEditHeight ); + mpActionBar->SetItemState(TBI_TEMPLATE_SEARCH,STATE_CHECK); + } + + SetSizePixel(aWinSize); + maView->SetPosPixel(aPos); + mpSearchView->SetPosPixel(aPos); + maButtonClose.SetPosPixel(aClosePos); + + // Hide search view + if (bVisible) + { + mpSearchView->Hide(); + maView->Show(); + } + + mpSearchEdit->Show(!bVisible); + mpSearchEdit->SetText(rtl::OUString()); +} + +void SfxTemplateManagerDlg::OnTemplateEdit () +{ + uno::Sequence< PropertyValue > aArgs(1); + aArgs[0].Name = "AsTemplate"; + aArgs[0].Value <<= sal_False; + + uno::Reference< XStorable > xStorable; + std::set<const ThumbnailViewItem*>::const_iterator pIter; + for (pIter = maSelTemplates.begin(); pIter != maSelTemplates.end(); ++pIter) + { + const TemplateViewItem *pItem = static_cast<const TemplateViewItem*>(*pIter); + + try + { + xStorable = uno::Reference< XStorable >( + mxDesktop->loadComponentFromURL(pItem->getPath(),rtl::OUString("_blank"), 0, aArgs ), + uno::UNO_QUERY ); + } + catch( const uno::Exception& ) + { + } + } +} + +void SfxTemplateManagerDlg::OnTemplateProperties () +{ +} + +void SfxTemplateManagerDlg::OnTemplateDelete () +{ + std::set<const ThumbnailViewItem*>::const_iterator pIter; + for (pIter = maSelTemplates.begin(); pIter != maSelTemplates.end();) + { + if (maView->removeTemplate((*pIter)->mnId)) + maSelTemplates.erase(pIter++); + else + ++pIter; + } +} + +void lcl_createTemplate(uno::Reference< com::sun::star::frame::XComponentLoader > xDesktop, + const FILTER_APPLICATION eApp) +{ + rtl::OUString aURL; + + switch(eApp) + { + case FILTER_APP_WRITER: + aURL = "private:factory/swriter"; + break; + case FILTER_APP_CALC: + aURL = "private:factory/scalc"; + break; + case FILTER_APP_IMPRESS: + aURL = "private:factory/simpress"; + break; + case FILTER_APP_DRAW: + aURL = "private:factory/sdraw"; + break; + default: + break; + } + + if (!aURL.isEmpty()) + { + uno::Sequence<PropertyValue> aArgs; + xDesktop->loadComponentFromURL(aURL,rtl::OUString("_default"), 0, aArgs ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/doc/templatedlg.hrc b/sfx2/source/doc/templatedlg.hrc new file mode 100644 index 000000000000..8a46b1113a14 --- /dev/null +++ b/sfx2/source/doc/templatedlg.hrc @@ -0,0 +1,61 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#define BTN_SELECT_ALL 1 +#define BTN_SELECT_DOCS 2 +#define BTN_SELECT_PRESENTATIONS 3 +#define BTN_SELECT_SHEETS 4 +#define BTN_SELECT_DRAWS 5 +#define BTN_SELECTION_MODE 6 + +#define TEMPLATE_VIEW 7 + +#define TBX_ACTION_VIEW 8 +#define TBI_TEMPLATE_CREATE 9 +#define TBI_TEMPLATE_IMPORT 10 + +#define TBX_ACTION_ACTION 11 +#define TBI_TEMPLATE_SEARCH 12 +#define TBI_TEMPLATE_ACTION 13 + +#define TBX_ACTION_TEMPLATES 14 +#define TBI_TEMPLATE_EDIT 15 +#define TBI_TEMPLATE_PROPERTIES 16 +#define TBI_TEMPLATE_MOVE 17 +#define TBI_TEMPLATE_DELETE 18 + +#define MNI_CREATE_TEXT 19 +#define MNI_CREATE_SHEET 20 +#define MNI_CREATE_PRESENT 21 +#define MNI_CREATE_DRAW 22 + +#define MNI_ACTION_SORT_NAME 23 + +#define BTN_TEMPLATE_CLOSE 24 + +#define STR_CREATE_TEXT 260 +#define STR_CREATE_SHEET 261 +#define STR_CREATE_PRESENT 262 +#define STR_CREATE_DRAW 263 + +#define STR_ACTION_SORT_NAME 264 + +#define MNI_MOVE_NEW 265 +#define MNI_MOVE_DELETE 266 +#define MNI_MOVE_FOLDER_BASE 267 + +#define STR_MOVE_NEW 268 +#define STR_MOVE_DELETE 270 +#define STR_INPUT_NEW 271 + +#define IMG_ONLINE_REPOSITORY 100 +#define IMG_CREATE_TEXT 300 +#define IMG_CREATE_SHEET 301 +#define IMG_CREATE_PRESENT 302 +#define IMG_CREATE_DRAW 303 +#define IMG_ACTION_SORT 304 diff --git a/sfx2/source/doc/templatedlg.src b/sfx2/source/doc/templatedlg.src new file mode 100644 index 000000000000..f0ac3322d345 --- /dev/null +++ b/sfx2/source/doc/templatedlg.src @@ -0,0 +1,280 @@ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "doc.hrc" +#include "templatedlg.hrc" +#include "helpid.hrc" + +String STR_CREATE_TEXT +{ + Text [ en-US ] = "Text Document Template"; +}; + +String STR_CREATE_SHEET +{ + Text [ en-US ] = "Spreedsheet Template"; +}; + +String STR_CREATE_PRESENT +{ + Text [ en-US ] = "Presentation Template"; +}; + +String STR_CREATE_DRAW +{ + Text [ en-US ] = "Drawing Template"; +}; + +String STR_ACTION_SORT_NAME +{ + Text [ en-US ] = "Sort by name"; +}; + +String STR_MOVE_NEW +{ + Text [ en-US ] = "New folder"; +}; + +String STR_MOVE_DELETE +{ + Text [ en-US ] = "No folder"; +}; + +String STR_INPUT_NEW +{ + Text [ en-US ] = "Enter folder name:"; +}; + +ModalDialog DLG_TEMPLATE_MANAGER +{ + HelpId = CMD_SID_TEMPLATE_MANAGER; + OutputSize = TRUE; + SVLook = TRUE; + Moveable = TRUE; + Closeable = TRUE; + Hide = TRUE; + Size = MAP_APPFONT ( 290 , 250 ); + Text [en-US] = "Template Manager"; + + PushButton BTN_SELECT_ALL + { + Pos = MAP_APPFONT(10,5); + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + DefButton = TRUE; + Text [en-US] = "All"; + }; + + PushButton BTN_SELECT_DOCS + { + Pos = MAP_APPFONT(60,5); + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + Text [en-US] = "Documents"; + }; + + PushButton BTN_SELECT_PRESENTATIONS + { + Pos = MAP_APPFONT(110,5); + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + Text [en-US] = "Presentations"; + }; + + PushButton BTN_SELECT_SHEETS + { + Pos = MAP_APPFONT(160,5); + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + Text [en-US] = "Spreedsheets"; + }; + + PushButton BTN_SELECT_DRAWS + { + Pos = MAP_APPFONT(210,5); + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + Text [en-US] = "Drawings"; + }; + + ImageButton BTN_SELECTION_MODE + { + Pos = MAP_APPFONT(265,5); + Size = MAP_APPFONT(14,14); + TabStop = TRUE; + + ButtonImage = Image + { + ImageBitmap = Bitmap { File = "select.png" ; }; + }; + + QuickHelpText [en-US] = "Enables selecting items by just clicking in the thumbnail or title."; + }; + + PushButton BTN_TEMPLATE_CLOSE + { + Size = MAP_APPFONT(50,14); + TabStop = TRUE; + Text [en-US] = "Close"; + }; + + Control TEMPLATE_VIEW + { + Pos = MAP_APPFONT(5,30); + Size = MAP_APPFONT(280,220); + TabStop = TRUE; + }; + + Image IMG_ONLINE_REPOSITORY + { + ImageBitmap = Bitmap + { + File = "ln053.png"; + }; + }; + + Image IMG_CREATE_TEXT + { + ImageBitmap = Bitmap + { + File = "create_text.png"; + }; + }; + + Image IMG_CREATE_SHEET + { + ImageBitmap = Bitmap + { + File = "create_sheet.png"; + }; + }; + + Image IMG_CREATE_PRESENT + { + ImageBitmap = Bitmap + { + File = "create_present.png"; + }; + }; + + Image IMG_CREATE_DRAW + { + ImageBitmap = Bitmap + { + File = "create_draw.png"; + }; + }; + + Image IMG_ACTION_SORT + { + ImageBitmap = Bitmap + { + File = "sortascending.png"; + }; + }; + + + ToolBox TBX_ACTION_VIEW + { + SVLook = TRUE ; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 4 , 22 ) ; + + ItemList = + { + ToolBoxItem + { + Identifier = TBI_TEMPLATE_CREATE; + Text [ en-US ] = "Create a template" ; + + ItemImage = Image + { + ImageBitmap = Bitmap { File = "create_text.png" ; }; + }; + }; + + ToolBoxItem + { + Identifier = TBI_TEMPLATE_IMPORT ; + Text [ en-US ] = "Import a template" ; + + ItemImage = Image + { + ImageBitmap = Bitmap { File = "import.png" ; }; + }; + }; + }; + }; + + ToolBox TBX_ACTION_ACTION + { + SVLook = TRUE ; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 4 , 22 ) ; + + ItemList = + { + ToolBoxItem + { + Identifier = TBI_TEMPLATE_SEARCH; + Text [en-US] = "Search"; + + ItemImage = Image + { + ImageBitmap = Bitmap { File = "search.png" ; }; + }; + }; + + ToolBoxItem + { + Identifier = TBI_TEMPLATE_ACTION; + Text [en-US] = "Action Menu"; + + ItemImage = Image + { + ImageBitmap = Bitmap { File = "exec_action.png" ; }; + }; + }; + }; + }; + + ToolBox TBX_ACTION_TEMPLATES + { + SVLook = TRUE ; + TabStop = TRUE ; + Pos = MAP_APPFONT ( 4 , 22 ) ; + Hide = TRUE; + + ItemList = + { + ToolBoxItem + { + Identifier = TBI_TEMPLATE_EDIT; + Text [ en-US ] = "Edit"; + }; + + ToolBoxItem + { + Identifier = TBI_TEMPLATE_PROPERTIES; + Text [ en-US ] = "Properties"; + }; + + ToolBoxItem + { + Identifier = TBI_TEMPLATE_MOVE; + Text [ en-US ] = "Move to folder" ; + }; + + ToolBoxItem + { + Identifier = TBI_TEMPLATE_DELETE; + Text [ en-US ] = "Delete"; + }; + }; + }; +}; diff --git a/sfx2/source/inc/inputdlg.hxx b/sfx2/source/inc/inputdlg.hxx new file mode 100644 index 000000000000..1dce2fb2baa9 --- /dev/null +++ b/sfx2/source/inc/inputdlg.hxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INPUTDLG_HXX +#define INPUTDLG_HXX + +#include <vcl/dialog.hxx> + +class Edit; +class FixedText; +class PushButton; + +class InputDialog : public ModalDialog +{ +public: + + InputDialog (const rtl::OUString &labelText, Window *pParent = NULL); + + virtual ~InputDialog(); + + rtl::OUString getEntryText () const; + +private: + + DECL_LINK(ClickHdl, PushButton*); + +private: + + Edit *mpEntry; + FixedText *mpLabel; + PushButton *mpOK; + PushButton *mpCancel; +}; + +#endif // INPUTDLG_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/inc/templatesearchview.hxx b/sfx2/source/inc/templatesearchview.hxx new file mode 100644 index 000000000000..3d453b3c21db --- /dev/null +++ b/sfx2/source/inc/templatesearchview.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright 2012 LibreOffice contributors. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __SFX2_TEMPLATESEARCHVIEW_HXX__ +#define __SFX2_TEMPLATESEARCHVIEW_HXX__ + +#include <sfx2/thumbnailview.hxx> + +class TemplateSearchView : public ThumbnailView +{ +public: + + TemplateSearchView ( Window* pParent, WinBits nWinStyle = WB_TABSTOP | WB_VSCROLL); + + virtual ~TemplateSearchView(); + + void AppendItem(sal_uInt16 nItemId, sal_uInt16 nRegionId, sal_uInt16 nIdx, + const rtl::OUString &rStr, const rtl::OUString &rPath, + const BitmapEx &rImage ); +}; + +#endif // __SFX2_TEMPLATESEARCHVIEW_HXX__ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |