nss: upgrade to release 3.73
[LibreOffice.git] / basctl / source / basicide / macrodlg.cxx
blob24cb210ea7e3fbecc757975197cc137b15a480ec
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 "macrodlg.hxx"
22 #include <basidesh.hxx>
23 #include <strings.hrc>
24 #include <iderid.hxx>
26 #include <iderdll.hxx>
27 #include "iderdll2.hxx"
29 #include "moduldlg.hxx"
30 #include <basic/basmgr.hxx>
31 #include <basic/sbmeth.hxx>
32 #include <basic/sbmod.hxx>
33 #include <com/sun/star/script/XLibraryContainer2.hpp>
35 #include <sfx2/app.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <sfx2/frame.hxx>
38 #include <sfx2/minfitem.hxx>
39 #include <sfx2/request.hxx>
40 #include <sfx2/sfxsids.hrc>
41 #include <tools/debug.hxx>
42 #include <vcl/commandevent.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vcl/weld.hxx>
45 #include <osl/diagnose.h>
47 namespace basctl
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
53 MacroChooser::MacroChooser(weld::Window* pParnt, const Reference< frame::XFrame >& xDocFrame)
54 : SfxDialogController(pParnt, "modules/BasicIDE/ui/basicmacrodialog.ui", "BasicMacroDialog")
55 , m_xDocumentFrame(xDocFrame)
56 // the Sfx doesn't ask the BasicManager whether modified or not
57 // => start saving in case of a change without a into the BasicIDE.
58 , bForceStoreBasic(false)
59 , nMode(All)
60 , m_xMacroNameEdit(m_xBuilder->weld_entry("macronameedit"))
61 , m_xMacroFromTxT(m_xBuilder->weld_label("macrofromft"))
62 , m_xMacrosSaveInTxt(m_xBuilder->weld_label("macrotoft"))
63 , m_xBasicBox(new SbTreeListBox(m_xBuilder->weld_tree_view("libraries"), m_xDialog.get()))
64 , m_xBasicBoxIter(m_xBasicBox->make_iterator())
65 , m_xMacrosInTxt(m_xBuilder->weld_label("existingmacrosft"))
66 , m_xMacroBox(m_xBuilder->weld_tree_view("macros"))
67 , m_xMacroBoxIter(m_xMacroBox->make_iterator())
68 , m_xRunButton(m_xBuilder->weld_button("ok"))
69 , m_xCloseButton(m_xBuilder->weld_button("close"))
70 , m_xAssignButton(m_xBuilder->weld_button("assign"))
71 , m_xEditButton(m_xBuilder->weld_button("edit"))
72 , m_xDelButton(m_xBuilder->weld_button("delete"))
73 , m_xNewButton(m_xBuilder->weld_button("new"))
74 , m_xOrganizeButton(m_xBuilder->weld_button("organize"))
75 , m_xNewLibButton(m_xBuilder->weld_button("newlibrary"))
76 , m_xNewModButton(m_xBuilder->weld_button("newmodule"))
78 m_xBasicBox->set_size_request(m_xBasicBox->get_approximate_digit_width() * 30, m_xBasicBox->get_height_rows(18));
79 m_xMacroBox->set_size_request(m_xMacroBox->get_approximate_digit_width() * 30, m_xMacroBox->get_height_rows(18));
81 m_aMacrosInTxtBaseStr = m_xMacrosInTxt->get_label();
83 m_xRunButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
84 m_xCloseButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
85 m_xAssignButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
86 m_xEditButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
87 m_xDelButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
88 m_xNewButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
89 m_xOrganizeButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
91 // Buttons only for MacroChooser::Recording
92 m_xNewLibButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
93 m_xNewModButton->connect_clicked( LINK( this, MacroChooser, ButtonHdl ) );
94 m_xNewLibButton->hide(); // default
95 m_xNewModButton->hide(); // default
96 m_xMacrosSaveInTxt->hide(); // default
98 m_xMacroNameEdit->connect_changed( LINK( this, MacroChooser, EditModifyHdl ) );
100 m_xBasicBox->connect_changed( LINK( this, MacroChooser, BasicSelectHdl ) );
102 m_xMacroBox->connect_row_activated( LINK( this, MacroChooser, MacroDoubleClickHdl ) );
103 m_xMacroBox->connect_changed( LINK( this, MacroChooser, MacroSelectHdl ) );
104 m_xMacroBox->connect_popup_menu( LINK( this, MacroChooser, ContextMenuHdl ) );
106 m_xBasicBox->SetMode( BrowseMode::Modules );
108 if (SfxDispatcher* pDispatcher = GetDispatcher())
109 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
111 m_xBasicBox->ScanAllEntries();
114 MacroChooser::~MacroChooser()
116 if (bForceStoreBasic)
118 SfxGetpApp()->SaveBasicAndDialogContainer();
119 bForceStoreBasic = false;
123 void MacroChooser::StoreMacroDescription()
125 m_xBasicBox->get_selected(m_xBasicBoxIter.get());
126 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
127 OUString aMethodName;
128 if (m_xMacroBox->get_selected(m_xMacroBoxIter.get()))
129 aMethodName = m_xMacroBox->get_text(*m_xMacroBoxIter);
130 else
131 aMethodName = m_xMacroNameEdit->get_text();
132 if ( !aMethodName.isEmpty() )
134 aDesc.SetMethodName( aMethodName );
135 aDesc.SetType( OBJ_TYPE_METHOD );
138 if (ExtraData* pData = basctl::GetExtraData())
139 pData->SetLastEntryDescriptor( aDesc );
142 void MacroChooser::RestoreMacroDescription()
144 EntryDescriptor aDesc;
145 if (Shell* pShell = GetShell())
147 if (BaseWindow* pCurWin = pShell->GetCurWindow())
148 aDesc = pCurWin->CreateEntryDescriptor();
150 else
152 if (ExtraData* pData = basctl::GetExtraData())
153 aDesc = pData->GetLastEntryDescriptor();
156 m_xBasicBox->SetCurrentEntry(aDesc);
157 BasicSelectHdl(m_xBasicBox->get_widget());
159 OUString aLastMacro( aDesc.GetMethodName() );
160 if (!aLastMacro.isEmpty())
162 // find entry in macro box
163 auto nIndex = m_xMacroBox->find_text(aLastMacro);
164 if (nIndex != -1)
165 m_xMacroBox->select(nIndex);
166 else
168 m_xMacroNameEdit->set_text(aLastMacro);
169 m_xMacroNameEdit->select_region(0, 0);
174 short MacroChooser::run()
176 RestoreMacroDescription();
178 // #104198 Check if "wrong" document is active
179 bool bSelectedEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
180 EntryDescriptor aDesc(m_xBasicBox->GetEntryDescriptor(bSelectedEntry ? m_xBasicBoxIter.get() : nullptr));
181 const ScriptDocument& rSelectedDoc(aDesc.GetDocument());
183 // App Basic is always ok, so only check if shell was found
184 if( rSelectedDoc.isDocument() && !rSelectedDoc.isActive() )
186 // Search for the right entry
187 bool bValidIter = m_xBasicBox->get_iter_first(*m_xBasicBoxIter);
188 while (bValidIter)
190 EntryDescriptor aCmpDesc(m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get()));
191 const ScriptDocument& rCmpDoc( aCmpDesc.GetDocument() );
192 if (rCmpDoc.isDocument() && rCmpDoc.isActive())
194 std::unique_ptr<weld::TreeIter> xEntry(m_xBasicBox->make_iterator());
195 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xEntry);
196 std::unique_ptr<weld::TreeIter> xLastValid(m_xBasicBox->make_iterator());
197 bool bValidEntryIter = true;
200 m_xBasicBox->copy_iterator(*xEntry, *xLastValid);
201 bValidEntryIter = m_xBasicBox->iter_children(*xEntry);
203 while (bValidEntryIter);
204 m_xBasicBox->set_cursor(*xLastValid);
206 bValidIter = m_xBasicBox->iter_next_sibling(*m_xBasicBoxIter);
210 CheckButtons();
211 UpdateFields();
213 // tdf#62955 - Allow searching a name with typing the first letter
214 m_xBasicBox->get_widget().grab_focus();
216 if ( StarBASIC::IsRunning() )
217 m_xCloseButton->grab_focus();
219 return SfxDialogController::run();
222 void MacroChooser::EnableButton(weld::Button& rButton, bool bEnable)
224 if ( bEnable )
226 if (nMode == ChooseOnly || nMode == Recording)
227 rButton.set_sensitive(&rButton == m_xRunButton.get());
228 else
229 rButton.set_sensitive(true);
231 else
232 rButton.set_sensitive(false);
235 SbMethod* MacroChooser::GetMacro()
237 if (!m_xBasicBox->get_cursor(m_xBasicBoxIter.get()))
238 return nullptr;
239 SbModule* pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get());
240 if (!pModule)
241 return nullptr;
242 if (!m_xMacroBox->get_selected(m_xMacroBoxIter.get()))
243 return nullptr;
244 OUString aMacroName(m_xMacroBox->get_text(*m_xMacroBoxIter));
245 return pModule->FindMethod(aMacroName, SbxClassType::Method);
248 void MacroChooser::DeleteMacro()
250 SbMethod* pMethod = GetMacro();
251 DBG_ASSERT( pMethod, "DeleteMacro: No Macro !" );
252 if (!(pMethod && QueryDelMacro(pMethod->GetName(), m_xDialog.get())))
253 return;
255 if (SfxDispatcher* pDispatcher = GetDispatcher())
256 pDispatcher->Execute( SID_BASICIDE_STOREALLMODULESOURCES );
258 // mark current doc as modified:
259 StarBASIC* pBasic = FindBasic(pMethod);
260 assert(pBasic && "Basic?!");
261 BasicManager* pBasMgr = FindBasicManager( pBasic );
262 DBG_ASSERT( pBasMgr, "BasMgr?" );
263 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
264 if ( aDocument.isDocument() )
266 aDocument.setDocumentModified();
267 if (SfxBindings* pBindings = GetBindingsPtr())
268 pBindings->Invalidate( SID_SAVEDOC );
271 SbModule* pModule = pMethod->GetModule();
272 assert(pModule && "DeleteMacro: No Module?!");
273 OUString aSource( pModule->GetSource32() );
274 sal_uInt16 nStart, nEnd;
275 pMethod->GetLineRange( nStart, nEnd );
276 pModule->GetMethods()->Remove( pMethod );
277 CutLines( aSource, nStart-1, nEnd-nStart+1 );
278 pModule->SetSource32( aSource );
280 // update module in library
281 OUString aLibName = pBasic->GetName();
282 OUString aModName = pModule->GetName();
283 OSL_VERIFY( aDocument.updateModule( aLibName, aModName, aSource ) );
285 bool bSelected = m_xMacroBox->get_selected(m_xMacroBoxIter.get());
286 DBG_ASSERT(bSelected, "DeleteMacro: Entry ?!");
287 m_xMacroBox->remove(*m_xMacroBoxIter);
288 bForceStoreBasic = true;
291 SbMethod* MacroChooser::CreateMacro()
293 SbMethod* pMethod = nullptr;
294 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
295 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
296 const ScriptDocument& aDocument( aDesc.GetDocument() );
297 OSL_ENSURE( aDocument.isAlive(), "MacroChooser::CreateMacro: no document!" );
298 if ( !aDocument.isAlive() )
299 return nullptr;
301 OUString aLibName( aDesc.GetLibName() );
303 if ( aLibName.isEmpty() )
304 aLibName = "Standard" ;
306 aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName );
308 OUString aOULibName( aLibName );
309 Reference< script::XLibraryContainer > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ) );
310 if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && !xModLibContainer->isLibraryLoaded( aOULibName ) )
311 xModLibContainer->loadLibrary( aOULibName );
312 Reference< script::XLibraryContainer > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ) );
313 if ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && !xDlgLibContainer->isLibraryLoaded( aOULibName ) )
314 xDlgLibContainer->loadLibrary( aOULibName );
316 BasicManager* pBasMgr = aDocument.getBasicManager();
317 StarBASIC* pBasic = pBasMgr ? pBasMgr->GetLib( aLibName ) : nullptr;
318 if ( pBasic )
320 SbModule* pModule = nullptr;
321 OUString aModName( aDesc.GetName() );
322 if ( !aModName.isEmpty() )
324 // extract the module name from the string like "Sheet1 (Example1)"
325 if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) )
327 aModName = aModName.getToken( 0, ' ' );
329 pModule = pBasic->FindModule( aModName );
331 else if ( !pBasic->GetModules().empty() )
332 pModule = pBasic->GetModules().front().get();
334 // Retain the desired macro name before the macro dialog box is forced to close
335 // by opening the module name dialog window when no module exists in the current library.
336 OUString aSubName = m_xMacroNameEdit->get_text();
338 if ( !pModule )
340 pModule = createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, aModName, false);
343 DBG_ASSERT( !pModule || !pModule->FindMethod( aSubName, SbxClassType::Method ), "Macro exists already!" );
344 pMethod = pModule ? basctl::CreateMacro( pModule, aSubName ) : nullptr;
347 return pMethod;
350 void MacroChooser::SaveSetCurEntry(weld::TreeView& rBox, const weld::TreeIter& rEntry)
352 // the edit would be killed by the highlight otherwise:
354 OUString aSaveText(m_xMacroNameEdit->get_text());
355 int nStartPos, nEndPos;
356 m_xMacroNameEdit->get_selection_bounds(nStartPos, nEndPos);
358 rBox.set_cursor(rEntry);
360 m_xMacroNameEdit->set_text(aSaveText);
361 m_xMacroNameEdit->select_region(nStartPos, nEndPos);
364 void MacroChooser::CheckButtons()
366 const bool bCurEntry = m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
367 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(bCurEntry ? m_xBasicBoxIter.get() : nullptr);
368 const bool bMacroEntry = m_xMacroBox->get_selected(nullptr);
369 SbMethod* pMethod = GetMacro();
371 // check, if corresponding libraries are readonly
372 bool bReadOnly = false;
373 sal_uInt16 nDepth = bCurEntry ? m_xBasicBox->get_iter_depth(*m_xBasicBoxIter) : 0;
374 if ( nDepth == 1 || nDepth == 2 )
376 const ScriptDocument& aDocument( aDesc.GetDocument() );
377 const OUString& aOULibName( aDesc.GetLibName() );
378 Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
379 Reference< script::XLibraryContainer2 > xDlgLibContainer( aDocument.getLibraryContainer( E_DIALOGS ), UNO_QUERY );
380 if ( ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && xModLibContainer->isLibraryReadOnly( aOULibName ) ) ||
381 ( xDlgLibContainer.is() && xDlgLibContainer->hasByName( aOULibName ) && xDlgLibContainer->isLibraryReadOnly( aOULibName ) ) )
383 bReadOnly = true;
387 if (nMode != Recording)
389 // Run...
390 bool bEnable = pMethod != nullptr;
391 if (nMode != ChooseOnly && StarBASIC::IsRunning())
392 bEnable = false;
393 EnableButton(*m_xRunButton, bEnable);
396 // organising still possible?
398 // Assign...
399 EnableButton(*m_xAssignButton, pMethod != nullptr);
401 // Edit...
402 EnableButton(*m_xEditButton, bMacroEntry);
404 // Organizer...
405 EnableButton(*m_xOrganizeButton, !StarBASIC::IsRunning() && nMode == All);
407 // m_xDelButton/m_xNewButton ->...
408 bool bProtected = bCurEntry && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get());
409 bool bShare = ( aDesc.GetLocation() == LIBRARY_LOCATION_SHARE );
410 bool bEnable = !StarBASIC::IsRunning() && nMode == All && !bProtected && !bReadOnly && !bShare;
411 EnableButton(*m_xDelButton, bEnable);
412 EnableButton(*m_xNewButton, bEnable);
413 if (nMode == All)
415 if (pMethod)
417 m_xDelButton->show();
418 m_xNewButton->hide();
420 else
422 m_xNewButton->show();
423 m_xDelButton->hide();
427 if (nMode == Recording)
429 // save button
430 m_xRunButton->set_sensitive(!bProtected && !bReadOnly && !bShare);
431 // new library button
432 m_xNewLibButton->set_sensitive(!bShare);
433 // new module button
434 m_xNewModButton->set_sensitive(!bProtected && !bReadOnly && !bShare);
438 IMPL_LINK_NOARG(MacroChooser, MacroDoubleClickHdl, weld::TreeView&, bool)
440 SbMethod* pMethod = GetMacro();
441 SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr;
442 StarBASIC* pBasic = pModule ? static_cast<StarBASIC*>(pModule->GetParent()) : nullptr;
443 BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr;
444 ScriptDocument aDocument(ScriptDocument::getDocumentForBasicManager(pBasMgr));
445 if (aDocument.isDocument() && !aDocument.allowMacros())
447 std::unique_ptr<weld::MessageDialog> xError(
448 Application::CreateMessageDialog(m_xDialog.get(), VclMessageType::Warning,
449 VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO)));
450 xError->run();
451 return true;
454 StoreMacroDescription();
455 if (nMode == Recording)
457 if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get()))
458 return true;
461 m_xDialog->response(Macro_OkRun);
462 return true;
465 IMPL_LINK_NOARG(MacroChooser, MacroSelectHdl, weld::TreeView&, void)
467 UpdateFields();
468 CheckButtons();
471 IMPL_LINK_NOARG(MacroChooser, BasicSelectHdl, weld::TreeView&, void)
473 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
474 SbModule* pModule = m_xBasicBox->FindModule(m_xBasicBoxIter.get());
475 m_xMacroBox->clear();
476 if (pModule)
478 m_xMacrosInTxt->set_label(m_aMacrosInTxtBaseStr + " " + pModule->GetName());
480 m_xMacroBox->freeze();
482 sal_uInt32 nMacroCount = pModule->GetMethods()->Count32();
483 for ( sal_uInt32 iMeth = 0; iMeth < nMacroCount; iMeth++ )
485 SbMethod* pMethod = static_cast<SbMethod*>(pModule->GetMethods()->Get32( iMeth ));
486 assert(pMethod && "Method not found!");
487 if (pMethod->IsHidden())
488 continue;
489 m_xMacroBox->append_text(pMethod->GetName());
492 m_xMacroBox->thaw();
494 if (m_xMacroBox->get_iter_first(*m_xMacroBoxIter))
495 m_xMacroBox->set_cursor(*m_xMacroBoxIter);
498 UpdateFields();
499 CheckButtons();
502 IMPL_LINK_NOARG(MacroChooser, EditModifyHdl, weld::Entry&, void)
504 // select the module in which the macro is put at "new",
505 // if BasicManager or Lib is selecting
506 if (m_xBasicBox->get_cursor(m_xBasicBoxIter.get()))
508 sal_uInt16 nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter);
509 if (nDepth == 1 && m_xBasicBox->IsEntryProtected(m_xBasicBoxIter.get()))
511 // then put to the respective Std-Lib...
512 m_xBasicBox->iter_parent(*m_xBasicBoxIter);
513 m_xBasicBox->iter_children(*m_xBasicBoxIter);
515 if (nDepth < 2)
517 std::unique_ptr<weld::TreeIter> xNewEntry(m_xBasicBox->make_iterator());
518 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry);
519 bool bCurEntry = true;
522 bCurEntry = m_xBasicBox->iter_children(*m_xBasicBoxIter);
523 if (bCurEntry)
525 m_xBasicBox->copy_iterator(*m_xBasicBoxIter, *xNewEntry);
526 nDepth = m_xBasicBox->get_iter_depth(*m_xBasicBoxIter);
529 while (bCurEntry && (nDepth < 2));
530 SaveSetCurEntry(m_xBasicBox->get_widget(), *xNewEntry);
532 auto nCount = m_xMacroBox->n_children();
533 if (nCount)
535 OUString aEdtText(m_xMacroNameEdit->get_text());
536 bool bFound = false;
537 bool bValidIter = m_xMacroBox->get_iter_first(*m_xMacroBoxIter);
538 while (bValidIter)
540 if (m_xMacroBox->get_text(*m_xMacroBoxIter).equalsIgnoreAsciiCase(aEdtText))
542 SaveSetCurEntry(*m_xMacroBox, *m_xMacroBoxIter);
543 bFound = true;
544 break;
546 bValidIter = m_xMacroBox->iter_next_sibling(*m_xMacroBoxIter);
548 if (!bFound)
550 bValidIter = m_xMacroBox->get_selected(m_xMacroBoxIter.get());
551 // if the entry exists ->Select ->Description...
552 if (bValidIter)
553 m_xMacroBox->unselect(*m_xMacroBoxIter);
558 CheckButtons();
561 IMPL_LINK(MacroChooser, ButtonHdl, weld::Button&, rButton, void)
563 // apart from New/Record the Description is done by LoseFocus
564 if (&rButton == m_xRunButton.get())
566 StoreMacroDescription();
568 // #116444# check security settings before macro execution
569 if (nMode == All)
571 SbMethod* pMethod = GetMacro();
572 SbModule* pModule = pMethod ? pMethod->GetModule() : nullptr;
573 StarBASIC* pBasic = pModule ? static_cast<StarBASIC*>(pModule->GetParent()) : nullptr;
574 BasicManager* pBasMgr = pBasic ? FindBasicManager(pBasic) : nullptr;
575 if ( pBasMgr )
577 ScriptDocument aDocument( ScriptDocument::getDocumentForBasicManager( pBasMgr ) );
578 if ( aDocument.isDocument() && !aDocument.allowMacros() )
580 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
581 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO)));
582 xError->run();
583 return;
587 else if (nMode == Recording )
589 if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) )
591 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
592 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
593 xError->run();
594 m_xMacroNameEdit->select_region(0, -1);
595 m_xMacroNameEdit->grab_focus();
596 return;
599 SbMethod* pMethod = GetMacro();
600 if (pMethod && !QueryReplaceMacro(pMethod->GetName(), m_xDialog.get()))
601 return;
604 m_xDialog->response(Macro_OkRun);
606 else if (&rButton == m_xCloseButton.get())
608 StoreMacroDescription();
609 m_xDialog->response(Macro_Close);
611 else if (&rButton == m_xEditButton.get() || &rButton == m_xDelButton.get() || &rButton == m_xNewButton.get())
613 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
614 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
615 const ScriptDocument& aDocument( aDesc.GetDocument() );
616 DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" );
617 if ( !aDocument.isAlive() )
618 return;
619 BasicManager* pBasMgr = aDocument.getBasicManager();
620 const OUString& aLib( aDesc.GetLibName() );
621 OUString aMod( aDesc.GetName() );
622 // extract the module name from the string like "Sheet1 (Example1)"
623 if( aDesc.GetLibSubName() == IDEResId(RID_STR_DOCUMENT_OBJECTS) )
625 aMod = aMod.getToken( 0, ' ' );
627 const OUString& aSub( aDesc.GetMethodName() );
628 SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLib, aMod, aSub, OUString() );
629 if (&rButton == m_xEditButton.get())
631 if (m_xMacroBox->get_selected(m_xMacroBoxIter.get()))
632 aInfoItem.SetMethod(m_xMacroBox->get_text(*m_xMacroBoxIter));
633 StoreMacroDescription();
634 m_xDialog->hide(); // tdf#126828 dismiss dialog before opening new window
636 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
637 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs );
638 SfxGetpApp()->ExecuteSlot( aRequest );
640 if (SfxDispatcher* pDispatcher = GetDispatcher())
642 pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO,
643 SfxCallMode::ASYNCHRON, { &aInfoItem });
645 m_xDialog->response(Macro_Edit);
647 else
649 if (&rButton == m_xDelButton.get())
651 DeleteMacro();
652 if (SfxDispatcher* pDispatcher = GetDispatcher())
654 pDispatcher->ExecuteList( SID_BASICIDE_UPDATEMODULESOURCE,
655 SfxCallMode::SYNCHRON, { &aInfoItem });
657 CheckButtons();
658 UpdateFields();
659 //if ( m_xMacroBox->GetCurEntry() ) // OV-Bug ?
660 // m_xMacroBox->Select( m_xMacroBox->GetCurEntry() );
662 else
664 if ( !IsValidSbxName(m_xMacroNameEdit->get_text()) )
666 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(m_xDialog.get(),
667 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
668 xError->run();
669 m_xMacroNameEdit->select_region(0, -1);
670 m_xMacroNameEdit->grab_focus();
671 return;
673 SbMethod* pMethod = CreateMacro();
674 if ( pMethod )
676 aInfoItem.SetMethod( pMethod->GetName() );
677 aInfoItem.SetModule( pMethod->GetModule()->GetName() );
678 aInfoItem.SetLib( pMethod->GetModule()->GetParent()->GetName() );
679 SfxAllItemSet aArgs( SfxGetpApp()->GetPool() );
680 SfxRequest aRequest( SID_BASICIDE_APPEAR, SfxCallMode::SYNCHRON, aArgs );
681 SfxGetpApp()->ExecuteSlot( aRequest );
683 if (SfxDispatcher* pDispatcher = GetDispatcher())
685 pDispatcher->ExecuteList(SID_BASICIDE_EDITMACRO,
686 SfxCallMode::ASYNCHRON, { &aInfoItem });
688 StoreMacroDescription();
689 m_xDialog->response(Macro_New);
694 else if (&rButton == m_xAssignButton.get())
696 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
697 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
698 const ScriptDocument& aDocument( aDesc.GetDocument() );
699 DBG_ASSERT( aDocument.isAlive(), "MacroChooser::ButtonHdl: no document, or document is dead!" );
700 if ( !aDocument.isAlive() )
701 return;
702 BasicManager* pBasMgr = aDocument.getBasicManager();
703 const OUString& aLib( aDesc.GetLibName() );
704 const OUString& aMod( aDesc.GetName() );
705 OUString aSub( m_xMacroNameEdit->get_text() );
706 SbMethod* pMethod = GetMacro();
707 DBG_ASSERT( pBasMgr, "BasMgr?" );
708 DBG_ASSERT( pMethod, "Method?" );
709 OUString aComment( GetInfo( pMethod ) );
710 SfxMacroInfoItem aItem( SID_MACROINFO, pBasMgr, aLib, aMod, aSub, aComment );
711 SfxAllItemSet Args( SfxGetpApp()->GetPool() );
713 SfxAllItemSet aInternalSet(SfxGetpApp()->GetPool());
714 if (m_xDocumentFrame.is())
715 aInternalSet.Put(SfxUnoFrameItem(SID_FILLFRAME, m_xDocumentFrame));
717 SfxRequest aRequest(SID_CONFIG, SfxCallMode::SYNCHRON, Args, aInternalSet);
718 aRequest.AppendItem( aItem );
719 SfxGetpApp()->ExecuteSlot( aRequest );
721 else if (&rButton == m_xNewLibButton.get())
723 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
724 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
725 const ScriptDocument& aDocument( aDesc.GetDocument() );
726 createLibImpl(m_xDialog.get(), aDocument, nullptr, m_xBasicBox.get());
728 else if (&rButton == m_xNewModButton.get())
730 m_xBasicBox->get_cursor(m_xBasicBoxIter.get());
731 EntryDescriptor aDesc = m_xBasicBox->GetEntryDescriptor(m_xBasicBoxIter.get());
732 const ScriptDocument& aDocument( aDesc.GetDocument() );
733 const OUString& aLibName( aDesc.GetLibName() );
734 createModImpl(m_xDialog.get(), aDocument, *m_xBasicBox, aLibName, OUString(), true);
736 else if (&rButton == m_xOrganizeButton.get())
738 StoreMacroDescription();
740 m_xBasicBox->get_selected(m_xBasicBoxIter.get());
741 auto xDlg(std::make_shared<OrganizeDialog>(m_xDialog.get(), 0));
742 weld::DialogController::runAsync(xDlg, [this](sal_Int32 nRet) {
743 if (nRet == RET_OK) // not only closed
745 m_xDialog->response(Macro_Edit);
746 return;
749 Shell* pShell = GetShell();
750 if ( pShell && pShell->IsAppBasicModified() )
751 bForceStoreBasic = true;
753 m_xBasicBox->UpdateEntries();
758 IMPL_LINK(MacroChooser, ContextMenuHdl, const CommandEvent&, rCEvt, bool)
760 if (rCEvt.GetCommand() != CommandEventId::ContextMenu || !m_xMacroBox->n_children())
761 return false;
763 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(m_xMacroBox.get(), "modules/BasicIDE/ui/sortmenu.ui"));
764 std::unique_ptr<weld::Menu> xPopup(xBuilder->weld_menu("sortmenu"));
765 std::unique_ptr<weld::Menu> xDropMenu(xBuilder->weld_menu("sortsubmenu"));
766 xDropMenu->set_active("alphabetically", m_xMacroBox->get_sort_order());
767 xDropMenu->set_active("properorder", !m_xMacroBox->get_sort_order());
769 OString sCommand(xPopup->popup_at_rect(m_xMacroBox.get(), tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1))));
770 if (sCommand == "alphabetically")
772 m_xMacroBox->make_sorted();
774 else if (sCommand == "properorder")
776 m_xMacroBox->make_unsorted();
777 BasicSelectHdl(m_xBasicBox->get_widget());
779 else if (!sCommand.isEmpty())
781 SAL_WARN("basctl.basicide", "Unknown context menu action: " << sCommand );
784 return true;
787 void MacroChooser::UpdateFields()
789 auto nMacroEntry = m_xMacroBox->get_selected_index();
790 m_xMacroNameEdit->set_text("");
791 if (nMacroEntry != -1)
792 m_xMacroNameEdit->set_text(m_xMacroBox->get_text(nMacroEntry));
795 void MacroChooser::SetMode (Mode nM)
797 nMode = nM;
798 switch (nMode)
800 case All:
802 m_xRunButton->set_label(IDEResId(RID_STR_RUN));
803 EnableButton(*m_xDelButton, true);
804 EnableButton(*m_xNewButton, true);
805 EnableButton(*m_xOrganizeButton, true);
806 break;
809 case ChooseOnly:
811 m_xRunButton->set_label(IDEResId(RID_STR_CHOOSE));
812 EnableButton(*m_xDelButton, false);
813 EnableButton(*m_xNewButton, false);
814 EnableButton(*m_xOrganizeButton, false);
815 break;
818 case Recording:
820 m_xRunButton->set_label(IDEResId(RID_STR_RECORD));
821 EnableButton(*m_xDelButton, false);
822 EnableButton(*m_xNewButton, false);
823 EnableButton(*m_xOrganizeButton, false);
825 m_xAssignButton->hide();
826 m_xEditButton->hide();
827 m_xDelButton->hide();
828 m_xNewButton->hide();
829 m_xOrganizeButton->hide();
830 m_xMacroFromTxT->hide();
832 m_xNewLibButton->show();
833 m_xNewModButton->show();
834 m_xMacrosSaveInTxt->show();
836 break;
839 CheckButtons();
842 OUString MacroChooser::GetInfo( SbxVariable* pVar )
844 OUString aComment;
845 SbxInfoRef xInfo = pVar->GetInfo();
846 if ( xInfo.is() )
847 aComment = xInfo->GetComment();
848 return aComment;
852 } // namespace basctl
854 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */