Bump version to 24.04.3.4
[LibreOffice.git] / basctl / source / basicide / baside3.cxx
blob4a6b1dfbfb5ce466404cee821cc1169ec4ad3aad
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 <strings.hrc>
21 #include <helpids.h>
22 #include <iderid.hxx>
24 #include <accessibledialogwindow.hxx>
25 #include <baside3.hxx>
26 #include <basidesh.hxx>
27 #include <bastype2.hxx>
28 #include <basobj.hxx>
29 #include <dlged.hxx>
30 #include <dlgeddef.hxx>
31 #include <dlgedmod.hxx>
32 #include <dlgedview.hxx>
33 #include <iderdll.hxx>
34 #include <localizationmgr.hxx>
35 #include <managelang.hxx>
37 #include <com/sun/star/script/XLibraryContainer2.hpp>
38 #include <com/sun/star/resource/StringResourceWithLocation.hpp>
39 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
40 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
41 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
42 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
43 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include <sfx2/filedlghelper.hxx>
47 #include <sfx2/request.hxx>
48 #include <sfx2/viewfrm.hxx>
49 #include <svl/visitem.hxx>
50 #include <svl/whiter.hxx>
51 #include <svx/svdundo.hxx>
52 #include <svx/svxids.hrc>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <tools/urlobj.hxx>
55 #include <vcl/commandevent.hxx>
56 #include <vcl/weld.hxx>
57 #include <vcl/settings.hxx>
58 #include <vcl/stdtext.hxx>
59 #include <vcl/svapp.hxx>
60 #include <xmlscript/xmldlg_imexp.hxx>
62 namespace basctl
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::ucb;
68 using namespace ::com::sun::star::io;
69 using namespace ::com::sun::star::resource;
70 using namespace ::com::sun::star::ui::dialogs;
72 #ifdef _WIN32
73 constexpr OUString FilterMask_All = u"*.*"_ustr;
74 #else
75 constexpr OUString FilterMask_All = u"*"_ustr;
76 #endif
78 DialogWindow::DialogWindow(DialogWindowLayout* pParent, ScriptDocument const& rDocument,
79 const OUString& aLibName, const OUString& aName,
80 css::uno::Reference<css::container::XNameContainer> const& xDialogModel)
81 : BaseWindow(pParent, rDocument, aLibName, aName)
82 ,m_rLayout(*pParent)
83 ,m_pEditor(new DlgEditor(*this, m_rLayout, rDocument.isDocument()
84 ? rDocument.getDocument()
85 : Reference<frame::XModel>(), xDialogModel))
86 ,m_pUndoMgr(new SfxUndoManager)
87 ,m_nControlSlotId(SID_INSERT_SELECT)
89 InitSettings();
91 m_pEditor->GetModel().SetNotifyUndoActionHdl(
92 &DialogWindow::NotifyUndoActionHdl
95 SetHelpId( HID_BASICIDE_DIALOGWINDOW );
97 // set readonly mode for readonly libraries
98 Reference< script::XLibraryContainer2 > xDlgLibContainer( GetDocument().getLibraryContainer( E_DIALOGS ), UNO_QUERY );
99 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aLibName ) && xDlgLibContainer->isLibraryReadOnly( aLibName ) )
100 SetReadOnly(true);
102 if ( rDocument.isDocument() && rDocument.isReadOnly() )
103 SetReadOnly(true);
106 void DialogWindow::dispose()
108 m_pEditor.reset();
109 BaseWindow::dispose();
112 void DialogWindow::LoseFocus()
114 if ( IsModified() )
115 StoreData();
117 Window::LoseFocus();
120 void DialogWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
122 m_pEditor->Paint(rRenderContext, rRect);
125 void DialogWindow::Resize()
127 if (GetHScrollBar() && GetVScrollBar())
129 m_pEditor->SetScrollBars( GetHScrollBar(), GetVScrollBar() );
133 void DialogWindow::MouseButtonDown( const MouseEvent& rMEvt )
135 m_pEditor->MouseButtonDown( rMEvt );
137 if (SfxBindings* pBindings = GetBindingsPtr())
138 pBindings->Invalidate( SID_SHOW_PROPERTYBROWSER );
141 void DialogWindow::MouseButtonUp( const MouseEvent& rMEvt )
143 m_pEditor->MouseButtonUp( rMEvt );
144 if( (m_pEditor->GetMode() == DlgEditor::INSERT) && !m_pEditor->IsCreateOK() )
146 m_nControlSlotId = SID_INSERT_SELECT;
147 m_pEditor->SetMode( DlgEditor::SELECT );
148 Shell::InvalidateControlSlots();
150 if (SfxBindings* pBindings = GetBindingsPtr())
152 pBindings->Invalidate( SID_SHOW_PROPERTYBROWSER );
153 pBindings->Invalidate( SID_DOC_MODIFIED );
154 pBindings->Invalidate( SID_SAVEDOC );
155 pBindings->Invalidate( SID_COPY );
156 pBindings->Invalidate( SID_CUT );
160 void DialogWindow::MouseMove( const MouseEvent& rMEvt )
162 m_pEditor->MouseMove( rMEvt );
165 void DialogWindow::KeyInput( const KeyEvent& rKEvt )
167 SfxBindings* pBindings = GetBindingsPtr();
169 if( rKEvt.GetKeyCode() == KEY_BACKSPACE )
171 if (SfxDispatcher* pDispatcher = GetDispatcher())
172 pDispatcher->Execute( SID_BACKSPACE );
174 else
176 if( pBindings && rKEvt.GetKeyCode() == KEY_TAB )
177 pBindings->Invalidate( SID_SHOW_PROPERTYBROWSER );
179 if( !m_pEditor->KeyInput( rKEvt ) )
181 if( !SfxViewShell::Current()->KeyInput( rKEvt ) )
182 Window::KeyInput( rKEvt );
186 // may be KEY_TAB, KEY_BACKSPACE, KEY_ESCAPE
187 if( pBindings )
189 pBindings->Invalidate( SID_COPY );
190 pBindings->Invalidate( SID_CUT );
194 void DialogWindow::Command( const CommandEvent& rCEvt )
196 if ( ( rCEvt.GetCommand() == CommandEventId::Wheel ) ||
197 ( rCEvt.GetCommand() == CommandEventId::StartAutoScroll ) ||
198 ( rCEvt.GetCommand() == CommandEventId::AutoScroll ) )
200 HandleScrollCommand( rCEvt, GetHScrollBar(), GetVScrollBar() );
202 else if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
204 if (GetDispatcher())
206 SdrView& rView = GetView();
207 if( !rCEvt.IsMouseEvent() && rView.AreObjectsMarked() )
209 tools::Rectangle aMarkedRect( rView.GetMarkedRect() );
210 Point MarkedCenter( aMarkedRect.Center() );
211 Point PosPixel( LogicToPixel( MarkedCenter ) );
212 SfxDispatcher::ExecutePopup( this, &PosPixel );
214 else
216 SfxDispatcher::ExecutePopup();
221 else
222 BaseWindow::Command( rCEvt );
226 void DialogWindow::NotifyUndoActionHdl( std::unique_ptr<SdrUndoAction> )
228 // #i120515# pUndoAction needs to be deleted, this hand over is an ownership
229 // change. As long as it does not get added to the undo manager, it needs at
230 // least to be deleted.
233 void DialogWindow::DoInit()
235 m_pEditor->SetScrollBars( GetHScrollBar(), GetVScrollBar() );
238 void DialogWindow::DoScroll( Scrollable* )
240 m_pEditor->DoScroll();
243 void DialogWindow::GetState( SfxItemSet& rSet )
245 SfxWhichIter aIter(rSet);
246 bool bIsCalc = false;
247 if ( GetDocument().isDocument() )
249 Reference< frame::XModel > xModel= GetDocument().getDocument();
250 if ( xModel.is() )
252 Reference< lang::XServiceInfo > xServiceInfo ( xModel, UNO_QUERY );
253 if ( xServiceInfo.is() && xServiceInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
254 bIsCalc = true;
258 for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich() )
260 switch ( nWh )
262 case SID_PASTE:
264 if ( !IsPasteAllowed() )
265 rSet.DisableItem( nWh );
267 if ( IsReadOnly() )
268 rSet.DisableItem( nWh );
270 break;
271 case SID_COPY:
273 // any object selected?
274 if ( !m_pEditor->GetView().AreObjectsMarked() )
275 rSet.DisableItem( nWh );
277 break;
278 case SID_CUT:
279 case SID_DELETE:
280 case SID_BACKSPACE:
282 // any object selected?
283 if ( !m_pEditor->GetView().AreObjectsMarked() )
284 rSet.DisableItem( nWh );
286 if ( IsReadOnly() )
287 rSet.DisableItem( nWh );
289 break;
290 case SID_REDO:
292 if ( !m_pUndoMgr->GetUndoActionCount() )
293 rSet.DisableItem( nWh );
295 break;
297 case SID_DIALOG_TESTMODE:
299 // is the IDE still active?
300 bool const bBool = GetShell()->GetFrame() &&
301 m_pEditor->GetMode() == DlgEditor::TEST;
302 rSet.Put(SfxBoolItem(SID_DIALOG_TESTMODE, bBool));
304 break;
306 case SID_CHOOSE_CONTROLS:
308 if ( IsReadOnly() )
309 rSet.DisableItem( nWh );
311 break;
313 case SID_SHOW_PROPERTYBROWSER:
315 Shell* pShell = GetShell();
316 SfxViewFrame* pViewFrame = pShell ? &pShell->GetViewFrame() : nullptr;
317 if ( pViewFrame && !pViewFrame->HasChildWindow( SID_SHOW_PROPERTYBROWSER ) && !m_pEditor->GetView().AreObjectsMarked() )
318 rSet.DisableItem( nWh );
320 if ( IsReadOnly() )
321 rSet.DisableItem( nWh );
323 break;
324 case SID_INSERT_FORM_RADIO:
325 case SID_INSERT_FORM_CHECK:
326 case SID_INSERT_FORM_LIST:
327 case SID_INSERT_FORM_COMBO:
328 case SID_INSERT_FORM_VSCROLL:
329 case SID_INSERT_FORM_HSCROLL:
330 case SID_INSERT_FORM_SPIN:
332 if ( !bIsCalc || IsReadOnly() )
333 rSet.DisableItem( nWh );
334 else
335 rSet.Put( SfxBoolItem( nWh, m_nControlSlotId == nWh ) );
337 break;
339 case SID_INSERT_SELECT:
340 case SID_INSERT_PUSHBUTTON:
341 case SID_INSERT_RADIOBUTTON:
342 case SID_INSERT_CHECKBOX:
343 case SID_INSERT_LISTBOX:
344 case SID_INSERT_COMBOBOX:
345 case SID_INSERT_GROUPBOX:
346 case SID_INSERT_EDIT:
347 case SID_INSERT_FIXEDTEXT:
348 case SID_INSERT_IMAGECONTROL:
349 case SID_INSERT_PROGRESSBAR:
350 case SID_INSERT_HSCROLLBAR:
351 case SID_INSERT_VSCROLLBAR:
352 case SID_INSERT_HFIXEDLINE:
353 case SID_INSERT_VFIXEDLINE:
354 case SID_INSERT_DATEFIELD:
355 case SID_INSERT_TIMEFIELD:
356 case SID_INSERT_NUMERICFIELD:
357 case SID_INSERT_CURRENCYFIELD:
358 case SID_INSERT_FORMATTEDFIELD:
359 case SID_INSERT_PATTERNFIELD:
360 case SID_INSERT_FILECONTROL:
361 case SID_INSERT_SPINBUTTON:
362 case SID_INSERT_GRIDCONTROL:
363 case SID_INSERT_HYPERLINKCONTROL:
364 case SID_INSERT_TREECONTROL:
366 if ( IsReadOnly() )
367 rSet.DisableItem( nWh );
368 else
369 rSet.Put( SfxBoolItem( nWh, m_nControlSlotId == nWh ) );
371 break;
372 case SID_SHOWLINES:
374 // if this is not a module window hide the
375 // setting, doesn't make sense for example if the
376 // dialog editor is open
377 rSet.DisableItem(nWh);
378 rSet.Put(SfxVisibilityItem(nWh, false));
379 break;
381 case SID_SELECTALL:
383 rSet.DisableItem( nWh );
385 break;
390 void DialogWindow::ExecuteCommand( SfxRequest& rReq )
392 const sal_uInt16 nSlotId(rReq.GetSlot());
393 SdrObjKind nInsertObj(SdrObjKind::NONE);
395 switch ( nSlotId )
397 case SID_CUT:
398 if ( !IsReadOnly() )
400 GetEditor().Cut();
401 if (SfxBindings* pBindings = GetBindingsPtr())
402 pBindings->Invalidate( SID_DOC_MODIFIED );
404 break;
405 case SID_DELETE:
406 if ( !IsReadOnly() )
408 GetEditor().Delete();
409 if (SfxBindings* pBindings = GetBindingsPtr())
410 pBindings->Invalidate( SID_DOC_MODIFIED );
412 break;
413 case SID_COPY:
414 GetEditor().Copy();
415 break;
416 case SID_PASTE:
417 if ( !IsReadOnly() )
419 GetEditor().Paste();
420 if (SfxBindings* pBindings = GetBindingsPtr())
421 pBindings->Invalidate( SID_DOC_MODIFIED );
423 break;
425 case SID_INSERT_FORM_RADIO:
426 nInsertObj = SdrObjKind::BasicDialogFormRadio;
427 break;
428 case SID_INSERT_FORM_CHECK:
429 nInsertObj = SdrObjKind::BasicDialogFormCheck;
430 break;
431 case SID_INSERT_FORM_LIST:
432 nInsertObj = SdrObjKind::BasicDialogFormList;
433 break;
434 case SID_INSERT_FORM_COMBO:
435 nInsertObj = SdrObjKind::BasicDialogFormCombo;
436 break;
437 case SID_INSERT_FORM_SPIN:
438 nInsertObj = SdrObjKind::BasicDialogFormSpin;
439 break;
440 case SID_INSERT_FORM_VSCROLL:
441 nInsertObj = SdrObjKind::BasicDialogFormVerticalScroll;
442 break;
443 case SID_INSERT_FORM_HSCROLL:
444 nInsertObj = SdrObjKind::BasicDialogFormHorizontalScroll;
445 break;
446 case SID_INSERT_PUSHBUTTON:
447 nInsertObj = SdrObjKind::BasicDialogPushButton;
448 break;
449 case SID_INSERT_RADIOBUTTON:
450 nInsertObj = SdrObjKind::BasicDialogRadioButton;
451 break;
452 case SID_INSERT_CHECKBOX:
453 nInsertObj = SdrObjKind::BasicDialogCheckbox;
454 break;
455 case SID_INSERT_LISTBOX:
456 nInsertObj = SdrObjKind::BasicDialogListbox;
457 break;
458 case SID_INSERT_COMBOBOX:
459 nInsertObj = SdrObjKind::BasicDialogCombobox;
460 break;
461 case SID_INSERT_GROUPBOX:
462 nInsertObj = SdrObjKind::BasicDialogGroupBox;
463 break;
464 case SID_INSERT_EDIT:
465 nInsertObj = SdrObjKind::BasicDialogEdit;
466 break;
467 case SID_INSERT_FIXEDTEXT:
468 nInsertObj = SdrObjKind::BasicDialogFixedText;
469 break;
470 case SID_INSERT_IMAGECONTROL:
471 nInsertObj = SdrObjKind::BasicDialogImageControl;
472 break;
473 case SID_INSERT_PROGRESSBAR:
474 nInsertObj = SdrObjKind::BasicDialogProgressbar;
475 break;
476 case SID_INSERT_HSCROLLBAR:
477 nInsertObj = SdrObjKind::BasicDialogHorizontalScrollbar;
478 break;
479 case SID_INSERT_VSCROLLBAR:
480 nInsertObj = SdrObjKind::BasicDialogVerticalScrollbar;
481 break;
482 case SID_INSERT_HFIXEDLINE:
483 nInsertObj = SdrObjKind::BasicDialogHorizontalFixedLine;
484 break;
485 case SID_INSERT_VFIXEDLINE:
486 nInsertObj = SdrObjKind::BasicDialogVerticalFixedLine;
487 break;
488 case SID_INSERT_DATEFIELD:
489 nInsertObj = SdrObjKind::BasicDialogDateField;
490 break;
491 case SID_INSERT_TIMEFIELD:
492 nInsertObj = SdrObjKind::BasicDialogTimeField;
493 break;
494 case SID_INSERT_NUMERICFIELD:
495 nInsertObj = SdrObjKind::BasicDialogNumericField;
496 break;
497 case SID_INSERT_CURRENCYFIELD:
498 nInsertObj = SdrObjKind::BasicDialogCurencyField;
499 break;
500 case SID_INSERT_FORMATTEDFIELD:
501 nInsertObj = SdrObjKind::BasicDialogFormattedField;
502 break;
503 case SID_INSERT_PATTERNFIELD:
504 nInsertObj = SdrObjKind::BasicDialogPatternField;
505 break;
506 case SID_INSERT_FILECONTROL:
507 nInsertObj = SdrObjKind::BasicDialogFileControl;
508 break;
509 case SID_INSERT_SPINBUTTON:
510 nInsertObj = SdrObjKind::BasicDialogSpinButton;
511 break;
512 case SID_INSERT_GRIDCONTROL:
513 nInsertObj = SdrObjKind::BasicDialogGridControl;
514 break;
515 case SID_INSERT_HYPERLINKCONTROL:
516 nInsertObj = SdrObjKind::BasicDialogHyperlinkControl;
517 break;
518 case SID_INSERT_TREECONTROL:
519 nInsertObj = SdrObjKind::BasicDialogTreeControl;
520 break;
521 case SID_INSERT_SELECT:
522 m_nControlSlotId = nSlotId;
523 GetEditor().SetMode( DlgEditor::SELECT );
524 Shell::InvalidateControlSlots();
525 break;
527 case SID_DIALOG_TESTMODE:
529 DlgEditor::Mode eOldMode = GetEditor().GetMode();
530 GetEditor().SetMode( DlgEditor::TEST );
531 GetEditor().SetMode( eOldMode );
532 rReq.Done();
533 if (SfxBindings* pBindings = GetBindingsPtr())
534 pBindings->Invalidate( SID_DIALOG_TESTMODE );
535 return;
537 case SID_EXPORT_DIALOG:
538 SaveDialog();
539 break;
541 case SID_IMPORT_DIALOG:
542 ImportDialog();
543 break;
545 case SID_BASICIDE_DELETECURRENT:
546 if (QueryDelDialog(m_aName, GetFrameWeld()))
548 if (RemoveDialog(m_aDocument, m_aLibName, m_aName))
550 MarkDocumentModified(m_aDocument);
551 GetShell()->RemoveWindow(this, true);
554 break;
557 if ( nInsertObj != SdrObjKind::NONE )
559 m_nControlSlotId = nSlotId;
560 GetEditor().SetMode( DlgEditor::INSERT );
561 GetEditor().SetInsertObj( nInsertObj );
563 if ( rReq.GetModifier() & KEY_MOD1 )
565 GetEditor().CreateDefaultObject();
566 if (SfxBindings* pBindings = GetBindingsPtr())
567 pBindings->Invalidate( SID_DOC_MODIFIED );
570 Shell::InvalidateControlSlots();
573 rReq.Done();
576 Reference< container::XNameContainer > const & DialogWindow::GetDialog() const
578 return m_pEditor->GetDialog();
581 bool DialogWindow::RenameDialog( const OUString& rNewName )
583 if (!basctl::RenameDialog(GetFrameWeld(), GetDocument(), GetLibName(), GetName(), rNewName))
584 return false;
586 if (SfxBindings* pBindings = GetBindingsPtr())
587 pBindings->Invalidate( SID_DOC_MODIFIED );
589 return true;
592 void DialogWindow::DisableBrowser()
594 m_rLayout.DisablePropertyBrowser();
597 void DialogWindow::UpdateBrowser()
599 m_rLayout.UpdatePropertyBrowser();
602 void DialogWindow::SaveDialog()
604 sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
605 FileDialogFlags::NONE, this->GetFrameWeld());
606 aDlg.SetContext(sfx2::FileDialogHelper::BasicExportDialog);
607 Reference<XFilePicker3> xFP = aDlg.GetFilePicker();
609 xFP.queryThrow<XFilePickerControlAccess>()->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, Any(true));
610 xFP->setDefaultName( GetName() );
612 OUString aDialogStr(IDEResId(RID_STR_STDDIALOGNAME));
613 xFP->appendFilter( aDialogStr, "*.xdl" );
614 xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
615 xFP->setCurrentFilter( aDialogStr );
617 if( aDlg.Execute() != ERRCODE_NONE )
618 return;
620 OUString aSelectedFileURL = xFP->getSelectedFiles()[0];
622 Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
623 Reference< XSimpleFileAccess3 > xSFI( SimpleFileAccess::create(xContext) );
625 Reference< XOutputStream > xOutput;
628 if( xSFI->exists(aSelectedFileURL) )
629 xSFI->kill(aSelectedFileURL);
630 xOutput = xSFI->openFileWrite(aSelectedFileURL);
632 catch(const Exception& )
635 if (!xOutput)
637 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
638 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTWRITE)));
639 xBox->run();
640 return;
643 // export dialog model to xml
644 auto xInput(xmlscript::exportDialogModel(GetDialog(), xContext, GetDocument().getDocumentOrNull())->createInputStream());
646 for (Sequence<sal_Int8> bytes; xInput->readBytes(bytes, xInput->available());)
647 xOutput->writeBytes(bytes);
649 // With resource?
650 Reference< resource::XStringResourceResolver > xStringResourceResolver;
651 if (auto xDialogModelPropSet = GetDialog().query<beans::XPropertySet>())
655 Any aResourceResolver = xDialogModelPropSet->getPropertyValue( "ResourceResolver" );
656 aResourceResolver >>= xStringResourceResolver;
658 catch(const beans::UnknownPropertyException& )
662 Sequence<lang::Locale> aLocaleSeq;
663 if (xStringResourceResolver)
664 aLocaleSeq = xStringResourceResolver->getLocales();
665 if (aLocaleSeq.hasElements())
667 INetURLObject aURLObj(aSelectedFileURL);
668 aURLObj.removeExtension();
669 OUString aDialogName( aURLObj.getName() );
670 aURLObj.removeSegment();
671 OUString aURL( aURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
672 OUString aComment = "# " + aDialogName + " strings" ;
673 Reference< task::XInteractionHandler > xDummyHandler;
675 // Remove old properties files in case of overwriting Dialog files
676 if( xSFI->isFolder( aURL ) )
678 Sequence< OUString > aContentSeq = xSFI->getFolderContents( aURL, false );
680 OUString aDialogName_ = aDialogName + "_" ;
681 for( const OUString& rCompleteName : aContentSeq )
683 OUString aPureName;
684 OUString aExtension;
685 sal_Int32 iDot = rCompleteName.lastIndexOf( '.' );
686 if( iDot != -1 )
688 sal_Int32 iSlash = rCompleteName.lastIndexOf( '/' );
689 sal_Int32 iCopyFrom = (iSlash != -1) ? iSlash + 1 : 0;
690 aPureName = rCompleteName.copy( iCopyFrom, iDot-iCopyFrom );
691 aExtension = rCompleteName.copy( iDot + 1 );
694 if( aExtension == "properties" || aExtension == "default" )
696 if( aPureName.startsWith( aDialogName_ ) )
700 xSFI->kill( rCompleteName );
702 catch(const uno::Exception& )
709 Reference< XStringResourceWithLocation > xStringResourceWithLocation =
710 StringResourceWithLocation::create( xContext, aURL, false/*bReadOnly*/,
711 xStringResourceResolver->getDefaultLocale(), aDialogName, aComment, xDummyHandler );
713 // Add locales
714 for( const lang::Locale& rLocale : aLocaleSeq )
716 xStringResourceWithLocation->newLocale( rLocale );
719 LocalizationMgr::copyResourceForDialog( GetDialog(),
720 xStringResourceResolver, xStringResourceWithLocation );
722 xStringResourceWithLocation->store();
726 static std::vector< lang::Locale > implGetLanguagesOnlyContainedInFirstSeq
727 ( const Sequence< lang::Locale >& aFirstSeq, const Sequence< lang::Locale >& aSecondSeq )
729 std::vector< lang::Locale > avRet;
731 std::copy_if(aFirstSeq.begin(), aFirstSeq.end(),
732 std::back_inserter(avRet),
733 [&aSecondSeq](const lang::Locale& rFirstLocale) {
734 return std::none_of(
735 aSecondSeq.begin(), aSecondSeq.end(),
736 [&rFirstLocale](const lang::Locale& rSecondLocale) {
737 return localesAreEqual(rFirstLocale, rSecondLocale);
740 return avRet;
743 namespace {
745 class NameClashQueryBox
747 private:
748 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
749 public:
750 NameClashQueryBox(weld::Window* pParent, const OUString& rTitle, const OUString& rMessage)
751 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, rMessage))
753 if (!rTitle.isEmpty())
754 m_xQueryBox->set_title(rTitle);
755 m_xQueryBox->add_button(IDEResId(RID_STR_DLGIMP_CLASH_RENAME), RET_YES);
756 m_xQueryBox->add_button(IDEResId(RID_STR_DLGIMP_CLASH_REPLACE), RET_NO);
757 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
758 m_xQueryBox->set_default_response(RET_YES);
760 short run() { return m_xQueryBox->run(); }
763 class LanguageMismatchQueryBox
765 private:
766 std::unique_ptr<weld::MessageDialog> m_xQueryBox;
767 public:
768 LanguageMismatchQueryBox(weld::Window* pParent, const OUString& rTitle, const OUString& rMessage)
769 : m_xQueryBox(Application::CreateMessageDialog(pParent, VclMessageType::Question, VclButtonsType::NONE, rMessage))
771 if (!rTitle.isEmpty())
772 m_xQueryBox->set_title(rTitle);
773 m_xQueryBox->add_button(IDEResId(RID_STR_DLGIMP_MISMATCH_ADD), RET_YES);
774 m_xQueryBox->add_button(IDEResId(RID_STR_DLGIMP_MISMATCH_OMIT), RET_NO);
775 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
776 m_xQueryBox->add_button(GetStandardText(StandardButtonType::Help), RET_HELP);
777 m_xQueryBox->set_default_response(RET_YES);
779 short run() { return m_xQueryBox->run(); }
784 bool implImportDialog(weld::Window* pWin, const ScriptDocument& rDocument, const OUString& aLibName)
786 bool bDone = false;
788 Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
789 sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
790 FileDialogFlags::NONE, pWin);
791 aDlg.SetContext(sfx2::FileDialogHelper::BasicImportDialog);
792 Reference<XFilePicker3> xFP = aDlg.GetFilePicker();
794 OUString aDialogStr(IDEResId(RID_STR_STDDIALOGNAME));
795 xFP->appendFilter( aDialogStr, "*.xdl" );
796 xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
797 xFP->setCurrentFilter( aDialogStr );
799 if( aDlg.Execute() == ERRCODE_NONE )
801 Sequence< OUString > aPaths = xFP->getSelectedFiles();
803 OUString aBasePath;
804 OUString aOUCurPath( aPaths[0] );
805 sal_Int32 iSlash = aOUCurPath.lastIndexOf( '/' );
806 if( iSlash != -1 )
807 aBasePath = aOUCurPath.copy( 0, iSlash + 1 );
811 // create dialog model
812 Reference< container::XNameContainer > xDialogModel(
813 xContext->getServiceManager()->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", xContext),
814 UNO_QUERY_THROW );
816 Reference< XSimpleFileAccess3 > xSFI( SimpleFileAccess::create(xContext) );
818 Reference< XInputStream > xInput;
819 if( xSFI->exists( aOUCurPath ) )
820 xInput = xSFI->openFileRead( aOUCurPath );
822 ::xmlscript::importDialogModel( xInput, xDialogModel, xContext, rDocument.isDocument() ? rDocument.getDocument() : Reference< frame::XModel >() );
824 OUString aXmlDlgName;
825 Reference< beans::XPropertySet > xDialogModelPropSet( xDialogModel, UNO_QUERY );
826 assert(xDialogModelPropSet.is());
829 Any aXmlDialogNameAny = xDialogModelPropSet->getPropertyValue( DLGED_PROP_NAME );
830 aXmlDialogNameAny >>= aXmlDlgName;
832 catch(const beans::UnknownPropertyException& )
834 TOOLS_WARN_EXCEPTION("basctl", "");
836 assert( !aXmlDlgName.isEmpty() );
838 bool bDialogAlreadyExists = rDocument.hasDialog( aLibName, aXmlDlgName );
840 OUString aNewDlgName = aXmlDlgName;
841 enum NameClashMode
843 NO_CLASH,
844 CLASH_OVERWRITE_DIALOG,
845 CLASH_RENAME_DIALOG,
847 NameClashMode eNameClashMode = NO_CLASH;
848 if( bDialogAlreadyExists )
850 OUString aQueryBoxTitle(IDEResId(RID_STR_DLGIMP_CLASH_TITLE));
851 OUString aQueryBoxText(IDEResId(RID_STR_DLGIMP_CLASH_TEXT));
852 aQueryBoxText = aQueryBoxText.replaceAll("$(ARG1)", aXmlDlgName);
854 NameClashQueryBox aQueryBox(pWin, aQueryBoxTitle, aQueryBoxText);
855 sal_uInt16 nRet = aQueryBox.run();
856 if( nRet == RET_YES )
858 // RET_YES == Rename, see NameClashQueryBox::NameClashQueryBox
859 eNameClashMode = CLASH_RENAME_DIALOG;
861 aNewDlgName = rDocument.createObjectName( E_DIALOGS, aLibName );
863 else if( nRet == RET_NO )
865 // RET_NO == Replace, see NameClashQueryBox::NameClashQueryBox
866 eNameClashMode = CLASH_OVERWRITE_DIALOG;
868 else if( nRet == RET_CANCEL )
870 return bDone;
874 Shell* pShell = GetShell();
875 assert(pShell);
877 // Resource?
878 css::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
879 Reference< task::XInteractionHandler > xDummyHandler;
880 Reference< XStringResourceWithLocation > xImportStringResource =
881 StringResourceWithLocation::create( xContext, aBasePath, true/*bReadOnly*/,
882 aLocale, aXmlDlgName, OUString(), xDummyHandler );
884 Sequence< lang::Locale > aImportLocaleSeq = xImportStringResource->getLocales();
885 sal_Int32 nImportLocaleCount = aImportLocaleSeq.getLength();
887 Reference< container::XNameContainer > xDialogLib( rDocument.getLibrary( E_DIALOGS, aLibName, true ) );
888 Reference< resource::XStringResourceManager > xLibStringResourceManager = LocalizationMgr::getStringResourceFromDialogLibrary( xDialogLib );
889 sal_Int32 nLibLocaleCount = 0;
890 Sequence< lang::Locale > aLibLocaleSeq;
891 if( xLibStringResourceManager.is() )
893 aLibLocaleSeq = xLibStringResourceManager->getLocales();
894 nLibLocaleCount = aLibLocaleSeq.getLength();
897 // Check language matches
898 std::vector< lang::Locale > aOnlyInImportLanguages =
899 implGetLanguagesOnlyContainedInFirstSeq( aImportLocaleSeq, aLibLocaleSeq );
900 int nOnlyInImportLanguageCount = aOnlyInImportLanguages.size();
902 // For now: Keep languages from lib
903 bool bLibLocalized = (nLibLocaleCount > 0);
904 bool bImportLocalized = (nImportLocaleCount > 0);
906 bool bAddDialogLanguagesToLib = false;
907 if( nOnlyInImportLanguageCount > 0 )
909 OUString aQueryBoxTitle(IDEResId(RID_STR_DLGIMP_MISMATCH_TITLE));
910 OUString aQueryBoxText(IDEResId(RID_STR_DLGIMP_MISMATCH_TEXT));
911 LanguageMismatchQueryBox aQueryBox(pWin, aQueryBoxTitle, aQueryBoxText);
912 sal_uInt16 nRet = aQueryBox.run();
913 if( nRet == RET_YES )
915 // RET_YES == Add, see LanguageMismatchQueryBox::LanguageMismatchQueryBox
916 bAddDialogLanguagesToLib = true;
918 // RET_NO == Omit, see LanguageMismatchQueryBox::LanguageMismatchQueryBox
919 // -> nothing to do here
920 //else if( RET_NO == nRet )
923 else if( nRet == RET_CANCEL )
925 return bDone;
929 if( bImportLocalized )
931 bool bCopyResourcesForDialog = true;
932 if( bAddDialogLanguagesToLib )
934 const std::shared_ptr<LocalizationMgr>& pCurMgr = pShell->GetCurLocalizationMgr();
936 lang::Locale aFirstLocale = aOnlyInImportLanguages[0];
937 if( nOnlyInImportLanguageCount > 1 )
939 // Check if import default belongs to only import languages and use it then
940 lang::Locale aImportDefaultLocale = xImportStringResource->getDefaultLocale();
942 if (std::any_of(aOnlyInImportLanguages.begin(), aOnlyInImportLanguages.end(),
943 [&aImportDefaultLocale](const lang::Locale& aTmpLocale) {
944 return localesAreEqual(aImportDefaultLocale, aTmpLocale);
947 aFirstLocale = aImportDefaultLocale;
951 pCurMgr->handleAddLocales( {aFirstLocale} );
953 if( nOnlyInImportLanguageCount > 1 )
955 Sequence< lang::Locale > aRemainingLocaleSeq( nOnlyInImportLanguageCount - 1 );
956 auto pRemainingLocaleSeq = aRemainingLocaleSeq.getArray();
957 int iSeq = 0;
958 for( const lang::Locale& rLocale : aOnlyInImportLanguages )
960 if( !localesAreEqual( aFirstLocale, rLocale ) )
961 pRemainingLocaleSeq[iSeq++] = rLocale;
963 pCurMgr->handleAddLocales( aRemainingLocaleSeq );
966 else if( !bLibLocalized )
968 LocalizationMgr::resetResourceForDialog( xDialogModel, xImportStringResource );
969 bCopyResourcesForDialog = false;
972 if( bCopyResourcesForDialog )
974 LocalizationMgr::copyResourceForDroppedDialog( xDialogModel, aXmlDlgName,
975 xLibStringResourceManager, xImportStringResource );
978 else if( bLibLocalized )
980 LocalizationMgr::setResourceIDsForDialog( xDialogModel, xLibStringResourceManager );
984 LocalizationMgr::setStringResourceAtDialog( rDocument, aLibName, aNewDlgName, xDialogModel );
986 if( eNameClashMode == CLASH_OVERWRITE_DIALOG )
988 if (basctl::RemoveDialog( rDocument, aLibName, aNewDlgName ) )
990 BaseWindow* pDlgWin = pShell->FindDlgWin( rDocument, aLibName, aNewDlgName, false, true );
991 if( pDlgWin != nullptr )
992 pShell->RemoveWindow( pDlgWin, false );
993 MarkDocumentModified( rDocument );
995 else
997 // TODO: Assertion?
998 return bDone;
1002 if( eNameClashMode == CLASH_RENAME_DIALOG )
1004 bool bRenamed = false;
1005 if( xDialogModelPropSet.is() )
1009 xDialogModelPropSet->setPropertyValue( DLGED_PROP_NAME, Any(aNewDlgName) );
1010 bRenamed = true;
1012 catch(const beans::UnknownPropertyException& )
1017 if( bRenamed )
1019 LocalizationMgr::renameStringResourceIDs( rDocument, aLibName, aNewDlgName, xDialogModel );
1021 else
1023 // TODO: Assertion?
1024 return bDone;
1028 Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xDialogModel, xContext, rDocument.isDocument() ? rDocument.getDocument() : Reference< frame::XModel >() );
1029 bool bSuccess = rDocument.insertDialog( aLibName, aNewDlgName, xISP );
1030 if( bSuccess )
1032 VclPtr<DialogWindow> pNewDlgWin = pShell->CreateDlgWin( rDocument, aLibName, aNewDlgName );
1033 pShell->SetCurWindow( pNewDlgWin, true );
1036 bDone = true;
1038 catch(const Exception& )
1042 return bDone;
1045 void DialogWindow::ImportDialog()
1047 const ScriptDocument& rDocument = GetDocument();
1048 OUString aLibName = GetLibName();
1049 implImportDialog(GetFrameWeld(), rDocument, aLibName);
1052 DlgEdModel& DialogWindow::GetModel() const
1054 return m_pEditor->GetModel();
1057 DlgEdPage& DialogWindow::GetPage() const
1059 return m_pEditor->GetPage();
1062 DlgEdView& DialogWindow::GetView() const
1064 return m_pEditor->GetView();
1067 bool DialogWindow::IsModified()
1069 return m_pEditor->IsModified();
1072 SfxUndoManager* DialogWindow::GetUndoManager()
1074 return m_pUndoMgr.get();
1077 OUString DialogWindow::GetTitle()
1079 return GetName();
1082 EntryDescriptor DialogWindow::CreateEntryDescriptor()
1084 ScriptDocument aDocument( GetDocument() );
1085 OUString aLibName( GetLibName() );
1086 LibraryLocation eLocation = aDocument.getLibraryLocation( aLibName );
1087 return EntryDescriptor( aDocument, eLocation, aLibName, OUString(), GetName(), OBJ_TYPE_DIALOG );
1090 void DialogWindow::SetReadOnly (bool bReadOnly)
1092 m_pEditor->SetMode(bReadOnly ? DlgEditor::READONLY : DlgEditor::SELECT);
1095 bool DialogWindow::IsReadOnly ()
1097 return m_pEditor->GetMode() == DlgEditor::READONLY;
1100 bool DialogWindow::IsPasteAllowed()
1102 return m_pEditor->IsPasteAllowed();
1105 void DialogWindow::StoreData()
1107 if ( !IsModified() )
1108 return;
1112 Reference< container::XNameContainer > xLib = GetDocument().getLibrary( E_DIALOGS, GetLibName(), true );
1114 if( xLib.is() )
1116 Reference< container::XNameContainer > xDialogModel = m_pEditor->GetDialog();
1118 if( xDialogModel.is() )
1120 Reference< XComponentContext > xContext(
1121 comphelper::getProcessComponentContext() );
1122 Reference< XInputStreamProvider > xISP = ::xmlscript::exportDialogModel( xDialogModel, xContext, GetDocument().isDocument() ? GetDocument().getDocument() : Reference< frame::XModel >() );
1123 xLib->replaceByName( GetName(), Any( xISP ) );
1127 catch (const uno::Exception& )
1129 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1131 MarkDocumentModified( GetDocument() );
1132 m_pEditor->ClearModifyFlag();
1135 void DialogWindow::Activating ()
1137 UpdateBrowser();
1138 Show();
1141 void DialogWindow::Deactivating()
1143 Hide();
1144 if ( IsModified() )
1145 MarkDocumentModified( GetDocument() );
1146 DisableBrowser();
1149 sal_Int32 DialogWindow::countPages( Printer* )
1151 return 1;
1154 void DialogWindow::printPage( sal_Int32 nPage, Printer* pPrinter )
1156 DlgEditor::printPage( nPage, pPrinter, CreateQualifiedName() );
1159 void DialogWindow::DataChanged( const DataChangedEvent& rDCEvt )
1161 if( (rDCEvt.GetType()==DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1163 InitSettings();
1164 Invalidate();
1166 else
1167 BaseWindow::DataChanged( rDCEvt );
1170 void DialogWindow::InitSettings()
1172 // FIXME RenderContext
1173 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1174 vcl::Font aFont = rStyleSettings.GetFieldFont();
1175 SetPointFont(*GetOutDev(), aFont);
1177 SetTextColor( rStyleSettings.GetFieldTextColor() );
1178 SetTextFillColor();
1180 SetBackground(rStyleSettings.GetFaceColor());
1183 css::uno::Reference< css::accessibility::XAccessible > DialogWindow::CreateAccessible()
1185 return new AccessibleDialogWindow(this);
1188 OUString DialogWindow::GetHid () const
1190 return HID_BASICIDE_DIALOGWINDOW;
1193 ItemType DialogWindow::GetType () const
1195 return TYPE_DIALOG;
1199 // DialogWindowLayout
1202 DialogWindowLayout::DialogWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) :
1203 Layout(pParent),
1204 rObjectCatalog(rObjectCatalog_),
1205 pPropertyBrowser(nullptr)
1207 ShowPropertyBrowser();
1210 DialogWindowLayout::~DialogWindowLayout()
1212 disposeOnce();
1215 void DialogWindowLayout::dispose()
1217 if (pPropertyBrowser)
1218 Remove(pPropertyBrowser);
1219 pPropertyBrowser.disposeAndClear();
1220 Layout::dispose();
1223 // shows the property browser (and creates if necessary)
1224 void DialogWindowLayout::ShowPropertyBrowser ()
1226 // not exists?
1227 if (!pPropertyBrowser)
1229 // creating
1230 pPropertyBrowser = VclPtr<PropBrw>::Create(*this);
1231 pPropertyBrowser->Show();
1232 // after OnFirstSize():
1233 if (HasSize())
1234 AddPropertyBrowser();
1235 // updating if necessary
1236 UpdatePropertyBrowser();
1238 else
1239 pPropertyBrowser->Show();
1240 // refreshing the button state
1241 if (SfxBindings* pBindings = GetBindingsPtr())
1242 pBindings->Invalidate(SID_SHOW_PROPERTYBROWSER);
1245 // disables the property browser
1246 void DialogWindowLayout::DisablePropertyBrowser ()
1248 if (pPropertyBrowser)
1249 pPropertyBrowser->Update(nullptr);
1252 // updates the property browser
1253 void DialogWindowLayout::UpdatePropertyBrowser ()
1255 if (pPropertyBrowser)
1256 pPropertyBrowser->Update(GetShell());
1259 void DialogWindowLayout::Activating (BaseWindow& rChild)
1261 assert(dynamic_cast<DialogWindow*>(&rChild));
1262 rObjectCatalog.SetLayoutWindow(this);
1263 rObjectCatalog.UpdateEntries();
1264 rObjectCatalog.Show();
1265 if (pPropertyBrowser)
1266 pPropertyBrowser->Show();
1267 Layout::Activating(rChild);
1270 void DialogWindowLayout::Deactivating ()
1272 Layout::Deactivating();
1273 rObjectCatalog.Hide();
1274 if (pPropertyBrowser)
1275 pPropertyBrowser->Hide();
1278 void DialogWindowLayout::ExecuteGlobal (SfxRequest& rReq)
1280 switch (rReq.GetSlot())
1282 case SID_SHOW_PROPERTYBROWSER:
1283 // toggling property browser
1284 if (pPropertyBrowser && pPropertyBrowser->IsVisible())
1285 pPropertyBrowser->Hide();
1286 else
1287 ShowPropertyBrowser();
1288 ArrangeWindows();
1289 // refreshing the button state
1290 if (SfxBindings* pBindings = GetBindingsPtr())
1291 pBindings->Invalidate(SID_SHOW_PROPERTYBROWSER);
1292 break;
1296 void DialogWindowLayout::GetState (SfxItemSet& rSet, unsigned nWhich)
1298 switch (nWhich)
1300 case SID_SHOW_PROPERTYBROWSER:
1301 rSet.Put(SfxBoolItem(nWhich, pPropertyBrowser && pPropertyBrowser->IsVisible()));
1302 break;
1304 case SID_BASICIDE_CHOOSEMACRO:
1305 rSet.Put(SfxVisibilityItem(nWhich, false));
1306 break;
1310 void DialogWindowLayout::OnFirstSize (tools::Long const nWidth, tools::Long const nHeight)
1312 AddToLeft(&rObjectCatalog, Size(nWidth * 0.25, nHeight * 0.35));
1313 if (pPropertyBrowser)
1314 AddPropertyBrowser();
1317 void DialogWindowLayout::AddPropertyBrowser () {
1318 Size const aSize = GetOutputSizePixel();
1319 AddToLeft(pPropertyBrowser, Size(aSize.Width() * 0.25, aSize.Height() * 0.65));
1323 } // namespace basctl
1325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */