1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
25 #include <strings.hrc>
26 #include <bitmaps.hlst>
28 #include "baside2.hxx"
30 #include <iderdll.hxx>
32 #include <basic/sbmeth.hxx>
33 #include <basic/sbuno.hxx>
34 #include <com/sun/star/beans/XMultiPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertiesChangeListener.hpp>
36 #include <com/sun/star/script/XLibraryContainer2.hpp>
37 #include <comphelper/string.hxx>
38 #include <officecfg/Office/Common.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <vcl/weld.hxx>
41 #include <svl/urihelper.hxx>
42 #include <svx/svxids.hrc>
43 #include <vcl/xtextedt.hxx>
44 #include <vcl/txtattr.hxx>
45 #include <vcl/settings.hxx>
46 #include <svtools/textwindowpeer.hxx>
47 #include <svtools/treelistentry.hxx>
48 #include <vcl/taskpanelist.hxx>
49 #include <vcl/help.hxx>
50 #include <cppuhelper/implbase.hxx>
52 #include <com/sun/star/reflection/theCoreReflection.hpp>
57 using namespace ::com::sun::star
;
58 using namespace ::com::sun::star::uno
;
63 sal_uInt16
const NoMarker
= 0xFFFF;
64 long const nBasePad
= 2;
65 long const nCursorPad
= 5;
67 long nVirtToolBoxHeight
; // inited in WatchWindow, used in Stackwindow
68 long nHeaderBarHeight
;
70 // Returns pBase converted to SbxVariable if valid and is not an SbxMethod.
71 SbxVariable
* IsSbxVariable (SbxBase
* pBase
)
73 if (SbxVariable
* pVar
= dynamic_cast<SbxVariable
*>(pBase
))
74 if (!dynamic_cast<SbxMethod
*>(pVar
))
79 Image
GetImage(const OUString
& rId
)
81 return Image(BitmapEx(rId
));
84 int const nScrollLine
= 12;
85 int const nScrollPage
= 60;
86 int const DWBORDER
= 3;
88 char const cSuffixes
[] = "%&!#@$";
94 * Helper functions to get/set text in TextEngine using
95 * the stream interface.
97 * get/setText() only supports tools Strings limited to 64K).
99 OUString
getTextEngineText (ExtTextEngine
& rEngine
)
101 SvMemoryStream aMemStream
;
102 aMemStream
.SetStreamCharSet( RTL_TEXTENCODING_UTF8
);
103 aMemStream
.SetLineDelimiter( LINEEND_LF
);
104 rEngine
.Write( aMemStream
);
105 std::size_t nSize
= aMemStream
.Tell();
106 OUString
aText( static_cast<const sal_Char
*>(aMemStream
.GetData()),
107 nSize
, RTL_TEXTENCODING_UTF8
);
111 void setTextEngineText (ExtTextEngine
& rEngine
, OUString
const& aStr
)
113 rEngine
.SetText(OUString());
114 OString aUTF8Str
= OUStringToOString( aStr
, RTL_TEXTENCODING_UTF8
);
115 SvMemoryStream
aMemStream( const_cast<char *>(aUTF8Str
.getStr()), aUTF8Str
.getLength(),
117 aMemStream
.SetStreamCharSet( RTL_TEXTENCODING_UTF8
);
118 aMemStream
.SetLineDelimiter( LINEEND_LF
);
119 rEngine
.Read(aMemStream
);
125 void lcl_DrawIDEWindowFrame(DockingWindow
const * pWin
, vcl::RenderContext
& rRenderContext
)
127 if (pWin
->IsFloatingMode())
130 Size
aSz(pWin
->GetOutputSizePixel());
131 const Color
aOldLineColor(rRenderContext
.GetLineColor());
132 rRenderContext
.SetLineColor(COL_WHITE
);
134 rRenderContext
.DrawLine(Point(0, 0), Point(aSz
.Width(), 0));
135 // Black line at bottom
136 rRenderContext
.SetLineColor(COL_BLACK
);
137 rRenderContext
.DrawLine(Point(0, aSz
.Height() - 1),
138 Point(aSz
.Width(), aSz
.Height() - 1));
139 rRenderContext
.SetLineColor(aOldLineColor
);
142 void lcl_SeparateNameAndIndex( const OUString
& rVName
, OUString
& rVar
, OUString
& rIndex
)
146 sal_Int32 nIndexStart
= rVar
.indexOf( '(' );
147 if ( nIndexStart
!= -1 )
149 sal_Int32 nIndexEnd
= rVar
.indexOf( ')', nIndexStart
);
150 if ( nIndexStart
!= -1 )
152 rIndex
= rVar
.copy( nIndexStart
+1, nIndexEnd
-nIndexStart
-1 );
153 rVar
= rVar
.copy( 0, nIndexStart
);
154 rVar
= comphelper::string::stripEnd(rVar
, ' ');
155 rIndex
= comphelper::string::strip(rIndex
, ' ');
159 if ( !rVar
.isEmpty() )
161 sal_uInt16 nLastChar
= rVar
.getLength()-1;
162 if ( strchr( cSuffixes
, rVar
[ nLastChar
] ) )
163 rVar
= rVar
.replaceAt( nLastChar
, 1, "" );
165 if ( !rIndex
.isEmpty() )
167 sal_uInt16 nLastChar
= rIndex
.getLength()-1;
168 if ( strchr( cSuffixes
, rIndex
[ nLastChar
] ) )
169 rIndex
= rIndex
.replaceAt( nLastChar
, 1, "" );
179 class EditorWindow::ChangesListener
:
180 public cppu::WeakImplHelper
< beans::XPropertiesChangeListener
>
183 explicit ChangesListener(EditorWindow
& editor
): editor_(editor
) {}
186 virtual ~ChangesListener() override
{}
188 virtual void SAL_CALL
disposing(lang::EventObject
const &) override
190 osl::MutexGuard
g(editor_
.mutex_
);
191 editor_
.notifier_
.clear();
194 virtual void SAL_CALL
propertiesChange(
195 Sequence
< beans::PropertyChangeEvent
> const &) override
198 editor_
.ImplSetFont();
201 EditorWindow
& editor_
;
204 class EditorWindow::ProgressInfo
: public SfxProgress
207 ProgressInfo (SfxObjectShell
* pObjSh
, OUString
const& rText
, sal_uInt32 nRange
) :
208 SfxProgress(pObjSh
, rText
, nRange
),
214 SetState(++nCurState
);
221 EditorWindow::EditorWindow (vcl::Window
* pParent
, ModulWindow
* pModulWindow
) :
222 Window(pParent
, WB_BORDER
),
223 rModulWindow(*pModulWindow
),
225 aHighlighter(HighlighterLanguage::Basic
),
226 bHighlighting(false),
227 bDoSyntaxHighlight(true),
228 bDelayHighlight(true),
229 pCodeCompleteWnd(VclPtr
<CodeCompleteWindow
>::Create(this))
231 SetBackground(Wallpaper(rModulWindow
.GetLayout().GetBackgroundColor()));
232 SetPointer( Pointer( PointerStyle::Text
) );
233 SetHelpId( HID_BASICIDE_EDITORWINDOW
);
235 listener_
= new ChangesListener(*this);
236 Reference
< beans::XMultiPropertySet
> n(
237 officecfg::Office::Common::Font::SourceViewFont::get(),
240 osl::MutexGuard
g(mutex_
);
243 const Sequence
<OUString
> aPropertyNames
{"FontHeight", "FontName"};
244 n
->addPropertiesChangeListener(aPropertyNames
, listener_
.get());
248 EditorWindow::~EditorWindow()
253 void EditorWindow::dispose()
255 Reference
< beans::XMultiPropertySet
> n
;
257 osl::MutexGuard
g(mutex_
);
261 n
->removePropertiesChangeListener(listener_
.get());
268 EndListening( *pEditEngine
);
269 pEditEngine
->RemoveView(pEditView
.get());
271 pCodeCompleteWnd
.disposeAndClear();
272 vcl::Window::dispose();
275 OUString
EditorWindow::GetWordAtCursor()
281 TextEngine
* pTextEngine
= pEditView
->GetTextEngine();
284 // check first, if the cursor is at a help URL
285 const TextSelection
& rSelection
= pEditView
->GetSelection();
286 const TextPaM
& rSelStart
= rSelection
.GetStart();
287 const TextPaM
& rSelEnd
= rSelection
.GetEnd();
288 OUString aText
= pTextEngine
->GetText( rSelEnd
.GetPara() );
289 CharClass
aClass( ::comphelper::getProcessComponentContext() , Application::GetSettings().GetLanguageTag() );
290 sal_Int32 nSelStart
= rSelStart
.GetIndex();
291 sal_Int32 nSelEnd
= rSelEnd
.GetIndex();
292 sal_Int32 nLength
= aText
.getLength();
293 sal_Int32 nStart
= 0;
294 sal_Int32 nEnd
= nLength
;
295 while ( nStart
< nLength
)
297 OUString
aURL( URIHelper::FindFirstURLInText( aText
, nStart
, nEnd
, aClass
) );
298 INetURLObject
aURLObj( aURL
);
299 if ( aURLObj
.GetProtocol() == INetProtocol::VndSunStarHelp
300 && nSelStart
>= nStart
&& nSelStart
<= nEnd
&& nSelEnd
>= nStart
&& nSelEnd
<= nEnd
)
309 // Not the selected range, but at the CursorPosition,
310 // if a word is partially selected.
311 if ( aWord
.isEmpty() )
312 aWord
= pTextEngine
->GetWord( rSelEnd
);
314 // Can be empty when full word selected, as Cursor behind it
315 if ( aWord
.isEmpty() && pEditView
->HasSelection() )
316 aWord
= pTextEngine
->GetWord( rSelStart
);
323 void EditorWindow::RequestHelp( const HelpEvent
& rHEvt
)
327 // Should have been activated at some point
330 if ( rHEvt
.GetMode() & HelpEventMode::CONTEXT
)
332 OUString aKeyword
= GetWordAtCursor();
333 Application::GetHelp()->SearchKeyword( aKeyword
);
336 else if ( rHEvt
.GetMode() & HelpEventMode::QUICK
)
340 if ( StarBASIC::IsRunning() )
342 Point aWindowPos
= rHEvt
.GetMousePosPixel();
343 aWindowPos
= ScreenToOutputPixel( aWindowPos
);
344 Point aDocPos
= GetEditView()->GetDocPos( aWindowPos
);
345 TextPaM aCursor
= GetEditView()->GetTextEngine()->GetPaM(aDocPos
);
346 TextPaM aStartOfWord
;
347 OUString aWord
= GetEditView()->GetTextEngine()->GetWord( aCursor
, &aStartOfWord
);
348 if ( !aWord
.isEmpty() && !comphelper::string::isdigitAsciiString(aWord
) )
350 sal_uInt16 nLastChar
= aWord
.getLength() - 1;
351 if ( strchr( cSuffixes
, aWord
[ nLastChar
] ) )
352 aWord
= aWord
.replaceAt( nLastChar
, 1, "" );
353 SbxBase
* pSBX
= StarBASIC::FindSBXInCurrentScope( aWord
);
354 if (SbxVariable
const* pVar
= IsSbxVariable(pSBX
))
356 SbxDataType eType
= pVar
->GetType();
357 if ( static_cast<sal_uInt8
>(eType
) == sal_uInt8(SbxOBJECT
) )
358 // might cause a crash e. g. at the selections-object
359 // Type == Object does not mean pVar == Object!
360 ; // aHelpText = ((SbxObject*)pVar)->GetClassName();
361 else if ( eType
& SbxARRAY
)
362 ; // aHelpText = "{...}";
363 else if ( static_cast<sal_uInt8
>(eType
) != sal_uInt8(SbxEMPTY
) )
365 aHelpText
= pVar
->GetName();
366 if ( aHelpText
.isEmpty() ) // name is not copied with the passed parameters
368 aHelpText
+= "=" + pVar
->GetOUString();
371 if ( !aHelpText
.isEmpty() )
373 aTopLeft
= GetEditView()->GetTextEngine()->PaMtoEditCursor( aStartOfWord
).BottomLeft();
374 aTopLeft
= GetEditView()->GetWindowPos( aTopLeft
);
375 aTopLeft
.AdjustX(5 );
376 aTopLeft
.AdjustY(5 );
377 aTopLeft
= OutputToScreenPixel( aTopLeft
);
381 Help::ShowQuickHelp( this, tools::Rectangle( aTopLeft
, Size( 1, 1 ) ), aHelpText
, QuickHelpFlags::Top
|QuickHelpFlags::Left
);
387 Window::RequestHelp( rHEvt
);
391 void EditorWindow::Resize()
393 // ScrollBars, etc. happens in Adjust...
396 long nVisY
= pEditView
->GetStartDocPos().Y();
398 pEditView
->ShowCursor();
399 Size
aOutSz( GetOutputSizePixel() );
400 long nMaxVisAreaStart
= pEditView
->GetTextEngine()->GetTextHeight() - aOutSz
.Height();
401 if ( nMaxVisAreaStart
< 0 )
402 nMaxVisAreaStart
= 0;
403 if ( pEditView
->GetStartDocPos().Y() > nMaxVisAreaStart
)
405 Point
aStartDocPos( pEditView
->GetStartDocPos() );
406 aStartDocPos
.setY( nMaxVisAreaStart
);
407 pEditView
->SetStartDocPos( aStartDocPos
);
408 pEditView
->ShowCursor();
409 rModulWindow
.GetBreakPointWindow().GetCurYOffset() = aStartDocPos
.Y();
410 rModulWindow
.GetLineNumberWindow().GetCurYOffset() = aStartDocPos
.Y();
413 if ( nVisY
!= pEditView
->GetStartDocPos().Y() )
419 void EditorWindow::MouseMove( const MouseEvent
&rEvt
)
422 pEditView
->MouseMove( rEvt
);
426 void EditorWindow::MouseButtonUp( const MouseEvent
&rEvt
)
430 pEditView
->MouseButtonUp( rEvt
);
431 if (SfxBindings
* pBindings
= GetBindingsPtr())
433 pBindings
->Invalidate( SID_BASICIDE_STAT_POS
);
434 pBindings
->Invalidate( SID_BASICIDE_STAT_TITLE
);
439 void EditorWindow::MouseButtonDown( const MouseEvent
&rEvt
)
443 pEditView
->MouseButtonDown( rEvt
);
444 if( pCodeCompleteWnd
->IsVisible() )
446 if( pEditView
->GetSelection() != pCodeCompleteWnd
->GetTextSelection() )
447 {//selection changed, code complete window should be hidden
448 pCodeCompleteWnd
->GetListBox()->HideAndRestoreFocus();
453 void EditorWindow::Command( const CommandEvent
& rCEvt
)
457 pEditView
->Command( rCEvt
);
458 if ( ( rCEvt
.GetCommand() == CommandEventId::Wheel
) ||
459 ( rCEvt
.GetCommand() == CommandEventId::StartAutoScroll
) ||
460 ( rCEvt
.GetCommand() == CommandEventId::AutoScroll
) )
462 HandleScrollCommand( rCEvt
, rModulWindow
.GetHScrollBar(), &rModulWindow
.GetEditVScrollBar() );
463 } else if ( rCEvt
.GetCommand() == CommandEventId::ContextMenu
) {
464 SfxDispatcher
* pDispatcher
= GetDispatcher();
467 SfxDispatcher::ExecutePopup();
469 if( pCodeCompleteWnd
->IsVisible() ) // hide the code complete window
470 pCodeCompleteWnd
->ClearAndHide();
475 bool EditorWindow::ImpCanModify()
477 bool bCanModify
= true;
478 if ( StarBASIC::IsRunning() && rModulWindow
.GetBasicStatus().bIsRunning
)
480 // If in Trace-mode, abort the trace or refuse input
481 // Remove markers in the modules in Notify at Basic::Stopped
482 std::unique_ptr
<weld::MessageDialog
> xQueryBox(Application::CreateMessageDialog(nullptr,
483 VclMessageType::Question
, VclButtonsType::OkCancel
,
484 IDEResId(RID_STR_WILLSTOPPRG
)));
485 if (xQueryBox
->run() == RET_OK
)
487 rModulWindow
.GetBasicStatus().bIsRunning
= false;
496 void EditorWindow::KeyInput( const KeyEvent
& rKEvt
)
498 if ( !pEditView
) // Happens in Win95
501 bool const bWasModified
= pEditEngine
->IsModified();
502 // see if there is an accelerator to be processed first
503 SfxViewShell
*pVS( SfxViewShell::Current());
504 bool bDone
= pVS
&& pVS
->KeyInput( rKEvt
);
506 if( pCodeCompleteWnd
->IsVisible() && CodeCompleteOptions::IsCodeCompleteOn() )
508 pCodeCompleteWnd
->GetListBox()->KeyInput(rKEvt
);
509 if( rKEvt
.GetKeyCode().GetCode() == KEY_UP
510 || rKEvt
.GetKeyCode().GetCode() == KEY_DOWN
511 || rKEvt
.GetKeyCode().GetCode() == KEY_TAB
512 || rKEvt
.GetKeyCode().GetCode() == KEY_POINT
)
516 if( (rKEvt
.GetKeyCode().GetCode() == KEY_SPACE
||
517 rKEvt
.GetKeyCode().GetCode() == KEY_TAB
||
518 rKEvt
.GetKeyCode().GetCode() == KEY_RETURN
) && CodeCompleteOptions::IsAutoCorrectOn() )
523 if( rKEvt
.GetCharCode() == '"' && CodeCompleteOptions::IsAutoCloseQuotesOn() )
524 {//autoclose double quotes
525 HandleAutoCloseDoubleQuotes();
528 if( rKEvt
.GetCharCode() == '(' && CodeCompleteOptions::IsAutoCloseParenthesisOn() )
529 {//autoclose parenthesis
530 HandleAutoCloseParen();
533 if( rKEvt
.GetKeyCode().GetCode() == KEY_RETURN
&& CodeCompleteOptions::IsProcedureAutoCompleteOn() )
534 {//autoclose implementation
535 HandleProcedureCompletion();
538 if( rKEvt
.GetKeyCode().GetCode() == KEY_POINT
&& CodeCompleteOptions::IsCodeCompleteOn() )
540 HandleCodeCompletion();
542 if ( !bDone
&& ( !TextEngine::DoesKeyChangeText( rKEvt
) || ImpCanModify() ) )
544 if ( ( rKEvt
.GetKeyCode().GetCode() == KEY_TAB
) && !rKEvt
.GetKeyCode().IsMod1() &&
545 !rKEvt
.GetKeyCode().IsMod2() && !GetEditView()->IsReadOnly() )
547 TextSelection
aSel( pEditView
->GetSelection() );
548 if ( aSel
.GetStart().GetPara() != aSel
.GetEnd().GetPara() )
550 bDelayHighlight
= false;
551 if ( !rKEvt
.GetKeyCode().IsShift() )
552 pEditView
->IndentBlock();
554 pEditView
->UnindentBlock();
555 bDelayHighlight
= true;
560 bDone
= pEditView
->KeyInput( rKEvt
);
564 Window::KeyInput( rKEvt
);
568 if (SfxBindings
* pBindings
= GetBindingsPtr())
570 pBindings
->Invalidate( SID_BASICIDE_STAT_POS
);
571 pBindings
->Invalidate( SID_BASICIDE_STAT_TITLE
);
572 if ( rKEvt
.GetKeyCode().GetGroup() == KEYGROUP_CURSOR
)
574 pBindings
->Update( SID_BASICIDE_STAT_POS
);
575 pBindings
->Update( SID_BASICIDE_STAT_TITLE
);
577 if ( !bWasModified
&& pEditEngine
->IsModified() )
579 pBindings
->Invalidate( SID_SAVEDOC
);
580 pBindings
->Invalidate( SID_DOC_MODIFIED
);
581 pBindings
->Invalidate( SID_UNDO
);
583 if ( rKEvt
.GetKeyCode().GetCode() == KEY_INSERT
)
584 pBindings
->Invalidate( SID_ATTR_INSERT
);
589 void EditorWindow::HandleAutoCorrect()
591 TextSelection aSel
= GetEditView()->GetSelection();
592 const sal_uInt32 nLine
= aSel
.GetStart().GetPara();
593 const sal_Int32 nIndex
= aSel
.GetStart().GetIndex();
594 OUString
aLine( pEditEngine
->GetText( nLine
) ); // the line being modified
595 const OUString
& sActSubName
= GetActualSubName( nLine
); // the actual procedure
597 std::vector
<HighlightPortion
> aPortions
;
598 aHighlighter
.getHighlightPortions( aLine
, aPortions
);
600 if( aPortions
.empty() )
603 HighlightPortion
& r
= aPortions
.back();
604 if( static_cast<size_t>(nIndex
) != aPortions
.size()-1 )
605 {//cursor is not standing at the end of the line
606 for (auto const& portion
: aPortions
)
608 if( portion
.nEnd
== nIndex
)
616 OUString sStr
= aLine
.copy( r
.nBegin
, r
.nEnd
- r
.nBegin
);
617 //if WS or empty string: stop, nothing to do
618 if( ( r
.tokenType
== TokenType::Whitespace
) || sStr
.isEmpty() )
620 //create the appropriate TextSelection, and update the cache
621 TextPaM
aStart( nLine
, r
.nBegin
);
622 TextPaM
aEnd( nLine
, r
.nBegin
+ sStr
.getLength() );
623 TextSelection
sTextSelection( aStart
, aEnd
);
624 rModulWindow
.UpdateModule();
625 rModulWindow
.GetSbModule()->GetCodeCompleteDataFromParse( aCodeCompleteCache
);
626 // correct the last entered keyword
627 if( r
.tokenType
== TokenType::Keywords
)
629 sStr
= sStr
.toAsciiLowerCase();
630 if( !SbModule::GetKeywordCase(sStr
).isEmpty() )
631 // if it is a keyword, get its correct case
632 sStr
= SbModule::GetKeywordCase(sStr
);
634 // else capitalize first letter/select the correct one, and replace
635 sStr
= sStr
.replaceAt( 0, 1, OUString(sStr
[0]).toAsciiUpperCase() );
637 pEditEngine
->ReplaceText( sTextSelection
, sStr
);
638 pEditView
->SetSelection( aSel
);
640 if( r
.tokenType
== TokenType::Identifier
)
641 {// correct variables
642 if( !aCodeCompleteCache
.GetCorrectCaseVarName( sStr
, sActSubName
).isEmpty() )
644 sStr
= aCodeCompleteCache
.GetCorrectCaseVarName( sStr
, sActSubName
);
645 pEditEngine
->ReplaceText( sTextSelection
, sStr
);
646 pEditView
->SetSelection( aSel
);
650 //autocorrect procedures
651 SbxArray
* pArr
= rModulWindow
.GetSbModule()->GetMethods().get();
652 for( sal_uInt32 i
=0; i
< pArr
->Count32(); ++i
)
654 if( pArr
->Get32(i
)->GetName().equalsIgnoreAsciiCase( sStr
) )
656 sStr
= pArr
->Get32(i
)->GetName(); //if found, get the correct case
657 pEditEngine
->ReplaceText( sTextSelection
, sStr
);
658 pEditView
->SetSelection( aSel
);
666 TextSelection
EditorWindow::GetLastHighlightPortionTextSelection()
667 {//creates a text selection from the highlight portion on the cursor
668 const sal_uInt32 nLine
= GetEditView()->GetSelection().GetStart().GetPara();
669 const sal_Int32 nIndex
= GetEditView()->GetSelection().GetStart().GetIndex();
670 OUString
aLine( pEditEngine
->GetText( nLine
) ); // the line being modified
671 std::vector
<HighlightPortion
> aPortions
;
672 aHighlighter
.getHighlightPortions( aLine
, aPortions
);
674 assert(!aPortions
.empty());
675 HighlightPortion
& r
= aPortions
.back();
676 if( static_cast<size_t>(nIndex
) != aPortions
.size()-1 )
677 {//cursor is not standing at the end of the line
678 for (auto const& portion
: aPortions
)
680 if( portion
.nEnd
== nIndex
)
688 if( aPortions
.empty() )
689 return TextSelection();
691 OUString sStr
= aLine
.copy( r
.nBegin
, r
.nEnd
- r
.nBegin
);
692 TextPaM
aStart( nLine
, r
.nBegin
);
693 TextPaM
aEnd( nLine
, r
.nBegin
+ sStr
.getLength() );
694 return TextSelection( aStart
, aEnd
);
697 void EditorWindow::HandleAutoCloseParen()
699 TextSelection aSel
= GetEditView()->GetSelection();
700 const sal_uInt32 nLine
= aSel
.GetStart().GetPara();
701 OUString
aLine( pEditEngine
->GetText( nLine
) ); // the line being modified
703 if( aLine
.getLength() > 0 && aLine
[aSel
.GetEnd().GetIndex()-1] != '(' )
705 GetEditView()->InsertText(")");
706 //leave the cursor on its place: inside the parenthesis
707 TextPaM
aEnd(nLine
, aSel
.GetEnd().GetIndex());
708 GetEditView()->SetSelection( TextSelection( aEnd
, aEnd
) );
712 void EditorWindow::HandleAutoCloseDoubleQuotes()
714 TextSelection aSel
= GetEditView()->GetSelection();
715 const sal_uInt32 nLine
= aSel
.GetStart().GetPara();
716 OUString
aLine( pEditEngine
->GetText( nLine
) ); // the line being modified
718 std::vector
<HighlightPortion
> aPortions
;
719 aHighlighter
.getHighlightPortions( aLine
, aPortions
);
721 if( aPortions
.empty() )
724 if( aLine
.getLength() > 0 && !aLine
.endsWith("\"") && (aPortions
.back().tokenType
!= TokenType::String
) )
726 GetEditView()->InsertText("\"");
727 //leave the cursor on its place: inside the two double quotes
728 TextPaM
aEnd(nLine
, aSel
.GetEnd().GetIndex());
729 GetEditView()->SetSelection( TextSelection( aEnd
, aEnd
) );
733 void EditorWindow::HandleProcedureCompletion()
736 TextSelection aSel
= GetEditView()->GetSelection();
737 const sal_uInt32 nLine
= aSel
.GetStart().GetPara();
738 OUString
aLine( pEditEngine
->GetText( nLine
) );
742 bool bFoundName
= GetProcedureName(aLine
, sProcType
, sProcName
);
746 OUString
sText("\nEnd ");
747 aSel
= GetEditView()->GetSelection();
748 if( sProcType
.equalsIgnoreAsciiCase("function") )
749 sText
+= "Function\n";
750 if( sProcType
.equalsIgnoreAsciiCase("sub") )
753 if( nLine
+1 == pEditEngine
->GetParagraphCount() )
755 pEditView
->InsertText( sText
);//append to the end
756 GetEditView()->SetSelection(aSel
);
760 for( sal_uInt32 i
= nLine
+1; i
< pEditEngine
->GetParagraphCount(); ++i
)
761 {//searching forward for end token, or another sub/function definition
762 OUString aCurrLine
= pEditEngine
->GetText( i
);
763 std::vector
<HighlightPortion
> aCurrPortions
;
764 aHighlighter
.getHighlightPortions( aCurrLine
, aCurrPortions
);
766 if( aCurrPortions
.size() >= 3 )
767 {//at least 3 tokens: (sub|function) whitespace identifier...
768 HighlightPortion
& r
= aCurrPortions
.front();
769 OUString sStr
= aCurrLine
.copy(r
.nBegin
, r
.nEnd
- r
.nBegin
);
771 if( r
.tokenType
== TokenType::Keywords
)
773 if( sStr
.equalsIgnoreAsciiCase("sub") || sStr
.equalsIgnoreAsciiCase("function") )
775 pEditView
->InsertText( sText
);//append to the end
776 GetEditView()->SetSelection(aSel
);
779 if( sStr
.equalsIgnoreAsciiCase("end") )
787 bool EditorWindow::GetProcedureName(OUString
const & rLine
, OUString
& rProcType
, OUString
& rProcName
) const
789 std::vector
<HighlightPortion
> aPortions
;
790 aHighlighter
.getHighlightPortions(rLine
, aPortions
);
792 if( aPortions
.empty() )
795 bool bFoundType
= false;
796 bool bFoundName
= false;
798 for (auto const& portion
: aPortions
)
800 OUString sTokStr
= rLine
.copy(portion
.nBegin
, portion
.nEnd
- portion
.nBegin
);
802 if( portion
.tokenType
== TokenType::Keywords
&& ( sTokStr
.equalsIgnoreAsciiCase("sub")
803 || sTokStr
.equalsIgnoreAsciiCase("function")) )
808 if( portion
.tokenType
== TokenType::Identifier
&& bFoundType
)
816 if( !bFoundType
|| !bFoundName
)
817 return false;// no sub/function keyword or there is no identifier
823 void EditorWindow::HandleCodeCompletion()
825 rModulWindow
.UpdateModule();
826 rModulWindow
.GetSbModule()->GetCodeCompleteDataFromParse(aCodeCompleteCache
);
827 TextSelection aSel
= GetEditView()->GetSelection();
828 const sal_uInt32 nLine
= aSel
.GetStart().GetPara();
829 OUString
aLine( pEditEngine
->GetText( nLine
) ); // the line being modified
830 std::vector
< OUString
> aVect
; //vector to hold the base variable+methods for the nested reflection
832 std::vector
<HighlightPortion
> aPortions
;
833 aLine
= aLine
.copy(0, aSel
.GetEnd().GetIndex());
834 aHighlighter
.getHighlightPortions( aLine
, aPortions
);
835 if( !aPortions
.empty() )
836 {//use the syntax highlighter to grab out nested reflection calls, eg. aVar.aMethod("aa").aOtherMethod ..
837 for( std::vector
<HighlightPortion
>::reverse_iterator
i(
839 i
!= aPortions
.rend(); ++i
)
841 if( i
->tokenType
== TokenType::Whitespace
) // a whitespace: stop; if there is no ws, it goes to the beginning of the line
843 if( i
->tokenType
== TokenType::Identifier
|| i
->tokenType
== TokenType::Keywords
) // extract the identifiers(methods, base variable)
844 /* an example: Dim aLocVar2 as com.sun.star.beans.PropertyValue
845 * here, aLocVar2.Name, and PropertyValue's Name field is treated as a keyword(?!)
847 aVect
.insert( aVect
.begin(), aLine
.copy(i
->nBegin
, i
->nEnd
- i
->nBegin
) );
850 if( aVect
.empty() )//nothing to do
853 OUString sBaseName
= aVect
[aVect
.size()-1];//variable name
854 OUString sVarType
= aCodeCompleteCache
.GetVarType( sBaseName
);
856 if( !sVarType
.isEmpty() && CodeCompleteOptions::IsAutoCorrectOn() )
857 {//correct variable name, if autocorrection on
858 const OUString
& sStr
= aCodeCompleteCache
.GetCorrectCaseVarName( sBaseName
, GetActualSubName(nLine
) );
859 if( !sStr
.isEmpty() )
861 TextPaM
aStart(nLine
, aSel
.GetStart().GetIndex() - sStr
.getLength() );
862 TextSelection
sTextSelection(aStart
, TextPaM(nLine
, aSel
.GetStart().GetIndex()));
863 pEditEngine
->ReplaceText( sTextSelection
, sStr
);
864 pEditView
->SetSelection( aSel
);
868 UnoTypeCodeCompletetor
aTypeCompletor( aVect
, sVarType
);
870 if( aTypeCompletor
.CanCodeComplete() )
872 std::vector
< OUString
> aEntryVect
;//entries to be inserted into the list
873 std::vector
< OUString
> aFieldVect
= aTypeCompletor
.GetXIdlClassFields();//fields
874 aEntryVect
.insert(aEntryVect
.end(), aFieldVect
.begin(), aFieldVect
.end() );
875 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
876 {// if extended types on, reflect classes, else just the structs (XIdlClass without methods)
877 std::vector
< OUString
> aMethVect
= aTypeCompletor
.GetXIdlClassMethods();//methods
878 aEntryVect
.insert(aEntryVect
.end(), aMethVect
.begin(), aMethVect
.end() );
880 if( aEntryVect
.size() > 0 )
881 SetupAndShowCodeCompleteWnd( aEntryVect
, aSel
);
886 void EditorWindow::SetupAndShowCodeCompleteWnd( const std::vector
< OUString
>& aEntryVect
, TextSelection aSel
)
889 pCodeCompleteWnd
->ClearListBox();
891 for(const auto & l
: aEntryVect
)
893 pCodeCompleteWnd
->InsertEntry( l
);
896 pCodeCompleteWnd
->Show();
897 pCodeCompleteWnd
->ResizeAndPositionListBox();
898 pCodeCompleteWnd
->SelectFirstEntry();
899 // correct text selection, and set it
900 ++aSel
.GetStart().GetIndex();
901 ++aSel
.GetEnd().GetIndex();
902 pCodeCompleteWnd
->SetTextSelection( aSel
);
903 //give the focus to the EditView
904 pEditView
->GetWindow()->GrabFocus();
907 void EditorWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& rRect
)
909 if (!pEditEngine
) // We need it now at latest
912 pEditView
->Paint(rRenderContext
, rRect
);
915 void EditorWindow::LoseFocus()
921 void EditorWindow::SetSourceInBasic()
923 if ( pEditEngine
&& pEditEngine
->IsModified()
924 && !GetEditView()->IsReadOnly() ) // Added for #i60626, otherwise
925 // any read only bug in the text engine could lead to a crash later
927 if ( !StarBASIC::IsRunning() ) // Not at runtime!
929 rModulWindow
.UpdateModule();
934 // Returns the position of the last character of any of the following
935 // EOL char combinations: CR, CR/LF, LF, return -1 if no EOL is found
936 sal_Int32
searchEOL( const OUString
& rStr
, sal_Int32 fromIndex
)
938 sal_Int32 iRetPos
= -1;
940 sal_Int32 iLF
= rStr
.indexOf( LINE_SEP
, fromIndex
);
947 iRetPos
= rStr
.indexOf( LINE_SEP_CR
, fromIndex
);
952 void EditorWindow::CreateEditEngine()
957 pEditEngine
.reset(new ExtTextEngine
);
958 pEditView
.reset(new TextView(pEditEngine
.get(), this));
959 pEditView
->SetAutoIndentMode(true);
960 pEditEngine
->SetUpdateMode(false);
961 pEditEngine
->InsertView(pEditView
.get());
965 aSyntaxIdle
.SetInvokeHandler( LINK( this, EditorWindow
, SyntaxTimerHdl
) );
967 bool bWasDoSyntaxHighlight
= bDoSyntaxHighlight
;
968 bDoSyntaxHighlight
= false; // too slow for large texts...
969 OUString
aOUSource(rModulWindow
.GetModule());
970 sal_Int32 nLines
= 0;
971 sal_Int32 nIndex
= -1;
975 nIndex
= searchEOL( aOUSource
, nIndex
+1 );
979 // nLines*4: SetText+Formatting+DoHighlight+Formatting
980 // it could be cut down on one formatting but you would wait even longer
981 // for the text then if the source code is long...
982 pProgress
.reset(new ProgressInfo(GetShell()->GetViewFrame()->GetObjectShell(),
983 IDEResId(RID_STR_GENERATESOURCE
),
985 setTextEngineText(*pEditEngine
, aOUSource
);
987 pEditView
->SetStartDocPos(Point(0, 0));
988 pEditView
->SetSelection(TextSelection());
989 rModulWindow
.GetBreakPointWindow().GetCurYOffset() = 0;
990 rModulWindow
.GetLineNumberWindow().GetCurYOffset() = 0;
991 pEditEngine
->SetUpdateMode(true);
992 rModulWindow
.Update(); // has only been invalidated at UpdateMode = true
994 pEditView
->ShowCursor();
996 StartListening(*pEditEngine
);
999 bDoSyntaxHighlight
= bWasDoSyntaxHighlight
;
1001 for (sal_Int32 nLine
= 0; nLine
< nLines
; nLine
++)
1002 aSyntaxLineTable
.insert(nLine
);
1003 ForceSyntaxTimeout();
1007 pEditEngine
->SetModified( false );
1008 pEditEngine
->EnableUndo( true );
1012 if (SfxBindings
* pBindings
= GetBindingsPtr())
1014 pBindings
->Invalidate(SID_BASICIDE_STAT_POS
);
1015 pBindings
->Invalidate(SID_BASICIDE_STAT_TITLE
);
1018 DBG_ASSERT(rModulWindow
.GetBreakPointWindow().GetCurYOffset() == 0, "CreateEditEngine: breakpoints moved?");
1020 // set readonly mode for readonly libraries
1021 ScriptDocument
aDocument(rModulWindow
.GetDocument());
1022 OUString
aOULibName(rModulWindow
.GetLibName());
1023 Reference
< script::XLibraryContainer2
> xModLibContainer( aDocument
.getLibraryContainer( E_SCRIPTS
), UNO_QUERY
);
1024 if (xModLibContainer
.is()
1025 && xModLibContainer
->hasByName(aOULibName
)
1026 && xModLibContainer
->isLibraryReadOnly(aOULibName
))
1028 rModulWindow
.SetReadOnly(true);
1031 if (aDocument
.isDocument() && aDocument
.isReadOnly())
1032 rModulWindow
.SetReadOnly(true);
1035 void EditorWindow::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1037 if (TextHint
const* pTextHint
= dynamic_cast<TextHint
const*>(&rHint
))
1039 TextHint
const& rTextHint
= *pTextHint
;
1040 if( rTextHint
.GetId() == SfxHintId::TextViewScrolled
)
1042 if ( rModulWindow
.GetHScrollBar() )
1043 rModulWindow
.GetHScrollBar()->SetThumbPos( pEditView
->GetStartDocPos().X() );
1044 rModulWindow
.GetEditVScrollBar().SetThumbPos( pEditView
->GetStartDocPos().Y() );
1045 rModulWindow
.GetBreakPointWindow().DoScroll
1046 ( rModulWindow
.GetBreakPointWindow().GetCurYOffset() - pEditView
->GetStartDocPos().Y() );
1047 rModulWindow
.GetLineNumberWindow().DoScroll
1048 ( rModulWindow
.GetLineNumberWindow().GetCurYOffset() - pEditView
->GetStartDocPos().Y() );
1050 else if( rTextHint
.GetId() == SfxHintId::TextHeightChanged
)
1052 if ( pEditView
->GetStartDocPos().Y() )
1054 long nOutHeight
= GetOutputSizePixel().Height();
1055 long nTextHeight
= pEditEngine
->GetTextHeight();
1056 if ( nTextHeight
< nOutHeight
)
1057 pEditView
->Scroll( 0, pEditView
->GetStartDocPos().Y() );
1059 rModulWindow
.GetLineNumberWindow().Invalidate();
1062 SetScrollBarRanges();
1064 else if( rTextHint
.GetId() == SfxHintId::TextFormatted
)
1066 if ( rModulWindow
.GetHScrollBar() )
1068 const long nWidth
= pEditEngine
->CalcTextWidth();
1069 if ( nWidth
!= nCurTextWidth
)
1071 nCurTextWidth
= nWidth
;
1072 rModulWindow
.GetHScrollBar()->SetRange( Range( 0, nCurTextWidth
-1) );
1073 rModulWindow
.GetHScrollBar()->SetThumbPos( pEditView
->GetStartDocPos().X() );
1076 long nPrevTextWidth
= nCurTextWidth
;
1077 nCurTextWidth
= pEditEngine
->CalcTextWidth();
1078 if ( nCurTextWidth
!= nPrevTextWidth
)
1079 SetScrollBarRanges();
1081 else if( rTextHint
.GetId() == SfxHintId::TextParaInserted
)
1083 ParagraphInsertedDeleted( rTextHint
.GetValue(), true );
1084 DoDelayedSyntaxHighlight( rTextHint
.GetValue() );
1086 else if( rTextHint
.GetId() == SfxHintId::TextParaRemoved
)
1088 ParagraphInsertedDeleted( rTextHint
.GetValue(), false );
1090 else if( rTextHint
.GetId() == SfxHintId::TextParaContentChanged
)
1092 DoDelayedSyntaxHighlight( rTextHint
.GetValue() );
1094 else if( rTextHint
.GetId() == SfxHintId::TextViewSelectionChanged
)
1096 if (SfxBindings
* pBindings
= GetBindingsPtr())
1098 pBindings
->Invalidate( SID_CUT
);
1099 pBindings
->Invalidate( SID_COPY
);
1105 OUString
EditorWindow::GetActualSubName( sal_uLong nLine
)
1107 SbxArrayRef pMethods
= rModulWindow
.GetSbModule()->GetMethods();
1108 for( sal_uInt16 i
=0; i
< pMethods
->Count(); i
++ )
1110 SbMethod
* pMeth
= dynamic_cast<SbMethod
*>( pMethods
->Get( i
) );
1114 pMeth
->GetLineRange(l1
,l2
);
1115 if( (l1
<= nLine
+1) && (nLine
+1 <= l2
) )
1117 return pMeth
->GetName();
1124 void EditorWindow::SetScrollBarRanges()
1126 // extra method, not InitScrollBars, because for EditEngine events too
1130 if ( rModulWindow
.GetHScrollBar() )
1131 rModulWindow
.GetHScrollBar()->SetRange( Range( 0, nCurTextWidth
-1 ) );
1133 rModulWindow
.GetEditVScrollBar().SetRange( Range( 0, pEditEngine
->GetTextHeight()-1 ) );
1136 void EditorWindow::InitScrollBars()
1141 SetScrollBarRanges();
1142 Size
aOutSz(GetOutputSizePixel());
1143 rModulWindow
.GetEditVScrollBar().SetVisibleSize(aOutSz
.Height());
1144 rModulWindow
.GetEditVScrollBar().SetPageSize(aOutSz
.Height() * 8 / 10);
1145 rModulWindow
.GetEditVScrollBar().SetLineSize(GetTextHeight());
1146 rModulWindow
.GetEditVScrollBar().SetThumbPos(pEditView
->GetStartDocPos().Y());
1147 rModulWindow
.GetEditVScrollBar().Show();
1149 if (rModulWindow
.GetHScrollBar())
1151 rModulWindow
.GetHScrollBar()->SetVisibleSize(aOutSz
.Width());
1152 rModulWindow
.GetHScrollBar()->SetPageSize(aOutSz
.Width() * 8 / 10);
1153 rModulWindow
.GetHScrollBar()->SetLineSize(GetTextWidth( "x" ) );
1154 rModulWindow
.GetHScrollBar()->SetThumbPos(pEditView
->GetStartDocPos().X());
1155 rModulWindow
.GetHScrollBar()->Show();
1159 void EditorWindow::ImpDoHighlight( sal_uLong nLine
)
1161 if ( bDoSyntaxHighlight
)
1163 OUString
aLine( pEditEngine
->GetText( nLine
) );
1164 bool const bWasModified
= pEditEngine
->IsModified();
1165 pEditEngine
->RemoveAttribs( nLine
);
1166 std::vector
<HighlightPortion
> aPortions
;
1167 aHighlighter
.getHighlightPortions( aLine
, aPortions
);
1169 for (auto const& portion
: aPortions
)
1171 Color
const aColor
= rModulWindow
.GetLayout().GetSyntaxColor(portion
.tokenType
);
1172 pEditEngine
->SetAttrib(TextAttribFontColor(aColor
), nLine
, portion
.nBegin
, portion
.nEnd
);
1175 pEditEngine
->SetModified(bWasModified
);
1179 void EditorWindow::ChangeFontColor( Color aColor
)
1183 vcl::Font
aFont(pEditEngine
->GetFont());
1184 aFont
.SetColor(aColor
);
1185 pEditEngine
->SetFont(aFont
);
1189 void EditorWindow::UpdateSyntaxHighlighting ()
1191 const sal_uInt32 nCount
= pEditEngine
->GetParagraphCount();
1192 for (sal_uInt32 i
= 0; i
< nCount
; ++i
)
1193 DoDelayedSyntaxHighlight(i
);
1196 void EditorWindow::ImplSetFont()
1198 OUString
sFontName(officecfg::Office::Common::Font::SourceViewFont::FontName::get().get_value_or(OUString()));
1199 if (sFontName
.isEmpty())
1201 vcl::Font
aTmpFont(OutputDevice::GetDefaultFont(DefaultFontType::FIXED
,
1202 Application::GetSettings().GetUILanguageTag().getLanguageType(),
1203 GetDefaultFontFlags::NONE
, this));
1204 sFontName
= aTmpFont
.GetFamilyName();
1206 Size
aFontSize(0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get());
1207 vcl::Font
aFont(sFontName
, aFontSize
);
1208 aFont
.SetColor(rModulWindow
.GetLayout().GetFontColor());
1209 SetPointFont(*this, aFont
); // FIXME RenderContext
1212 rModulWindow
.GetBreakPointWindow().SetFont(aFont
);
1213 rModulWindow
.GetLineNumberWindow().SetFont(aFont
);
1217 bool const bModified
= pEditEngine
->IsModified();
1218 pEditEngine
->SetFont(aFont
);
1219 pEditEngine
->SetModified(bModified
);
1223 void EditorWindow::DoSyntaxHighlight( sal_uLong nPara
)
1225 // because of the DelayedSyntaxHighlight it's possible
1226 // that this line does not exist anymore!
1227 if ( nPara
< pEditEngine
->GetParagraphCount() )
1229 // unfortunately I'm not sure that exactly this line does Modified()...
1231 pProgress
->StepProgress();
1232 ImpDoHighlight( nPara
);
1236 void EditorWindow::DoDelayedSyntaxHighlight( sal_uLong nPara
)
1238 // line is only added to list, processed in TimerHdl
1239 // => don't manipulate breaks while EditEngine is formatting
1241 pProgress
->StepProgress();
1243 if ( !bHighlighting
&& bDoSyntaxHighlight
)
1245 if ( bDelayHighlight
)
1247 aSyntaxLineTable
.insert( nPara
);
1248 aSyntaxIdle
.Start();
1251 DoSyntaxHighlight( nPara
);
1255 IMPL_LINK_NOARG(EditorWindow
, SyntaxTimerHdl
, Timer
*, void)
1257 DBG_ASSERT( pEditView
, "Not yet a View, but Syntax-Highlight?!" );
1259 bool const bWasModified
= pEditEngine
->IsModified();
1260 //pEditEngine->SetUpdateMode(false);
1262 bHighlighting
= true;
1263 for (auto const& syntaxLine
: aSyntaxLineTable
)
1265 DoSyntaxHighlight(syntaxLine
);
1270 pEditView
->ShowCursor( false );
1272 pEditEngine
->SetModified( bWasModified
);
1274 aSyntaxLineTable
.clear();
1275 bHighlighting
= false;
1278 void EditorWindow::ParagraphInsertedDeleted( sal_uLong nPara
, bool bInserted
)
1281 pProgress
->StepProgress();
1283 if ( !bInserted
&& ( nPara
== TEXT_PARA_ALL
) )
1285 rModulWindow
.GetBreakPoints().reset();
1286 rModulWindow
.GetBreakPointWindow().Invalidate();
1287 rModulWindow
.GetLineNumberWindow().Invalidate();
1291 rModulWindow
.GetBreakPoints().AdjustBreakPoints( static_cast<sal_uInt16
>(nPara
)+1, bInserted
);
1293 long nLineHeight
= GetTextHeight();
1294 Size aSz
= rModulWindow
.GetBreakPointWindow().GetOutputSize();
1295 tools::Rectangle
aInvRect( Point( 0, 0 ), aSz
);
1296 long nY
= nPara
*nLineHeight
- rModulWindow
.GetBreakPointWindow().GetCurYOffset();
1297 aInvRect
.SetTop( nY
);
1298 rModulWindow
.GetBreakPointWindow().Invalidate( aInvRect
);
1300 Size
aLnSz(rModulWindow
.GetLineNumberWindow().GetWidth(),
1301 GetOutputSizePixel().Height() - 2 * DWBORDER
);
1302 rModulWindow
.GetLineNumberWindow().SetPosSizePixel(Point(DWBORDER
+ 19, DWBORDER
), aLnSz
);
1303 rModulWindow
.GetLineNumberWindow().Invalidate();
1307 void EditorWindow::CreateProgress( const OUString
& rText
, sal_uInt32 nRange
)
1309 DBG_ASSERT( !pProgress
, "ProgressInfo exists already" );
1310 pProgress
.reset(new ProgressInfo(
1311 GetShell()->GetViewFrame()->GetObjectShell(),
1317 void EditorWindow::DestroyProgress()
1322 void EditorWindow::ForceSyntaxTimeout()
1325 aSyntaxIdle
.Invoke();
1330 BreakPointWindow::BreakPointWindow (vcl::Window
* pParent
, ModulWindow
* pModulWindow
)
1331 : Window(pParent
, WB_BORDER
)
1332 , rModulWindow(*pModulWindow
)
1333 , nCurYOffset(0) // memorize nCurYOffset and not take it from EditEngine
1334 , nMarkerPos(NoMarker
)
1335 , bErrorMarker(false)
1337 setBackgroundColor(GetSettings().GetStyleSettings().GetFieldColor());
1338 SetHelpId(HID_BASICIDE_BREAKPOINTWINDOW
);
1341 void BreakPointWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1346 Size
const aOutSz
= rRenderContext
.GetOutputSize();
1347 long const nLineHeight
= rRenderContext
.GetTextHeight();
1349 Image
const aBrk
[2] =
1351 GetImage(RID_BMP_BRKDISABLED
),
1352 GetImage(RID_BMP_BRKENABLED
)
1355 Size
const aBmpSz
= rRenderContext
.PixelToLogic(aBrk
[1].GetSizePixel());
1356 Point
const aBmpOff((aOutSz
.Width() - aBmpSz
.Width()) / 2,
1357 (nLineHeight
- aBmpSz
.Height()) / 2);
1359 for (size_t i
= 0, n
= GetBreakPoints().size(); i
< n
; ++i
)
1361 BreakPoint
& rBrk
= *GetBreakPoints().at(i
);
1362 size_t const nLine
= rBrk
.nLine
- 1;
1363 size_t const nY
= nLine
*nLineHeight
- nCurYOffset
;
1364 rRenderContext
.DrawImage(Point(0, nY
) + aBmpOff
, aBrk
[rBrk
.bEnabled
]);
1367 ShowMarker(rRenderContext
);
1370 void BreakPointWindow::ShowMarker(vcl::RenderContext
& rRenderContext
)
1372 if (nMarkerPos
== NoMarker
)
1375 Size
const aOutSz
= GetOutputSize();
1376 long const nLineHeight
= GetTextHeight();
1378 Image aMarker
= GetImage(bErrorMarker
? OUStringLiteral(RID_BMP_ERRORMARKER
) : OUStringLiteral(RID_BMP_STEPMARKER
));
1380 Size
aMarkerSz(aMarker
.GetSizePixel());
1381 aMarkerSz
= rRenderContext
.PixelToLogic(aMarkerSz
);
1382 Point
aMarkerOff(0, 0);
1383 aMarkerOff
.setX( (aOutSz
.Width() - aMarkerSz
.Width()) / 2 );
1384 aMarkerOff
.setY( (nLineHeight
- aMarkerSz
.Height()) / 2 );
1386 sal_uLong nY
= nMarkerPos
* nLineHeight
- nCurYOffset
;
1390 rRenderContext
.DrawImage(aPos
, aMarker
);
1393 void BreakPointWindow::DoScroll( long nVertScroll
)
1395 nCurYOffset
-= nVertScroll
;
1396 Window::Scroll( 0, nVertScroll
);
1399 void BreakPointWindow::SetMarkerPos( sal_uInt16 nLine
, bool bError
)
1401 if ( SyncYOffset() )
1405 bErrorMarker
= bError
;
1409 void BreakPointWindow::SetNoMarker ()
1411 SetMarkerPos(NoMarker
);
1414 BreakPoint
* BreakPointWindow::FindBreakPoint( const Point
& rMousePos
)
1416 size_t nLineHeight
= GetTextHeight();
1417 nLineHeight
= nLineHeight
> 0 ? nLineHeight
: 1;
1418 size_t nYPos
= rMousePos
.Y() + nCurYOffset
;
1420 for ( size_t i
= 0, n
= GetBreakPoints().size(); i
< n
; ++i
)
1422 BreakPoint
* pBrk
= GetBreakPoints().at( i
);
1423 size_t nLine
= pBrk
->nLine
-1;
1424 size_t nY
= nLine
*nLineHeight
;
1425 if ( ( nYPos
> nY
) && ( nYPos
< ( nY
+ nLineHeight
) ) )
1431 void BreakPointWindow::MouseButtonDown( const MouseEvent
& rMEvt
)
1433 if ( rMEvt
.GetClicks() == 2 )
1435 Point
aMousePos( PixelToLogic( rMEvt
.GetPosPixel() ) );
1436 long nLineHeight
= GetTextHeight();
1439 long nYPos
= aMousePos
.Y() + nCurYOffset
;
1440 long nLine
= nYPos
/ nLineHeight
+ 1;
1441 rModulWindow
.ToggleBreakPoint( static_cast<sal_uLong
>(nLine
) );
1447 void BreakPointWindow::Command( const CommandEvent
& rCEvt
)
1449 if ( rCEvt
.GetCommand() == CommandEventId::ContextMenu
)
1452 mpUIBuilder
.reset(new VclBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/BasicIDE/ui/breakpointmenus.ui", ""));
1454 Point
aPos( rCEvt
.IsMouseEvent() ? rCEvt
.GetMousePosPixel() : Point(1,1) );
1455 Point
aEventPos( PixelToLogic( aPos
) );
1456 BreakPoint
* pBrk
= rCEvt
.IsMouseEvent() ? FindBreakPoint( aEventPos
) : nullptr;
1459 // test if break point is enabled...
1460 VclPtr
<PopupMenu
> xBrkPropMenu
= mpUIBuilder
->get_menu("breakmenu");
1461 xBrkPropMenu
->CheckItem(xBrkPropMenu
->GetItemId("active"), pBrk
->bEnabled
);
1462 OString sCommand
= xBrkPropMenu
->GetItemIdent(xBrkPropMenu
->Execute(this, aPos
));
1463 if (sCommand
== "active")
1465 pBrk
->bEnabled
= !pBrk
->bEnabled
;
1466 rModulWindow
.UpdateBreakPoint( *pBrk
);
1469 else if (sCommand
== "properties")
1471 ScopedVclPtrInstance
<BreakPointDialog
> aBrkDlg(this, GetBreakPoints());
1472 aBrkDlg
->SetCurrentBreakPoint( pBrk
);
1479 VclPtr
<PopupMenu
> xBrkListMenu
= mpUIBuilder
->get_menu("breaklistmenu");
1480 OString sCommand
= xBrkListMenu
->GetItemIdent(xBrkListMenu
->Execute(this, aPos
));
1481 if (sCommand
== "manage")
1483 ScopedVclPtrInstance
< BreakPointDialog
> aBrkDlg( this, GetBreakPoints() );
1491 bool BreakPointWindow::SyncYOffset()
1493 TextView
* pView
= rModulWindow
.GetEditView();
1496 long nViewYOffset
= pView
->GetStartDocPos().Y();
1497 if ( nCurYOffset
!= nViewYOffset
)
1499 nCurYOffset
= nViewYOffset
;
1508 void BreakPointWindow::DataChanged(DataChangedEvent
const & rDCEvt
)
1510 Window::DataChanged(rDCEvt
);
1511 if (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
1512 && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
1514 Color
aColor(GetSettings().GetStyleSettings().GetFieldColor());
1515 const AllSettings
* pOldSettings
= rDCEvt
.GetOldSettings();
1516 if (!pOldSettings
|| aColor
!= pOldSettings
->GetStyleSettings().GetFieldColor())
1518 setBackgroundColor(aColor
);
1524 void BreakPointWindow::setBackgroundColor(Color aColor
)
1526 SetBackground(Wallpaper(aColor
));
1529 void BreakPointWindow::dispose()
1531 mpUIBuilder
.reset();
1537 const sal_uInt16 ITEM_ID_VARIABLE
= 1;
1538 const sal_uInt16 ITEM_ID_VALUE
= 2;
1539 const sal_uInt16 ITEM_ID_TYPE
= 3;
1542 WatchWindow::WatchWindow (Layout
* pParent
)
1543 : DockingWindow(pParent
)
1544 , aWatchStr(IDEResId( RID_STR_REMOVEWATCH
))
1545 , aXEdit(VclPtr
<ExtendedEdit
>::Create(this, WB_BORDER
| WB_3DLOOK
))
1546 , aRemoveWatchButton(VclPtr
<ImageButton
>::Create(this, WB_SMALLSTYLE
))
1547 , aTreeListBox(VclPtr
<WatchTreeListBox
>::Create(this, WB_BORDER
| WB_3DLOOK
| WB_HASBUTTONS
|
1548 WB_HASLINES
| WB_HSCROLL
| WB_TABSTOP
|
1549 WB_HASLINESATROOT
| WB_HASBUTTONSATROOT
))
1550 , aHeaderBar(VclPtr
<HeaderBar
>::Create(this, WB_BUTTONSTYLE
| WB_BORDER
))
1552 aXEdit
->SetAccessibleName(IDEResId(RID_STR_WATCHNAME
));
1553 aXEdit
->SetHelpId(HID_BASICIDE_WATCHWINDOW_EDIT
);
1554 aXEdit
->SetSizePixel(aXEdit
->LogicToPixel(Size(80, 12), MapMode(MapUnit::MapAppFont
)));
1555 aTreeListBox
->SetAccessibleName(IDEResId(RID_STR_WATCHNAME
));
1557 long nTextLen
= GetTextWidth( aWatchStr
) + DWBORDER
+ 3;
1558 aXEdit
->SetPosPixel( Point( nTextLen
, 3 ) );
1559 aXEdit
->SetAccHdl( LINK( this, WatchWindow
, EditAccHdl
) );
1560 aXEdit
->GetAccelerator().InsertItem( 1, vcl::KeyCode( KEY_RETURN
) );
1561 aXEdit
->GetAccelerator().InsertItem( 2, vcl::KeyCode( KEY_ESCAPE
) );
1564 aRemoveWatchButton
->Disable();
1565 aRemoveWatchButton
->SetClickHdl( LINK( this, WatchWindow
, ButtonHdl
) );
1566 aRemoveWatchButton
->SetPosPixel( Point( nTextLen
+ aXEdit
->GetSizePixel().Width() + 4, 2 ) );
1567 aRemoveWatchButton
->SetHelpId(HID_BASICIDE_REMOVEWATCH
);
1568 aRemoveWatchButton
->SetModeImage(Image(BitmapEx(RID_BMP_REMOVEWATCH
)));
1569 aRemoveWatchButton
->SetQuickHelpText(IDEResId(RID_STR_REMOVEWATCHTIP
));
1570 Size
aSz( aRemoveWatchButton
->GetModeImage().GetSizePixel() );
1571 aSz
.AdjustWidth(6 );
1572 aSz
.AdjustHeight(6 );
1573 aRemoveWatchButton
->SetSizePixel( aSz
);
1574 aRemoveWatchButton
->Show();
1576 long nRWBtnSize
= aRemoveWatchButton
->GetModeImage().GetSizePixel().Height() + 10;
1577 nVirtToolBoxHeight
= aXEdit
->GetSizePixel().Height() + 7;
1579 if ( nRWBtnSize
> nVirtToolBoxHeight
)
1580 nVirtToolBoxHeight
= nRWBtnSize
;
1582 nHeaderBarHeight
= 16;
1584 aTreeListBox
->SetHelpId(HID_BASICIDE_WATCHWINDOW_LIST
);
1585 aTreeListBox
->EnableInplaceEditing(true);
1586 aTreeListBox
->SetSelectHdl( LINK( this, WatchWindow
, TreeListHdl
) );
1587 aTreeListBox
->SetPosPixel( Point( DWBORDER
, nVirtToolBoxHeight
+ nHeaderBarHeight
) );
1588 aTreeListBox
->SetHighlightRange( 1, 5 );
1590 Point
aPnt( DWBORDER
, nVirtToolBoxHeight
+ 1 );
1591 aHeaderBar
->SetPosPixel( aPnt
);
1592 aHeaderBar
->SetEndDragHdl( LINK( this, WatchWindow
, implEndDragHdl
) );
1594 long nVarTabWidth
= 220;
1595 long nValueTabWidth
= 100;
1596 long const nTypeTabWidth
= 1250;
1597 aHeaderBar
->InsertItem( ITEM_ID_VARIABLE
, IDEResId(RID_STR_WATCHVARIABLE
), nVarTabWidth
);
1598 aHeaderBar
->InsertItem( ITEM_ID_VALUE
, IDEResId(RID_STR_WATCHVALUE
), nValueTabWidth
);
1599 aHeaderBar
->InsertItem( ITEM_ID_TYPE
, IDEResId(RID_STR_WATCHTYPE
), nTypeTabWidth
);
1601 long aTabPositions
[] = { 0, nVarTabWidth
, nVarTabWidth
+ nValueTabWidth
};
1602 aTreeListBox
->SvHeaderTabListBox::SetTabs( SAL_N_ELEMENTS(aTabPositions
), aTabPositions
, MapUnit::MapPixel
);
1603 aTreeListBox
->InitHeaderBar( aHeaderBar
.get() );
1605 aTreeListBox
->SetNodeDefaultImages( );
1609 aTreeListBox
->Show();
1611 SetText(IDEResId(RID_STR_WATCHNAME
));
1613 SetHelpId( HID_BASICIDE_WATCHWINDOW
);
1615 // make watch window keyboard accessible
1616 GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1620 WatchWindow::~WatchWindow()
1625 void WatchWindow::dispose()
1627 aXEdit
.disposeAndClear();
1628 aRemoveWatchButton
.disposeAndClear();
1629 aHeaderBar
.disposeAndClear();
1630 aTreeListBox
.disposeAndClear();
1632 GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1633 DockingWindow::dispose();
1636 void WatchWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1638 rRenderContext
.DrawText(Point(DWBORDER
, 7), aWatchStr
);
1639 lcl_DrawIDEWindowFrame(this, rRenderContext
);
1642 void WatchWindow::Resize()
1644 Size aSz
= GetOutputSizePixel();
1645 Size
aBoxSz( aSz
.Width() - 2*DWBORDER
, aSz
.Height() - nVirtToolBoxHeight
- DWBORDER
);
1647 if ( aBoxSz
.Width() < 4 )
1648 aBoxSz
.setWidth( 0 );
1649 if ( aBoxSz
.Height() < 4 )
1650 aBoxSz
.setHeight( 0 );
1652 aBoxSz
.AdjustHeight( -nHeaderBarHeight
);
1653 aTreeListBox
->SetSizePixel( aBoxSz
);
1654 aTreeListBox
->GetHScroll()->SetPageSize( aTreeListBox
->GetHScroll()->GetVisibleSize() );
1656 aBoxSz
.setHeight( nHeaderBarHeight
);
1657 aHeaderBar
->SetSizePixel( aBoxSz
);
1665 OUString maDisplayName
;
1666 SbxObjectRef mpObject
;
1667 std::vector
<OUString
> maMemberList
;
1669 SbxDimArrayRef mpArray
;
1670 int nDimLevel
; // 0 = Root
1672 std::vector
<short> vIndices
;
1674 WatchItem
* mpArrayParentItem
;
1676 explicit WatchItem (OUString
const& rName
):
1680 mpArrayParentItem(nullptr)
1683 void clearWatchItem ()
1685 maMemberList
.clear();
1688 WatchItem
* GetRootItem();
1689 SbxDimArray
* GetRootArray();
1692 WatchItem
* WatchItem::GetRootItem()
1694 WatchItem
* pItem
= mpArrayParentItem
;
1697 if( pItem
->mpArray
.is() )
1699 pItem
= pItem
->mpArrayParentItem
;
1704 SbxDimArray
* WatchItem::GetRootArray()
1706 WatchItem
* pRootItem
= GetRootItem();
1707 SbxDimArray
* pRet
= nullptr;
1709 pRet
= pRootItem
->mpArray
.get();
1713 void WatchWindow::AddWatch( const OUString
& rVName
)
1715 OUString aVar
, aIndex
;
1716 lcl_SeparateNameAndIndex( rVName
, aVar
, aIndex
);
1717 WatchItem
* pWatchItem
= new WatchItem(aVar
);
1719 OUString aWatchStr_
= aVar
+ "\t\t";
1720 SvTreeListEntry
* pNewEntry
= aTreeListBox
->InsertEntry( aWatchStr_
, nullptr, true );
1721 pNewEntry
->SetUserData( pWatchItem
);
1723 aTreeListBox
->Select(pNewEntry
);
1724 aTreeListBox
->MakeVisible(pNewEntry
);
1725 aRemoveWatchButton
->Enable();
1727 UpdateWatches(false);
1730 void WatchWindow::RemoveSelectedWatch()
1732 SvTreeListEntry
* pEntry
= aTreeListBox
->GetCurEntry();
1735 aTreeListBox
->GetModel()->Remove( pEntry
);
1736 pEntry
= aTreeListBox
->GetCurEntry();
1738 aXEdit
->SetText( static_cast<WatchItem
*>(pEntry
->GetUserData())->maName
);
1740 aXEdit
->SetText( OUString() );
1741 if ( !aTreeListBox
->GetEntryCount() )
1742 aRemoveWatchButton
->Disable();
1747 IMPL_LINK( WatchWindow
, ButtonHdl
, Button
*, pButton
, void )
1749 if (pButton
== aRemoveWatchButton
.get())
1750 if (SfxDispatcher
* pDispatcher
= GetDispatcher())
1751 pDispatcher
->Execute(SID_BASICIDE_REMOVEWATCH
);
1754 IMPL_LINK_NOARG(WatchWindow
, TreeListHdl
, SvTreeListBox
*, void)
1756 SvTreeListEntry
* pCurEntry
= aTreeListBox
->GetCurEntry();
1757 if ( pCurEntry
&& pCurEntry
->GetUserData() )
1758 aXEdit
->SetText( static_cast<WatchItem
*>(pCurEntry
->GetUserData())->maName
);
1761 IMPL_LINK_NOARG( WatchWindow
, implEndDragHdl
, HeaderBar
*, void )
1763 const sal_Int32 TAB_WIDTH_MIN
= 10;
1764 sal_Int32 nMaxWidth
=
1765 aHeaderBar
->GetSizePixel().getWidth() - 2 * TAB_WIDTH_MIN
;
1767 sal_Int32 nVariableWith
= aHeaderBar
->GetItemSize( ITEM_ID_VARIABLE
);
1768 if( nVariableWith
< TAB_WIDTH_MIN
)
1769 aHeaderBar
->SetItemSize( ITEM_ID_VARIABLE
, TAB_WIDTH_MIN
);
1770 else if( nVariableWith
> nMaxWidth
)
1771 aHeaderBar
->SetItemSize( ITEM_ID_VARIABLE
, nMaxWidth
);
1773 sal_Int32 nValueWith
= aHeaderBar
->GetItemSize( ITEM_ID_VALUE
);
1774 if( nValueWith
< TAB_WIDTH_MIN
)
1775 aHeaderBar
->SetItemSize( ITEM_ID_VALUE
, TAB_WIDTH_MIN
);
1776 else if( nValueWith
> nMaxWidth
)
1777 aHeaderBar
->SetItemSize( ITEM_ID_VALUE
, nMaxWidth
);
1779 if (aHeaderBar
->GetItemSize( ITEM_ID_TYPE
) < TAB_WIDTH_MIN
)
1780 aHeaderBar
->SetItemSize( ITEM_ID_TYPE
, TAB_WIDTH_MIN
);
1783 sal_uInt16 nTabs
= aHeaderBar
->GetItemCount();
1784 for( sal_uInt16 i
= 1 ; i
< nTabs
; ++i
)
1786 nPos
+= aHeaderBar
->GetItemSize( i
);
1787 aTreeListBox
->SetTab( i
, nPos
, MapUnit::MapPixel
);
1791 IMPL_LINK( WatchWindow
, EditAccHdl
, Accelerator
&, rAcc
, void )
1793 switch ( rAcc
.GetCurKeyCode().GetCode() )
1797 OUString
aCurText( aXEdit
->GetText() );
1798 if ( !aCurText
.isEmpty() )
1800 AddWatch( aCurText
);
1801 aXEdit
->SetSelection( Selection( 0, 0xFFFF ) );
1807 aXEdit
->SetText( OUString() );
1813 void WatchWindow::UpdateWatches( bool bBasicStopped
)
1815 aTreeListBox
->UpdateWatches( bBasicStopped
);
1822 StackWindow::StackWindow (Layout
* pParent
) :
1823 DockingWindow(pParent
),
1824 aTreeListBox( VclPtr
<SvTreeListBox
>::Create(this, WB_BORDER
| WB_3DLOOK
| WB_HSCROLL
| WB_TABSTOP
) ),
1825 aStackStr( IDEResId( RID_STR_STACK
) )
1827 aTreeListBox
->SetHelpId(HID_BASICIDE_STACKWINDOW_LIST
);
1828 aTreeListBox
->SetAccessibleName(IDEResId(RID_STR_STACKNAME
));
1829 aTreeListBox
->SetPosPixel( Point( DWBORDER
, nVirtToolBoxHeight
) );
1830 aTreeListBox
->SetHighlightRange();
1831 aTreeListBox
->SetSelectionMode( SelectionMode::NONE
);
1832 aTreeListBox
->InsertEntry( OUString() );
1833 aTreeListBox
->Show();
1835 SetText(IDEResId(RID_STR_STACKNAME
));
1837 SetHelpId( HID_BASICIDE_STACKWINDOW
);
1839 // make stack window keyboard accessible
1840 GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1844 StackWindow::~StackWindow()
1849 void StackWindow::dispose()
1852 GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1853 aTreeListBox
.disposeAndClear();
1854 DockingWindow::dispose();
1857 void StackWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1859 rRenderContext
.DrawText(Point(DWBORDER
, 7), aStackStr
);
1860 lcl_DrawIDEWindowFrame(this, rRenderContext
);
1863 void StackWindow::Resize()
1865 Size aSz
= GetOutputSizePixel();
1866 Size
aBoxSz(aSz
.Width() - 2*DWBORDER
, aSz
.Height() - nVirtToolBoxHeight
- DWBORDER
);
1868 if ( aBoxSz
.Width() < 4 )
1869 aBoxSz
.setWidth( 0 );
1870 if ( aBoxSz
.Height() < 4 )
1871 aBoxSz
.setHeight( 0 );
1873 aTreeListBox
->SetSizePixel( aBoxSz
);
1878 void StackWindow::UpdateCalls()
1880 aTreeListBox
->SetUpdateMode(false);
1881 aTreeListBox
->Clear();
1883 if (StarBASIC::IsRunning())
1885 ErrCode eOld
= SbxBase::GetError();
1886 aTreeListBox
->SetSelectionMode( SelectionMode::Single
);
1888 sal_Int32 nScope
= 0;
1889 SbMethod
* pMethod
= StarBASIC::GetActiveMethod( nScope
);
1892 OUString
aEntry( OUString::number(nScope
));
1893 if ( aEntry
.getLength() < 2 )
1894 aEntry
= " " + aEntry
;
1895 aEntry
+= ": " + pMethod
->GetName();
1896 SbxArray
* pParams
= pMethod
->GetParameters();
1897 SbxInfo
* pInfo
= pMethod
->GetInfo();
1901 // 0 is the sub's name...
1902 for ( sal_uInt16 nParam
= 1; nParam
< pParams
->Count(); nParam
++ )
1904 SbxVariable
* pVar
= pParams
->Get( nParam
);
1905 assert(pVar
&& "Parameter?!");
1906 if ( !pVar
->GetName().isEmpty() )
1908 aEntry
+= pVar
->GetName();
1912 const SbxParamInfo
* pParam
= pInfo
->GetParam( nParam
);
1915 aEntry
+= pParam
->aName
;
1919 SbxDataType eType
= pVar
->GetType();
1920 if( eType
& SbxARRAY
)
1924 else if( eType
!= SbxOBJECT
)
1926 aEntry
+= pVar
->GetOUString();
1928 if ( nParam
< ( pParams
->Count() - 1 ) )
1935 aTreeListBox
->InsertEntry( aEntry
);
1937 pMethod
= StarBASIC::GetActiveMethod( nScope
);
1940 SbxBase::ResetError();
1941 if( eOld
!= ERRCODE_NONE
)
1942 SbxBase::SetError( eOld
);
1946 aTreeListBox
->SetSelectionMode( SelectionMode::NONE
);
1947 aTreeListBox
->InsertEntry( OUString() );
1950 aTreeListBox
->SetUpdateMode(true);
1953 ComplexEditorWindow::ComplexEditorWindow( ModulWindow
* pParent
) :
1954 Window( pParent
, WB_3DLOOK
| WB_CLIPCHILDREN
),
1955 aBrkWindow(VclPtr
<BreakPointWindow
>::Create(this, pParent
)),
1956 aLineNumberWindow(VclPtr
<LineNumberWindow
>::Create(this, pParent
)),
1957 aEdtWindow(VclPtr
<EditorWindow
>::Create(this, pParent
)),
1958 aEWVScrollBar( VclPtr
<ScrollBar
>::Create(this, WB_VSCROLL
| WB_DRAG
) )
1963 aEWVScrollBar
->SetLineSize(nScrollLine
);
1964 aEWVScrollBar
->SetPageSize(nScrollPage
);
1965 aEWVScrollBar
->SetScrollHdl( LINK( this, ComplexEditorWindow
, ScrollHdl
) );
1966 aEWVScrollBar
->Show();
1969 ComplexEditorWindow::~ComplexEditorWindow()
1974 void ComplexEditorWindow::dispose()
1976 aBrkWindow
.disposeAndClear();
1977 aLineNumberWindow
.disposeAndClear();
1978 aEdtWindow
.disposeAndClear();
1979 aEWVScrollBar
.disposeAndClear();
1980 vcl::Window::dispose();
1983 void ComplexEditorWindow::Resize()
1985 Size aOutSz
= GetOutputSizePixel();
1987 aSz
.AdjustWidth( -(2*DWBORDER
) );
1988 aSz
.AdjustHeight( -(2*DWBORDER
) );
1989 long nBrkWidth
= 20;
1990 long nSBWidth
= aEWVScrollBar
->GetSizePixel().Width();
1992 Size
aBrkSz(nBrkWidth
, aSz
.Height());
1994 Size
aLnSz(aLineNumberWindow
->GetWidth(), aSz
.Height());
1996 if (aLineNumberWindow
->IsVisible())
1998 aBrkWindow
->SetPosSizePixel( Point( DWBORDER
, DWBORDER
), aBrkSz
);
1999 aLineNumberWindow
->SetPosSizePixel(Point(DWBORDER
+ aBrkSz
.Width() - 1, DWBORDER
), aLnSz
);
2000 Size
aEWSz(aSz
.Width() - nBrkWidth
- aLineNumberWindow
->GetWidth() - nSBWidth
+ 2, aSz
.Height());
2001 aEdtWindow
->SetPosSizePixel( Point( DWBORDER
+ aBrkSz
.Width() + aLnSz
.Width() - 1, DWBORDER
), aEWSz
);
2005 aBrkWindow
->SetPosSizePixel( Point( DWBORDER
, DWBORDER
), aBrkSz
);
2006 Size
aEWSz(aSz
.Width() - nBrkWidth
- nSBWidth
+ 2, aSz
.Height());
2007 aEdtWindow
->SetPosSizePixel(Point(DWBORDER
+ aBrkSz
.Width() - 1, DWBORDER
), aEWSz
);
2010 aEWVScrollBar
->SetPosSizePixel( Point( aOutSz
.Width() - DWBORDER
- nSBWidth
, DWBORDER
), Size( nSBWidth
, aSz
.Height() ) );
2013 IMPL_LINK(ComplexEditorWindow
, ScrollHdl
, ScrollBar
*, pCurScrollBar
, void )
2015 if (aEdtWindow
->GetEditView())
2017 DBG_ASSERT( pCurScrollBar
== aEWVScrollBar
.get(), "Who is scrolling?" );
2018 long nDiff
= aEdtWindow
->GetEditView()->GetStartDocPos().Y() - pCurScrollBar
->GetThumbPos();
2019 aEdtWindow
->GetEditView()->Scroll( 0, nDiff
);
2020 aBrkWindow
->DoScroll( nDiff
);
2021 aLineNumberWindow
->DoScroll( nDiff
);
2022 aEdtWindow
->GetEditView()->ShowCursor(false);
2023 pCurScrollBar
->SetThumbPos( aEdtWindow
->GetEditView()->GetStartDocPos().Y() );
2027 void ComplexEditorWindow::DataChanged(DataChangedEvent
const & rDCEvt
)
2029 Window::DataChanged(rDCEvt
);
2030 if (rDCEvt
.GetType() == DataChangedEventType::SETTINGS
2031 && (rDCEvt
.GetFlags() & AllSettingsFlags::STYLE
))
2033 Color
aColor(GetSettings().GetStyleSettings().GetFaceColor());
2034 const AllSettings
* pOldSettings
= rDCEvt
.GetOldSettings();
2035 if (!pOldSettings
|| aColor
!= pOldSettings
->GetStyleSettings().GetFaceColor())
2037 SetBackground(Wallpaper(aColor
));
2043 void ComplexEditorWindow::SetLineNumberDisplay(bool b
)
2045 aLineNumberWindow
->Show(b
);
2049 uno::Reference
< awt::XWindowPeer
>
2050 EditorWindow::GetComponentInterface(bool bCreate
)
2052 uno::Reference
< awt::XWindowPeer
> xPeer(
2053 Window::GetComponentInterface(false));
2054 if (!xPeer
.is() && bCreate
)
2056 // Make sure edit engine and view are available:
2060 xPeer
= svt::createTextWindowPeer(*GetEditView());
2061 SetComponentInterface(xPeer
);
2070 WatchTreeListBox::WatchTreeListBox( vcl::Window
* pParent
, WinBits nWinBits
)
2071 : SvHeaderTabListBox( pParent
, nWinBits
)
2074 WatchTreeListBox::~WatchTreeListBox()
2079 void WatchTreeListBox::dispose()
2081 // Destroy user data
2082 SvTreeListEntry
* pEntry
= First();
2085 delete static_cast<WatchItem
*>(pEntry
->GetUserData());
2086 pEntry
->SetUserData(nullptr);
2087 pEntry
= Next( pEntry
);
2089 SvHeaderTabListBox::dispose();
2092 void WatchTreeListBox::SetTabs()
2094 SvHeaderTabListBox::SetTabs();
2095 sal_uInt16 nTabCount_
= aTabs
.size();
2096 for( sal_uInt16 i
= 0 ; i
< nTabCount_
; i
++ )
2098 SvLBoxTab
* pTab
= aTabs
[i
];
2100 pTab
->nFlags
|= SvLBoxTabFlags::EDITABLE
;
2102 pTab
->nFlags
&= ~SvLBoxTabFlags::EDITABLE
;
2106 void WatchTreeListBox::RequestingChildren( SvTreeListEntry
* pParent
)
2108 if( !StarBASIC::IsRunning() )
2111 if( GetChildCount( pParent
) > 0 )
2114 SvTreeListEntry
* pEntry
= pParent
;
2115 WatchItem
* pItem
= static_cast<WatchItem
*>(pEntry
->GetUserData());
2117 SbxDimArray
* pArray
= pItem
->mpArray
.get();
2118 SbxDimArray
* pRootArray
= pItem
->GetRootArray();
2119 bool bArrayIsRootArray
= false;
2120 if( !pArray
&& pRootArray
)
2122 pArray
= pRootArray
;
2123 bArrayIsRootArray
= true;
2126 SbxObject
* pObj
= pItem
->mpObject
.get();
2129 createAllObjectProperties( pObj
);
2130 SbxArray
* pProps
= pObj
->GetProperties();
2131 sal_uInt16 nPropCount
= pProps
->Count();
2132 if ( nPropCount
>= 3 &&
2133 pProps
->Get( nPropCount
-1 )->GetName().equalsIgnoreAsciiCase( "Dbg_Methods" ) &&
2134 pProps
->Get( nPropCount
-2 )->GetName().equalsIgnoreAsciiCase( "Dbg_Properties" ) &&
2135 pProps
->Get( nPropCount
-3 )->GetName().equalsIgnoreAsciiCase( "Dbg_SupportedInterfaces" ) )
2139 pItem
->maMemberList
.reserve(nPropCount
);
2141 for( sal_uInt16 i
= 0 ; i
< nPropCount
; ++i
)
2143 SbxVariable
* pVar
= pProps
->Get( i
);
2145 pItem
->maMemberList
.push_back(pVar
->GetName());
2146 OUString
const& rName
= pItem
->maMemberList
.back();
2147 SvTreeListEntry
* pChildEntry
= SvTreeListBox::InsertEntry( rName
, pEntry
);
2148 pChildEntry
->SetUserData(new WatchItem(rName
));
2150 if( nPropCount
> 0 )
2157 sal_uInt16 nElementCount
= 0;
2159 // Loop through indices of current level
2160 int nParentLevel
= bArrayIsRootArray
? pItem
->nDimLevel
: 0;
2161 int nThisLevel
= nParentLevel
+ 1;
2162 sal_Int32 nMin
, nMax
;
2163 pArray
->GetDim32( nThisLevel
, nMin
, nMax
);
2164 for( sal_Int32 i
= nMin
; i
<= nMax
; i
++ )
2166 WatchItem
* pChildItem
= new WatchItem(pItem
->maName
);
2168 // Copy data and create name
2170 OUString aIndexStr
= "(";
2171 pChildItem
->mpArrayParentItem
= pItem
;
2172 pChildItem
->nDimLevel
= nThisLevel
;
2173 pChildItem
->nDimCount
= pItem
->nDimCount
;
2174 pChildItem
->vIndices
.resize(pChildItem
->nDimCount
);
2176 for( j
= 0 ; j
< nParentLevel
; j
++ )
2178 short n
= pChildItem
->vIndices
[j
] = pItem
->vIndices
[j
];
2179 aIndexStr
+= OUString::number( n
) + ",";
2181 pChildItem
->vIndices
[nParentLevel
] = sal::static_int_cast
<short>( i
);
2182 aIndexStr
+= OUString::number( i
) + ")";
2184 OUString aDisplayName
;
2185 WatchItem
* pArrayRootItem
= pChildItem
->GetRootItem();
2186 if( pArrayRootItem
&& pArrayRootItem
->mpArrayParentItem
)
2187 aDisplayName
= pItem
->maDisplayName
;
2189 aDisplayName
= pItem
->maName
;
2190 aDisplayName
+= aIndexStr
;
2191 pChildItem
->maDisplayName
= aDisplayName
;
2193 SvTreeListEntry
* pChildEntry
= SvTreeListBox::InsertEntry( aDisplayName
, pEntry
);
2195 pChildEntry
->SetUserData( pChildItem
);
2197 if( nElementCount
> 0 )
2204 SbxBase
* WatchTreeListBox::ImplGetSBXForEntry( SvTreeListEntry
* pEntry
, bool& rbArrayElement
)
2206 SbxBase
* pSBX
= nullptr;
2207 rbArrayElement
= false;
2209 WatchItem
* pItem
= static_cast<WatchItem
*>(pEntry
->GetUserData());
2210 OUString
aVName( pItem
->maName
);
2212 SvTreeListEntry
* pParentEntry
= GetParent( pEntry
);
2213 WatchItem
* pParentItem
= pParentEntry
? static_cast<WatchItem
*>(pParentEntry
->GetUserData()) : nullptr;
2216 SbxObject
* pObj
= pParentItem
->mpObject
.get();
2217 SbxDimArray
* pArray
;
2220 pSBX
= pObj
->Find( aVName
, SbxClassType::DontCare
);
2221 if (SbxVariable
const* pVar
= IsSbxVariable(pSBX
))
2223 // Force getting value
2225 aRes
.eType
= SbxVOID
;
2230 else if( (pArray
= pItem
->GetRootArray()) != nullptr )
2232 rbArrayElement
= true;
2233 if( pParentItem
->nDimLevel
+ 1 == pParentItem
->nDimCount
)
2234 pSBX
= pArray
->Get(pItem
->vIndices
.empty() ? nullptr : &*pItem
->vIndices
.begin());
2239 pSBX
= StarBASIC::FindSBXInCurrentScope( aVName
);
2244 bool WatchTreeListBox::EditingEntry( SvTreeListEntry
* pEntry
, Selection
& )
2246 WatchItem
* pItem
= static_cast<WatchItem
*>(pEntry
->GetUserData());
2249 if ( StarBASIC::IsRunning() && StarBASIC::GetActiveMethod() && !SbxBase::IsError() )
2251 // No out of scope entries
2253 SbxBase
* pSbx
= ImplGetSBXForEntry( pEntry
, bArrayElement
);
2254 if (IsSbxVariable(pSbx
) || bArrayElement
)
2256 // Accept no objects and only end nodes of arrays for editing
2257 if( !pItem
->mpObject
.is() && ( !pItem
->mpArray
.is() || pItem
->nDimLevel
== pItem
->nDimCount
) )
2259 aEditingRes
= SvHeaderTabListBox::GetEntryText( pEntry
, ITEM_ID_VALUE
-1 );
2260 aEditingRes
= comphelper::string::strip(aEditingRes
, ' ');
2269 bool WatchTreeListBox::EditedEntry( SvTreeListEntry
* pEntry
, const OUString
& rNewText
)
2271 OUString aResult
= comphelper::string::strip(rNewText
, ' ');
2273 sal_uInt16 nResultLen
= aResult
.getLength();
2274 sal_Unicode cFirst
= aResult
[0];
2275 sal_Unicode cLast
= aResult
[ nResultLen
- 1 ];
2276 if( cFirst
== '\"' && cLast
== '\"' )
2277 aResult
= aResult
.copy( 1, nResultLen
- 2 );
2279 return aResult
!= aEditingRes
&& ImplBasicEntryEdited(pEntry
, aResult
);
2282 bool WatchTreeListBox::ImplBasicEntryEdited( SvTreeListEntry
* pEntry
, const OUString
& rResult
)
2285 SbxBase
* pSBX
= ImplGetSBXForEntry( pEntry
, bArrayElement
);
2287 if (SbxVariable
* pVar
= IsSbxVariable(pSBX
))
2289 SbxDataType eType
= pVar
->GetType();
2290 if ( static_cast<sal_uInt8
>(eType
) != sal_uInt8(SbxOBJECT
)
2291 && ( eType
& SbxARRAY
) == 0 )
2293 // If the type is variable, the conversion of the SBX does not matter,
2294 // else the string is converted.
2295 pVar
->PutStringExt( rResult
);
2299 if ( SbxBase::IsError() )
2301 SbxBase::ResetError();
2306 // The text should never be taken/copied 1:1,
2307 // as the UpdateWatches will be lost
2315 void implCollapseModifiedObjectEntry( SvTreeListEntry
* pParent
, WatchTreeListBox
* pThis
)
2317 pThis
->Collapse( pParent
);
2319 SvTreeList
* pModel
= pThis
->GetModel();
2320 SvTreeListEntry
* pDeleteEntry
;
2321 while( (pDeleteEntry
= pThis
->SvTreeListBox::GetEntry( pParent
, 0 )) != nullptr )
2323 implCollapseModifiedObjectEntry( pDeleteEntry
, pThis
);
2325 delete static_cast<WatchItem
*>(pDeleteEntry
->GetUserData());
2326 pModel
->Remove( pDeleteEntry
);
2330 OUString
implCreateTypeStringForDimArray( WatchItem
* pItem
, SbxDataType eType
)
2332 OUString aRetStr
= getBasicTypeName( eType
);
2334 SbxDimArray
* pArray
= pItem
->mpArray
.get();
2336 pArray
= pItem
->GetRootArray();
2339 int nDimLevel
= pItem
->nDimLevel
;
2340 int nDims
= pItem
->nDimCount
;
2341 if( nDimLevel
< nDims
)
2344 for( int i
= nDimLevel
; i
< nDims
; i
++ )
2347 pArray
->GetDim( sal::static_int_cast
<short>( i
+1 ), nMin
, nMax
);
2348 aRetStr
+= OUString::number(nMin
) + " to " + OUString::number(nMax
);
2358 void implEnableChildren( SvTreeListEntry
* pEntry
, bool bEnable
)
2363 (pEntry
->GetFlags() & ~SvTLEntryFlags(SvTLEntryFlags::NO_NODEBMP
| SvTLEntryFlags::HAD_CHILDREN
))
2364 | SvTLEntryFlags::CHILDREN_ON_DEMAND
);
2368 pEntry
->SetFlags( pEntry
->GetFlags() & ~SvTLEntryFlags::CHILDREN_ON_DEMAND
);
2374 void WatchTreeListBox::UpdateWatches( bool bBasicStopped
)
2376 SbMethod
* pCurMethod
= StarBASIC::GetActiveMethod();
2378 ErrCode eOld
= SbxBase::GetError();
2379 setBasicWatchMode( true );
2381 SvTreeListEntry
* pEntry
= First();
2384 WatchItem
* pItem
= static_cast<WatchItem
*>(pEntry
->GetUserData());
2385 DBG_ASSERT( !pItem
->maName
.isEmpty(), "Var? - Must not be empty!" );
2391 SbxBase
* pSBX
= ImplGetSBXForEntry( pEntry
, bArrayElement
);
2393 // Array? If no end node create type string
2394 if( bArrayElement
&& pItem
->nDimLevel
< pItem
->nDimCount
)
2396 SbxDimArray
* pRootArray
= pItem
->GetRootArray();
2397 SbxDataType eType
= pRootArray
->GetType();
2398 aTypeStr
= implCreateTypeStringForDimArray( pItem
, eType
);
2399 implEnableChildren( pEntry
, true );
2402 bool bCollapse
= false;
2403 if (SbxVariable
const* pVar
= IsSbxVariable(pSBX
))
2405 // extra treatment of arrays
2406 SbxDataType eType
= pVar
->GetType();
2407 if ( eType
& SbxARRAY
)
2409 // consider multidimensional arrays!
2410 if (SbxDimArray
* pNewArray
= dynamic_cast<SbxDimArray
*>(pVar
->GetObject()))
2412 SbxDimArray
* pOldArray
= pItem
->mpArray
.get();
2414 bool bArrayChanged
= false;
2415 if( pNewArray
!= nullptr && pOldArray
!= nullptr )
2417 // Compare Array dimensions to see if array has changed
2418 // Can be a copy, so comparing pointers does not work
2419 sal_uInt16 nOldDims
= pOldArray
->GetDims();
2420 sal_uInt16 nNewDims
= pNewArray
->GetDims();
2421 if( nOldDims
!= nNewDims
)
2423 bArrayChanged
= true;
2427 for( int i
= 0 ; i
< nOldDims
; i
++ )
2429 short nOldMin
, nOldMax
;
2430 short nNewMin
, nNewMax
;
2432 pOldArray
->GetDim( sal::static_int_cast
<short>( i
+1 ), nOldMin
, nOldMax
);
2433 pNewArray
->GetDim( sal::static_int_cast
<short>( i
+1 ), nNewMin
, nNewMax
);
2434 if( nOldMin
!= nNewMin
|| nOldMax
!= nNewMax
)
2436 bArrayChanged
= true;
2442 else if( pNewArray
== nullptr || pOldArray
== nullptr )
2444 bArrayChanged
= true;
2448 implEnableChildren( pEntry
, true );
2450 // #i37227 Clear always and replace array
2451 if( pNewArray
!= pOldArray
)
2453 pItem
->clearWatchItem();
2456 implEnableChildren( pEntry
, true );
2458 pItem
->mpArray
= pNewArray
;
2459 sal_uInt16 nDims
= pNewArray
->GetDims();
2460 pItem
->nDimLevel
= 0;
2461 pItem
->nDimCount
= nDims
;
2464 if( bArrayChanged
&& pOldArray
!= nullptr )
2468 aTypeStr
= implCreateTypeStringForDimArray( pItem
, eType
);
2475 else if ( static_cast<sal_uInt8
>(eType
) == sal_uInt8(SbxOBJECT
) )
2477 if (SbxObject
* pObj
= dynamic_cast<SbxObject
*>(pVar
->GetObject()))
2479 if ( pItem
->mpObject
.is() && !pItem
->maMemberList
.empty() )
2481 bool bObjChanged
= false; // Check if member list has changed
2482 SbxArray
* pProps
= pObj
->GetProperties();
2483 sal_uInt16 nPropCount
= pProps
->Count();
2484 for( sal_uInt16 i
= 0 ; i
< nPropCount
- 3 ; i
++ )
2486 SbxVariable
* pVar_
= pProps
->Get( i
);
2487 OUString
aName( pVar_
->GetName() );
2488 if( pItem
->maMemberList
[i
] != aName
)
2500 pItem
->mpObject
= pObj
;
2501 implEnableChildren( pEntry
, true );
2502 aTypeStr
= getBasicObjectTypeName( pObj
);
2507 if( pItem
->mpObject
.is() )
2510 pItem
->clearWatchItem();
2512 implEnableChildren( pEntry
, false );
2518 if( pItem
->mpObject
.is() )
2521 pItem
->clearWatchItem();
2523 implEnableChildren( pEntry
, false );
2526 bool bString
= (static_cast<sal_uInt8
>(eType
) == sal_uInt8(SbxSTRING
));
2527 OUString
aStrStr( "\"" );
2530 aWatchStr
+= aStrStr
;
2532 aWatchStr
+= pVar
->GetOUString();
2535 aWatchStr
+= aStrStr
;
2538 if( aTypeStr
.isEmpty() )
2540 if( !pVar
->IsFixed() )
2542 aTypeStr
= "Variant/";
2544 aTypeStr
+= getBasicTypeName( pVar
->GetType() );
2547 else if( !bArrayElement
)
2549 aWatchStr
+= "<Out of Scope>";
2554 implCollapseModifiedObjectEntry( pEntry
, this );
2558 else if( bBasicStopped
)
2560 if( pItem
->mpObject
.is() || pItem
->mpArray
.is() )
2562 implCollapseModifiedObjectEntry( pEntry
, this );
2563 pItem
->mpObject
= nullptr;
2567 SvHeaderTabListBox::SetEntryText( aWatchStr
, pEntry
, ITEM_ID_VALUE
-1 );
2568 SvHeaderTabListBox::SetEntryText( aTypeStr
, pEntry
, ITEM_ID_TYPE
-1 );
2570 pEntry
= Next( pEntry
);
2576 SbxBase::ResetError();
2577 if( eOld
!= ERRCODE_NONE
)
2578 SbxBase::SetError( eOld
);
2579 setBasicWatchMode( false );
2582 CodeCompleteListBox::CodeCompleteListBox( CodeCompleteWindow
* pPar
)
2583 : ListBox(pPar
, WB_SORT
| WB_BORDER
),
2584 pCodeCompleteWindow( pPar
)
2586 SetDoubleClickHdl(LINK(this, CodeCompleteListBox
, ImplDoubleClickHdl
));
2587 SetSelectHdl(LINK(this, CodeCompleteListBox
, ImplSelectHdl
));
2590 CodeCompleteListBox::~CodeCompleteListBox()
2595 void CodeCompleteListBox::dispose()
2597 pCodeCompleteWindow
.clear();
2601 IMPL_LINK_NOARG(CodeCompleteListBox
, ImplDoubleClickHdl
, ListBox
&, void)
2603 InsertSelectedEntry();
2606 IMPL_LINK_NOARG(CodeCompleteListBox
, ImplSelectHdl
, ListBox
&, void)
2607 {//give back the focus to the parent
2608 pCodeCompleteWindow
->pParent
->GrabFocus();
2611 TextView
* CodeCompleteListBox::GetParentEditView()
2613 return pCodeCompleteWindow
->pParent
->GetEditView();
2616 void CodeCompleteListBox::InsertSelectedEntry()
2618 if( !aFuncBuffer
.isEmpty() )
2620 // if the user typed in something: remove, and insert
2621 GetParentEditView()->SetSelection( pCodeCompleteWindow
->pParent
->GetLastHighlightPortionTextSelection() );
2622 GetParentEditView()->DeleteSelected();
2624 if( !GetSelectedEntry().isEmpty() )
2625 {//if the user selected something
2626 GetParentEditView()->InsertText( GetSelectedEntry() );
2631 if( !GetSelectedEntry().isEmpty() )
2632 {//if the user selected something
2633 GetParentEditView()->InsertText( GetSelectedEntry() );
2636 HideAndRestoreFocus();
2639 void CodeCompleteListBox::SetMatchingEntries()
2641 for(sal_Int32 i
=0; i
< GetEntryCount(); ++i
)
2643 OUString sEntry
= GetEntry(i
);
2644 if( sEntry
.startsWithIgnoreAsciiCase( aFuncBuffer
.toString() ) )
2646 SelectEntry(sEntry
);
2652 void CodeCompleteListBox::KeyInput( const KeyEvent
& rKeyEvt
)
2654 sal_Unicode aChar
= rKeyEvt
.GetKeyCode().GetCode();
2655 if( (( aChar
>= KEY_A
) && ( aChar
<= KEY_Z
))
2656 || ((aChar
>= KEY_0
) && (aChar
<= KEY_9
)) )
2658 aFuncBuffer
.append(rKeyEvt
.GetCharCode());
2659 SetMatchingEntries();
2665 case KEY_ESCAPE
: // hide, do nothing
2666 HideAndRestoreFocus();
2670 TextSelection
aTextSelection( GetParentEditView()->GetSelection() );
2671 if( aTextSelection
.GetEnd().GetPara() != pCodeCompleteWindow
->GetTextSelection().GetEnd().GetPara()-1 )
2673 HideAndRestoreFocus();
2679 TextSelection
aTextSelection( GetParentEditView()->GetSelection() );
2680 if( aTextSelection
.GetStart().GetIndex()-1 < pCodeCompleteWindow
->GetTextSelection().GetStart().GetIndex() )
2681 {//leave the cursor where it is
2682 HideAndRestoreFocus();
2688 TextSelection aTextSelection
= pCodeCompleteWindow
->pParent
->GetLastHighlightPortionTextSelection();
2689 OUString sTypedText
= pCodeCompleteWindow
->pParent
->GetEditEngine()->GetText(aTextSelection
);
2690 if( !aFuncBuffer
.isEmpty() )
2692 sal_Int32 nInd
= GetSelectedEntryPos();
2693 if( nInd
!= LISTBOX_ENTRY_NOTFOUND
)
2694 {//if there is something selected
2695 bool bFound
= false;
2696 if( nInd
== GetEntryCount() )
2698 for( sal_Int32 i
= nInd
; i
!= GetEntryCount(); ++i
)
2700 OUString sEntry
= GetEntry(i
);
2701 if( sEntry
.startsWithIgnoreAsciiCase( aFuncBuffer
.toString() )
2702 && (aFuncBuffer
.toString() != sTypedText
) && (i
!= nInd
) )
2704 SelectEntry( sEntry
);
2710 SetMatchingEntries();
2712 GetParentEditView()->SetSelection( aTextSelection
);
2713 GetParentEditView()->DeleteSelected();
2714 GetParentEditView()->InsertText( GetSelectedEntry() );
2720 HideAndRestoreFocus();
2722 case KEY_BACKSPACE
: case KEY_DELETE
:
2723 if( !aFuncBuffer
.isEmpty() )
2725 //if there was something inserted by tab: add it to aFuncBuffer
2726 TextSelection
aSel( GetParentEditView()->GetSelection() );
2727 TextPaM
aEnd( GetParentEditView()->CursorEndOfLine(pCodeCompleteWindow
->GetTextSelection().GetEnd()) );
2728 GetParentEditView()->SetSelection(TextSelection(pCodeCompleteWindow
->GetTextSelection().GetStart(), aEnd
) );
2729 OUString
aTabInsertedStr( GetParentEditView()->GetSelected() );
2730 GetParentEditView()->SetSelection( aSel
);
2732 if( !aTabInsertedStr
.isEmpty() && aTabInsertedStr
!= aFuncBuffer
.toString() )
2734 aFuncBuffer
= aTabInsertedStr
;
2736 aFuncBuffer
.remove(aFuncBuffer
.getLength()-1, 1);
2737 SetMatchingEntries();
2740 pCodeCompleteWindow
->ClearAndHide();
2743 InsertSelectedEntry();
2745 case KEY_UP
: case KEY_DOWN
:
2746 NotifyEvent
nEvt( MouseNotifyEvent::KEYINPUT
, nullptr, &rKeyEvt
);
2751 ListBox::KeyInput(rKeyEvt
);
2754 void CodeCompleteListBox::HideAndRestoreFocus()
2756 pCodeCompleteWindow
->Hide();
2757 pCodeCompleteWindow
->pParent
->GrabFocus();
2760 CodeCompleteWindow::CodeCompleteWindow( EditorWindow
* pPar
)
2763 pListBox( VclPtr
<CodeCompleteListBox
>::Create(this) )
2765 SetSizePixel( Size(151,151) ); //default, later it changes
2769 CodeCompleteWindow::~CodeCompleteWindow()
2774 void CodeCompleteWindow::dispose()
2776 pListBox
.disposeAndClear();
2778 vcl::Window::dispose();
2781 void CodeCompleteWindow::InitListBox()
2783 pListBox
->SetSizePixel( Size(150,150) ); //default, this will adopt the line length
2785 pListBox
->EnableQuickSelection( false );
2788 void CodeCompleteWindow::InsertEntry( const OUString
& aStr
)
2790 pListBox
->InsertEntry( aStr
);
2793 void CodeCompleteWindow::ClearListBox()
2796 pListBox
->aFuncBuffer
.setLength(0);
2799 void CodeCompleteWindow::SetTextSelection( const TextSelection
& aSel
)
2801 aTextSelection
= aSel
;
2805 void CodeCompleteWindow::ResizeAndPositionListBox()
2807 if( pListBox
->GetEntryCount() >= 1 )
2808 {// if there is at least one element inside
2809 // calculate basic position: under the current line
2810 tools::Rectangle aRect
= static_cast<TextEngine
*>(pParent
->GetEditEngine())->PaMtoEditCursor( pParent
->GetEditView()->GetSelection().GetEnd() );
2811 long nViewYOffset
= pParent
->GetEditView()->GetStartDocPos().Y();
2812 Point aPos
= aRect
.BottomRight();// this variable will be used later (if needed)
2813 aPos
.setY( (aPos
.Y() - nViewYOffset
) + nBasePad
);
2815 OUString aLongestEntry
= pListBox
->GetEntry( 0 );// grab the longest one: max search
2816 for( sal_Int32 i
=1; i
< pListBox
->GetEntryCount(); ++i
)
2818 if( pListBox
->GetEntry( i
).getLength() > aLongestEntry
.getLength() )
2819 aLongestEntry
= pListBox
->GetEntry( i
);
2821 // get column/line count
2822 const sal_uInt16
& nColumns
= aLongestEntry
.getLength();
2823 const sal_uInt16 nLines
= static_cast<sal_uInt16
>( std::min( sal_Int32(6), pListBox
->GetEntryCount() ));
2825 Size aSize
= pListBox
->CalcBlockSize( nColumns
, nLines
);
2827 SetSizePixel( aSize
);
2828 //1 px smaller, to see the border
2829 aSize
.setWidth( aSize
.getWidth() - 1 );
2830 aSize
.setHeight( aSize
.getHeight() - 1 );
2831 pListBox
->SetSizePixel( aSize
);
2833 //calculate position
2834 const tools::Rectangle
aVisArea( pParent
->GetEditView()->GetStartDocPos(), pParent
->GetOutputSizePixel() ); //the visible area
2835 const Point
& aBottomPoint
= aVisArea
.BottomRight();
2837 if( aVisArea
.TopRight().getY() + aPos
.getY() + aSize
.getHeight() > aBottomPoint
.getY() )
2838 {//clipped at the bottom: move it up
2839 const long& nParentFontHeight
= pParent
->GetEditEngine()->GetFont().GetFontHeight(); //parent's font (in the IDE): needed for height
2840 aPos
.AdjustY( -(aSize
.getHeight() + nParentFontHeight
+ nCursorPad
) );
2843 if( aVisArea
.TopLeft().getX() + aPos
.getX() + aSize
.getWidth() > aBottomPoint
.getX() )
2844 {//clipped at the right side, move it a bit left
2845 aPos
.AdjustX( -(aSize
.getWidth() + aVisArea
.TopLeft().getX()) );
2848 SetPosPixel( aPos
);
2852 void CodeCompleteWindow::SelectFirstEntry()
2854 if( pListBox
->GetEntryCount() > 0 )
2856 pListBox
->SelectEntryPos( 0 );
2860 void CodeCompleteWindow::ClearAndHide()
2863 pListBox
->HideAndRestoreFocus();
2866 UnoTypeCodeCompletetor::UnoTypeCodeCompletetor( const std::vector
< OUString
>& aVect
, const OUString
& sVarType
)
2867 : bCanComplete( true )
2869 if( aVect
.empty() || sVarType
.isEmpty() )
2871 bCanComplete
= false;//invalid parameters, nothing to code complete
2877 // Get the base class for reflection:
2878 xClass
= css::reflection::theCoreReflection::get(
2879 comphelper::getProcessComponentContext())->forName(sVarType
);
2881 catch( const Exception
& )
2883 bCanComplete
= false;
2887 auto j
= aVect
.begin() + 1;//start from aVect[1]: aVect[0] is the variable name
2890 while( j
!= aVect
.end() )
2894 if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
2896 if( !CheckMethod(sMethName
) && !CheckField(sMethName
) )
2898 bCanComplete
= false;
2904 if( !CheckField(sMethName
) )
2906 bCanComplete
= false;
2915 std::vector
< OUString
> UnoTypeCodeCompletetor::GetXIdlClassMethods() const
2917 std::vector
< OUString
> aRetVect
;
2918 if( bCanComplete
&& ( xClass
!= nullptr ) )
2920 Sequence
< Reference
< reflection::XIdlMethod
> > aMethods
= xClass
->getMethods();
2921 if( aMethods
.getLength() != 0 )
2923 for(sal_Int32 l
= 0; l
< aMethods
.getLength(); ++l
)
2925 aRetVect
.push_back( aMethods
[l
]->getName() );
2929 return aRetVect
;//this is empty when cannot code complete
2932 std::vector
< OUString
> UnoTypeCodeCompletetor::GetXIdlClassFields() const
2934 std::vector
< OUString
> aRetVect
;
2935 if( bCanComplete
&& ( xClass
!= nullptr ) )
2937 Sequence
< Reference
< reflection::XIdlField
> > aFields
= xClass
->getFields();
2938 if( aFields
.getLength() != 0 )
2940 for(sal_Int32 l
= 0; l
< aFields
.getLength(); ++l
)
2942 aRetVect
.push_back( aFields
[l
]->getName() );
2946 return aRetVect
;//this is empty when cannot code complete
2950 bool UnoTypeCodeCompletetor::CheckField( const OUString
& sFieldName
)
2951 {// modifies xClass!!!
2953 if ( xClass
== nullptr )
2956 Reference
< reflection::XIdlField
> xField
= xClass
->getField( sFieldName
);
2957 if( xField
!= nullptr )
2959 xClass
= xField
->getType();
2960 if( xClass
!= nullptr )
2968 bool UnoTypeCodeCompletetor::CheckMethod( const OUString
& sMethName
)
2969 {// modifies xClass!!!
2972 if ( xClass
== nullptr )
2975 Reference
< reflection::XIdlMethod
> xMethod
= xClass
->getMethod( sMethName
);
2976 if( xMethod
!= nullptr ) //method OK, check return type
2978 xClass
= xMethod
->getReturnType();
2979 if( xClass
!= nullptr )
2987 } // namespace basctl
2989 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */