android: Update app-specific/MIME type icons
[LibreOffice.git] / basctl / source / basicide / bastypes.cxx
blobbbd71ad08ce014d4024fc370a2754901cbf650a2
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 <string_view>
24 #include <strings.hrc>
25 #include <helpids.h>
26 #include <iderid.hxx>
28 #include "baside2.hxx"
29 #include <baside3.hxx>
30 #include <basidesh.hxx>
31 #include <basobj.hxx>
32 #include <iderdll.hxx>
33 #include "iderdll2.hxx"
35 #include <com/sun/star/script/XLibraryContainerPassword.hpp>
36 #include <sal/log.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/infobar.hxx>
39 #include <sfx2/passwd.hxx>
40 #include <sfx2/sfxsids.hrc>
41 #include <sfx2/viewfrm.hxx>
42 #include <svl/intitem.hxx>
43 #include <svl/stritem.hxx>
44 #include <svl/srchdefs.hxx>
45 #include <utility>
46 #include <vcl/commandevent.hxx>
47 #include <vcl/event.hxx>
48 #include <vcl/svapp.hxx>
49 #include <vcl/weld.hxx>
50 #include <tools/stream.hxx>
51 #include <o3tl/hash_combine.hxx>
53 namespace basctl
56 // ID used for the read-only infobar
57 constexpr OUStringLiteral BASIC_IDE_READONLY_INFOBAR = u"readonly";
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star;
62 BaseWindow::BaseWindow( vcl::Window* pParent, ScriptDocument aDocument, OUString aLibName, OUString aName )
63 :Window( pParent, WinBits( WB_3DLOOK ) )
64 ,pShellHScrollBar( nullptr)
65 ,pShellVScrollBar( nullptr)
66 ,nStatus( 0)
67 ,m_aDocument(std::move( aDocument ))
68 ,m_aLibName(std::move( aLibName ))
69 ,m_aName(std::move( aName ))
73 BaseWindow::~BaseWindow()
75 disposeOnce();
78 void BaseWindow::dispose()
80 if (pShellVScrollBar && !pShellVScrollBar->isDisposed())
81 pShellVScrollBar->SetScrollHdl( Link<weld::Scrollbar&,void>() );
82 if (pShellHScrollBar && !pShellHScrollBar->isDisposed())
83 pShellHScrollBar->SetScrollHdl( Link<weld::Scrollbar&,void>() );
84 pShellVScrollBar.clear();
85 pShellHScrollBar.clear();
86 vcl::Window::dispose();
89 void BaseWindow::Init()
91 if ( pShellVScrollBar )
92 pShellVScrollBar->SetScrollHdl( LINK( this, BaseWindow, VertScrollHdl ) );
93 if ( pShellHScrollBar )
94 pShellHScrollBar->SetScrollHdl( LINK( this, BaseWindow, HorzScrollHdl ) );
96 // Show the read-only infobar if the module/dialog is read-only
97 GetShell()->GetViewFrame().RemoveInfoBar(BASIC_IDE_READONLY_INFOBAR);
98 if (IsReadOnly())
99 ShowReadOnlyInfoBar();
101 DoInit(); // virtual...
104 void BaseWindow::DoInit()
108 void BaseWindow::GrabScrollBars(ScrollAdaptor* pHScroll, ScrollAdaptor* pVScroll)
110 pShellHScrollBar = pHScroll;
111 pShellVScrollBar = pVScroll;
114 IMPL_LINK_NOARG(BaseWindow, VertScrollHdl, weld::Scrollbar&, void)
116 DoScroll(pShellVScrollBar);
119 IMPL_LINK_NOARG(BaseWindow, HorzScrollHdl, weld::Scrollbar&, void)
121 DoScroll(pShellHScrollBar);
124 void BaseWindow::ExecuteCommand (SfxRequest&)
128 void BaseWindow::ExecuteGlobal (SfxRequest&)
132 bool BaseWindow::EventNotify( NotifyEvent& rNEvt )
134 bool bDone = false;
136 if ( rNEvt.GetType() == NotifyEventType::KEYINPUT )
138 KeyEvent aKEvt = *rNEvt.GetKeyEvent();
139 vcl::KeyCode aCode = aKEvt.GetKeyCode();
140 sal_uInt16 nCode = aCode.GetCode();
142 switch ( nCode )
144 case KEY_PAGEUP:
145 case KEY_PAGEDOWN:
147 if ( aCode.IsMod1() )
149 if (Shell* pShell = GetShell())
150 pShell->NextPage( nCode == KEY_PAGEUP );
151 bDone = true;
154 break;
158 return bDone || Window::EventNotify( rNEvt );
161 void BaseWindow::ShowShellScrollBars(bool bVisible)
163 if (bVisible)
165 if (pShellHScrollBar)
167 pShellHScrollBar->Enable();
168 pShellHScrollBar->Show();
170 if (pShellVScrollBar)
172 pShellVScrollBar->Enable();
173 pShellVScrollBar->Show();
176 else
178 if (pShellHScrollBar)
180 pShellHScrollBar->Disable();
181 pShellHScrollBar->Hide();
183 if (pShellVScrollBar)
185 pShellVScrollBar->Disable();
186 pShellVScrollBar->Hide();
191 void BaseWindow::DoScroll( Scrollable* )
195 void BaseWindow::StoreData()
199 bool BaseWindow::AllowUndo()
201 return true;
204 void BaseWindow::UpdateData()
208 OUString BaseWindow::GetTitle()
210 return OUString();
213 OUString BaseWindow::CreateQualifiedName()
215 OUString aName;
216 if ( !m_aLibName.isEmpty() )
218 LibraryLocation eLocation = m_aDocument.getLibraryLocation( m_aLibName );
219 aName = m_aDocument.getTitle(eLocation) + "." + m_aLibName + "." +
220 GetTitle();
222 return aName;
225 void BaseWindow::SetReadOnly (bool)
229 bool BaseWindow::IsReadOnly ()
231 return false;
234 // Show the read-only warning messages for module and dialog windows
235 void BaseWindow::ShowReadOnlyInfoBar()
237 OUString aMsg;
238 if (dynamic_cast<ModulWindow*>(this))
239 aMsg = IDEResId(RID_STR_MODULE_READONLY);
240 else
241 aMsg = IDEResId(RID_STR_DIALOG_READONLY);
243 GetShell()->GetViewFrame().AppendInfoBar(BASIC_IDE_READONLY_INFOBAR, OUString(),
244 aMsg, InfobarType::INFO, true);
247 void BaseWindow::BasicStarted()
251 void BaseWindow::BasicStopped()
255 bool BaseWindow::IsModified ()
257 return true;
260 SfxUndoManager* BaseWindow::GetUndoManager()
262 return nullptr;
265 SearchOptionFlags BaseWindow::GetSearchOptions()
267 return SearchOptionFlags::NONE;
270 sal_uInt16 BaseWindow::StartSearchAndReplace (SvxSearchItem const&, bool)
272 return 0;
275 void BaseWindow::OnNewDocument ()
278 void BaseWindow::InsertLibInfo () const
280 if (ExtraData* pData = GetExtraData())
281 pData->GetLibInfo().InsertInfo(m_aDocument, m_aLibName, m_aName, GetType());
284 bool BaseWindow::Is (
285 ScriptDocument const& rDocument,
286 std::u16string_view rLibName, std::u16string_view rName,
287 ItemType eType, bool bFindSuspended
290 if (bFindSuspended || !IsSuspended())
292 // any non-suspended window is ok
293 if (rLibName.empty() || rName.empty() || eType == TYPE_UNKNOWN)
294 return true;
295 // ok if the parameters match
296 if (m_aDocument == rDocument && m_aLibName == rLibName && m_aName == rName && GetType() == eType)
297 return true;
299 return false;
302 bool BaseWindow::HasActiveEditor () const
304 return false;
308 // DockingWindow
311 // style bits for DockingWindow
312 WinBits const DockingWindow::StyleBits =
313 WB_BORDER | WB_3DLOOK | WB_CLIPCHILDREN |
314 WB_MOVEABLE | WB_SIZEABLE | WB_DOCKABLE;
316 DockingWindow::DockingWindow(vcl::Window* pParent, const OUString& rUIXMLDescription, const OUString& rID)
317 : ResizableDockingWindow(pParent)
318 , m_xBuilder(Application::CreateInterimBuilder(m_xBox.get(), rUIXMLDescription, true))
319 , pLayout(nullptr)
320 , nShowCount(0)
322 m_xContainer = m_xBuilder->weld_container(rID);
325 DockingWindow::DockingWindow (Layout* pParent)
326 : ResizableDockingWindow(pParent, StyleBits)
327 , pLayout(pParent)
328 , nShowCount(0)
331 DockingWindow::~DockingWindow()
333 disposeOnce();
336 void DockingWindow::dispose()
338 m_xContainer.reset();
339 m_xBuilder.reset();
340 pLayout.clear();
341 ResizableDockingWindow::dispose();
344 // Sets the position and the size of the docking window. This property is saved
345 // when the window is floating. Called by Layout.
346 void DockingWindow::ResizeIfDocking (Point const& rPos, Size const& rSize)
348 tools::Rectangle const rRect(rPos, rSize);
349 if (rRect != aDockingRect)
351 // saving the position and the size
352 aDockingRect = rRect;
353 // resizing if actually docking
354 if (!IsFloatingMode())
355 SetPosSizePixel(rPos, rSize);
358 void DockingWindow::ResizeIfDocking (Size const& rSize)
360 ResizeIfDocking(aDockingRect.TopLeft(), rSize);
363 // Sets the parent Layout window.
364 // The physical parent is set only when the window is docking.
365 void DockingWindow::SetLayoutWindow (Layout* pLayout_)
367 pLayout = pLayout_;
368 if (!IsFloatingMode())
369 SetParent(pLayout);
373 // Increases the "show" reference count.
374 // The window is shown when the reference count is positive.
375 void DockingWindow::Show (bool bShow) // = true
377 if (bShow)
379 if (++nShowCount == 1)
380 ResizableDockingWindow::Show();
382 else
384 if (--nShowCount == 0)
385 ResizableDockingWindow::Hide();
389 // Decreases the "show" reference count.
390 // The window is hidden when the reference count reaches zero.
391 void DockingWindow::Hide ()
393 Show(false);
396 bool DockingWindow::Docking( const Point& rPos, tools::Rectangle& rRect )
398 if (aDockingRect.Contains(rPos))
400 rRect.SetSize(aDockingRect.GetSize());
401 return false; // dock
403 else // adjust old size
405 if (!aFloatingRect.IsEmpty())
406 rRect.SetSize(aFloatingRect.GetSize());
407 return true; // float
411 void DockingWindow::EndDocking( const tools::Rectangle& rRect, bool bFloatMode )
413 if ( bFloatMode )
414 ResizableDockingWindow::EndDocking( rRect, bFloatMode );
415 else
417 SetFloatingMode(false);
418 DockThis();
422 void DockingWindow::ToggleFloatingMode()
424 if (IsFloatingMode())
426 if (!aFloatingRect.IsEmpty())
427 SetPosSizePixel(
428 GetParent()->ScreenToOutputPixel(aFloatingRect.TopLeft()),
429 aFloatingRect.GetSize()
432 DockThis();
435 bool DockingWindow::PrepareToggleFloatingMode()
437 if (IsFloatingMode())
439 // memorize position and size on the desktop...
440 aFloatingRect = tools::Rectangle(
441 GetParent()->OutputToScreenPixel(GetPosPixel()),
442 GetSizePixel()
445 return true;
448 void DockingWindow::StartDocking()
450 if (IsFloatingMode())
452 aFloatingRect = tools::Rectangle(
453 GetParent()->OutputToScreenPixel(GetPosPixel()),
454 GetSizePixel()
459 void DockingWindow::DockThis ()
461 // resizing when floating -> docking
462 if (!IsFloatingMode())
464 Point const aPos = aDockingRect.TopLeft();
465 Size const aSize = aDockingRect.GetSize();
466 if (aSize != GetSizePixel() || aPos != GetPosPixel())
467 SetPosSizePixel(aPos, aSize);
470 if (pLayout)
472 if (!IsFloatingMode() && GetParent() != pLayout)
473 SetParent(pLayout);
474 pLayout->ArrangeWindows();
478 TabBar::TabBar( vcl::Window* pParent ) :
479 ::TabBar( pParent, WinBits( WB_3DLOOK | WB_SCROLL | WB_BORDER | WB_DRAG ) )
481 EnableEditMode();
483 SetHelpId( HID_BASICIDE_TABBAR );
486 void TabBar::MouseButtonDown( const MouseEvent& rMEvt )
488 if ( rMEvt.IsLeft() && ( rMEvt.GetClicks() == 2 ) && !IsInEditMode() )
490 if (SfxDispatcher* pDispatcher = GetDispatcher())
491 pDispatcher->Execute( SID_BASICIDE_MODULEDLG );
493 else
495 ::TabBar::MouseButtonDown( rMEvt ); // base class version
499 void TabBar::Command( const CommandEvent& rCEvt )
501 if ( ( rCEvt.GetCommand() == CommandEventId::ContextMenu ) && !IsInEditMode() )
503 Point aPos( rCEvt.IsMouseEvent() ? rCEvt.GetMousePosPixel() : Point(1,1) );
504 if ( rCEvt.IsMouseEvent() ) // select right tab
506 Point aP = PixelToLogic( aPos );
507 MouseEvent aMouseEvent( aP, 1, MouseEventModifiers::SIMPLECLICK, MOUSE_LEFT );
508 ::TabBar::MouseButtonDown( aMouseEvent ); // base class
510 if (SfxDispatcher* pDispatcher = GetDispatcher())
511 pDispatcher->ExecutePopup("tabbar", this, &aPos);
515 TabBarAllowRenamingReturnCode TabBar::AllowRenaming()
517 bool const bValid = IsValidSbxName(GetEditText());
519 if ( !bValid )
521 std::unique_ptr<weld::MessageDialog> xError(Application::CreateMessageDialog(GetFrameWeld(),
522 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_BADSBXNAME)));
523 xError->run();
526 return bValid ? TABBAR_RENAMING_YES : TABBAR_RENAMING_NO;
530 void TabBar::EndRenaming()
532 if ( !IsEditModeCanceled() )
534 SfxUInt16Item aID( SID_BASICIDE_ARG_TABID, GetEditPageId() );
535 SfxStringItem aNewName( SID_BASICIDE_ARG_MODULENAME, GetEditText() );
536 if (SfxDispatcher* pDispatcher = GetDispatcher())
537 pDispatcher->ExecuteList( SID_BASICIDE_NAMECHANGEDONTAB,
538 SfxCallMode::SYNCHRON, { &aID, &aNewName });
543 namespace
546 // helper class for sorting TabBar
547 struct TabBarSortHelper
549 sal_uInt16 nPageId;
550 OUString aPageText;
552 bool operator < (TabBarSortHelper const& rComp) const
554 return aPageText.compareToIgnoreAsciiCase(rComp.aPageText) < 0;
558 } // namespace
560 void TabBar::Sort()
562 Shell* pShell = GetShell();
563 if (!pShell)
564 return;
566 Shell::WindowTable& aWindowTable = pShell->GetWindowTable();
567 TabBarSortHelper aTabBarSortHelper;
568 std::vector<TabBarSortHelper> aModuleList;
569 std::vector<TabBarSortHelper> aDialogList;
570 sal_uInt16 nPageCount = GetPageCount();
571 sal_uInt16 i;
573 // create module and dialog lists for sorting
574 for ( i = 0; i < nPageCount; i++)
576 sal_uInt16 nId = GetPageId( i );
577 aTabBarSortHelper.nPageId = nId;
578 aTabBarSortHelper.aPageText = GetPageText( nId );
579 BaseWindow* pWin = aWindowTable[ nId ].get();
581 if (dynamic_cast<ModulWindow*>(pWin))
583 aModuleList.push_back( aTabBarSortHelper );
585 else if (dynamic_cast<DialogWindow*>(pWin))
587 aDialogList.push_back( aTabBarSortHelper );
591 // sort module and dialog lists by page text
592 std::sort( aModuleList.begin() , aModuleList.end() );
593 std::sort( aDialogList.begin() , aDialogList.end() );
596 sal_uInt16 nModules = sal::static_int_cast<sal_uInt16>( aModuleList.size() );
597 sal_uInt16 nDialogs = sal::static_int_cast<sal_uInt16>( aDialogList.size() );
599 // move module pages to new positions
600 for (i = 0; i < nModules; i++)
602 MovePage( aModuleList[i].nPageId , i );
605 // move dialog pages to new positions
606 for (i = 0; i < nDialogs; i++)
608 MovePage( aDialogList[i].nPageId , nModules + i );
612 void CutLines( OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines )
614 sal_Int32 nStartPos = 0;
615 sal_Int32 nLine = 0;
616 while ( nLine < nStartLine )
618 nStartPos = searchEOL( rStr, nStartPos );
619 if( nStartPos == -1 )
620 break;
621 nStartPos++; // not the \n.
622 nLine++;
625 SAL_WARN_IF( nStartPos == -1, "basctl.basicide", "CutLines: Start line not found!" );
627 if ( nStartPos == -1 )
628 return;
630 sal_Int32 nEndPos = nStartPos;
632 for ( sal_Int32 i = 0; i < nLines; i++ )
633 nEndPos = searchEOL( rStr, nEndPos+1 );
635 if ( nEndPos == -1 ) // might happen at the last line
636 nEndPos = rStr.getLength();
637 else
638 nEndPos++;
640 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( nEndPos );
642 // erase trailing empty lines
644 sal_Int32 n = nStartPos;
645 sal_Int32 nLen = rStr.getLength();
646 while ( ( n < nLen ) && ( rStr[ n ] == LINE_SEP ||
647 rStr[ n ] == LINE_SEP_CR ) )
649 n++;
652 if ( n > nStartPos )
654 rStr = OUString::Concat(rStr.subView( 0, nStartPos )) + rStr.subView( n );
659 sal_uInt32 CalcLineCount( SvStream& rStream )
661 sal_uInt32 nLFs = 0;
662 sal_uInt32 nCRs = 0;
663 char c;
665 rStream.Seek( 0 );
666 rStream.ReadChar( c );
667 while ( !rStream.eof() )
669 if ( c == '\n' )
670 nLFs++;
671 else if ( c == '\r' )
672 nCRs++;
673 rStream.ReadChar( c );
676 rStream.Seek( 0 );
677 if ( nLFs > nCRs )
678 return nLFs;
679 return nCRs;
683 // LibInfo
686 LibInfo::LibInfo ()
689 LibInfo::~LibInfo ()
692 void LibInfo::InsertInfo (
693 ScriptDocument const& rDocument,
694 OUString const& rLibName,
695 OUString const& rCurrentName,
696 ItemType eCurrentType
699 Key aKey(rDocument, rLibName);
700 m_aMap.erase(aKey);
701 m_aMap.emplace(aKey, Item(rCurrentName, eCurrentType));
704 void LibInfo::RemoveInfoFor (ScriptDocument const& rDocument)
706 Map::iterator it = std::find_if(m_aMap.begin(), m_aMap.end(),
707 [&rDocument](Map::reference rEntry) { return rEntry.first.GetDocument() == rDocument; });
708 if (it != m_aMap.end())
709 m_aMap.erase(it);
712 LibInfo::Item const* LibInfo::GetInfo (
713 ScriptDocument const& rDocument, OUString const& rLibName
716 Map::iterator it = m_aMap.find(Key(rDocument, rLibName));
717 return it != m_aMap.end() ? &it->second : nullptr;
720 LibInfo::Key::Key (ScriptDocument aDocument, OUString aLibName) :
721 m_aDocument(std::move(aDocument)), m_aLibName(std::move(aLibName))
724 bool LibInfo::Key::operator == (Key const& rKey) const
726 return m_aDocument == rKey.m_aDocument && m_aLibName == rKey.m_aLibName;
729 size_t LibInfo::Key::Hash::operator () (Key const& rKey) const
731 std::size_t seed = 0;
732 o3tl::hash_combine(seed, rKey.m_aDocument.hashCode());
733 o3tl::hash_combine(seed, rKey.m_aLibName.hashCode());
734 return seed;
737 LibInfo::Item::Item (
738 OUString aCurrentName,
739 ItemType eCurrentType
741 m_aCurrentName(std::move(aCurrentName)),
742 m_eCurrentType(eCurrentType)
745 static bool QueryDel(std::u16string_view rName, const OUString &rStr, weld::Widget* pParent)
747 OUString aName = OUString::Concat("\'") + rName + "\'";
748 OUString aQuery = rStr.replaceAll("XX", aName);
749 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pParent,
750 VclMessageType::Question, VclButtonsType::YesNo, aQuery));
751 return (xQueryBox->run() == RET_YES);
754 bool QueryDelMacro( std::u16string_view rName, weld::Widget* pParent )
756 return QueryDel( rName, IDEResId( RID_STR_QUERYDELMACRO ), pParent );
759 bool QueryReplaceMacro( std::u16string_view rName, weld::Widget* pParent )
761 return QueryDel( rName, IDEResId( RID_STR_QUERYREPLACEMACRO ), pParent );
764 bool QueryDelDialog( std::u16string_view rName, weld::Widget* pParent )
766 return QueryDel( rName, IDEResId( RID_STR_QUERYDELDIALOG ), pParent );
769 bool QueryDelLib( std::u16string_view rName, bool bRef, weld::Widget* pParent )
771 return QueryDel( rName, IDEResId( bRef ? RID_STR_QUERYDELLIBREF : RID_STR_QUERYDELLIB ), pParent );
774 bool QueryDelModule( std::u16string_view rName, weld::Widget* pParent )
776 return QueryDel( rName, IDEResId( RID_STR_QUERYDELMODULE ), pParent );
779 bool QueryPassword(weld::Widget* pDialogParent, const Reference< script::XLibraryContainer >& xLibContainer, const OUString& rLibName, OUString& rPassword, bool bRepeat, bool bNewTitle)
781 bool bOK = false;
782 sal_uInt16 nRet = 0;
786 // password dialog
787 SfxPasswordDialog aDlg(pDialogParent);
788 aDlg.SetMinLen(1);
790 // set new title
791 if ( bNewTitle )
793 OUString aTitle(IDEResId(RID_STR_ENTERPASSWORD));
794 aTitle = aTitle.replaceAll("XX", rLibName);
795 aDlg.set_title(aTitle);
798 // execute dialog
799 nRet = aDlg.run();
801 // verify password
802 if ( nRet == RET_OK )
804 if ( xLibContainer.is() && xLibContainer->hasByName( rLibName ) )
806 Reference< script::XLibraryContainerPassword > xPasswd( xLibContainer, UNO_QUERY );
807 if ( xPasswd.is() && xPasswd->isLibraryPasswordProtected( rLibName ) && !xPasswd->isLibraryPasswordVerified( rLibName ) )
809 rPassword = aDlg.GetPassword();
810 bOK = xPasswd->verifyLibraryPassword( rLibName, rPassword );
812 if ( !bOK )
814 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pDialogParent,
815 VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_WRONGPASSWORD)));
816 xErrorBox->run();
822 while ( bRepeat && !bOK && nRet == RET_OK );
824 return bOK;
828 } // namespace basctl
830 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */