Bump version to 6.4-15
[LibreOffice.git] / svx / source / gallery2 / galbrws1.cxx
blob6754f8feab42d7c4af734e2630dbc99ff57f75bc
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 .
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>
33 #include <helpids.h>
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>
40 #include <algorithm>
41 #include <svx/dialmgr.hxx>
43 #include <svx/svxdlg.hxx>
44 #include <memory>
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 )
65 InitSettings();
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 ) )
78 InitSettings();
79 else
80 ListBox::DataChanged( rDCEvt );
83 bool GalleryThemeListBox::PreNotify( NotifyEvent& rNEvt )
85 bool bDone = false;
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();
98 if( pKEvt )
99 bDone = static_cast< GalleryBrowser1* >( GetParent() )->KeyInput( *pKEvt, this );
102 return( bDone || ListBox::PreNotify( rNEvt ) );
106 GalleryBrowser1::GalleryBrowser1(
107 vcl::Window* pParent,
108 Gallery* pGallery,
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();
141 maNewTheme->Show();
142 mpThemes->Show();
145 GalleryBrowser1::~GalleryBrowser1()
147 disposeOnce();
150 void GalleryBrowser1::dispose()
152 EndListening( *mpGallery );
153 mpThemePropertiesDialog.clear();
154 mpThemes.disposeAndClear();
155 mpExchangeData.reset();
156 maNewTheme.disposeAndClear();
157 Control::dispose();
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 ) )
168 const Image* pImage;
170 if( pEntry->IsReadOnly() )
171 pImage = &aImgReadOnly;
172 else if( pEntry->IsDefault() )
173 pImage = &aImgDefault;
174 else
175 pImage = &aImgNormal;
177 nRet = mpThemes->InsertEntry( pEntry->GetThemeName(), *pImage );
180 return nRet;
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 );
227 if( pTheme )
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;
239 else
240 bUpdateAllowed = bRenameAllowed = bRemoveAllowed = true;
242 if( bUpdateAllowed && pTheme->GetObjectCount() )
243 o_aExec.emplace_back("update");
245 if( bRenameAllowed )
246 o_aExec.emplace_back("rename");
248 if( bRemoveAllowed )
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());
271 if ( bCreateNew )
273 mpThemePropertiesDialog->StartExecuteAsync([this](sal_Int32 nResult){
274 EndNewThemePropertiesDlgHdl(nResult);
277 else
279 mpThemePropertiesDialog->StartExecuteAsync([this](sal_Int32 nResult){
280 EndThemePropertiesDlgHdl(nResult);
285 void GalleryBrowser1::ImplEndGalleryThemeProperties(bool bCreateNew, sal_Int32 nRet)
287 if( nRet == RET_OK )
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 );
304 if ( bCreateNew )
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()
408 Control::Resize();
409 ImplAdjustControls();
412 void GalleryBrowser1::GetFocus()
414 Control::GetFocus();
415 if( maNewTheme->IsEnabled() )
416 maNewTheme->GrabFocus();
417 else
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() ) );
429 break;
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 );
445 break;
447 case GalleryHintType::THEME_REMOVED:
449 mpThemes->RemoveEntry( rGalleryHint.GetThemeName() );
451 break;
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 );
464 else
465 mpThemes->SetNoSelection();
467 SelectThemeHdl( *mpThemes );
470 break;
472 default:
473 break;
477 void GalleryBrowser1::ShowContextMenu()
479 Application::PostUserEvent( LINK( this, GalleryBrowser1, ShowContextMenuHdl ), this, true );
482 bool GalleryBrowser1::KeyInput( const KeyEvent& rKEvt, vcl::Window* pWindow )
484 bool bRet = false;
485 if (maKeyInputHandler)
486 bRet = maKeyInputHandler(rKEvt, pWindow);
488 if( !bRet )
490 std::vector<OString> aExecVector;
491 ImplGetExecuteVector(aExecVector);
492 OString sExecuteIdent;
493 bool bMod1 = rKEvt.GetKeyCode().IsMod1();
495 switch( rKEvt.GetKeyCode().GetCode() )
497 case KEY_INSERT:
498 ClickNewThemeHdl( nullptr );
499 break;
501 case KEY_I:
503 if( bMod1 )
504 ClickNewThemeHdl( nullptr );
506 break;
508 case KEY_U:
510 if( bMod1 )
511 sExecuteIdent = "update";
513 break;
515 case KEY_DELETE:
516 sExecuteIdent = "delete";
517 break;
519 case KEY_D:
521 if( bMod1 )
522 sExecuteIdent = "delete";
524 break;
526 case KEY_R:
528 if( bMod1 )
529 sExecuteIdent = "rename";
531 break;
533 case KEY_RETURN:
535 if( bMod1 )
536 sExecuteIdent = "properties";
538 break;
541 if (!sExecuteIdent.isEmpty() && (std::find( aExecVector.begin(), aExecVector.end(), sExecuteIdent) != aExecVector.end()))
543 ImplExecute(sExecuteIdent);
544 bRet = true;
548 return bRet;
551 IMPL_LINK_NOARG(GalleryBrowser1, ShowContextMenuHdl, void*, void)
553 std::vector<OString> aExecVector;
554 ImplGetExecuteVector(aExecVector);
556 if( aExecVector.empty() )
557 return;
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());
582 return false;
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: */