Bump version to 6.4-15
[LibreOffice.git] / svx / source / gallery2 / galbrws2.cxx
blob9109b81ad4c7814ff28a7f9046d6b07cc17cce64
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sot/formats.hxx>
22 #include <svl/urlbmk.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/intitem.hxx>
25 #include <svl/eitem.hxx>
26 #include <vcl/transfer.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <sfx2/sfxsids.hrc>
31 #include <vcl/graphicfilter.hxx>
32 #include <editeng/brushitem.hxx>
33 #include <helpids.h>
34 #include <svx/gallery.hxx>
35 #include <svx/svxids.hrc>
36 #include <galobj.hxx>
37 #include <svx/gallery1.hxx>
38 #include <svx/galtheme.hxx>
39 #include <svx/galctrl.hxx>
40 #include <svx/galmisc.hxx>
41 #include <galbrws2.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/settings.hxx>
44 #include <vcl/weld.hxx>
45 #include <svx/fmmodel.hxx>
46 #include <svx/dialmgr.hxx>
47 #include <svx/svxdlg.hxx>
48 #include <svx/strings.hrc>
49 #include <GalleryControl.hxx>
50 #include <bitmaps.hlst>
51 #include <svx/galleryitem.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <com/sun/star/frame/FrameSearchFlag.hpp>
54 #include <com/sun/star/frame/XDispatchProvider.hpp>
55 #include <com/sun/star/gallery/GalleryItemType.hpp>
56 #include <com/sun/star/graphic/XGraphic.hpp>
57 #include <com/sun/star/style/GraphicLocation.hpp>
58 #include <map>
59 #include <memory>
60 #include <cppuhelper/implbase.hxx>
62 #undef GALLERY_USE_CLIPBOARD
64 #define TBX_ID_ICON 1
65 #define TBX_ID_LIST 2
67 GalleryBrowserMode GalleryBrowser2::meInitMode = GALLERYBROWSERMODE_ICON;
69 struct DispatchInfo
71 css::util::URL TargetURL;
72 css::uno::Sequence< css::beans::PropertyValue > Arguments;
73 css::uno::Reference< css::frame::XDispatch > Dispatch;
76 IMPL_STATIC_LINK( GalleryBrowser2, AsyncDispatch_Impl, void*, p, void )
78 DispatchInfo* pDispatchInfo = static_cast<DispatchInfo*>(p);
79 if ( pDispatchInfo && pDispatchInfo->Dispatch.is() )
81 try
83 pDispatchInfo->Dispatch->dispatch( pDispatchInfo->TargetURL,
84 pDispatchInfo->Arguments );
86 catch ( const css::uno::Exception& )
91 delete pDispatchInfo;
94 namespace
97 struct CommandInfo
99 css::util::URL URL;
100 css::uno::Reference< css::frame::XDispatch > Dispatch;
102 explicit CommandInfo( const OUString &rURL )
104 URL.Complete = rURL;
108 class GalleryThemePopup : public ::cppu::WeakImplHelper< css::frame::XStatusListener >
110 private:
111 const GalleryTheme* mpTheme;
112 sal_uInt32 const mnObjectPos;
113 bool const mbPreview;
114 VclBuilder maBuilder;
115 VclPtr<PopupMenu> mpPopupMenu;
116 VclPtr<PopupMenu> mpBackgroundPopup;
117 VclPtr<GalleryBrowser2> mpBrowser;
119 typedef std::map< int, CommandInfo > CommandInfoMap;
120 CommandInfoMap m_aCommandInfo;
122 static void Execute( const CommandInfo &rCmdInfo,
123 const css::uno::Sequence< css::beans::PropertyValue > &rArguments );
125 DECL_LINK( MenuSelectHdl, Menu*, bool );
126 DECL_LINK( BackgroundMenuSelectHdl, Menu*, bool );
127 public:
128 GalleryThemePopup( const GalleryTheme* pTheme,
129 sal_uInt32 nObjectPos,
130 bool bPreview,
131 GalleryBrowser2* pBrowser );
133 void ExecutePopup( vcl::Window *pParent, const ::Point &aPos );
135 virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent &rEvent) override;
136 virtual void SAL_CALL disposing( const css::lang::EventObject &rSource) override;
140 GalleryThemePopup::GalleryThemePopup(
141 const GalleryTheme* pTheme,
142 sal_uInt32 nObjectPos,
143 bool bPreview,
144 GalleryBrowser2* pBrowser )
145 : mpTheme( pTheme )
146 , mnObjectPos( nObjectPos )
147 , mbPreview( bPreview )
148 , maBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/gallerymenu2.ui", "")
149 , mpPopupMenu(maBuilder.get_menu("menu"))
150 , mpBackgroundPopup( VclPtr<PopupMenu>::Create() )
151 , mpBrowser( pBrowser )
153 mpPopupMenu->SetPopupMenu(mpPopupMenu->GetItemId("background"), mpBackgroundPopup);
155 // SID_GALLERY_ENABLE_ADDCOPY
156 m_aCommandInfo.emplace(
157 SID_GALLERY_ENABLE_ADDCOPY,
158 CommandInfo( ".uno:GalleryEnableAddCopy" ));
159 // SID_GALLERY_BG_BRUSH
160 m_aCommandInfo.emplace(
161 SID_GALLERY_BG_BRUSH,
162 CommandInfo( ".uno:BackgroundImage" ));
163 // SID_GALLERY_FORMATS
164 m_aCommandInfo.emplace(
165 SID_GALLERY_FORMATS,
166 CommandInfo( ".uno:InsertGalleryPic" ));
170 void SAL_CALL GalleryThemePopup::statusChanged(
171 const css::frame::FeatureStateEvent &rEvent )
173 const OUString &rURL = rEvent.FeatureURL.Complete;
174 if ( rURL == ".uno:GalleryEnableAddCopy" )
176 if ( !rEvent.IsEnabled )
178 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("add"), false);
181 else if ( rURL == ".uno:BackgroundImage" )
183 mpBackgroundPopup->Clear();
184 if ( rEvent.IsEnabled )
186 OUString sItem;
187 css::uno::Sequence< OUString > sItems;
188 if ( ( rEvent.State >>= sItem ) && sItem.getLength() )
190 mpBackgroundPopup->InsertItem( 1, sItem );
192 else if ( ( rEvent.State >>= sItems ) && sItems.hasElements() )
194 sal_uInt16 nId = 1;
195 for ( const OUString& rStr : std::as_const(sItems) )
197 mpBackgroundPopup->InsertItem( nId, rStr );
198 nId++;
205 void SAL_CALL GalleryThemePopup::disposing(
206 const css::lang::EventObject &/*rSource*/)
210 void GalleryThemePopup::Execute(
211 const CommandInfo &rCmdInfo,
212 const css::uno::Sequence< css::beans::PropertyValue > &rArguments )
214 if ( rCmdInfo.Dispatch.is() )
216 std::unique_ptr<DispatchInfo> pInfo(new DispatchInfo);
217 pInfo->TargetURL = rCmdInfo.URL;
218 pInfo->Arguments = rArguments;
219 pInfo->Dispatch = rCmdInfo.Dispatch;
221 if ( Application::PostUserEvent(
222 LINK( nullptr, GalleryBrowser2, AsyncDispatch_Impl), pInfo.get() ) )
223 pInfo.release();
227 void GalleryThemePopup::ExecutePopup( vcl::Window *pWindow, const ::Point &aPos )
229 css::uno::Reference< css::frame::XStatusListener > xThis( this );
231 const SgaObjKind eObjKind = mpTheme->GetObjectKind( mnObjectPos );
232 INetURLObject aURL;
234 const_cast< GalleryTheme* >( mpTheme )->GetURL( mnObjectPos, aURL );
235 const bool bValidURL = ( aURL.GetProtocol() != INetProtocol::NotValid );
237 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("add"), bValidURL && SgaObjKind::Sound != eObjKind);
239 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("preview"), bValidURL);
240 mpPopupMenu->CheckItem("preview", mbPreview);
242 if( mpTheme->IsReadOnly() || !mpTheme->GetObjectCount() )
244 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("delete"), false);
245 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("title"), false);
246 if (mpTheme->IsReadOnly())
247 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("paste"), false);
249 if (!mpTheme->GetObjectCount())
250 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("copy"), false);
252 else
254 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("delete"), !mbPreview);
255 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("title"));
256 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("copy"));
257 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("paste"));
260 // update status
261 css::uno::Reference< css::frame::XDispatchProvider> xDispatchProvider(
262 GalleryBrowser2::GetFrame(), css::uno::UNO_QUERY );
263 css::uno::Reference< css::util::XURLTransformer > xTransformer(
264 mpBrowser->GetURLTransformer() );
265 for ( auto& rInfo : m_aCommandInfo )
269 CommandInfo &rCmdInfo = rInfo.second;
270 if ( xTransformer.is() )
271 xTransformer->parseStrict( rCmdInfo.URL );
273 if ( xDispatchProvider.is() )
275 rCmdInfo.Dispatch = xDispatchProvider->queryDispatch(
276 rCmdInfo.URL,
277 "_self",
278 css::frame::FrameSearchFlag::SELF );
281 if ( rCmdInfo.Dispatch.is() )
283 rCmdInfo.Dispatch->addStatusListener( this, rCmdInfo.URL );
284 rCmdInfo.Dispatch->removeStatusListener( this, rCmdInfo.URL );
287 catch ( ... )
291 if( !mpBackgroundPopup->GetItemCount() || ( eObjKind == SgaObjKind::SvDraw ) || ( eObjKind == SgaObjKind::Sound ) )
292 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("background"), false);
293 else
295 mpPopupMenu->EnableItem(mpPopupMenu->GetItemId("background"));
296 mpBackgroundPopup->SetSelectHdl( LINK( this, GalleryThemePopup, BackgroundMenuSelectHdl ) );
299 mpPopupMenu->RemoveDisabledEntries();
301 mpPopupMenu->SetSelectHdl( LINK( this, GalleryThemePopup, MenuSelectHdl ) );
302 mpPopupMenu->Execute( pWindow, aPos );
305 IMPL_LINK( GalleryThemePopup, MenuSelectHdl, Menu*, pMenu, bool )
307 if( !pMenu )
308 return false;
310 OString sIdent(pMenu->GetCurItemIdent());
311 if (sIdent == "add")
313 const CommandInfoMap::const_iterator it = m_aCommandInfo.find( SID_GALLERY_FORMATS );
314 if (it != m_aCommandInfo.end())
315 mpBrowser->DispatchAdd(it->second.Dispatch, it->second.URL);
317 else
318 mpBrowser->Execute(sIdent);
320 return false;
323 IMPL_LINK( GalleryThemePopup, BackgroundMenuSelectHdl, Menu*, pMenu, bool )
325 if( !pMenu )
326 return false;
328 sal_uInt16 nPos( pMenu->GetCurItemId() - 1 );
329 OUString aURL( mpBrowser->GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
330 OUString aFilterName( mpBrowser->GetFilterName() );
332 css::uno::Sequence< css::beans::PropertyValue > aArgs( 6 );
333 aArgs[0].Name = "Background.Transparent";
334 aArgs[0].Value <<= sal_Int32( 0 ); // 0 - 100
335 aArgs[1].Name = "Background.BackColor";
336 aArgs[1].Value <<= sal_Int32( - 1 );
337 aArgs[2].Name = "Background.URL";
338 aArgs[2].Value <<= aURL;
339 aArgs[3].Name = "Background.Filtername"; // FIXME should be FilterName
340 aArgs[3].Value <<= aFilterName;
341 aArgs[4].Name = "Background.Position";
342 aArgs[4].Value <<= css::style::GraphicLocation_TILED;
343 aArgs[5].Name = "Position";
344 aArgs[5].Value <<= nPos;
346 const CommandInfoMap::const_iterator it = m_aCommandInfo.find( SID_GALLERY_BG_BRUSH );
347 if ( it != m_aCommandInfo.end() )
348 Execute( it->second, aArgs );
350 return false;
353 } // end anonymous namespace
356 GalleryToolBox::GalleryToolBox( GalleryBrowser2* pParent ) :
357 ToolBox( pParent, WB_TABSTOP )
361 void GalleryToolBox::KeyInput( const KeyEvent& rKEvt )
363 if( !static_cast< GalleryBrowser2* >( GetParent() )->KeyInput( rKEvt, this ) )
365 if( KEY_ESCAPE != rKEvt.GetKeyCode().GetCode() )
366 ToolBox::KeyInput(rKEvt);
371 GalleryBrowser2::GalleryBrowser2( vcl::Window* pParent, Gallery* pGallery ) :
372 Control ( pParent, WB_TABSTOP ),
373 mpGallery ( pGallery ),
374 mpCurTheme ( nullptr ),
375 mpIconView ( VclPtr<GalleryIconView>::Create( this, nullptr ) ),
376 mpListView ( VclPtr<GalleryListView>::Create( this, nullptr ) ),
377 mpPreview ( VclPtr<GalleryPreview>::Create(this) ),
378 maViewBox ( VclPtr<GalleryToolBox>::Create(this) ),
379 maSeparator ( VclPtr<FixedLine>::Create(this, WB_VERT) ),
380 maInfoBar ( VclPtr<FixedText>::Create(this, WB_LEFT | WB_VCENTER) ),
381 mnCurActionPos ( 0xffffffff ),
382 meMode ( GALLERYBROWSERMODE_NONE ),
383 meLastMode ( GALLERYBROWSERMODE_NONE )
386 m_xContext.set( ::comphelper::getProcessComponentContext() );
388 m_xTransformer.set(
389 m_xContext->getServiceManager()->createInstanceWithContext(
390 "com.sun.star.util.URLTransformer", m_xContext ),
391 css::uno::UNO_QUERY );
393 Image aDummyImage;
394 vcl::Font aInfoFont( maInfoBar->GetControlFont() );
396 maMiscOptions.AddListenerLink( LINK( this, GalleryBrowser2, MiscHdl ) );
398 maViewBox->InsertItem( TBX_ID_ICON, aDummyImage );
399 maViewBox->SetItemBits( TBX_ID_ICON, ToolBoxItemBits::RADIOCHECK | ToolBoxItemBits::AUTOCHECK );
400 maViewBox->SetHelpId( TBX_ID_ICON, HID_GALLERY_ICONVIEW );
401 maViewBox->SetQuickHelpText( TBX_ID_ICON, SvxResId(RID_SVXSTR_GALLERY_ICONVIEW) );
403 maViewBox->InsertItem( TBX_ID_LIST, aDummyImage );
404 maViewBox->SetItemBits( TBX_ID_LIST, ToolBoxItemBits::RADIOCHECK | ToolBoxItemBits::AUTOCHECK );
405 maViewBox->SetHelpId( TBX_ID_LIST, HID_GALLERY_LISTVIEW );
406 maViewBox->SetQuickHelpText( TBX_ID_LIST, SvxResId(RID_SVXSTR_GALLERY_LISTVIEW) );
408 MiscHdl( nullptr );
409 maViewBox->SetSelectHdl( LINK( this, GalleryBrowser2, SelectTbxHdl ) );
410 maViewBox->Show();
412 mpIconView->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERY_THEMEITEMS));
413 mpListView->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERY_THEMEITEMS));
415 maInfoBar->Show();
416 maSeparator->Show();
418 mpIconView->SetSelectHdl( LINK( this, GalleryBrowser2, SelectObjectValueSetHdl ) );
419 mpListView->SetSelectHdl( LINK( this, GalleryBrowser2, SelectObjectHdl ) );
421 InitSettings();
423 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GalleryBrowser2::meInitMode ) ? GalleryBrowser2::meInitMode : GALLERYBROWSERMODE_ICON );
425 if(maInfoBar->GetText().isEmpty())
426 mpIconView->SetAccessibleRelationLabeledBy(mpIconView);
427 else
428 mpIconView->SetAccessibleRelationLabeledBy(maInfoBar.get());
431 GalleryBrowser2::~GalleryBrowser2()
433 disposeOnce();
436 void GalleryBrowser2::dispose()
438 maMiscOptions.RemoveListenerLink( LINK( this, GalleryBrowser2, MiscHdl ) );
440 mpPreview.disposeAndClear();
441 mpListView.disposeAndClear();
442 mpIconView.disposeAndClear();
444 if( mpCurTheme )
445 mpGallery->ReleaseTheme( mpCurTheme, *this );
446 maSeparator.disposeAndClear();
447 maInfoBar.disposeAndClear();
448 maViewBox.disposeAndClear();
449 Control::dispose();
452 void GalleryBrowser2::InitSettings()
454 vcl::Font aInfoFont( maInfoBar->GetControlFont() );
456 aInfoFont.SetWeight( WEIGHT_BOLD );
457 aInfoFont.SetColor( GALLERY_FG_COLOR );
458 maInfoBar->SetControlFont( aInfoFont );
460 maInfoBar->SetBackground( Wallpaper( GALLERY_DLG_COLOR ) );
461 maInfoBar->SetControlBackground( GALLERY_DLG_COLOR );
463 maSeparator->SetBackground( Wallpaper( GALLERY_BG_COLOR ) );
464 maSeparator->SetControlBackground( GALLERY_BG_COLOR );
465 maSeparator->SetControlForeground( GALLERY_FG_COLOR );
468 void GalleryBrowser2::DataChanged( const DataChangedEvent& rDCEvt )
470 if ( ( rDCEvt.GetType() == DataChangedEventType::SETTINGS ) && ( rDCEvt.GetFlags() & AllSettingsFlags::STYLE ) )
471 InitSettings();
472 else
473 Control::DataChanged( rDCEvt );
476 void GalleryBrowser2::Resize()
478 Control::Resize();
480 mpIconView->Hide();
481 mpListView->Hide();
482 mpPreview->Hide();
484 const Size aOutSize( GetOutputSizePixel() );
485 const Size aBoxSize( maViewBox->GetOutputSizePixel() );
486 const long nOffset = 2, nSepWidth = 2;
487 const long nInfoBarX = aBoxSize.Width() + ( nOffset * 3 ) + nSepWidth;
488 const Point aPt( 0, aBoxSize.Height() + 3 );
489 const Size aSz( aOutSize.Width(), aOutSize.Height() - aPt.Y() );
491 maSeparator->SetPosSizePixel( Point( aBoxSize.Width() + nOffset, 0 ), Size( nSepWidth, aBoxSize.Height() ) );
492 maInfoBar->SetPosSizePixel( Point( nInfoBarX, 0 ), Size( aOutSize.Width() - nInfoBarX, aBoxSize.Height() ) );
494 mpIconView->SetPosSizePixel( aPt, aSz );
495 mpListView->SetPosSizePixel( aPt, aSz );
496 mpPreview->SetPosSizePixel( aPt, aSz );
498 switch( GetMode() )
500 case GALLERYBROWSERMODE_ICON: mpIconView->Show(); break;
501 case GALLERYBROWSERMODE_LIST: mpListView->Show(); break;
502 case GALLERYBROWSERMODE_PREVIEW: mpPreview->Show(); break;
504 default:
505 break;
509 void GalleryBrowser2::Notify( SfxBroadcaster&, const SfxHint& rHint )
511 const GalleryHint& rGalleryHint = static_cast<const GalleryHint&>(rHint);
513 switch( rGalleryHint.GetType() )
515 case GalleryHintType::THEME_UPDATEVIEW:
517 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
518 SetMode( meLastMode );
520 ImplUpdateViews( reinterpret_cast<size_t>(rGalleryHint.GetData1()) + 1 );
522 break;
524 default:
525 break;
529 sal_Int8 GalleryBrowser2::AcceptDrop( DropTargetHelper& rTarget )
531 sal_Int8 nRet = DND_ACTION_NONE;
533 if( mpCurTheme && !mpCurTheme->IsReadOnly() )
535 if( !mpCurTheme->IsDragging() )
537 if( rTarget.IsDropFormatSupported( SotClipboardFormatId::DRAWING ) ||
538 rTarget.IsDropFormatSupported( SotClipboardFormatId::FILE_LIST ) ||
539 rTarget.IsDropFormatSupported( SotClipboardFormatId::SIMPLE_FILE ) ||
540 rTarget.IsDropFormatSupported( SotClipboardFormatId::SVXB ) ||
541 rTarget.IsDropFormatSupported( SotClipboardFormatId::GDIMETAFILE ) ||
542 rTarget.IsDropFormatSupported( SotClipboardFormatId::BITMAP ) )
544 nRet = DND_ACTION_COPY;
547 else
548 nRet = DND_ACTION_COPY;
551 return nRet;
554 sal_Int8 GalleryBrowser2::ExecuteDrop( const ExecuteDropEvent& rEvt )
556 sal_Int8 nRet = DND_ACTION_NONE;
558 if( mpCurTheme )
560 Point aSelPos;
561 const sal_uInt32 nItemId = ImplGetSelectedItemId( &rEvt.maPosPixel, aSelPos );
562 const sal_uInt32 nInsertPos = (nItemId ? (nItemId - 1) : mpCurTheme->GetObjectCount());
564 if( mpCurTheme->IsDragging() )
565 mpCurTheme->ChangeObjectPos( mpCurTheme->GetDragPos(), nInsertPos );
566 else
567 nRet = mpCurTheme->InsertTransferable( rEvt.maDropEvent.Transferable, nInsertPos ) ? 1 : 0;
570 return nRet;
573 void GalleryBrowser2::StartDrag( const Point* pDragPoint )
575 if( mpCurTheme )
577 Point aSelPos;
578 const sal_uInt32 nItemId = ImplGetSelectedItemId( pDragPoint, aSelPos );
580 if( nItemId )
581 mpCurTheme->StartDrag( this, nItemId - 1 );
585 void GalleryBrowser2::TogglePreview()
587 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
588 GetViewWindow()->GrabFocus();
591 void GalleryBrowser2::ShowContextMenu( const Point* pContextPoint )
593 Point aSelPos;
594 const sal_uInt32 nItemId = ImplGetSelectedItemId( pContextPoint, aSelPos );
596 if( mpCurTheme && nItemId && ( nItemId <= mpCurTheme->GetObjectCount() ) )
598 ImplSelectItemId( nItemId );
600 css::uno::Reference< css::frame::XFrame > xFrame( GetFrame() );
601 if ( xFrame.is() )
603 mnCurActionPos = nItemId - 1;
604 rtl::Reference< GalleryThemePopup > rPopup(
605 new GalleryThemePopup(
606 mpCurTheme,
607 mnCurActionPos,
608 GALLERYBROWSERMODE_PREVIEW == GetMode(),
609 this ) );
610 rPopup->ExecutePopup( this, aSelPos );
615 bool GalleryBrowser2::KeyInput( const KeyEvent& rKEvt, vcl::Window* /*pWindow*/ )
617 Point aSelPos;
618 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
619 bool bRet = false;
620 svx::sidebar::GalleryControl* pParentControl = dynamic_cast<svx::sidebar::GalleryControl*>(GetParent());
621 if (pParentControl != nullptr)
622 bRet = pParentControl->GalleryKeyInput(rKEvt);
624 if( !bRet && !maViewBox->HasFocus() && nItemId && mpCurTheme )
626 OString sExecuteIdent;
627 INetURLObject aURL;
629 mpCurTheme->GetURL( nItemId - 1, aURL );
631 const bool bValidURL = ( aURL.GetProtocol() != INetProtocol::NotValid );
632 bool bPreview = bValidURL;
633 bool bDelete = false;
634 bool bTitle = false;
636 if( !mpCurTheme->IsReadOnly() && mpCurTheme->GetObjectCount() )
638 bDelete = ( GALLERYBROWSERMODE_PREVIEW != GetMode() );
639 bTitle = true;
642 switch( rKEvt.GetKeyCode().GetCode() )
644 case KEY_SPACE:
645 case KEY_RETURN:
646 case KEY_P:
648 if( bPreview )
650 TogglePreview();
651 bRet = true;
654 break;
656 case KEY_INSERT:
657 case KEY_I:
659 // Inserting a gallery item in the document must be dispatched
660 if( bValidURL )
662 DispatchAdd(css::uno::Reference<css::frame::XDispatch>(), css::util::URL());
663 return true;
666 break;
668 case KEY_DELETE:
669 case KEY_D:
671 if( bDelete )
672 sExecuteIdent = "delete";
674 break;
676 case KEY_T:
678 if( bTitle )
679 sExecuteIdent = "title";
681 break;
683 default:
684 break;
687 if (!sExecuteIdent.isEmpty())
689 Execute(sExecuteIdent);
690 bRet = true;
694 return bRet;
697 void GalleryBrowser2::SelectTheme( const OUString& rThemeName )
699 mpIconView.disposeAndClear();
700 mpListView.disposeAndClear();
701 mpPreview.disposeAndClear();
703 if( mpCurTheme )
704 mpGallery->ReleaseTheme( mpCurTheme, *this );
706 mpCurTheme = mpGallery->AcquireTheme( rThemeName, *this );
708 mpIconView = VclPtr<GalleryIconView>::Create( this, mpCurTheme );
709 mpListView = VclPtr<GalleryListView>::Create( this, mpCurTheme );
710 mpPreview = VclPtr<GalleryPreview>::Create( this, WB_TABSTOP | WB_BORDER, mpCurTheme );
712 mpIconView->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERY_THEMEITEMS));
713 mpListView->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERY_THEMEITEMS));
714 mpPreview->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERY_PREVIEW));
716 mpIconView->SetSelectHdl( LINK( this, GalleryBrowser2, SelectObjectValueSetHdl ) );
717 mpListView->SetSelectHdl( LINK( this, GalleryBrowser2, SelectObjectHdl ) );
719 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
720 meMode = meLastMode;
722 Resize();
723 ImplUpdateViews( 1 );
725 maViewBox->EnableItem( TBX_ID_ICON );
726 maViewBox->EnableItem( TBX_ID_LIST );
727 maViewBox->CheckItem( ( GALLERYBROWSERMODE_ICON == GetMode() ) ? TBX_ID_ICON : TBX_ID_LIST );
729 if(maInfoBar->GetText().isEmpty())
730 mpIconView->SetAccessibleRelationLabeledBy(mpIconView);
731 else
732 mpIconView->SetAccessibleRelationLabeledBy(maInfoBar.get());
735 void GalleryBrowser2::SetMode( GalleryBrowserMode eMode )
737 if( GetMode() != eMode )
739 meLastMode = GetMode();
741 switch( eMode )
743 case GALLERYBROWSERMODE_ICON:
745 mpListView->Hide();
747 mpPreview->Hide();
748 mpPreview->SetGraphic( Graphic() );
749 GalleryPreview::PreviewMedia( INetURLObject() );
751 mpIconView->Show();
753 maViewBox->EnableItem( TBX_ID_ICON );
754 maViewBox->EnableItem( TBX_ID_LIST );
756 maViewBox->CheckItem( TBX_ID_ICON );
757 maViewBox->CheckItem( TBX_ID_LIST, false );
759 break;
761 case GALLERYBROWSERMODE_LIST:
763 mpIconView->Hide();
765 mpPreview->Hide();
766 mpPreview->SetGraphic( Graphic() );
767 GalleryPreview::PreviewMedia( INetURLObject() );
769 mpListView->Show();
771 maViewBox->EnableItem( TBX_ID_ICON );
772 maViewBox->EnableItem( TBX_ID_LIST );
774 maViewBox->CheckItem( TBX_ID_ICON, false );
775 maViewBox->CheckItem( TBX_ID_LIST );
777 break;
779 case GALLERYBROWSERMODE_PREVIEW:
781 Graphic aGraphic;
782 Point aSelPos;
783 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
785 if( nItemId )
787 const sal_uInt32 nPos = nItemId - 1;
789 mpIconView->Hide();
790 mpListView->Hide();
792 if( mpCurTheme )
793 mpCurTheme->GetGraphic( nPos, aGraphic );
795 mpPreview->SetGraphic( aGraphic );
796 mpPreview->Show();
798 if( mpCurTheme && mpCurTheme->GetObjectKind( nPos ) == SgaObjKind::Sound )
799 GalleryPreview::PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );
801 maViewBox->EnableItem( TBX_ID_ICON, false );
802 maViewBox->EnableItem( TBX_ID_LIST, false );
805 break;
807 default:
808 break;
811 GalleryBrowser2::meInitMode = meMode = eMode;
815 vcl::Window* GalleryBrowser2::GetViewWindow() const
817 vcl::Window* pRet;
819 switch( GetMode() )
821 case GALLERYBROWSERMODE_LIST: pRet = mpListView; break;
822 case GALLERYBROWSERMODE_PREVIEW: pRet = mpPreview; break;
824 default:
825 pRet = mpIconView;
826 break;
829 return pRet;
832 void GalleryBrowser2::Travel( GalleryBrowserTravel eTravel )
834 if( mpCurTheme )
836 Point aSelPos;
837 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
839 if( nItemId )
841 sal_uInt32 nNewItemId = nItemId;
843 switch( eTravel )
845 case GalleryBrowserTravel::First: nNewItemId = 1; break;
846 case GalleryBrowserTravel::Last: nNewItemId = mpCurTheme->GetObjectCount(); break;
847 case GalleryBrowserTravel::Previous: nNewItemId--; break;
848 case GalleryBrowserTravel::Next: nNewItemId++; break;
849 default:
850 break;
853 if( nNewItemId < 1 )
854 nNewItemId = 1;
855 else if( nNewItemId > mpCurTheme->GetObjectCount() )
856 nNewItemId = mpCurTheme->GetObjectCount();
858 if( nNewItemId != nItemId )
860 ImplSelectItemId( nNewItemId );
861 ImplUpdateInfoBar();
863 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
865 Graphic aGraphic;
866 const sal_uInt32 nPos = nNewItemId - 1;
868 mpCurTheme->GetGraphic( nPos, aGraphic );
869 mpPreview->SetGraphic( aGraphic );
871 if( SgaObjKind::Sound == mpCurTheme->GetObjectKind( nPos ) )
872 GalleryPreview::PreviewMedia( mpCurTheme->GetObjectURL( nPos ) );
874 mpPreview->Invalidate();
881 void GalleryBrowser2::ImplUpdateViews( sal_uInt16 nSelectionId )
883 mpIconView->Hide();
884 mpListView->Hide();
885 mpPreview->Hide();
887 mpIconView->Clear();
888 mpListView->Clear();
890 if( mpCurTheme )
892 for (sal_uInt32 i = 0, nCount = mpCurTheme->GetObjectCount(); i < nCount;)
894 mpListView->RowInserted( i++ );
895 mpIconView->InsertItem( static_cast<sal_uInt16>(i) );
898 ImplSelectItemId( std::min<sal_uInt16>( nSelectionId, mpCurTheme->GetObjectCount() ) );
901 switch( GetMode() )
903 case GALLERYBROWSERMODE_ICON: mpIconView->Show(); break;
904 case GALLERYBROWSERMODE_LIST: mpListView->Show(); break;
905 case GALLERYBROWSERMODE_PREVIEW: mpPreview->Show(); break;
907 default:
908 break;
911 ImplUpdateInfoBar();
914 void GalleryBrowser2::ImplUpdateInfoBar()
916 if( mpCurTheme )
917 maInfoBar->SetText( mpCurTheme->GetName() );
920 sal_uInt32 GalleryBrowser2::ImplGetSelectedItemId( const Point* pSelPos, Point& rSelPos )
922 const Size aOutputSizePixel( GetOutputSizePixel() );
923 sal_uInt32 nRet = 0;
925 if( GALLERYBROWSERMODE_PREVIEW == GetMode() )
927 nRet = ( ( GALLERYBROWSERMODE_ICON == meLastMode ) ? mpIconView->GetSelectedItemId() : ( mpListView->FirstSelectedRow() + 1 ) );
929 if( pSelPos )
930 rSelPos = GetPointerPosPixel();
931 else
932 rSelPos = Point( aOutputSizePixel.Width() >> 1, aOutputSizePixel.Height() >> 1 );
934 else if( GALLERYBROWSERMODE_ICON == GetMode() )
936 if( pSelPos )
938 nRet = mpIconView->GetItemId( *pSelPos );
939 rSelPos = GetPointerPosPixel();
941 else
943 nRet = mpIconView->GetSelectedItemId();
944 rSelPos = mpIconView->GetItemRect(nRet).Center();
947 else
949 if( pSelPos )
951 nRet = mpListView->GetRowAtYPosPixel( pSelPos->Y() ) + 1;
952 rSelPos = GetPointerPosPixel();
954 else
956 nRet = mpListView->FirstSelectedRow() + 1;
957 rSelPos = mpListView->GetFieldRectPixel( static_cast<sal_uInt16>(nRet), 1 ).Center();
961 rSelPos.setX( std::max( std::min( rSelPos.X(), aOutputSizePixel.Width() - 1 ), 0L ) );
962 rSelPos.setY( std::max( std::min( rSelPos.Y(), aOutputSizePixel.Height() - 1 ), 0L ) );
964 if( nRet && ( !mpCurTheme || ( nRet > mpCurTheme->GetObjectCount() ) ) )
966 nRet = 0;
969 return nRet;
972 void GalleryBrowser2::ImplSelectItemId(sal_uInt32 nItemId)
974 if( nItemId )
977 mpIconView->SelectItem(nItemId);
978 mpListView->SelectRow( nItemId - 1 );
982 css::uno::Reference< css::frame::XFrame >
983 GalleryBrowser2::GetFrame()
985 css::uno::Reference< css::frame::XFrame > xFrame;
986 SfxViewFrame* pCurrentViewFrame = SfxViewFrame::Current();
987 if ( pCurrentViewFrame )
989 SfxBindings& rBindings = pCurrentViewFrame->GetBindings();
990 xFrame.set( rBindings.GetActiveFrame() );
993 return xFrame;
996 void GalleryBrowser2::DispatchAdd(
997 const css::uno::Reference< css::frame::XDispatch > &rxDispatch,
998 const css::util::URL &rURL)
1000 Point aSelPos;
1001 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
1003 if( !mpCurTheme || !nItemId )
1004 return;
1006 mnCurActionPos = nItemId - 1;
1008 css::uno::Reference< css::frame::XDispatch > xDispatch( rxDispatch );
1009 css::util::URL aURL = rURL;
1011 if ( !xDispatch.is() )
1013 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider(
1014 GetFrame(), css::uno::UNO_QUERY );
1015 if ( !xDispatchProvider.is() || !m_xTransformer.is() )
1016 return;
1018 aURL.Complete = ".uno:InsertGalleryPic";
1019 m_xTransformer->parseStrict( aURL );
1020 xDispatch = xDispatchProvider->queryDispatch(
1021 aURL,
1022 "_self",
1023 css::frame::FrameSearchFlag::SELF );
1026 if ( !xDispatch.is() )
1027 return;
1029 sal_Int8 nType = 0;
1030 OUString aFilterName;
1031 css::uno::Reference< css::lang::XComponent > xDrawing;
1032 css::uno::Reference< css::graphic::XGraphic > xGraphic;
1034 aFilterName = GetFilterName();
1036 switch( mpCurTheme->GetObjectKind( mnCurActionPos ) )
1038 case SgaObjKind::Bitmap:
1039 case SgaObjKind::Animation:
1040 case SgaObjKind::Inet:
1041 // TODO drawing objects are inserted as drawings only via drag&drop
1042 case SgaObjKind::SvDraw:
1043 nType = css::gallery::GalleryItemType::GRAPHIC;
1044 break;
1046 case SgaObjKind::Sound :
1047 nType = css::gallery::GalleryItemType::MEDIA;
1048 break;
1050 default:
1051 nType = css::gallery::GalleryItemType::EMPTY;
1052 break;
1055 Graphic aGraphic;
1056 bool bGraphic = mpCurTheme->GetGraphic( mnCurActionPos, aGraphic );
1057 if ( bGraphic && !aGraphic.IsNone() )
1058 xGraphic.set( aGraphic.GetXGraphic() );
1059 OSL_ENSURE( xGraphic.is(), "gallery item is graphic, but the reference is invalid!" );
1061 css::uno::Sequence< css::beans::PropertyValue > aSeq( SVXGALLERYITEM_PARAMS );
1063 aSeq[0].Name = SVXGALLERYITEM_TYPE;
1064 aSeq[0].Value <<= nType;
1065 aSeq[1].Name = SVXGALLERYITEM_URL;
1066 aSeq[1].Value <<= OUString();
1067 aSeq[2].Name = SVXGALLERYITEM_FILTER;
1068 aSeq[2].Value <<= aFilterName;
1069 aSeq[3].Name = SVXGALLERYITEM_DRAWING;
1070 aSeq[3].Value <<= xDrawing;
1071 aSeq[4].Name = SVXGALLERYITEM_GRAPHIC;
1072 aSeq[4].Value <<= xGraphic;
1074 css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 );
1075 aArgs[0].Name = SVXGALLERYITEM_ARGNAME;
1076 aArgs[0].Value <<= aSeq;
1078 std::unique_ptr<DispatchInfo> pInfo(new DispatchInfo);
1079 pInfo->TargetURL = aURL;
1080 pInfo->Arguments = aArgs;
1081 pInfo->Dispatch = xDispatch;
1083 if ( Application::PostUserEvent(
1084 LINK( nullptr, GalleryBrowser2, AsyncDispatch_Impl), pInfo.get() ) )
1085 pInfo.release();
1088 void GalleryBrowser2::Execute(const OString &rIdent)
1090 Point aSelPos;
1091 const sal_uInt32 nItemId = ImplGetSelectedItemId( nullptr, aSelPos );
1093 if( mpCurTheme && nItemId )
1095 mnCurActionPos = nItemId - 1;
1097 if (rIdent == "preview")
1098 SetMode( ( GALLERYBROWSERMODE_PREVIEW != GetMode() ) ? GALLERYBROWSERMODE_PREVIEW : meLastMode );
1099 else if (rIdent == "delete")
1101 if (!mpCurTheme->IsReadOnly())
1103 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "svx/ui/querydeleteobjectdialog.ui"));
1104 std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryDeleteObjectDialog"));
1105 if (xQuery->run() == RET_YES)
1107 mpCurTheme->RemoveObject( mnCurActionPos );
1111 else if (rIdent == "title")
1113 std::unique_ptr<SgaObject> pObj = mpCurTheme->AcquireObject( mnCurActionPos );
1115 if( pObj )
1117 const OUString aOldTitle( GetItemText( *pObj, GalleryItemFlags::Title ) );
1119 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1120 ScopedVclPtr<AbstractTitleDialog> aDlg(pFact->CreateTitleDialog(GetFrameWeld(), aOldTitle));
1121 if( aDlg->Execute() == RET_OK )
1123 OUString aNewTitle( aDlg->GetTitle() );
1125 if( ( aNewTitle.isEmpty() && !pObj->GetTitle().isEmpty() ) || ( aNewTitle != aOldTitle ) )
1127 if( aNewTitle.isEmpty() )
1128 aNewTitle = "__<empty>__";
1130 pObj->SetTitle( aNewTitle );
1131 mpCurTheme->InsertObject( *pObj );
1136 else if (rIdent == "copy")
1138 vcl::Window* pWindow;
1140 switch( GetMode() )
1142 case GALLERYBROWSERMODE_ICON: pWindow = mpIconView; break;
1143 case GALLERYBROWSERMODE_LIST: pWindow = mpListView; break;
1144 case GALLERYBROWSERMODE_PREVIEW: pWindow = mpPreview; break;
1146 default:
1147 pWindow = nullptr;
1148 break;
1151 mpCurTheme->CopyToClipboard( pWindow, mnCurActionPos );
1153 else if (rIdent == "paste")
1155 if( !mpCurTheme->IsReadOnly() )
1157 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( this ) );
1158 mpCurTheme->InsertTransferable( aDataHelper.GetTransferable(), mnCurActionPos );
1164 OUString GalleryBrowser2::GetItemText( const SgaObject& rObj, GalleryItemFlags nItemTextFlags )
1166 OUString aRet;
1168 const INetURLObject& aURL(rObj.GetURL());
1170 if( nItemTextFlags & GalleryItemFlags::Title )
1172 OUString aTitle( rObj.GetTitle() );
1174 if( aTitle.isEmpty() )
1175 aTitle = aURL.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::Unambiguous );
1177 if( aTitle.isEmpty() )
1179 aTitle = aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous );
1180 aTitle = aTitle.copy( aTitle.lastIndexOf('/')+1 );
1183 aRet += aTitle;
1186 if( nItemTextFlags & GalleryItemFlags::Path )
1188 const OUString aPath( aURL.getFSysPath( FSysStyle::Detect ) );
1190 if( !aPath.isEmpty() && ( nItemTextFlags & GalleryItemFlags::Title ) )
1191 aRet += " (";
1193 aRet += aURL.getFSysPath( FSysStyle::Detect );
1195 if( !aPath.isEmpty() && ( nItemTextFlags & GalleryItemFlags::Title ) )
1196 aRet += ")";
1199 return aRet;
1202 INetURLObject GalleryBrowser2::GetURL() const
1204 INetURLObject aURL;
1206 if( mpCurTheme && mnCurActionPos != 0xffffffff )
1207 aURL = mpCurTheme->GetObjectURL( mnCurActionPos );
1209 return aURL;
1212 OUString GalleryBrowser2::GetFilterName() const
1214 OUString aFilterName;
1216 if( mpCurTheme && mnCurActionPos != 0xffffffff )
1218 const SgaObjKind eObjKind = mpCurTheme->GetObjectKind( mnCurActionPos );
1220 if( ( SgaObjKind::Bitmap == eObjKind ) || ( SgaObjKind::Animation == eObjKind ) )
1222 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
1223 INetURLObject aURL;
1224 mpCurTheme->GetURL( mnCurActionPos, aURL );
1225 sal_uInt16 nFilter = rFilter.GetImportFormatNumberForShortName(aURL.GetFileExtension());
1227 if( GRFILTER_FORMAT_DONTKNOW != nFilter )
1228 aFilterName = rFilter.GetImportFormatName( nFilter );
1232 return aFilterName;
1236 IMPL_LINK_NOARG(GalleryBrowser2, SelectObjectValueSetHdl, ValueSet*, void)
1238 ImplUpdateInfoBar();
1241 IMPL_LINK_NOARG(GalleryBrowser2, SelectObjectHdl, GalleryListView*, void)
1243 ImplUpdateInfoBar();
1246 IMPL_LINK( GalleryBrowser2, SelectTbxHdl, ToolBox*, pBox, void )
1248 if( pBox->GetCurItemId() == TBX_ID_ICON )
1249 SetMode( GALLERYBROWSERMODE_ICON );
1250 else if( pBox->GetCurItemId() == TBX_ID_LIST )
1251 SetMode( GALLERYBROWSERMODE_LIST );
1254 IMPL_LINK_NOARG(GalleryBrowser2, MiscHdl, LinkParamNone*, void)
1256 maViewBox->SetOutStyle( maMiscOptions.GetToolboxStyle() );
1258 BitmapEx aIconBmpEx(RID_SVXBMP_GALLERY_VIEW_ICON);
1259 BitmapEx aListBmpEx(RID_SVXBMP_GALLERY_VIEW_LIST);
1261 if( maMiscOptions.AreCurrentSymbolsLarge() )
1263 const Size aLargeSize( 24, 24);
1265 aIconBmpEx.Scale( aLargeSize );
1266 aListBmpEx.Scale( aLargeSize );
1269 maViewBox->SetItemImage(TBX_ID_ICON, Image(aIconBmpEx));
1270 maViewBox->SetItemImage(TBX_ID_LIST, Image(aListBmpEx));
1271 maViewBox->SetSizePixel( maViewBox->CalcWindowSizePixel() );
1273 Resize();
1276 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */