1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <sal/config.h>
22 #include <comphelper/processfactory.hxx>
23 #include <tools/datetime.hxx>
24 #include <unotools/datetime.hxx>
25 #include <vcl/commandevent.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/weld.hxx>
30 #include <ucbhelper/content.hxx>
31 #include <com/sun/star/ucb/ContentCreationException.hpp>
32 #include <sfx2/app.hxx>
34 #include <svx/gallery1.hxx>
35 #include <svx/galtheme.hxx>
36 #include <svx/galmisc.hxx>
37 #include "galbrws1.hxx"
38 #include <com/sun/star/util/DateTime.hpp>
39 #include <svx/strings.hrc>
41 #include <svx/dialmgr.hxx>
43 #include <svx/svxdlg.hxx>
45 #include <bitmaps.hlst>
47 using namespace ::com::sun::star
;
50 GalleryButton::GalleryButton( GalleryBrowser1
* pParent
, WinBits nWinBits
) :
51 PushButton( pParent
, nWinBits
)
55 void GalleryButton::KeyInput( const KeyEvent
& rKEvt
)
57 if( !static_cast< GalleryBrowser1
* >( GetParent() )->KeyInput( rKEvt
, this ) )
58 PushButton::KeyInput( rKEvt
);
62 GalleryThemeListBox::GalleryThemeListBox( GalleryBrowser1
* pParent
, WinBits nWinBits
) :
63 ListBox( pParent
, nWinBits
)
68 void GalleryThemeListBox::InitSettings()
70 SetBackground( Wallpaper( GALLERY_BG_COLOR
) );
71 SetControlBackground( GALLERY_BG_COLOR
);
72 SetControlForeground( GALLERY_FG_COLOR
);
75 void GalleryThemeListBox::DataChanged( const DataChangedEvent
& rDCEvt
)
77 if ( ( rDCEvt
.GetType() == DataChangedEventType::SETTINGS
) && ( rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
) )
80 ListBox::DataChanged( rDCEvt
);
83 bool GalleryThemeListBox::PreNotify( NotifyEvent
& rNEvt
)
87 if( rNEvt
.GetType() == MouseNotifyEvent::COMMAND
)
89 const CommandEvent
* pCEvt
= rNEvt
.GetCommandEvent();
91 if( pCEvt
&& pCEvt
->GetCommand() == CommandEventId::ContextMenu
)
92 static_cast< GalleryBrowser1
* >( GetParent() )->ShowContextMenu();
94 else if( rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
)
96 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
99 bDone
= static_cast< GalleryBrowser1
* >( GetParent() )->KeyInput( *pKEvt
, this );
102 return( bDone
|| ListBox::PreNotify( rNEvt
) );
106 GalleryBrowser1::GalleryBrowser1(
107 vcl::Window
* pParent
,
109 const std::function
<sal_Bool (const KeyEvent
&,Window
*)>& rKeyInputHandler
,
110 const std::function
<void ()>& rThemeSlectionHandler
)
112 Control ( pParent
, WB_TABSTOP
),
113 maNewTheme ( VclPtr
<GalleryButton
>::Create(this, WB_3DLOOK
) ),
114 mpThemes ( VclPtr
<GalleryThemeListBox
>::Create( this, WB_TABSTOP
| WB_3DLOOK
| WB_BORDER
| WB_HSCROLL
| WB_VSCROLL
| WB_AUTOHSCROLL
| WB_SORT
) ),
115 mpGallery ( pGallery
),
116 mpExchangeData ( new ExchangeData
),
117 aImgNormal ( GalleryResGetBitmapEx( RID_SVXBMP_THEME_NORMAL
) ),
118 aImgDefault ( GalleryResGetBitmapEx( RID_SVXBMP_THEME_DEFAULT
) ),
119 aImgReadOnly ( GalleryResGetBitmapEx( RID_SVXBMP_THEME_READONLY
) ),
120 maKeyInputHandler(rKeyInputHandler
),
121 maThemeSlectionHandler(rThemeSlectionHandler
)
123 StartListening( *mpGallery
);
125 maNewTheme
->SetHelpId( HID_GALLERY_NEWTHEME
);
126 maNewTheme
->SetText( SvxResId(RID_SVXSTR_GALLERY_CREATETHEME
));
127 maNewTheme
->SetClickHdl( LINK( this, GalleryBrowser1
, ClickNewThemeHdl
) );
129 // disable creation of new themes if a writable directory is not available
130 if( mpGallery
->GetUserURL().GetProtocol() == INetProtocol::NotValid
)
131 maNewTheme
->Disable();
133 mpThemes
->SetHelpId( HID_GALLERY_THEMELIST
);
134 mpThemes
->SetSelectHdl( LINK( this, GalleryBrowser1
, SelectThemeHdl
) );
135 mpThemes
->SetAccessibleName(SvxResId(RID_SVXSTR_GALLERYPROPS_GALTHEME
));
137 for( sal_uIntPtr i
= 0, nCount
= mpGallery
->GetThemeCount(); i
< nCount
; i
++ )
138 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( i
) );
140 ImplAdjustControls();
145 GalleryBrowser1::~GalleryBrowser1()
150 void GalleryBrowser1::dispose()
152 EndListening( *mpGallery
);
153 mpThemePropertiesDialog
.clear();
154 mpThemes
.disposeAndClear();
155 mpExchangeData
.reset();
156 maNewTheme
.disposeAndClear();
160 sal_uIntPtr
GalleryBrowser1::ImplInsertThemeEntry( const GalleryThemeEntry
* pEntry
)
162 static const bool bShowHiddenThemes
= ( getenv( "GALLERY_SHOW_HIDDEN_THEMES" ) != nullptr );
164 sal_uIntPtr nRet
= LISTBOX_ENTRY_NOTFOUND
;
166 if( pEntry
&& ( !pEntry
->IsHidden() || bShowHiddenThemes
) )
170 if( pEntry
->IsReadOnly() )
171 pImage
= &aImgReadOnly
;
172 else if( pEntry
->IsDefault() )
173 pImage
= &aImgDefault
;
175 pImage
= &aImgNormal
;
177 nRet
= mpThemes
->InsertEntry( pEntry
->GetThemeName(), *pImage
);
183 void GalleryBrowser1::ImplAdjustControls()
185 const Size
aOutSize( GetOutputSizePixel() );
186 const long nNewThemeHeight
= LogicToPixel(Size(0, 14), MapMode(MapUnit::MapAppFont
)).Height();
187 const long nStartY
= nNewThemeHeight
+ 4;
189 maNewTheme
->SetPosSizePixel( Point(),
190 Size( aOutSize
.Width(), nNewThemeHeight
) );
192 mpThemes
->SetPosSizePixel( Point( 0, nStartY
),
193 Size( aOutSize
.Width(), aOutSize
.Height() - nStartY
) );
196 void GalleryBrowser1::ImplFillExchangeData( const GalleryTheme
* pThm
, ExchangeData
& rData
)
198 rData
.pTheme
= const_cast<GalleryTheme
*>(pThm
);
199 rData
.aEditedTitle
= pThm
->GetName();
203 ::ucbhelper::Content
aCnt( pThm
->GetThmURL().GetMainURL( INetURLObject::DecodeMechanism::NONE
), uno::Reference
< ucb::XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
204 util::DateTime aDateTimeModified
;
205 DateTime
aDateTime( DateTime::EMPTY
);
207 aCnt
.getPropertyValue("DateModified") >>= aDateTimeModified
;
208 ::utl::typeConvert( aDateTimeModified
, aDateTime
);
209 rData
.aThemeChangeDate
= aDateTime
;
210 rData
.aThemeChangeTime
= aDateTime
;
212 catch( const ucb::ContentCreationException
& )
215 catch( const uno::RuntimeException
& )
218 catch( const uno::Exception
& )
223 void GalleryBrowser1::ImplGetExecuteVector(std::vector
<OString
>& o_aExec
)
225 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
229 bool bUpdateAllowed
, bRenameAllowed
, bRemoveAllowed
;
230 static const bool bIdDialog
= ( getenv( "GALLERY_ENABLE_ID_DIALOG" ) != nullptr );
232 if( pTheme
->IsReadOnly() )
233 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= false;
234 else if( pTheme
->IsDefault() )
236 bUpdateAllowed
= bRenameAllowed
= true;
237 bRemoveAllowed
= false;
240 bUpdateAllowed
= bRenameAllowed
= bRemoveAllowed
= true;
242 if( bUpdateAllowed
&& pTheme
->GetObjectCount() )
243 o_aExec
.emplace_back("update");
246 o_aExec
.emplace_back("rename");
249 o_aExec
.emplace_back("delete");
251 if( bIdDialog
&& !pTheme
->IsReadOnly() )
252 o_aExec
.emplace_back("assign");
254 o_aExec
.emplace_back("properties");
256 mpGallery
->ReleaseTheme( pTheme
, *this );
260 void GalleryBrowser1::ImplGalleryThemeProperties( const OUString
& rThemeName
, bool bCreateNew
)
262 DBG_ASSERT(!mpThemePropsDlgItemSet
, "mpThemePropsDlgItemSet already set!");
263 mpThemePropsDlgItemSet
.reset(new SfxItemSet( SfxGetpApp()->GetPool() ));
264 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( rThemeName
, *this );
266 ImplFillExchangeData( pTheme
, *mpExchangeData
);
268 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
269 mpThemePropertiesDialog
= pFact
->CreateGalleryThemePropertiesDialog(GetFrameWeld(), mpExchangeData
.get(), mpThemePropsDlgItemSet
.get());
273 mpThemePropertiesDialog
->StartExecuteAsync([this](sal_Int32 nResult
){
274 EndNewThemePropertiesDlgHdl(nResult
);
279 mpThemePropertiesDialog
->StartExecuteAsync([this](sal_Int32 nResult
){
280 EndThemePropertiesDlgHdl(nResult
);
285 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew
, sal_Int32 nRet
)
289 OUString
aName( mpExchangeData
->pTheme
->GetName() );
291 if( !mpExchangeData
->aEditedTitle
.isEmpty() && aName
!= mpExchangeData
->aEditedTitle
)
293 OUString
aTitle( mpExchangeData
->aEditedTitle
);
294 sal_uInt16 nCount
= 0;
296 while( mpGallery
->HasTheme( aTitle
) && ( nCount
++ < 16000 ) )
298 aTitle
= mpExchangeData
->aEditedTitle
+ " " + OUString::number( nCount
);
301 mpGallery
->RenameTheme( aName
, aTitle
);
306 mpThemes
->SelectEntry( mpExchangeData
->pTheme
->GetName() );
307 SelectThemeHdl( *mpThemes
);
311 OUString
aThemeName( mpExchangeData
->pTheme
->GetName() );
312 mpGallery
->ReleaseTheme( mpExchangeData
->pTheme
, *this );
314 if ( bCreateNew
&& ( nRet
!= RET_OK
) )
316 mpGallery
->RemoveTheme( aThemeName
);
319 // destroy mpThemeProps asynchronously
320 Application::PostUserEvent( LINK( this, GalleryBrowser1
, DestroyThemePropertiesDlgHdl
), nullptr, true );
323 void GalleryBrowser1::EndNewThemePropertiesDlgHdl(sal_Int32 nResult
)
325 ImplEndGalleryThemeProperties(true, nResult
);
328 void GalleryBrowser1::EndThemePropertiesDlgHdl(sal_Int32 nResult
)
330 ImplEndGalleryThemeProperties(false, nResult
);
333 IMPL_LINK( GalleryBrowser1
, DestroyThemePropertiesDlgHdl
, void*, /*p*/, void )
335 mpThemePropertiesDialog
.disposeAndClear();
336 mpThemePropsDlgItemSet
.reset();
339 void GalleryBrowser1::ImplExecute(const OString
&rIdent
)
341 if (rIdent
== "update")
343 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
345 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
346 ScopedVclPtr
<VclAbstractDialog
> aActualizeProgress(pFact
->CreateActualizeProgressDialog(GetFrameWeld(), pTheme
));
348 aActualizeProgress
->Execute();
349 mpGallery
->ReleaseTheme( pTheme
, *this );
351 else if (rIdent
== "delete")
353 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(GetFrameWeld(), "svx/ui/querydeletethemedialog.ui"));
354 std::unique_ptr
<weld::MessageDialog
> xQuery(xBuilder
->weld_message_dialog("QueryDeleteThemeDialog"));
355 if (xQuery
->run() == RET_YES
)
356 mpGallery
->RemoveTheme( mpThemes
->GetSelectedEntry() );
358 else if (rIdent
== "rename")
360 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
361 const OUString
aOldName( pTheme
->GetName() );
363 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
364 ScopedVclPtr
<AbstractTitleDialog
> aDlg(pFact
->CreateTitleDialog(GetFrameWeld(), aOldName
));
366 if( aDlg
->Execute() == RET_OK
)
368 const OUString
aNewName( aDlg
->GetTitle() );
370 if( !aNewName
.isEmpty() && ( aNewName
!= aOldName
) )
372 OUString
aName( aNewName
);
373 sal_uInt16 nCount
= 0;
375 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
377 aName
= aNewName
+ " " + OUString::number( nCount
);
380 mpGallery
->RenameTheme( aOldName
, aName
);
383 mpGallery
->ReleaseTheme( pTheme
, *this );
385 else if (rIdent
== "assign")
387 GalleryTheme
* pTheme
= mpGallery
->AcquireTheme( GetSelectedTheme(), *this );
389 if (pTheme
&& !pTheme
->IsReadOnly())
392 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
393 ScopedVclPtr
<AbstractGalleryIdDialog
> aDlg(pFact
->CreateGalleryIdDialog(GetFrameWeld(), pTheme
));
394 if( aDlg
->Execute() == RET_OK
)
395 pTheme
->SetId( aDlg
->GetId(), true );
398 mpGallery
->ReleaseTheme( pTheme
, *this );
400 else if (rIdent
== "properties")
402 ImplGalleryThemeProperties( GetSelectedTheme(), false );
406 void GalleryBrowser1::Resize()
409 ImplAdjustControls();
412 void GalleryBrowser1::GetFocus()
415 if( maNewTheme
->IsEnabled() )
416 maNewTheme
->GrabFocus();
418 mpThemes
->GrabFocus();
421 void GalleryBrowser1::Notify( SfxBroadcaster
&, const SfxHint
& rHint
)
423 const GalleryHint
& rGalleryHint
= static_cast<const GalleryHint
&>(rHint
);
425 switch( rGalleryHint
.GetType() )
427 case GalleryHintType::THEME_CREATED
:
428 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetThemeName() ) );
431 case GalleryHintType::THEME_RENAMED
:
433 const sal_Int32 nCurSelectPos
= mpThemes
->GetSelectedEntryPos();
434 const sal_Int32 nRenameEntryPos
= mpThemes
->GetEntryPos( rGalleryHint
.GetThemeName() );
436 mpThemes
->RemoveEntry( rGalleryHint
.GetThemeName() );
437 ImplInsertThemeEntry( mpGallery
->GetThemeInfo( rGalleryHint
.GetStringData() ) );
439 if( nCurSelectPos
== nRenameEntryPos
)
441 mpThemes
->SelectEntry( rGalleryHint
.GetStringData() );
442 SelectThemeHdl( *mpThemes
);
447 case GalleryHintType::THEME_REMOVED
:
449 mpThemes
->RemoveEntry( rGalleryHint
.GetThemeName() );
453 case GalleryHintType::CLOSE_THEME
:
455 const sal_Int32 nCurSelectPos
= mpThemes
->GetSelectedEntryPos();
456 const sal_Int32 nCloseEntryPos
= mpThemes
->GetEntryPos( rGalleryHint
.GetThemeName() );
458 if( nCurSelectPos
== nCloseEntryPos
)
460 if( nCurSelectPos
< ( mpThemes
->GetEntryCount() - 1 ) )
461 mpThemes
->SelectEntryPos( nCurSelectPos
+ 1 );
462 else if( nCurSelectPos
)
463 mpThemes
->SelectEntryPos( nCurSelectPos
- 1 );
465 mpThemes
->SetNoSelection();
467 SelectThemeHdl( *mpThemes
);
477 void GalleryBrowser1::ShowContextMenu()
479 Application::PostUserEvent( LINK( this, GalleryBrowser1
, ShowContextMenuHdl
), this, true );
482 bool GalleryBrowser1::KeyInput( const KeyEvent
& rKEvt
, vcl::Window
* pWindow
)
485 if (maKeyInputHandler
)
486 bRet
= maKeyInputHandler(rKEvt
, pWindow
);
490 std::vector
<OString
> aExecVector
;
491 ImplGetExecuteVector(aExecVector
);
492 OString sExecuteIdent
;
493 bool bMod1
= rKEvt
.GetKeyCode().IsMod1();
495 switch( rKEvt
.GetKeyCode().GetCode() )
498 ClickNewThemeHdl( nullptr );
504 ClickNewThemeHdl( nullptr );
511 sExecuteIdent
= "update";
516 sExecuteIdent
= "delete";
522 sExecuteIdent
= "delete";
529 sExecuteIdent
= "rename";
536 sExecuteIdent
= "properties";
541 if (!sExecuteIdent
.isEmpty() && (std::find( aExecVector
.begin(), aExecVector
.end(), sExecuteIdent
) != aExecVector
.end()))
543 ImplExecute(sExecuteIdent
);
551 IMPL_LINK_NOARG(GalleryBrowser1
, ShowContextMenuHdl
, void*, void)
553 std::vector
<OString
> aExecVector
;
554 ImplGetExecuteVector(aExecVector
);
556 if( aExecVector
.empty() )
559 VclBuilder
aBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "svx/ui/gallerymenu1.ui", "");
560 VclPtr
<PopupMenu
> aMenu(aBuilder
.get_menu("menu"));
562 aMenu
->EnableItem( aMenu
->GetItemId("update"), std::find( aExecVector
.begin(), aExecVector
.end(), "update" ) != aExecVector
.end() );
563 aMenu
->EnableItem( aMenu
->GetItemId("rename"), std::find( aExecVector
.begin(), aExecVector
.end(), "rename" ) != aExecVector
.end() );
564 aMenu
->EnableItem( aMenu
->GetItemId("delete"), std::find( aExecVector
.begin(), aExecVector
.end(), "delete" ) != aExecVector
.end() );
565 aMenu
->EnableItem( aMenu
->GetItemId("assign"), std::find( aExecVector
.begin(), aExecVector
.end(), "assign" ) != aExecVector
.end() );
566 aMenu
->EnableItem( aMenu
->GetItemId("properties"), std::find( aExecVector
.begin(), aExecVector
.end(), "properties" ) != aExecVector
.end() );
567 aMenu
->SetSelectHdl( LINK( this, GalleryBrowser1
, PopupMenuHdl
) );
568 aMenu
->RemoveDisabledEntries();
570 const tools::Rectangle
aThemesRect( mpThemes
->GetPosPixel(), mpThemes
->GetOutputSizePixel() );
571 Point
aSelPos( mpThemes
->GetBoundingRectangle( mpThemes
->GetSelectedEntryPos() ).Center() );
573 aSelPos
.setX( std::max( std::min( aSelPos
.X(), aThemesRect
.Right() ), aThemesRect
.Left() ) );
574 aSelPos
.setY( std::max( std::min( aSelPos
.Y(), aThemesRect
.Bottom() ), aThemesRect
.Top() ) );
576 aMenu
->Execute( this, aSelPos
);
579 IMPL_LINK( GalleryBrowser1
, PopupMenuHdl
, Menu
*, pMenu
, bool )
581 ImplExecute(pMenu
->GetCurItemIdent());
585 IMPL_LINK_NOARG(GalleryBrowser1
, SelectThemeHdl
, ListBox
&, void)
587 if (maThemeSlectionHandler
)
588 maThemeSlectionHandler();
591 IMPL_LINK_NOARG(GalleryBrowser1
, ClickNewThemeHdl
, Button
*, void)
593 OUString
aNewTheme( SvxResId(RID_SVXSTR_GALLERY_NEWTHEME
) );
594 OUString
aName( aNewTheme
);
595 sal_uIntPtr nCount
= 0;
597 while( mpGallery
->HasTheme( aName
) && ( nCount
++ < 16000 ) )
599 aName
= aNewTheme
+ " " + OUString::number( nCount
);
602 if( !mpGallery
->HasTheme( aName
) && mpGallery
->CreateTheme( aName
) )
604 ImplGalleryThemeProperties( aName
, true );
608 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */