Files
libreoffice/basctl/source/basicide/baside2b.cxx
Tomcsik Bence 0e8eb19a53 Object Catalog pane in Basic IDE
Object Catalog was a floating window. It has been converted to a fixed
pane on the right hand side of the editor window. While it is a
BasicDockingWindow, at the moment it is not possible to undock, move,
or resize it. Also, the Object Catalog toolbar button does not show
the visibility status of the pane, ideally it should look pressed, when
the Object Catalog pane is visible. Another missing feature is that
the Object Catalog pane cannot be switched on together with the
dialog editor.
2012-03-11 21:49:13 +01:00

2323 lines
73 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#define _BASIC_TEXTPORTIONS
#include "helpid.hrc"
#include "baside2.hrc"
#include "baside2.hxx"
#include "brkdlg.hxx"
#include "iderdll.hxx"
#include "iderdll2.hxx"
#include "objdlg.hxx"
#include <basic/sbmeth.hxx>
#include <basic/sbuno.hxx>
#include <com/sun/star/script/XLibraryContainer2.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
#include <officecfg/Office/Common.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/sound.hxx>
#include <svl/urihelper.hxx>
#include <svtools/xtextedt.hxx>
#include <svtools/txtattr.hxx>
#include <svtools/textwindowpeer.hxx>
#include <vcl/taskpanelist.hxx>
#include <vcl/help.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
long nVirtToolBoxHeight; // inited in WatchWindow, used in Stackwindow
long nHeaderBarHeight;
#define SCROLL_LINE 12
#define SCROLL_PAGE 60
#define DWBORDER 3
static const char cSuffixes[] = "%&!#@$";
MapUnit eEditMapUnit = MAP_100TH_MM;
/**
* Helper functions to get/set text in TextEngine using
* the stream interface.
*
* get/setText() only supports tools Strings limited to 64K).
*/
::rtl::OUString getTextEngineText( ExtTextEngine* pEngine )
{
SvMemoryStream aMemStream;
aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
aMemStream.SetLineDelimiter( LINEEND_LF );
pEngine->Write( aMemStream );
sal_uLong nSize = aMemStream.Tell();
::rtl::OUString aText( (const sal_Char*)aMemStream.GetData(),
nSize, RTL_TEXTENCODING_UTF8 );
return aText;
}
void setTextEngineText( ExtTextEngine* pEngine, const ::rtl::OUString aStr )
{
pEngine->SetText( String() );
::rtl::OString aUTF8Str = ::rtl::OUStringToOString( aStr, RTL_TEXTENCODING_UTF8 );
SvMemoryStream aMemStream( (void*)aUTF8Str.getStr(), aUTF8Str.getLength(),
STREAM_READ | STREAM_SEEK_TO_BEGIN );
aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
aMemStream.SetLineDelimiter( LINEEND_LF );
pEngine->Read( aMemStream );
}
void lcl_DrawIDEWindowFrame( DockingWindow* pWin )
{
if ( pWin->IsFloatingMode() )
return;
Size aSz = pWin->GetOutputSizePixel();
const Color aOldLineColor( pWin->GetLineColor() );
pWin->SetLineColor( Color( COL_WHITE ) );
// White line on top
pWin->DrawLine( Point( 0, 0 ), Point( aSz.Width(), 0 ) );
// Black line at bottom
pWin->SetLineColor( Color( COL_BLACK ) );
pWin->DrawLine( Point( 0, aSz.Height() - 1 ),
Point( aSz.Width(), aSz.Height() - 1 ) );
pWin->SetLineColor( aOldLineColor );
}
void lcl_SeparateNameAndIndex( const String& rVName, String& rVar, String& rIndex )
{
rVar = rVName;
rIndex.Erase();
sal_uInt16 nIndexStart = rVar.Search( '(' );
if ( nIndexStart != STRING_NOTFOUND )
{
sal_uInt16 nIndexEnd = rVar.Search( ')', nIndexStart );
if ( nIndexStart != STRING_NOTFOUND )
{
rIndex = rVar.Copy( nIndexStart+1, nIndexEnd-nIndexStart-1 );
rVar.Erase( nIndexStart );
rVar.EraseTrailingChars();
rIndex.EraseLeadingChars();
rIndex.EraseTrailingChars();
}
}
if ( rVar.Len() )
{
sal_uInt16 nLastChar = rVar.Len()-1;
if ( strchr( cSuffixes, rVar.GetChar( nLastChar ) ) )
rVar.Erase( nLastChar, 1 );
}
if ( rIndex.Len() )
{
sal_uInt16 nLastChar = rIndex.Len()-1;
if ( strchr( cSuffixes, rIndex.GetChar( nLastChar ) ) )
rIndex.Erase( nLastChar, 1 );
}
}
class EditorWindow::ChangesListener:
public cppu::WeakImplHelper1< beans::XPropertiesChangeListener >
{
public:
ChangesListener(EditorWindow & editor): editor_(editor) {}
private:
virtual ~ChangesListener() {}
virtual void SAL_CALL disposing(lang::EventObject const &) throw (RuntimeException)
{
osl::MutexGuard g(editor_.mutex_);
editor_.notifier_.clear();
}
virtual void SAL_CALL propertiesChange(
Sequence< beans::PropertyChangeEvent > const &) throw (RuntimeException)
{
SolarMutexGuard g;
editor_.ImplSetFont();
}
EditorWindow & editor_;
};
EditorWindow::EditorWindow( Window* pParent ) :
Window( pParent, WB_BORDER )
{
bDoSyntaxHighlight = sal_True;
bDelayHighlight = sal_True;
pModulWindow = 0;
pEditView = 0;
pEditEngine = 0;
bHighlightning = sal_False;
pProgress = 0;
nCurTextWidth = 0;
SetBackground(
Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
SetPointer( Pointer( POINTER_TEXT ) );
SetHelpId( HID_BASICIDE_EDITORWINDOW );
// Using "this" in ctor is a little fishy, but should work here at least as
// long as there are no derivations:
listener_ = new ChangesListener(*this);
Reference< beans::XMultiPropertySet > n(
officecfg::Office::Common::Font::SourceViewFont::get(),
UNO_QUERY_THROW);
{
osl::MutexGuard g(mutex_);
notifier_ = n;
}
Sequence< rtl::OUString > s(2);
s[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FontHeight"));
s[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FontName"));
n->addPropertiesChangeListener(s, listener_.get());
}
EditorWindow::~EditorWindow()
{
Reference< beans::XMultiPropertySet > n;
{
osl::MutexGuard g(mutex_);
n = notifier_;
}
if (n.is()) {
n->removePropertiesChangeListener(listener_.get());
}
aSyntaxIdleTimer.Stop();
if ( pEditEngine )
{
EndListening( *pEditEngine );
pEditEngine->RemoveView( pEditView );
delete pEditView;
delete pEditEngine;
}
}
String EditorWindow::GetWordAtCursor()
{
String aWord;
if ( pEditView )
{
TextEngine* pTextEngine = pEditView->GetTextEngine();
if ( pTextEngine )
{
// check first, if the cursor is at a help URL
const TextSelection& rSelection = pEditView->GetSelection();
const TextPaM& rSelStart = rSelection.GetStart();
const TextPaM& rSelEnd = rSelection.GetEnd();
String aText = pTextEngine->GetText( rSelEnd.GetPara() );
CharClass aClass( ::comphelper::getProcessServiceFactory() , Application::GetSettings().GetLocale() );
xub_StrLen nSelStart = static_cast< xub_StrLen >( rSelStart.GetIndex() );
xub_StrLen nSelEnd = static_cast< xub_StrLen >( rSelEnd.GetIndex() );
xub_StrLen nLength = static_cast< xub_StrLen >( aText.Len() );
xub_StrLen nStart = 0;
xub_StrLen nEnd = nLength;
while ( nStart < nLength )
{
String aURL( URIHelper::FindFirstURLInText( aText, nStart, nEnd, aClass ) );
INetURLObject aURLObj( aURL );
if ( aURLObj.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP
&& nSelStart >= nStart && nSelStart <= nEnd && nSelEnd >= nStart && nSelEnd <= nEnd )
{
aWord = aURL;
break;
}
nStart = nEnd;
nEnd = nLength;
}
// Not the selected range, but at the CursorPosition,
// if a word is partially selected.
if ( !aWord.Len() )
aWord = pTextEngine->GetWord( rSelEnd );
// Can be empty when full word selected, as Cursor behing it
if ( !aWord.Len() && pEditView->HasSelection() )
aWord = pTextEngine->GetWord( rSelStart );
}
}
return aWord;
}
void EditorWindow::RequestHelp( const HelpEvent& rHEvt )
{
sal_Bool bDone = sal_False;
// Should have been activated at some point
if ( pEditEngine )
{
if ( rHEvt.GetMode() & HELPMODE_CONTEXT )
{
String aKeyword = GetWordAtCursor();
Application::GetHelp()->SearchKeyword( aKeyword );
bDone = sal_True;
}
else if ( rHEvt.GetMode() & HELPMODE_QUICK )
{
String aHelpText;
Point aTopLeft;
if ( StarBASIC::IsRunning() )
{
Point aWindowPos = rHEvt.GetMousePosPixel();
aWindowPos = ScreenToOutputPixel( aWindowPos );
Point aDocPos = GetEditView()->GetDocPos( aWindowPos );
TextPaM aCursor = GetEditView()->GetTextEngine()->GetPaM( aDocPos, sal_False );
TextPaM aStartOfWord;
String aWord = GetEditView()->GetTextEngine()->GetWord( aCursor, &aStartOfWord );
if ( aWord.Len() && !comphelper::string::isdigitAsciiString(aWord) )
{
sal_uInt16 nLastChar =aWord.Len()-1;
if ( strchr( cSuffixes, aWord.GetChar( nLastChar ) ) )
aWord.Erase( nLastChar, 1 );
SbxBase* pSBX = StarBASIC::FindSBXInCurrentScope( aWord );
if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
{
SbxVariable* pVar = (SbxVariable*)pSBX;
SbxDataType eType = pVar->GetType();
if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
// might cause a crash e. g. at the selections-object
// Type == Object does not mean pVar == Object!
; // aHelpText = ((SbxObject*)pVar)->GetClassName();
else if ( eType & SbxARRAY )
; // aHelpText = "{...}";
else if ( (sal_uInt8)eType != (sal_uInt8)SbxEMPTY )
{
aHelpText = pVar->GetName();
if ( !aHelpText.Len() ) // name is not copied with the passed parameters
aHelpText = aWord;
aHelpText += '=';
aHelpText += pVar->GetString();
}
}
if ( aHelpText.Len() )
{
aTopLeft = GetEditView()->GetTextEngine()->PaMtoEditCursor( aStartOfWord ).BottomLeft();
aTopLeft = GetEditView()->GetWindowPos( aTopLeft );
aTopLeft.X() += 5;
aTopLeft.Y() += 5;
aTopLeft = OutputToScreenPixel( aTopLeft );
}
}
}
Help::ShowQuickHelp( this, Rectangle( aTopLeft, Size( 1, 1 ) ), aHelpText, QUICKHELP_TOP|QUICKHELP_LEFT);
bDone = sal_True;
}
}
if ( !bDone )
Window::RequestHelp( rHEvt );
}
void EditorWindow::Resize()
{
// ScrollBars, etc. happens in Adjust...
if ( pEditView )
{
long nVisY = pEditView->GetStartDocPos().Y();
pEditView->ShowCursor();
Size aOutSz( GetOutputSizePixel() );
long nMaxVisAreaStart = pEditView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
if ( nMaxVisAreaStart < 0 )
nMaxVisAreaStart = 0;
if ( pEditView->GetStartDocPos().Y() > nMaxVisAreaStart )
{
Point aStartDocPos( pEditView->GetStartDocPos() );
aStartDocPos.Y() = nMaxVisAreaStart;
pEditView->SetStartDocPos( aStartDocPos );
pEditView->ShowCursor();
pModulWindow->GetBreakPointWindow().GetCurYOffset() = aStartDocPos.Y();
pModulWindow->GetLineNumberWindow().GetCurYOffset() = aStartDocPos.Y();
}
InitScrollBars();
if ( nVisY != pEditView->GetStartDocPos().Y() )
Invalidate();
}
}
void EditorWindow::MouseMove( const MouseEvent &rEvt )
{
if ( pEditView )
pEditView->MouseMove( rEvt );
}
void EditorWindow::MouseButtonUp( const MouseEvent &rEvt )
{
if ( pEditView )
{
pEditView->MouseButtonUp( rEvt );
SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
if ( pBindings )
pBindings->Invalidate( SID_BASICIDE_STAT_POS );
}
}
void EditorWindow::MouseButtonDown( const MouseEvent &rEvt )
{
GrabFocus();
if ( pEditView )
{
pEditView->MouseButtonDown( rEvt );
}
}
void EditorWindow::Command( const CommandEvent& rCEvt )
{
if ( pEditView )
{
pEditView->Command( rCEvt );
if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) ||
( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) ||
( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) )
{
HandleScrollCommand( rCEvt, pModulWindow->GetHScrollBar(), &pModulWindow->GetEditVScrollBar() );
}
}
}
sal_Bool EditorWindow::ImpCanModify()
{
sal_Bool bCanModify = sal_True;
if ( StarBASIC::IsRunning() )
{
// If in Trace-mode, abort the trace or refuse input
// Remove markers in the modules in Notify at Basic::Stoped
if ( QueryBox( 0, WB_OK_CANCEL, String( IDEResId( RID_STR_WILLSTOPPRG ) ) ).Execute() == RET_OK )
{
pModulWindow->GetBasicStatus().bIsRunning = sal_False;
BasicIDE::StopBasic();
}
else
bCanModify = sal_False;
}
return bCanModify;
}
void EditorWindow::KeyInput( const KeyEvent& rKEvt )
{
if ( !pEditView ) // Happens in Win95
return;
#if OSL_DEBUG_LEVEL > 1
Range aRange = pModulWindow->GetHScrollBar()->GetRange(); (void)aRange;
long nVisSz = pModulWindow->GetHScrollBar()->GetVisibleSize(); (void)nVisSz;
long nPapSz = pModulWindow->GetHScrollBar()->GetPageSize(); (void)nPapSz;
long nLinSz = pModulWindow->GetHScrollBar()->GetLineSize(); (void)nLinSz;
long nThumb = pModulWindow->GetHScrollBar()->GetThumbPos(); (void)nThumb;
#endif
sal_Bool bWasModified = pEditEngine->IsModified();
// see if there is an accelerator to be processed first
sal_Bool bDone = SfxViewShell::Current()->KeyInput( rKEvt );
if ( !bDone && ( !TextEngine::DoesKeyChangeText( rKEvt ) || ImpCanModify() ) )
{
if ( ( rKEvt.GetKeyCode().GetCode() == KEY_Y ) && rKEvt.GetKeyCode().IsMod1() )
bDone = sal_True;
else
{
if ( ( rKEvt.GetKeyCode().GetCode() == KEY_TAB ) && !rKEvt.GetKeyCode().IsMod1() &&
!rKEvt.GetKeyCode().IsMod2() && !GetEditView()->IsReadOnly() )
{
TextSelection aSel( pEditView->GetSelection() );
if ( aSel.GetStart().GetPara() != aSel.GetEnd().GetPara() )
{
bDelayHighlight = sal_False;
if ( !rKEvt.GetKeyCode().IsShift() )
pEditView->IndentBlock();
else
pEditView->UnindentBlock();
bDelayHighlight = sal_True;
bDone = sal_True;
}
}
if ( !bDone )
bDone = pEditView->KeyInput( rKEvt );
}
}
if ( !bDone )
{
Window::KeyInput( rKEvt );
}
else
{
SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
if ( pBindings )
{
pBindings->Invalidate( SID_BASICIDE_STAT_POS );
if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR )
pBindings->Update( SID_BASICIDE_STAT_POS );
if ( !bWasModified && pEditEngine->IsModified() )
{
pBindings->Invalidate( SID_SAVEDOC );
pBindings->Invalidate( SID_DOC_MODIFIED );
pBindings->Invalidate( SID_UNDO );
}
if ( rKEvt.GetKeyCode().GetCode() == KEY_INSERT )
pBindings->Invalidate( SID_ATTR_INSERT );
}
}
}
void EditorWindow::Paint( const Rectangle& rRect )
{
if ( !pEditEngine ) // We need it now at latest
CreateEditEngine();
pEditView->Paint( rRect );
}
void EditorWindow::LoseFocus()
{
SetSourceInBasic();
Window::LoseFocus();
}
sal_Bool EditorWindow::SetSourceInBasic( sal_Bool bQuiet )
{
(void)bQuiet;
sal_Bool bChanged = sal_False;
if ( pEditEngine && pEditEngine->IsModified()
&& !GetEditView()->IsReadOnly() ) // Added for #i60626, otherwise
// any read only bug in the text engine could lead to a crash later
{
if ( !StarBASIC::IsRunning() ) // Not at runtime!
{
::rtl::OUString aModule = getTextEngineText( pEditEngine );
// update module in basic
#ifdef DBG_UTIL
SbModule* pModule = pModulWindow->GetSbModule();
#endif
DBG_ASSERT(pModule, "EditorWindow::SetSourceInBasic: No Module found!");
// update module in module window
pModulWindow->SetModule( aModule );
// update module in library
ScriptDocument aDocument( pModulWindow->GetDocument() );
String aLibName = pModulWindow->GetLibName();
String aName = pModulWindow->GetName();
OSL_VERIFY( aDocument.updateModule( aLibName, aName, aModule ) );
pEditEngine->SetModified( sal_False );
BasicIDE::MarkDocumentModified( aDocument );
bChanged = sal_True;
}
}
return bChanged;
}
// Returns the position of the last character of any of the following
// EOL char combinations: CR, CR/LF, LF, return -1 if no EOL is found
sal_Int32 searchEOL( const ::rtl::OUString& rStr, sal_Int32 fromIndex )
{
sal_Int32 iRetPos = -1;
sal_Int32 iLF = rStr.indexOf( LINE_SEP, fromIndex );
if( iLF != -1 )
{
iRetPos = iLF;
}
else
{
iRetPos = rStr.indexOf( LINE_SEP_CR, fromIndex );
}
return iRetPos;
}
void EditorWindow::CreateEditEngine()
{
if ( pEditEngine )
return;
pEditEngine = new ExtTextEngine;
pEditView = new ExtTextView( pEditEngine, this );
pEditView->SetAutoIndentMode( sal_True );
pEditEngine->SetUpdateMode( sal_False );
pEditEngine->InsertView( pEditView );
ImplSetFont();
aSyntaxIdleTimer.SetTimeout( 200 );
aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, EditorWindow, SyntaxTimerHdl ) );
aHighlighter.initialize( HIGHLIGHT_BASIC );
sal_Bool bWasDoSyntaxHighlight = bDoSyntaxHighlight;
bDoSyntaxHighlight = sal_False; // too slow for large texts...
::rtl::OUString aOUSource( pModulWindow->GetModule() );
sal_Int32 nLines = 0;
sal_Int32 nIndex = -1;
do
{
nLines++;
nIndex = searchEOL( aOUSource, nIndex+1 );
}
while ( nIndex >= 0 );
// nLines*4: SetText+Formatting+DoHighlight+Formatting
// it could be cut down on one formatting but you would wait even longer
// for the text then if the source code is long...
pProgress = new ProgressInfo( BasicIDEGlobals::GetShell()->GetViewFrame()->GetObjectShell(), String( IDEResId( RID_STR_GENERATESOURCE ) ), nLines*4 );
setTextEngineText( pEditEngine, aOUSource );
pEditView->SetStartDocPos( Point( 0, 0 ) );
pEditView->SetSelection( TextSelection() );
pModulWindow->GetBreakPointWindow().GetCurYOffset() = 0;
pModulWindow->GetLineNumberWindow().GetCurYOffset() = 0;
pEditEngine->SetUpdateMode( sal_True );
Update(); // has only been invalidated at UpdateMode = sal_True
pModulWindow->GetLayout()->GetWatchWindow().Update();
pModulWindow->GetLayout()->GetStackWindow().Update();
pModulWindow->GetBreakPointWindow().Update();
pModulWindow->GetLineNumberWindow().Update();
pEditView->ShowCursor( sal_True, sal_True );
StartListening( *pEditEngine );
aSyntaxIdleTimer.Stop();
bDoSyntaxHighlight = bWasDoSyntaxHighlight;
for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
aSyntaxLineTable.Insert( nLine, (void*)(sal_uInt16)1 );
ForceSyntaxTimeout();
DELETEZ( pProgress );
pEditView->EraseVirtualDevice();
pEditEngine->SetModified( sal_False );
pEditEngine->EnableUndo( sal_True );
InitScrollBars();
SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
if ( pBindings )
pBindings->Invalidate( SID_BASICIDE_STAT_POS );
DBG_ASSERT( pModulWindow->GetBreakPointWindow().GetCurYOffset() == 0, "CreateEditEngine: Brechpunkte verschoben?" );
// set readonly mode for readonly libraries
ScriptDocument aDocument( pModulWindow->GetDocument() );
::rtl::OUString aOULibName( pModulWindow->GetLibName() );
Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && xModLibContainer->isLibraryReadOnly( aOULibName ) )
{
pModulWindow->SetReadOnly( sal_True );
}
if ( aDocument.isDocument() && aDocument.isReadOnly() )
pModulWindow->SetReadOnly( sal_True );
}
// virtual
void EditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
Window::DataChanged(rDCEvt);
if (rDCEvt.GetType() == DATACHANGED_SETTINGS
&& (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
{
Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
if (aColor
!= rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
{
SetBackground(Wallpaper(aColor));
Invalidate();
}
if (pEditEngine != 0)
{
aColor = GetSettings().GetStyleSettings().GetFieldTextColor();
if (aColor != rDCEvt.GetOldSettings()->
GetStyleSettings().GetFieldTextColor())
{
Font aFont(pEditEngine->GetFont());
aFont.SetColor(aColor);
pEditEngine->SetFont(aFont);
}
}
}
}
void EditorWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
{
if ( rHint.ISA( TextHint ) )
{
const TextHint& rTextHint = (const TextHint&)rHint;
if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
{
if ( pModulWindow->GetHScrollBar() )
pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
pModulWindow->GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
pModulWindow->GetBreakPointWindow().DoScroll
( 0, pModulWindow->GetBreakPointWindow().GetCurYOffset() - pEditView->GetStartDocPos().Y() );
pModulWindow->GetLineNumberWindow().DoScroll
( 0, pModulWindow->GetLineNumberWindow().GetCurYOffset() - pEditView->GetStartDocPos().Y() );
pModulWindow->Invalidate();
}
else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
{
if ( pEditView->GetStartDocPos().Y() )
{
long nOutHeight = GetOutputSizePixel().Height();
long nTextHeight = pEditEngine->GetTextHeight();
if ( nTextHeight < nOutHeight )
pEditView->Scroll( 0, pEditView->GetStartDocPos().Y() );
pModulWindow->GetLineNumberWindow().Invalidate();
}
SetScrollBarRanges();
}
else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED )
{
if ( pModulWindow->GetHScrollBar() )
{
sal_uLong nWidth = pEditEngine->CalcTextWidth();
if ( (long)nWidth != nCurTextWidth )
{
nCurTextWidth = nWidth;
pModulWindow->GetHScrollBar()->SetRange( Range( 0, (long)nCurTextWidth-1) );
pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
}
}
long nPrevTextWidth = nCurTextWidth;
nCurTextWidth = pEditEngine->CalcTextWidth();
if ( nCurTextWidth != nPrevTextWidth )
SetScrollBarRanges();
}
else if( rTextHint.GetId() == TEXT_HINT_PARAINSERTED )
{
ParagraphInsertedDeleted( rTextHint.GetValue(), sal_True );
DoDelayedSyntaxHighlight( rTextHint.GetValue() );
}
else if( rTextHint.GetId() == TEXT_HINT_PARAREMOVED )
{
ParagraphInsertedDeleted( rTextHint.GetValue(), sal_False );
}
else if( rTextHint.GetId() == TEXT_HINT_PARACONTENTCHANGED )
{
DoDelayedSyntaxHighlight( rTextHint.GetValue() );
}
}
}
void EditorWindow::SetScrollBarRanges()
{
// extra method, not InitScrollBars, because for EditEngine events too
if ( !pEditEngine )
return;
if ( pModulWindow->GetHScrollBar() )
pModulWindow->GetHScrollBar()->SetRange( Range( 0, nCurTextWidth-1 ) );
pModulWindow->GetEditVScrollBar().SetRange( Range( 0, pEditEngine->GetTextHeight()-1 ) );
}
void EditorWindow::InitScrollBars()
{
if ( !pEditEngine )
return;
SetScrollBarRanges();
Size aOutSz( GetOutputSizePixel() );
pModulWindow->GetEditVScrollBar().SetVisibleSize( aOutSz.Height() );
pModulWindow->GetEditVScrollBar().SetPageSize( aOutSz.Height() * 8 / 10 );
pModulWindow->GetEditVScrollBar().SetLineSize( GetTextHeight() );
pModulWindow->GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
pModulWindow->GetEditVScrollBar().Show();
if ( pModulWindow->GetHScrollBar() )
{
pModulWindow->GetHScrollBar()->SetVisibleSize( aOutSz.Width() );
pModulWindow->GetHScrollBar()->SetPageSize( aOutSz.Width() * 8 / 10 );
pModulWindow->GetHScrollBar()->SetLineSize( GetTextWidth( 'x' ) );
pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
pModulWindow->GetHScrollBar()->Show();
}
}
void EditorWindow::ImpDoHighlight( sal_uLong nLine )
{
if ( bDoSyntaxHighlight )
{
String aLine( pEditEngine->GetText( nLine ) );
Range aChanges = aHighlighter.notifyChange( nLine, 0, &aLine, 1 );
if ( aChanges.Len() )
{
for ( long n = aChanges.Min() + 1; n <= aChanges.Max(); n++ )
aSyntaxLineTable.Insert( n, (void*)(sal_uLong)1 );
aSyntaxIdleTimer.Start();
}
sal_Bool bWasModified = pEditEngine->IsModified();
pEditEngine->RemoveAttribs( nLine, sal_True );
HighlightPortions aPortions;
aHighlighter.getHighlightPortions( nLine, aLine, aPortions );
for ( size_t i = 0; i < aPortions.size(); i++ )
{
HighlightPortion& r = aPortions[i];
const Color& rColor = dynamic_cast<ModulWindowLayout*>(pModulWindow->GetLayoutWindow())->getSyntaxColor(r.tokenType);
pEditEngine->SetAttrib( TextAttribFontColor( rColor ), nLine, r.nBegin, r.nEnd, sal_True );
}
pEditEngine->SetModified( bWasModified );
}
}
void EditorWindow::ImplSetFont()
{
rtl::OUString sFontName(
officecfg::Office::Common::Font::SourceViewFont::FontName::get().
get_value_or( rtl::OUString() ) );
if ( sFontName.isEmpty() )
{
Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetUILanguage(), 0 , this ) );
sFontName = aTmpFont.GetName();
}
Size aFontSize(
0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() );
Font aFont( sFontName, aFontSize );
aFont.SetColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
SetPointFont( aFont );
aFont = GetFont();
if ( pModulWindow )
{
pModulWindow->GetBreakPointWindow().SetFont( aFont );
pModulWindow->GetLineNumberWindow().SetFont( aFont );
}
if ( pEditEngine )
{
sal_Bool bModified = pEditEngine->IsModified();
pEditEngine->SetFont( aFont );
pEditEngine->SetModified( bModified );
}
}
void EditorWindow::DoSyntaxHighlight( sal_uLong nPara )
{
// because of the DelayedSyntaxHighlight it's possible
// that this line does not exist anymore!
if ( nPara < pEditEngine->GetParagraphCount() )
{
// unfortunately I'm not sure that excactly this line does Modified() ...
if ( pProgress )
pProgress->StepProgress();
ImpDoHighlight( nPara );
}
}
void EditorWindow::DoDelayedSyntaxHighlight( sal_uLong nPara )
{
// line is only added to 'Liste' (list), processed in TimerHdl
// => don't manipulate breaks while EditEngine is formatting
if ( pProgress )
pProgress->StepProgress();
if ( !bHighlightning && bDoSyntaxHighlight )
{
if ( bDelayHighlight )
{
aSyntaxLineTable.Insert( nPara, (void*)(sal_uLong)1 );
aSyntaxIdleTimer.Start();
}
else
DoSyntaxHighlight( nPara );
}
}
IMPL_LINK_NOARG(EditorWindow, SyntaxTimerHdl)
{
DBG_ASSERT( pEditView, "Noch keine View, aber Syntax-Highlight ?!" );
sal_Bool bWasModified = pEditEngine->IsModified();
// pEditEngine->SetUpdateMode( sal_False );
bHighlightning = sal_True;
sal_uInt16 nLine;
void* p = aSyntaxLineTable.First();
while ( p )
{
nLine = (sal_uInt16)aSyntaxLineTable.GetCurKey();
DoSyntaxHighlight( nLine );
p = aSyntaxLineTable.Next();
}
// #i45572#
if ( pEditView )
pEditView->ShowCursor( sal_False, sal_True );
pEditEngine->SetModified( bWasModified );
aSyntaxLineTable.Clear();
bHighlightning = sal_False;
return 0;
}
void EditorWindow::ParagraphInsertedDeleted( sal_uLong nPara, sal_Bool bInserted )
{
if ( pProgress )
pProgress->StepProgress();
if ( !bInserted && ( nPara == TEXT_PARA_ALL ) )
{
pModulWindow->GetBreakPoints().reset();
pModulWindow->GetBreakPointWindow().Invalidate();
pModulWindow->GetLineNumberWindow().Invalidate();
aHighlighter.initialize( HIGHLIGHT_BASIC );
}
else
{
pModulWindow->GetBreakPoints().AdjustBreakPoints( (sal_uInt16)nPara+1, bInserted );
long nLineHeight = GetTextHeight();
Size aSz = pModulWindow->GetBreakPointWindow().GetOutputSize();
Rectangle aInvRec( Point( 0, 0 ), aSz );
long nY = nPara*nLineHeight - pModulWindow->GetBreakPointWindow().GetCurYOffset();
aInvRec.Top() = nY;
pModulWindow->GetBreakPointWindow().Invalidate( aInvRec );
Size aLnSz(pModulWindow->GetLineNumberWindow().GetWidth(),
GetOutputSizePixel().Height() - 2 * DWBORDER);
pModulWindow->GetLineNumberWindow().SetPosSizePixel(Point(DWBORDER + 19, DWBORDER), aLnSz);
pModulWindow->GetLineNumberWindow().Invalidate();
if ( bDoSyntaxHighlight )
{
String aDummy;
aHighlighter.notifyChange( nPara, bInserted ? 1 : (-1), &aDummy, 1 );
}
}
}
void EditorWindow::CreateProgress( const String& rText, sal_uLong nRange )
{
DBG_ASSERT( !pProgress, "ProgressInfo existiert schon" );
pProgress = new ProgressInfo( BasicIDEGlobals::GetShell()->GetViewFrame()->GetObjectShell(), rText, nRange );
}
void EditorWindow::DestroyProgress()
{
DELETEZ( pProgress );
}
void EditorWindow::ForceSyntaxTimeout()
{
aSyntaxIdleTimer.Stop();
((Link&)aSyntaxIdleTimer.GetTimeoutHdl()).Call( &aSyntaxIdleTimer );
}
BreakPointWindow::BreakPointWindow( Window* pParent ) :
Window( pParent, WB_BORDER )
{
pModulWindow = 0;
nCurYOffset = 0;
setBackgroundColor(GetSettings().GetStyleSettings().GetFieldColor());
nMarkerPos = MARKER_NOMARKER;
// memorize nCurYOffset and not take it from EditEngine
SetHelpId( HID_BASICIDE_BREAKPOINTWINDOW );
}
BreakPointWindow::~BreakPointWindow()
{
}
void BreakPointWindow::Resize()
{
/// Invalidate();
}
void BreakPointWindow::Paint( const Rectangle& )
{
if ( SyncYOffset() )
return;
Size aOutSz( GetOutputSize() );
long nLineHeight = GetTextHeight();
ModulWindowLayout* pModulWindowLayout = dynamic_cast<ModulWindowLayout*>(pModulWindow->GetLayoutWindow());
Image aBrk1(pModulWindowLayout->getImage(IMGID_BRKENABLED));
Image aBrk0(pModulWindowLayout->getImage(IMGID_BRKDISABLED));
Size aBmpSz( aBrk1.GetSizePixel() );
aBmpSz = PixelToLogic( aBmpSz );
Point aBmpOff( 0, 0 );
aBmpOff.X() = ( aOutSz.Width() - aBmpSz.Width() ) / 2;
aBmpOff.Y() = ( nLineHeight - aBmpSz.Height() ) / 2;
for ( size_t i = 0, n = GetBreakPoints().size(); i < n ; ++i )
{
BreakPoint* pBrk = GetBreakPoints().at( i );
size_t nLine = pBrk->nLine-1;
size_t nY = nLine*nLineHeight - nCurYOffset;
DrawImage( Point( 0, nY ) + aBmpOff, pBrk->bEnabled ? aBrk1 : aBrk0 );
}
ShowMarker( sal_True );
}
void BreakPointWindow::DoScroll( long nHorzScroll, long nVertScroll )
{
nCurYOffset -= nVertScroll;
Window::Scroll( nHorzScroll, nVertScroll );
}
void BreakPointWindow::SetMarkerPos( sal_uInt16 nLine, sal_Bool bError )
{
if ( SyncYOffset() )
Update();
ShowMarker( sal_False );
nMarkerPos = nLine;
bErrorMarker = bError;
ShowMarker( sal_True );
}
void BreakPointWindow::ShowMarker( sal_Bool bShow )
{
if ( nMarkerPos == MARKER_NOMARKER )
return;
Size aOutSz( GetOutputSize() );
long nLineHeight = GetTextHeight();
ModulWindowLayout* pModulWindowLayout = dynamic_cast<ModulWindowLayout*>(pModulWindow->GetLayoutWindow());
Image aMarker(pModulWindowLayout->getImage(bErrorMarker ? IMGID_ERRORMARKER : IMGID_STEPMARKER));
Size aMarkerSz( aMarker.GetSizePixel() );
aMarkerSz = PixelToLogic( aMarkerSz );
Point aMarkerOff( 0, 0 );
aMarkerOff.X() = ( aOutSz.Width() - aMarkerSz.Width() ) / 2;
aMarkerOff.Y() = ( nLineHeight - aMarkerSz.Height() ) / 2;
sal_uLong nY = nMarkerPos*nLineHeight - nCurYOffset;
Point aPos( 0, nY );
aPos += aMarkerOff;
if ( bShow )
DrawImage( aPos, aMarker );
else
Invalidate( Rectangle( aPos, aMarkerSz ) );
}
BreakPoint* BreakPointWindow::FindBreakPoint( const Point& rMousePos )
{
size_t nLineHeight = GetTextHeight();
size_t nYPos = rMousePos.Y() + nCurYOffset;
for ( size_t i = 0, n = GetBreakPoints().size(); i < n ; ++i )
{
BreakPoint* pBrk = GetBreakPoints().at( i );
size_t nLine = pBrk->nLine-1;
size_t nY = nLine*nLineHeight;
if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) )
return pBrk;
}
return 0;
}
void BreakPointWindow::MouseButtonDown( const MouseEvent& rMEvt )
{
if ( rMEvt.GetClicks() == 2 )
{
Point aMousePos( PixelToLogic( rMEvt.GetPosPixel() ) );
long nLineHeight = GetTextHeight();
long nYPos = aMousePos.Y() + nCurYOffset;
long nLine = nYPos / nLineHeight + 1;
pModulWindow->ToggleBreakPoint( (sal_uLong)nLine );
Invalidate();
}
}
void BreakPointWindow::Command( const CommandEvent& rCEvt )
{
if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
{
Point aPos( rCEvt.IsMouseEvent() ? rCEvt.GetMousePosPixel() : Point(1,1) );
Point aEventPos( PixelToLogic( aPos ) );
BreakPoint* pBrk = rCEvt.IsMouseEvent() ? FindBreakPoint( aEventPos ) : 0;
if ( pBrk )
{
// test if break point is enabled...
PopupMenu aBrkPropMenu( IDEResId( RID_POPUP_BRKPROPS ) );
aBrkPropMenu.CheckItem( RID_ACTIV, pBrk->bEnabled );
switch ( aBrkPropMenu.Execute( this, aPos ) )
{
case RID_ACTIV:
{
pBrk->bEnabled = pBrk->bEnabled ? sal_False : sal_True;
pModulWindow->UpdateBreakPoint( *pBrk );
Invalidate();
}
break;
case RID_BRKPROPS:
{
BreakPointDialog aBrkDlg( this, GetBreakPoints() );
aBrkDlg.SetCurrentBreakPoint( pBrk );
aBrkDlg.Execute();
Invalidate();
}
break;
}
}
else
{
PopupMenu aBrkListMenu( IDEResId( RID_POPUP_BRKDLG ) );
switch ( aBrkListMenu.Execute( this, aPos ) )
{
case RID_BRKDLG:
{
BreakPointDialog aBrkDlg( this, GetBreakPoints() );
aBrkDlg.Execute();
Invalidate();
}
break;
}
}
}
}
sal_Bool BreakPointWindow::SyncYOffset()
{
TextView* pView = pModulWindow->GetEditView();
if ( pView )
{
long nViewYOffset = pView->GetStartDocPos().Y();
if ( nCurYOffset != nViewYOffset )
{
nCurYOffset = nViewYOffset;
Invalidate();
return sal_True;
}
}
return sal_False;
}
// virtual
void BreakPointWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
Window::DataChanged(rDCEvt);
if (rDCEvt.GetType() == DATACHANGED_SETTINGS
&& (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
{
Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
if (aColor
!= rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
{
setBackgroundColor(aColor);
Invalidate();
}
}
}
void BreakPointWindow::setBackgroundColor(Color aColor)
{
SetBackground(Wallpaper(aColor));
}
const sal_uInt16 ITEM_ID_VARIABLE = 1;
const sal_uInt16 ITEM_ID_VALUE = 2;
const sal_uInt16 ITEM_ID_TYPE = 3;
WatchWindow::WatchWindow( Window* pParent ) :
BasicDockingWindow( pParent ),
aWatchStr( IDEResId( RID_STR_REMOVEWATCH ) ),
aXEdit( this, IDEResId( RID_EDT_WATCHEDIT ) ),
aRemoveWatchButton( this, IDEResId( RID_IMGBTN_REMOVEWATCH ) ),
aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HASBUTTONS | WB_HASLINES | WB_HSCROLL | WB_TABSTOP
| WB_HASLINESATROOT | WB_HASBUTTONSATROOT ),
aHeaderBar( this, WB_BUTTONSTYLE | WB_BORDER )
{
aXEdit.SetAccessibleName(String(IDEResId( RID_STR_WATCHNAME)));
aTreeListBox.SetAccessibleName(String(IDEResId(RID_STR_WATCHNAME)));
long nTextLen = GetTextWidth( aWatchStr ) + DWBORDER + 3;
aXEdit.SetPosPixel( Point( nTextLen, 3 ) );
aXEdit.SetAccHdl( LINK( this, WatchWindow, EditAccHdl ) );
aXEdit.GetAccelerator().InsertItem( 1, KeyCode( KEY_RETURN ) );
aXEdit.GetAccelerator().InsertItem( 2, KeyCode( KEY_ESCAPE ) );
aXEdit.Show();
aRemoveWatchButton.Disable();
aRemoveWatchButton.SetClickHdl( LINK( this, WatchWindow, ButtonHdl ) );
aRemoveWatchButton.SetPosPixel( Point( nTextLen + aXEdit.GetSizePixel().Width() + 4, 2 ) );
Size aSz( aRemoveWatchButton.GetModeImage().GetSizePixel() );
aSz.Width() += 6;
aSz.Height() += 6;
aRemoveWatchButton.SetSizePixel( aSz );
aRemoveWatchButton.Show();
long nRWBtnSize = aRemoveWatchButton.GetModeImage().GetSizePixel().Height() + 10;
nVirtToolBoxHeight = aXEdit.GetSizePixel().Height() + 7;
if ( nRWBtnSize > nVirtToolBoxHeight )
nVirtToolBoxHeight = nRWBtnSize;
nHeaderBarHeight = 16;
aTreeListBox.SetHelpId(HID_BASICIDE_WATCHWINDOW_LIST);
aTreeListBox.EnableInplaceEditing( sal_True );
aTreeListBox.SetSelectHdl( LINK( this, WatchWindow, TreeListHdl ) );
aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight + nHeaderBarHeight ) );
aTreeListBox.SetHighlightRange( 1, 5 );
Point aPnt( DWBORDER, nVirtToolBoxHeight + 1 );
aHeaderBar.SetPosPixel( aPnt );
aHeaderBar.SetEndDragHdl( LINK( this, WatchWindow, implEndDragHdl ) );
long nVarTabWidth = 220;
long nValueTabWidth = 100;
long nTypeTabWidth = 1250;
aHeaderBar.InsertItem( ITEM_ID_VARIABLE, String( IDEResId( RID_STR_WATCHVARIABLE ) ), nVarTabWidth );
aHeaderBar.InsertItem( ITEM_ID_VALUE, String( IDEResId( RID_STR_WATCHVALUE ) ), nValueTabWidth );
aHeaderBar.InsertItem( ITEM_ID_TYPE, String( IDEResId( RID_STR_WATCHTYPE ) ), nTypeTabWidth );
long tabs[ 4 ];
tabs[ 0 ] = 3; // two tabs
tabs[ 1 ] = 0;
tabs[ 2 ] = nVarTabWidth;
tabs[ 3 ] = nVarTabWidth + nValueTabWidth;
aTreeListBox.SvHeaderTabListBox::SetTabs( tabs, MAP_PIXEL );
aTreeListBox.InitHeaderBar( &aHeaderBar );
aTreeListBox.SetNodeDefaultImages( );
aHeaderBar.Show();
aTreeListBox.Show();
SetText( String( IDEResId( RID_STR_WATCHNAME ) ) );
SetHelpId( HID_BASICIDE_WATCHWINDOW );
// make watch window keyboard accessible
GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
}
WatchWindow::~WatchWindow()
{
GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
}
void WatchWindow::Paint( const Rectangle& )
{
DrawText( Point( DWBORDER, 7 ), aWatchStr );
lcl_DrawIDEWindowFrame( this );
}
void WatchWindow::Resize()
{
Size aSz = GetOutputSizePixel();
Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
if ( aBoxSz.Width() < 4 )
aBoxSz.Width() = 0;
if ( aBoxSz.Height() < 4 )
aBoxSz.Height() = 0;
aBoxSz.Height() -= nHeaderBarHeight;
aTreeListBox.SetSizePixel( aBoxSz );
aTreeListBox.GetHScroll()->SetPageSize( aTreeListBox.GetHScroll()->GetVisibleSize() );
aBoxSz.Height() = nHeaderBarHeight;
aHeaderBar.SetSizePixel( aBoxSz );
Invalidate();
}
struct MemberList
{
String* mpMemberNames;
int mnMemberCount;
MemberList( void )
: mpMemberNames( NULL )
, mnMemberCount( 0 )
{}
~MemberList()
{
clear();
}
void clear( void );
void allocList( int nCount );
};
void MemberList::clear( void )
{
if( mnMemberCount )
{
delete[] mpMemberNames;
mnMemberCount = 0;
}
}
void MemberList::allocList( int nCount )
{
clear();
if( nCount > 0 )
{
mnMemberCount = nCount;
mpMemberNames = new String[ mnMemberCount ];
}
}
struct WatchItem
{
String maName;
String maDisplayName;
SbxObjectRef mpObject;
MemberList maMemberList;
SbxDimArrayRef mpArray;
int nDimLevel; // 0 = Root
int nDimCount;
short* pIndices;
WatchItem* mpArrayParentItem;
WatchItem( void )
: nDimLevel( 0 )
, nDimCount( 0 )
, pIndices( NULL )
, mpArrayParentItem( NULL )
{}
~WatchItem()
{ clearWatchItem(); }
void clearWatchItem( bool bIncludeArrayData=true )
{
mpObject = NULL;
maMemberList.clear();
if( bIncludeArrayData )
{
mpArray = NULL;
nDimLevel = 0;
nDimCount = 0;
delete[] pIndices;
pIndices = NULL;
}
}
WatchItem* GetRootItem( void );
SbxDimArray* GetRootArray( void );
};
WatchItem* WatchItem::GetRootItem( void )
{
WatchItem* pItem = mpArrayParentItem;
while( pItem )
{
if( pItem->mpArray.Is() )
break;
pItem = pItem->mpArrayParentItem;
}
return pItem;
}
SbxDimArray* WatchItem::GetRootArray( void )
{
WatchItem* pRootItem = GetRootItem();
SbxDimArray* pRet = NULL;
if( pRootItem )
pRet = pRootItem->mpArray;
return pRet;
}
void WatchWindow::AddWatch( const String& rVName )
{
WatchItem* pWatchItem = new WatchItem;
String aVar, aIndex;
lcl_SeparateNameAndIndex( rVName, aVar, aIndex );
pWatchItem->maName = aVar;
String aWatchStr_( aVar );
aWatchStr_ += String( RTL_CONSTASCII_USTRINGPARAM( "\t\t" ) );
SvLBoxEntry* pNewEntry = aTreeListBox.InsertEntry( aWatchStr_, 0, sal_True, LIST_APPEND );
pNewEntry->SetUserData( pWatchItem );
aTreeListBox.Select( pNewEntry, sal_True );
aTreeListBox.MakeVisible( pNewEntry );
aRemoveWatchButton.Enable();
}
sal_Bool WatchWindow::RemoveSelectedWatch()
{
SvLBoxEntry* pEntry = aTreeListBox.GetCurEntry();
if ( pEntry )
{
aTreeListBox.GetModel()->Remove( pEntry );
pEntry = aTreeListBox.GetCurEntry();
if ( pEntry )
aXEdit.SetText( ((WatchItem*)pEntry->GetUserData())->maName );
else
aXEdit.SetText( String() );
if ( !aTreeListBox.GetEntryCount() )
aRemoveWatchButton.Disable();
return sal_True;
}
else
return sal_False;
}
IMPL_LINK_INLINE_START( WatchWindow, ButtonHdl, ImageButton *, pButton )
{
if ( pButton == &aRemoveWatchButton )
{
BasicIDEShell* pIDEShell = BasicIDEGlobals::GetShell();
SfxViewFrame* pViewFrame = pIDEShell ? pIDEShell->GetViewFrame() : NULL;
SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : NULL;
if( pDispatcher )
{
pDispatcher->Execute( SID_BASICIDE_REMOVEWATCH );
}
}
return 0;
}
IMPL_LINK_INLINE_END( WatchWindow, ButtonHdl, ImageButton *, pButton )
IMPL_LINK_NOARG_INLINE_START(WatchWindow, TreeListHdl)
{
SvLBoxEntry* pCurEntry = aTreeListBox.GetCurEntry();
if ( pCurEntry && pCurEntry->GetUserData() )
aXEdit.SetText( ((WatchItem*)pCurEntry->GetUserData())->maName );
return 0;
}
IMPL_LINK_NOARG_INLINE_END(WatchWindow, TreeListHdl)
IMPL_LINK_INLINE_START( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
{
(void)pBar;
const sal_Int32 TAB_WIDTH_MIN = 10;
sal_Int32 nMaxWidth =
aHeaderBar.GetSizePixel().getWidth() - 2 * TAB_WIDTH_MIN;
sal_Int32 nVariableWith = aHeaderBar.GetItemSize( ITEM_ID_VARIABLE );
if( nVariableWith < TAB_WIDTH_MIN )
aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, TAB_WIDTH_MIN );
else if( nVariableWith > nMaxWidth )
aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, nMaxWidth );
sal_Int32 nValueWith = aHeaderBar.GetItemSize( ITEM_ID_VALUE );
if( nValueWith < TAB_WIDTH_MIN )
aHeaderBar.SetItemSize( ITEM_ID_VALUE, TAB_WIDTH_MIN );
else if( nValueWith > nMaxWidth )
aHeaderBar.SetItemSize( ITEM_ID_VALUE, nMaxWidth );
if (aHeaderBar.GetItemSize( ITEM_ID_TYPE ) < TAB_WIDTH_MIN)
aHeaderBar.SetItemSize( ITEM_ID_TYPE, TAB_WIDTH_MIN );
sal_Int32 nPos = 0;
sal_uInt16 nTabs = aHeaderBar.GetItemCount();
for( sal_uInt16 i = 1 ; i < nTabs ; ++i )
{
nPos += aHeaderBar.GetItemSize( i );
aTreeListBox.SetTab( i, nPos, MAP_PIXEL );
}
return 0;
}
IMPL_LINK_INLINE_END( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
IMPL_LINK( WatchWindow, EditAccHdl, Accelerator *, pAcc )
{
switch ( pAcc->GetCurKeyCode().GetCode() )
{
case KEY_RETURN:
{
String aCurText( aXEdit.GetText() );
if ( aCurText.Len() )
{
AddWatch( aCurText );
aXEdit.SetSelection( Selection( 0, 0xFFFF ) );
UpdateWatches();
}
else
Sound::Beep();
}
break;
case KEY_ESCAPE:
{
aXEdit.SetText( String() );
}
break;
}
return 0;
}
void WatchWindow::UpdateWatches( bool bBasicStopped )
{
aTreeListBox.UpdateWatches( bBasicStopped );
}
StackWindow::StackWindow( Window* pParent ) :
BasicDockingWindow( pParent ),
aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HSCROLL | WB_TABSTOP ),
aStackStr( IDEResId( RID_STR_STACK ) )
{
aTreeListBox.SetHelpId(HID_BASICIDE_STACKWINDOW_LIST);
aTreeListBox.SetAccessibleName(String( IDEResId(RID_STR_STACKNAME)));
aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight ) );
aTreeListBox.SetHighlightRange();
aTreeListBox.SetSelectionMode( NO_SELECTION );
aTreeListBox.InsertEntry( String(), 0, sal_False, LIST_APPEND );
aTreeListBox.Show();
SetText( String( IDEResId( RID_STR_STACKNAME ) ) );
SetHelpId( HID_BASICIDE_STACKWINDOW );
// make stack window keyboard accessible
GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
}
StackWindow::~StackWindow()
{
GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
}
void StackWindow::Paint( const Rectangle& )
{
DrawText( Point( DWBORDER, 7 ), aStackStr );
lcl_DrawIDEWindowFrame( this );
}
void StackWindow::Resize()
{
Size aSz = GetOutputSizePixel();
Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
if ( aBoxSz.Width() < 4 )
aBoxSz.Width() = 0;
if ( aBoxSz.Height() < 4 )
aBoxSz.Height() = 0;
aTreeListBox.SetSizePixel( aBoxSz );
Invalidate();
}
void StackWindow::UpdateCalls()
{
aTreeListBox.SetUpdateMode( sal_False );
aTreeListBox.Clear();
if ( StarBASIC::IsRunning() )
{
SbxError eOld = SbxBase::GetError();
aTreeListBox.SetSelectionMode( SINGLE_SELECTION );
sal_uInt16 nScope = 0;
SbMethod* pMethod = StarBASIC::GetActiveMethod( nScope );
while ( pMethod )
{
String aEntry( String::CreateFromInt32(nScope ));
if ( aEntry.Len() < 2 )
aEntry.Insert( ' ', 0 );
aEntry += String( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
aEntry += pMethod->GetName();
SbxArray* pParams = pMethod->GetParameters();
SbxInfo* pInfo = pMethod->GetInfo();
if ( pParams )
{
aEntry += '(';
// 0 is the sub's name...
for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ )
{
SbxVariable* pVar = pParams->Get( nParam );
DBG_ASSERT( pVar, "Parameter?!" );
if ( pVar->GetName().Len() )
aEntry += pVar->GetName();
else if ( pInfo )
{
const SbxParamInfo* pParam = pInfo->GetParam( nParam );
if ( pParam )
aEntry += pParam->aName;
}
aEntry += '=';
SbxDataType eType = pVar->GetType();
if( eType & SbxARRAY )
aEntry += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
else if( eType != SbxOBJECT )
aEntry += pVar->GetString();
if ( nParam < ( pParams->Count() - 1 ) )
aEntry += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) );
}
aEntry += ')';
}
aTreeListBox.InsertEntry( aEntry, 0, sal_False, LIST_APPEND );
nScope++;
pMethod = StarBASIC::GetActiveMethod( nScope );
}
SbxBase::ResetError();
if( eOld != SbxERR_OK )
SbxBase::SetError( eOld );
}
else
{
aTreeListBox.SetSelectionMode( NO_SELECTION );
aTreeListBox.InsertEntry( String(), 0, sal_False, LIST_APPEND );
}
aTreeListBox.SetUpdateMode( sal_True );
}
ComplexEditorWindow::ComplexEditorWindow( ModulWindow* pParent ) :
Window( pParent, WB_3DLOOK | WB_CLIPCHILDREN ),
aBrkWindow( this ),
aLineNumberWindow( this, pParent ),
aEdtWindow( this ),
aEWVScrollBar( this, WB_VSCROLL | WB_DRAG ),
bLineNumberDisplay(false),
bObjectCatalogDisplay(true)
{
aEdtWindow.SetModulWindow( pParent );
aBrkWindow.SetModulWindow( pParent );
aEdtWindow.Show();
aBrkWindow.Show();
aEWVScrollBar.SetLineSize( SCROLL_LINE );
aEWVScrollBar.SetPageSize( SCROLL_PAGE );
aEWVScrollBar.SetScrollHdl( LINK( this, ComplexEditorWindow, ScrollHdl ) );
aEWVScrollBar.Show();
}
void ComplexEditorWindow::Resize()
{
Size aOutSz = GetOutputSizePixel();
Size aSz( aOutSz );
aSz.Width() -= 2*DWBORDER;
aSz.Height() -= 2*DWBORDER;
long nBrkWidth = 20;
long nSBWidth = aEWVScrollBar.GetSizePixel().Width();
Size aBrkSz(nBrkWidth, aSz.Height());
Size aLnSz(aLineNumberWindow.GetWidth(), aSz.Height());
if(bLineNumberDisplay)
{
aBrkWindow.SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
aLineNumberWindow.SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aLnSz);
Size aEWSz(aSz.Width() - nBrkWidth - aLineNumberWindow.GetWidth() - nSBWidth + 2, aSz.Height());
aEdtWindow.SetPosSizePixel( Point( DWBORDER + aBrkSz.Width() + aLnSz.Width() - 1, DWBORDER ), aEWSz );
}
else
{
aBrkWindow.SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
Size aEWSz(aSz.Width() - nBrkWidth - nSBWidth + 2, aSz.Height());
aEdtWindow.SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aEWSz);
}
aEWVScrollBar.SetPosSizePixel( Point( aOutSz.Width() - DWBORDER - nSBWidth, DWBORDER ), Size( nSBWidth, aSz.Height() ) );
}
IMPL_LINK( ComplexEditorWindow, ScrollHdl, ScrollBar *, pCurScrollBar )
{
if ( aEdtWindow.GetEditView() )
{
DBG_ASSERT( pCurScrollBar == &aEWVScrollBar, "Wer scrollt hier ?" );
long nDiff = aEdtWindow.GetEditView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
aEdtWindow.GetEditView()->Scroll( 0, nDiff );
aBrkWindow.DoScroll( 0, nDiff );
aLineNumberWindow.DoScroll(0, nDiff);
aEdtWindow.GetEditView()->ShowCursor( sal_False, sal_True );
pCurScrollBar->SetThumbPos( aEdtWindow.GetEditView()->GetStartDocPos().Y() );
}
return 0;
}
void ComplexEditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
{
Window::DataChanged(rDCEvt);
if (rDCEvt.GetType() == DATACHANGED_SETTINGS
&& (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
{
Color aColor(GetSettings().GetStyleSettings().GetFaceColor());
if (aColor
!= rDCEvt.GetOldSettings()->GetStyleSettings().GetFaceColor())
{
SetBackground(Wallpaper(aColor));
Invalidate();
}
}
}
void ComplexEditorWindow::SetLineNumberDisplay(bool b)
{
bLineNumberDisplay = b;
Resize();
if(b)
aLineNumberWindow.Show();
else
aLineNumberWindow.Hide();
}
void ComplexEditorWindow::SetObjectCatalogDisplay(bool b)
{
bObjectCatalogDisplay = b;
Resize();
}
uno::Reference< awt::XWindowPeer >
EditorWindow::GetComponentInterface(sal_Bool bCreate)
{
uno::Reference< awt::XWindowPeer > xPeer(
Window::GetComponentInterface(false));
if (!xPeer.is() && bCreate)
{
// Make sure edit engine and view are available:
if (!pEditEngine)
CreateEditEngine();
xPeer = new ::svt::TextWindowPeer(*GetEditView());
SetComponentInterface(xPeer);
}
return xPeer;
}
WatchTreeListBox::WatchTreeListBox( Window* pParent, WinBits nWinBits )
: SvHeaderTabListBox( pParent, nWinBits )
{}
WatchTreeListBox::~WatchTreeListBox()
{
// Destroy user data
SvLBoxEntry* pEntry = First();
while ( pEntry )
{
delete (WatchItem*)pEntry->GetUserData();
pEntry = Next( pEntry );
}
}
void WatchTreeListBox::SetTabs()
{
SvHeaderTabListBox::SetTabs();
sal_uInt16 nTabCount_ = aTabs.Count();
for( sal_uInt16 i = 0 ; i < nTabCount_ ; i++ )
{
SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(i);
if( i == 2 )
pTab->nFlags |= SV_LBOXTAB_EDITABLE;
else
pTab->nFlags &= ~SV_LBOXTAB_EDITABLE;
}
}
void WatchTreeListBox::RequestingChildren( SvLBoxEntry * pParent )
{
if( !StarBASIC::IsRunning() )
return;
if( GetChildCount( pParent ) > 0 )
return;
SvLBoxEntry * pEntry = pParent;
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
SbxDimArray* pArray = pItem->mpArray;
SbxDimArray* pRootArray = pItem->GetRootArray();
bool bArrayIsRootArray = false;
if( !pArray && pRootArray )
{
pArray = pRootArray;
bArrayIsRootArray = true;
}
SbxObject* pObj = pItem->mpObject;
if( pObj )
{
createAllObjectProperties( pObj );
SbxArray* pProps = pObj->GetProperties();
sal_uInt16 nPropCount = pProps->Count();
pItem->maMemberList.allocList( nPropCount );
for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
{
SbxVariable* pVar = pProps->Get( i );
String aName( pVar->GetName() );
pItem->maMemberList.mpMemberNames[i] = aName;
SvLBoxEntry* pChildEntry = SvTreeListBox::InsertEntry( aName, pEntry );
WatchItem* pChildItem = new WatchItem();
pChildItem->maName = aName;
pChildEntry->SetUserData( pChildItem );
}
if( nPropCount > 0 )
{
UpdateWatches();
}
}
else if( pArray )
{
sal_uInt16 nElementCount = 0;
// Loop through indices of current level
int nParentLevel = bArrayIsRootArray ? pItem->nDimLevel : 0;
int nThisLevel = nParentLevel + 1;
sal_Int32 nMin, nMax;
pArray->GetDim32( nThisLevel, nMin, nMax );
for( sal_Int32 i = nMin ; i <= nMax ; i++ )
{
WatchItem* pChildItem = new WatchItem();
// Copy data and create name
String aBaseName( pItem->maName );
pChildItem->maName = aBaseName;
String aIndexStr = String( RTL_CONSTASCII_USTRINGPARAM( "(" ) );
pChildItem->mpArrayParentItem = pItem;
pChildItem->nDimLevel = nThisLevel;
pChildItem->nDimCount = pItem->nDimCount;
pChildItem->pIndices = new short[ pChildItem->nDimCount ];
sal_uInt16 j;
for( j = 0 ; j < nParentLevel ; j++ )
{
short n = pChildItem->pIndices[j] = pItem->pIndices[j];
aIndexStr += String::CreateFromInt32( n );
aIndexStr += String( RTL_CONSTASCII_USTRINGPARAM( "," ) );
}
pChildItem->pIndices[ nParentLevel ] = sal::static_int_cast<short>( i );
aIndexStr += String::CreateFromInt32( i );
aIndexStr += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
String aDisplayName;
WatchItem* pArrayRootItem = pChildItem->GetRootItem();
if( pArrayRootItem && pArrayRootItem->mpArrayParentItem )
aDisplayName = pItem->maDisplayName;
else
aDisplayName = aBaseName;
aDisplayName += aIndexStr;
pChildItem->maDisplayName = aDisplayName;
SvLBoxEntry* pChildEntry = SvTreeListBox::InsertEntry( aDisplayName, pEntry );
nElementCount++;
pChildEntry->SetUserData( pChildItem );
}
if( nElementCount > 0 )
{
UpdateWatches();
}
}
}
SbxBase* WatchTreeListBox::ImplGetSBXForEntry( SvLBoxEntry* pEntry, bool& rbArrayElement )
{
SbxBase* pSBX = NULL;
rbArrayElement = false;
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
String aVName( pItem->maName );
SvLBoxEntry* pParentEntry = GetParent( pEntry );
WatchItem* pParentItem = pParentEntry ? (WatchItem*)pParentEntry->GetUserData() : NULL;
if( pParentItem )
{
SbxObject* pObj = pParentItem->mpObject;
SbxDimArray* pArray;
if( pObj )
{
pSBX = pObj->Find( aVName, SbxCLASS_DONTCARE );
SbxVariable* pVar;
if ( pSBX && (pVar = PTR_CAST( SbxVariable, pSBX )) != NULL
&& !pSBX->ISA( SbxMethod ) )
{
// Force getting value
SbxValues aRes;
aRes.eType = SbxVOID;
pVar->Get( aRes );
}
}
// Array?
else if( (pArray = pItem->GetRootArray()) != NULL )
{
rbArrayElement = true;
if( pParentItem->nDimLevel + 1 == pParentItem->nDimCount )
pSBX = pArray->Get( pItem->pIndices );
}
}
else
{
pSBX = StarBASIC::FindSBXInCurrentScope( aVName );
}
return pSBX;
}
sal_Bool WatchTreeListBox::EditingEntry( SvLBoxEntry* pEntry, Selection& )
{
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
sal_Bool bEdit = sal_False;
if ( StarBASIC::IsRunning() && StarBASIC::GetActiveMethod() && !SbxBase::IsError() )
{
// No out of scope entries
bool bArrayElement;
SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
if ( ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) ) || bArrayElement )
{
// Accept no objects and only end nodes of arrays for editing
if( !pItem->mpObject && (pItem->mpArray == NULL || pItem->nDimLevel == pItem->nDimCount) )
{
aEditingRes = SvHeaderTabListBox::GetEntryText( pEntry, ITEM_ID_VALUE-1 );
aEditingRes.EraseLeadingChars();
aEditingRes.EraseTrailingChars();
bEdit = sal_True;
}
}
}
if ( !bEdit )
Sound::Beep();
return bEdit;
}
sal_Bool WatchTreeListBox::EditedEntry( SvLBoxEntry* pEntry, const String& rNewText )
{
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
String aVName( pItem->maName );
String aResult = rNewText;
aResult.EraseLeadingChars();
aResult.EraseTrailingChars();
sal_uInt16 nResultLen = aResult.Len();
sal_Unicode cFirst = aResult.GetChar( 0 );
sal_Unicode cLast = aResult.GetChar( nResultLen - 1 );
if( cFirst == '\"' && cLast == '\"' )
aResult = aResult.Copy( 1, nResultLen - 2 );
sal_Bool bResModified = ( aResult != aEditingRes ) ? sal_True : sal_False;
sal_Bool bError = sal_False;
if ( !aVName.Len() )
{
bError = sal_True;
}
sal_Bool bRet = sal_False;
if ( bError )
{
Sound::Beep();
}
else if ( bResModified )
{
bRet = ImplBasicEntryEdited( pEntry, aResult );
}
return bRet;
}
sal_Bool WatchTreeListBox::ImplBasicEntryEdited( SvLBoxEntry* pEntry, const String& rResult )
{
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
String aVName( pItem->maName );
sal_Bool bError = sal_False;
String aResult( rResult );
String aIndex;
bool bArrayElement;
SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
SbxBase* pToBeChanged = NULL;
if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
{
SbxVariable* pVar = (SbxVariable*)pSBX;
SbxDataType eType = pVar->GetType();
if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
bError = sal_True;
else if ( eType & SbxARRAY )
bError = sal_True;
else
pToBeChanged = pSBX;
}
if ( pToBeChanged )
{
if ( pToBeChanged->ISA( SbxVariable ) )
{
// If the type is variable, the conversion of the SBX does not matter,
// else the string is converted.
((SbxVariable*)pToBeChanged)->PutStringExt( aResult );
}
else
bError = sal_True;
}
if ( SbxBase::IsError() )
{
bError = sal_True;
SbxBase::ResetError();
}
if ( bError )
Sound::Beep();
UpdateWatches();
// The text should never be taken/copied 1:1,
// as the UpdateWatches will be lost
return sal_False;
}
static void implCollapseModifiedObjectEntry( SvLBoxEntry* pParent, WatchTreeListBox* pThis )
{
pThis->Collapse( pParent );
SvLBoxTreeList* pModel = pThis->GetModel();
SvLBoxEntry* pDeleteEntry;
while( (pDeleteEntry = pThis->SvTreeListBox::GetEntry( pParent, 0 )) != NULL )
{
implCollapseModifiedObjectEntry( pDeleteEntry, pThis );
WatchItem* pItem = (WatchItem*)pDeleteEntry->GetUserData();
delete pItem;
pModel->Remove( pDeleteEntry );
}
}
static String implCreateTypeStringForDimArray( WatchItem* pItem, SbxDataType eType )
{
String aRetStr = getBasicTypeName( eType );
SbxDimArray* pArray = pItem->mpArray;
if( !pArray )
pArray = pItem->GetRootArray();
if( pArray )
{
int nDimLevel = pItem->nDimLevel;
int nDims = pItem->nDimCount;
if( nDimLevel < nDims )
{
aRetStr += '(';
for( int i = nDimLevel ; i < nDims ; i++ )
{
short nMin, nMax;
pArray->GetDim( sal::static_int_cast<short>( i+1 ), nMin, nMax );
aRetStr += String::CreateFromInt32( nMin );
aRetStr += String( RTL_CONSTASCII_USTRINGPARAM( " to " ) );
aRetStr += String::CreateFromInt32( nMax );
if( i < nDims - 1 )
aRetStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) );
}
aRetStr += ')';
}
}
return aRetStr;
}
void implEnableChildren( SvLBoxEntry* pEntry, bool bEnable )
{
if( bEnable )
{
pEntry->SetFlags(
(pEntry->GetFlags() &
~(SV_ENTRYFLAG_NO_NODEBMP | SV_ENTRYFLAG_HAD_CHILDREN))
| SV_ENTRYFLAG_CHILDREN_ON_DEMAND );
}
else
{
pEntry->SetFlags(
(pEntry->GetFlags() & ~(SV_ENTRYFLAG_CHILDREN_ON_DEMAND)) );
}
}
void WatchTreeListBox::UpdateWatches( bool bBasicStopped )
{
SbMethod* pCurMethod = StarBASIC::GetActiveMethod();
SbxError eOld = SbxBase::GetError();
setBasicWatchMode( true );
SvLBoxEntry* pEntry = First();
while ( pEntry )
{
WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
String aVName( pItem->maName );
DBG_ASSERT( aVName.Len(), "Var? - Must not be empty!" );
String aWatchStr;
String aTypeStr;
if ( pCurMethod )
{
bool bArrayElement;
SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
// Array? If no end node create type string
if( bArrayElement && pItem->nDimLevel < pItem->nDimCount )
{
SbxDimArray* pRootArray = pItem->GetRootArray();
SbxDataType eType = pRootArray->GetType();
aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
implEnableChildren( pEntry, true );
}
bool bCollapse = false;
if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
{
SbxVariable* pVar = (SbxVariable*)pSBX;
// extra treatment of arrays
SbxDataType eType = pVar->GetType();
if ( eType & SbxARRAY )
{
// consider multidimensinal arrays!
SbxBase* pBase = pVar->GetObject();
if ( pBase && pBase->ISA( SbxDimArray ) )
{
SbxDimArray* pNewArray = (SbxDimArray*)pBase;
SbxDimArray* pOldArray = pItem->mpArray;
bool bArrayChanged = false;
if( pNewArray != NULL && pOldArray != NULL )
{
// Compare Array dimensions to see if array has changed
// Can be a copy, so comparing pointers does not work
sal_uInt16 nOldDims = pOldArray->GetDims();
sal_uInt16 nNewDims = pNewArray->GetDims();
if( nOldDims != nNewDims )
{
bArrayChanged = true;
}
else
{
for( int i = 0 ; i < nOldDims ; i++ )
{
short nOldMin, nOldMax;
short nNewMin, nNewMax;
pOldArray->GetDim( sal::static_int_cast<short>( i+1 ), nOldMin, nOldMax );
pNewArray->GetDim( sal::static_int_cast<short>( i+1 ), nNewMin, nNewMax );
if( nOldMin != nNewMin || nOldMax != nNewMax )
{
bArrayChanged = true;
break;
}
}
}
}
else if( pNewArray == NULL || pOldArray == NULL )
bArrayChanged = true;
if( pNewArray )
implEnableChildren( pEntry, true );
// #i37227 Clear always and replace array
if( pNewArray != pOldArray )
{
pItem->clearWatchItem( false );
if( pNewArray )
{
implEnableChildren( pEntry, true );
pItem->mpArray = pNewArray;
sal_uInt16 nDims = pNewArray->GetDims();
pItem->nDimLevel = 0;
pItem->nDimCount = nDims;
}
}
if( bArrayChanged && pOldArray != NULL )
bCollapse = true;
aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
}
else
aWatchStr += String( RTL_CONSTASCII_USTRINGPARAM( "<?>" ) );
}
else if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
{
SbxObject* pObj = NULL;
SbxBase* pBase = pVar->GetObject();
if( pBase && pBase->ISA( SbxObject ) )
pObj = (SbxObject*)pBase;
if( pObj )
{
// Check if member list has changed
bool bObjChanged = false;
if( pItem->mpObject != NULL && pItem->maMemberList.mpMemberNames != NULL )
{
SbxArray* pProps = pObj->GetProperties();
sal_uInt16 nPropCount = pProps->Count();
for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
{
SbxVariable* pVar_ = pProps->Get( i );
String aName( pVar_->GetName() );
if( pItem->maMemberList.mpMemberNames[i] != aName )
{
bObjChanged = true;
break;
}
}
if( bObjChanged )
bCollapse = true;
}
pItem->mpObject = pObj;
implEnableChildren( pEntry, true );
aTypeStr = getBasicObjectTypeName( pObj );
}
else
{
aWatchStr = String( RTL_CONSTASCII_USTRINGPARAM( "Null" ) );
if( pItem->mpObject != NULL )
{
bCollapse = true;
pItem->clearWatchItem( false );
implEnableChildren( pEntry, false );
}
}
}
else
{
if( pItem->mpObject != NULL )
{
bCollapse = true;
pItem->clearWatchItem( false );
implEnableChildren( pEntry, false );
}
bool bString = ((sal_uInt8)eType == (sal_uInt8)SbxSTRING);
String aStrStr( RTL_CONSTASCII_USTRINGPARAM( "\"" ) );
if( bString )
aWatchStr += aStrStr;
aWatchStr += pVar->GetString();
if( bString )
aWatchStr += aStrStr;
}
if( !aTypeStr.Len() )
{
if( !pVar->IsFixed() )
aTypeStr = String( RTL_CONSTASCII_USTRINGPARAM( "Variant/" ) );
aTypeStr += getBasicTypeName( pVar->GetType() );
}
}
else if( !bArrayElement )
aWatchStr += String( RTL_CONSTASCII_USTRINGPARAM( "<Out of Scope>" ) );
if( bCollapse )
implCollapseModifiedObjectEntry( pEntry, this );
}
else if( bBasicStopped )
{
if( pItem->mpObject || pItem->mpArray )
{
implCollapseModifiedObjectEntry( pEntry, this );
pItem->mpObject = NULL;
}
}
SvHeaderTabListBox::SetEntryText( aWatchStr, pEntry, ITEM_ID_VALUE-1 );
SvHeaderTabListBox::SetEntryText( aTypeStr, pEntry, ITEM_ID_TYPE-1 );
pEntry = Next( pEntry );
}
// Force redraw
Invalidate();
SbxBase::ResetError();
if( eOld != SbxERR_OK )
SbxBase::SetError( eOld );
setBasicWatchMode( false );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */