Files
libreoffice/basctl/source/basicide/baside2.cxx
Rafael Lima 076e21f4e3 tdf#156925 Add Color Scheme selector to the Basic IDE
This patch implements a color scheme selector for the Basic IDE. With this new feature the user can either:
1) Choose to stick with "Application Colors", meaning that the colors defined in "Tools - Options - Application Colors" are applied.
2) Use one of the available color schemes in the dialog

To access the color scheme dialog, go to View - Color Scheme.

A color schema was defined in the "BasicIDE.xcs" file and six color schemes were defined in "BasicIDE.xcu" to be shipped with LibreOffice.

This way, it is possible to install more color schemes via extensions;

Change-Id: I5d382d19f982d02ba3c0fda5d1596aed2c38f13c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155928
Tested-by: Jenkins
Tested-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
Reviewed-by: Rafael Lima <rafael.palma.lima@gmail.com>
2024-01-08 19:13:38 +01:00

1664 lines
49 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "baside2.hxx"
#include <baside3.hxx>
#include <basobj.hxx>
#include <basidesh.hxx>
#include "brkdlg.hxx"
#include <iderdll.hxx>
#include <iderid.hxx>
#include "moduldlg.hxx"
#include <docsignature.hxx>
#include <colorscheme.hxx>
#include <officecfg/Office/BasicIDE.hxx>
#include <helpids.h>
#include <strings.hrc>
#include <basic/basmgr.hxx>
#include <basic/basrdll.hxx>
#include <basic/sbmeth.hxx>
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#include <com/sun/star/script/ModuleType.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
#include <comphelper/SetFlagContextHelper.hxx>
#include <comphelper/string.hxx>
#include <svl/srchdefs.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/filedlghelper.hxx>
#include <sfx2/request.hxx>
#include <sfx2/viewfrm.hxx>
#include <sot/exchange.hxx>
#include <svl/eitem.hxx>
#include <svl/srchitem.hxx>
#include <svl/stritem.hxx>
#include <svl/visitem.hxx>
#include <svl/whiter.hxx>
#include <svx/svxids.hrc>
#include <tools/debug.hxx>
#include <utility>
#include <vcl/locktoplevels.hxx>
#include <vcl/errinf.hxx>
#include <vcl/event.hxx>
#include <vcl/print.hxx>
#include <vcl/svapp.hxx>
#include <vcl/textview.hxx>
#include <vcl/weld.hxx>
#include <vcl/xtextedt.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <cassert>
#include <osl/diagnose.h>
#include <officecfg/Office/Common.hxx>
#include <BasicColorConfig.hxx>
namespace basctl
{
namespace
{
namespace Print
{
tools::Long const nLeftMargin = 1700;
tools::Long const nRightMargin = 900;
tools::Long const nTopMargin = 2000;
tools::Long const nBottomMargin = 1000;
tools::Long const nBorder = 300;
}
short const ValidWindow = 0x1234;
// What (who) are OW and MTF? Compare to baside3.cxx where an
// identically named variable, used in the same way, has the value
// "*.*" on Windows, "*" otherwise. Is that what should be done here,
// too?
#if defined(OW) || defined(MTF)
char const FilterMask_All[] = "*";
#else
constexpr OUString FilterMask_All = u"*.*"_ustr;
#endif
} // end anonymous namespace
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::ui::dialogs;
using namespace utl;
using namespace comphelper;
namespace
{
void lcl_PrintHeader( Printer* pPrinter, sal_uInt16 nPages, sal_uInt16 nCurPage, const OUString& rTitle, bool bOutput )
{
Size const aSz = pPrinter->GetOutputSize();
const Color aOldLineColor( pPrinter->GetLineColor() );
const Color aOldFillColor( pPrinter->GetFillColor() );
const vcl::Font aOldFont( pPrinter->GetFont() );
pPrinter->SetLineColor( COL_BLACK );
pPrinter->SetFillColor();
vcl::Font aFont( aOldFont );
aFont.SetWeight( WEIGHT_BOLD );
aFont.SetAlignment( ALIGN_BOTTOM );
pPrinter->SetFont( aFont );
tools::Long nFontHeight = pPrinter->GetTextHeight();
// 1st Border => line, 2+3 Border = free space
tools::Long nYTop = Print::nTopMargin - 3*Print::nBorder - nFontHeight;
tools::Long nXLeft = Print::nLeftMargin - Print::nBorder;
tools::Long nXRight = aSz.Width() - Print::nRightMargin + Print::nBorder;
if( bOutput )
pPrinter->DrawRect(tools::Rectangle(
Point(nXLeft, nYTop),
Size(nXRight - nXLeft, aSz.Height() - nYTop - Print::nBottomMargin + Print::nBorder)
));
tools::Long nY = Print::nTopMargin - 2*Print::nBorder;
Point aPos(Print::nLeftMargin, nY);
if( bOutput )
pPrinter->DrawText( aPos, rTitle );
if ( nPages != 1 )
{
aFont.SetWeight( WEIGHT_NORMAL );
pPrinter->SetFont( aFont );
aPos.AdjustX(pPrinter->GetTextWidth( rTitle ) );
if( bOutput )
{
OUString aPageStr = " [" + IDEResId(RID_STR_PAGE) + " " + OUString::number( nCurPage ) + "]";
pPrinter->DrawText( aPos, aPageStr );
}
}
nY = Print::nTopMargin - Print::nBorder;
if( bOutput )
pPrinter->DrawLine( Point( nXLeft, nY ), Point( nXRight, nY ) );
pPrinter->SetFont( aOldFont );
pPrinter->SetFillColor( aOldFillColor );
pPrinter->SetLineColor( aOldLineColor );
}
void lcl_ConvertTabsToSpaces( OUString& rLine )
{
if ( rLine.isEmpty() )
return;
OUStringBuffer aResult( rLine );
sal_Int32 nPos = 0;
sal_Int32 nMax = aResult.getLength();
while ( nPos < nMax )
{
if ( aResult[nPos] == '\t' )
{
// not 4 Blanks, but at 4 TabPos:
OUStringBuffer aBlanker;
string::padToLength(aBlanker, ( 4 - ( nPos % 4 ) ), ' ');
aResult.remove( nPos, 1 );
aResult.insert( nPos, aBlanker );
nMax = aResult.getLength();
}
++nPos;
}
rLine = aResult.makeStringAndClear();
}
} // namespace
ModulWindow::ModulWindow (ModulWindowLayout* pParent, ScriptDocument const& rDocument,
const OUString& aLibName, const OUString& aName, OUString aModule)
: BaseWindow(pParent, rDocument, aLibName, aName)
, m_rLayout(*pParent)
, m_nValid(ValidWindow)
, m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
, m_aModule(std::move(aModule))
{
// Active editor color scheme
m_sWinColorScheme = GetShell()->GetColorConfig()->GetCurrentColorSchemeName();
m_aXEditorWindow->Show();
SetBackground();
}
SbModuleRef const & ModulWindow::XModule()
{
// ModuleWindows can now be created as a result of the
// modules getting created via the api. This is a result of an
// elementInserted event from the BasicLibrary container.
// However the SbModule is also created from a different listener to
// the same event ( in basmgr ) Therefore it is possible when we look
// for m_xModule it may not yet be available, here we keep trying to access
// the module until such time as it exists
if ( !m_xModule.is() )
{
BasicManager* pBasMgr = GetDocument().getBasicManager();
if ( pBasMgr )
{
StarBASIC* pBasic = pBasMgr->GetLib( GetLibName() );
if ( pBasic )
{
m_xBasic = pBasic;
m_xModule = pBasic->FindModule( GetName() );
}
}
}
return m_xModule;
}
ModulWindow::~ModulWindow()
{
disposeOnce();
}
void ModulWindow::dispose()
{
m_nValid = 0;
StarBASIC::Stop();
m_aXEditorWindow.disposeAndClear();
BaseWindow::dispose();
}
void ModulWindow::GetFocus()
{
if (m_nValid != ValidWindow)
return;
m_aXEditorWindow->GetEdtWindow().GrabFocus();
// don't call basic calls because focus is somewhere else...
}
void ModulWindow::DoInit()
{
GetEditorWindow().InitScrollBars();
}
void ModulWindow::Paint(vcl::RenderContext& /*rRenderContext*/, const tools::Rectangle&)
{
}
void ModulWindow::Resize()
{
m_aXEditorWindow->SetPosSizePixel( Point( 0, 0 ), GetOutputSizePixel() );
}
void ModulWindow::CheckCompileBasic()
{
if ( !XModule().is() )
return;
// never compile while running!
bool const bRunning = StarBASIC::IsRunning();
bool const bModified = ( !m_xModule->IsCompiled() ||
( GetEditEngine() && GetEditEngine()->IsModified() ) );
if ( bRunning || !bModified )
return;
bool bDone = false;
GetShell()->GetViewFrame().GetWindow().EnterWait();
AssertValidEditEngine();
GetEditorWindow().SetSourceInBasic();
bool bWasModified = GetBasic()->IsModified();
{
// tdf#106529: only use strict compilation mode when compiling from the IDE
css::uno::ContextLayer layer(comphelper::NewFlagContext("BasicStrict"));
bDone = m_xModule->Compile();
}
if ( !bWasModified )
GetBasic()->SetModified(false);
if ( bDone )
{
GetBreakPoints().SetBreakPointsInBasic( m_xModule.get() );
}
GetShell()->GetViewFrame().GetWindow().LeaveWait();
m_aStatus.bError = !bDone;
m_aStatus.bIsRunning = false;
}
void ModulWindow::BasicExecute()
{
// #116444# check security settings before macro execution
ScriptDocument aDocument( GetDocument() );
bool bMacrosDisabled = officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
if (bMacrosDisabled || (aDocument.isDocument() && !aDocument.allowMacros()))
{
std::unique_ptr<weld::MessageDialog> xBox(
Application::CreateMessageDialog(GetFrameWeld(), VclMessageType::Warning,
VclButtonsType::Ok, IDEResId(RID_STR_CANNOTRUNMACRO)));
xBox->run();
return;
}
CheckCompileBasic();
if ( !XModule().is() || !m_xModule->IsCompiled() || m_aStatus.bError )
return;
if ( GetBreakPoints().size() )
m_aStatus.nBasicFlags = m_aStatus.nBasicFlags | BasicDebugFlags::Break;
if ( !m_aStatus.bIsRunning )
{
DBG_ASSERT( m_xModule.is(), "No Module!" );
AddStatus( BASWIN_RUNNINGBASIC );
sal_uInt16 nStart, nEnd;
TextSelection aSel = GetEditView()->GetSelection();
// Init cursor to top
const sal_uInt32 nCurMethodStart = aSel.GetStart().GetPara() + 1;
SbMethod* pMethod = nullptr;
// first Macro, else blind "Main" (ExtSearch?)
for (sal_uInt32 nMacro = 0; nMacro < m_xModule->GetMethods()->Count(); nMacro++)
{
SbMethod* pM = static_cast<SbMethod*>(m_xModule->GetMethods()->Get(nMacro));
assert(pM && "Method?");
pM->GetLineRange( nStart, nEnd );
if ( nCurMethodStart >= nStart && nCurMethodStart <= nEnd )
{
// matched a method to the cursor position
pMethod = pM;
break;
}
}
if ( !pMethod )
{
// If not in a method then prompt the user
ChooseMacro(GetFrameWeld(), uno::Reference<frame::XModel>());
return;
}
pMethod->SetDebugFlags(m_aStatus.nBasicFlags);
BasicDLL::SetDebugMode(true);
RunMethod(pMethod);
BasicDLL::SetDebugMode(false);
// if cancelled during Interactive=false
BasicDLL::EnableBreak(true);
ClearStatus( BASWIN_RUNNINGBASIC );
}
else
m_aStatus.bIsRunning = false; // cancel of Reschedule()
}
void ModulWindow::CompileBasic()
{
CheckCompileBasic();
XModule().is() && m_xModule->IsCompiled();
}
void ModulWindow::BasicRun()
{
m_aStatus.nBasicFlags = BasicDebugFlags::NONE;
BasicExecute();
}
void ModulWindow::BasicStepOver()
{
m_aStatus.nBasicFlags = BasicDebugFlags::StepInto | BasicDebugFlags::StepOver;
BasicExecute();
}
void ModulWindow::BasicStepInto()
{
m_aStatus.nBasicFlags = BasicDebugFlags::StepInto;
BasicExecute();
}
void ModulWindow::BasicStepOut()
{
m_aStatus.nBasicFlags = BasicDebugFlags::StepOut;
BasicExecute();
}
void ModulWindow::BasicStop()
{
StarBASIC::Stop();
m_aStatus.bIsRunning = false;
}
void ModulWindow::LoadBasic()
{
sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
FileDialogFlags::NONE, this->GetFrameWeld());
aDlg.SetContext(sfx2::FileDialogHelper::BasicImportSource);
Reference<XFilePicker3> xFP = aDlg.GetFilePicker();
xFP->appendFilter( "BASIC" , "*.bas" );
xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
xFP->setCurrentFilter( "BASIC" );
if( aDlg.Execute() != ERRCODE_NONE )
return;
Sequence< OUString > aPaths = xFP->getSelectedFiles();
SfxMedium aMedium( aPaths[0], StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE );
SvStream* pStream = aMedium.GetInStream();
if ( pStream )
{
AssertValidEditEngine();
sal_uInt32 nLines = CalcLineCount( *pStream );
// nLines*4: ReadText/Formatting/Highlighting/Formatting
GetEditorWindow().CreateProgress( IDEResId(RID_STR_GENERATESOURCE), nLines*4 );
GetEditEngine()->SetUpdateMode( false );
// tdf#139196 - import macros using either default or utf-8 text encoding
pStream->StartReadingUnicodeText(RTL_TEXTENCODING_UTF8);
if (pStream->Tell() == 3)
pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
GetEditView()->Read( *pStream );
GetEditEngine()->SetUpdateMode( true );
GetEditorWindow().PaintImmediately();
GetEditorWindow().ForceSyntaxTimeout();
GetEditorWindow().DestroyProgress();
ErrCodeMsg nError = aMedium.GetErrorIgnoreWarning();
if ( nError )
ErrorHandler::HandleError( nError );
}
else
{
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTREAD)));
xBox->run();
}
}
void ModulWindow::SaveBasicSource()
{
sfx2::FileDialogHelper aDlg(ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
FileDialogFlags::NONE, this->GetFrameWeld());
aDlg.SetContext(sfx2::FileDialogHelper::BasicExportSource);
const Reference<XFilePicker3>& xFP = aDlg.GetFilePicker();
xFP.queryThrow<XFilePickerControlAccess>()->setValue(ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, 0, Any(true));
xFP->appendFilter( "BASIC", "*.bas" );
xFP->appendFilter( IDEResId(RID_STR_FILTER_ALLFILES), FilterMask_All );
xFP->setCurrentFilter( "BASIC" );
if( aDlg.Execute() != ERRCODE_NONE )
return;
Sequence< OUString > aPaths = xFP->getSelectedFiles();
SfxMedium aMedium( aPaths[0], StreamMode::WRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC );
SvStream* pStream = aMedium.GetOutStream();
if ( pStream )
{
EnterWait();
AssertValidEditEngine();
// tdf#139196 - export macros using utf-8 including BOM
pStream->SetStreamCharSet(RTL_TEXTENCODING_UTF8);
pStream->WriteUChar(0xEF).WriteUChar(0xBB).WriteUChar(0xBF);
GetEditEngine()->Write( *pStream );
aMedium.Commit();
LeaveWait();
ErrCodeMsg nError = aMedium.GetErrorIgnoreWarning();
if ( nError )
ErrorHandler::HandleError( nError );
}
else
{
std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(GetFrameWeld(),
VclMessageType::Warning, VclButtonsType::Ok, IDEResId(RID_STR_COULDNTWRITE)));
xErrorBox->run();
}
}
void ModulWindow::ImportDialog()
{
const ScriptDocument& rDocument = GetDocument();
OUString aLibName = GetLibName();
implImportDialog(GetFrameWeld(), rDocument, aLibName);
}
void ModulWindow::ToggleBreakPoint( sal_uInt16 nLine )
{
DBG_ASSERT( XModule().is(), "No Module!" );
if ( !XModule().is() )
return;
CheckCompileBasic();
if ( m_aStatus.bError )
{
return;
}
BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nLine );
if ( pBrk ) // remove
{
m_xModule->ClearBP( nLine );
GetBreakPoints().remove( pBrk );
}
else // create one
{
if ( m_xModule->SetBP( nLine ))
{
GetBreakPoints().InsertSorted( BreakPoint( nLine ) );
if ( StarBASIC::IsRunning() )
{
for (sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count(); nMethod++)
{
SbMethod* pMethod
= static_cast<SbMethod*>(m_xModule->GetMethods()->Get(nMethod));
assert(pMethod && "Method not found! (NULL)");
pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
}
}
}
}
}
void ModulWindow::UpdateBreakPoint( const BreakPoint& rBrk )
{
DBG_ASSERT( XModule().is(), "No Module!" );
if ( XModule().is() )
{
CheckCompileBasic();
if ( rBrk.bEnabled )
m_xModule->SetBP( rBrk.nLine );
else
m_xModule->ClearBP( rBrk.nLine );
}
}
void ModulWindow::BasicToggleBreakPoint()
{
AssertValidEditEngine();
TextSelection aSel = GetEditView()->GetSelection();
aSel.GetStart().GetPara()++; // Basic lines start at 1!
aSel.GetEnd().GetPara()++;
for ( sal_uInt32 nLine = aSel.GetStart().GetPara(); nLine <= aSel.GetEnd().GetPara(); ++nLine )
{
ToggleBreakPoint( nLine );
}
m_aXEditorWindow->GetBrkWindow().Invalidate();
}
void ModulWindow::BasicToggleBreakPointEnabled()
{
AssertValidEditEngine();
TextView* pView = GetEditView();
if ( !pView )
return;
TextSelection aSel = pView->GetSelection();
BreakPointList& rList = GetBreakPoints();
for ( sal_uInt32 nLine = ++aSel.GetStart().GetPara(), nEnd = ++aSel.GetEnd().GetPara(); nLine <= nEnd; ++nLine )
{
BreakPoint* pBrk = rList.FindBreakPoint( nLine );
if ( pBrk )
{
pBrk->bEnabled = !pBrk->bEnabled;
UpdateBreakPoint( *pBrk );
}
}
GetBreakPointWindow().Invalidate();
}
void ModulWindow::ManageBreakPoints()
{
BreakPointWindow& rBrkWin = GetBreakPointWindow();
BreakPointDialog aBrkDlg(rBrkWin.GetFrameWeld(), GetBreakPoints());
aBrkDlg.run();
rBrkWin.Invalidate();
}
void ModulWindow::BasicErrorHdl( StarBASIC const * pBasic )
{
GetShell()->GetViewFrame().ToTop();
// Return value: BOOL
// FALSE: cancel
// TRUE: go on...
sal_uInt16 nErrorLine = StarBASIC::GetLine() - 1;
sal_uInt16 nErrCol1 = StarBASIC::GetCol1();
sal_uInt16 nErrCol2 = StarBASIC::GetCol2();
if ( nErrCol2 != 0xFFFF )
nErrCol2++;
AssertValidEditEngine();
GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, nErrCol1 ), TextPaM( nErrorLine, nErrCol2 ) ) );
// if other basic, the IDE should try to display the correct module
bool const bMarkError = pBasic == GetBasic();
if ( bMarkError )
m_aXEditorWindow->GetBrkWindow().SetMarkerPos(nErrorLine, true);
// #i47002#
Reference< awt::XWindow > xWindow = VCLUnoHelper::GetInterface( this );
// tdf#118572 make a currently running dialog, regardless of what its modal
// to, insensitive to user input until after this error dialog goes away.
TopLevelWindowLocker aBusy;
aBusy.incBusy(nullptr);
ErrorHandler::HandleError(StarBASIC::GetErrorCode(), GetFrameWeld());
aBusy.decBusy();
// #i47002#
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
if ( !pWindow )
return;
if ( bMarkError )
m_aXEditorWindow->GetBrkWindow().SetNoMarker();
return;
}
BasicDebugFlags ModulWindow::BasicBreakHdl()
{
// Return value: sal_uInt16 => see SB-Debug-Flags
sal_uInt16 nErrorLine = StarBASIC::GetLine();
BreakPoint* pBrk = GetBreakPoints().FindBreakPoint( nErrorLine );
if ( pBrk )
{
pBrk->nHitCount++;
if ( pBrk->nHitCount <= pBrk->nStopAfter && GetBasic()->IsBreak() )
return m_aStatus.nBasicFlags; // go on...
}
nErrorLine--; // EditEngine starts at 0, Basic at 1
AssertValidEditEngine();
GetEditView()->SetSelection( TextSelection( TextPaM( nErrorLine, 0 ), TextPaM( nErrorLine, 0 ) ) );
m_aXEditorWindow->GetBrkWindow().SetMarkerPos( nErrorLine );
m_rLayout.UpdateDebug(false);
m_aStatus.bIsInReschedule = true;
m_aStatus.bIsRunning = true;
AddStatus( BASWIN_INRESCHEDULE );
InvalidateDebuggerSlots();
while( m_aStatus.bIsRunning && !Application::IsQuit())
Application::Yield();
m_aStatus.bIsInReschedule = false;
m_aXEditorWindow->GetBrkWindow().SetNoMarker();
ClearStatus( BASWIN_INRESCHEDULE );
return m_aStatus.nBasicFlags;
}
void ModulWindow::BasicAddWatch()
{
AssertValidEditEngine();
bool bAdd = true;
if ( !GetEditView()->HasSelection() )
{
// tdf#57307 - expand selection to include connector punctuations
TextSelection aSel;
OUString aWord = GetEditEngine()->GetWord( GetEditView()->GetSelection().GetEnd(), &aSel.GetStart(), &aSel.GetEnd() );
if ( !aWord.isEmpty() )
GetEditView()->SetSelection( aSel );
else
bAdd = false;
}
if ( bAdd )
{
TextSelection aSel = GetEditView()->GetSelection();
if ( aSel.GetStart().GetPara() == aSel.GetEnd().GetPara() ) // single line selection
m_rLayout.BasicAddWatch(GetEditView()->GetSelected());
}
}
void ModulWindow::EditMacro( const OUString& rMacroName )
{
DBG_ASSERT( XModule().is(), "No Module!" );
if ( !XModule().is() )
return;
CheckCompileBasic();
if ( m_aStatus.bError )
return;
sal_uInt16 nStart, nEnd;
SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->Find( rMacroName, SbxClassType::Method ));
if ( !pMethod )
return;
pMethod->GetLineRange( nStart, nEnd );
if ( nStart )
{
nStart--;
nEnd--;
}
TextSelection aSel( TextPaM( nStart, 0 ), TextPaM( nStart, 0 ) );
AssertValidEditEngine();
TextView * pView = GetEditView();
// scroll if applicable so that first line is at the top
tools::Long nVisHeight = GetOutputSizePixel().Height();
if ( pView->GetTextEngine()->GetTextHeight() > nVisHeight )
{
tools::Long nMaxY = pView->GetTextEngine()->GetTextHeight() - nVisHeight;
tools::Long nOldStartY = pView->GetStartDocPos().Y();
tools::Long nNewStartY = static_cast<tools::Long>(nStart) * pView->GetTextEngine()->GetCharHeight();
nNewStartY = std::min( nNewStartY, nMaxY );
pView->Scroll( 0, -(nNewStartY-nOldStartY) );
pView->ShowCursor( false );
GetEditVScrollBar().SetThumbPos( pView->GetStartDocPos().Y() );
}
pView->SetSelection( aSel );
pView->ShowCursor();
pView->GetWindow()->GrabFocus();
}
void ModulWindow::StoreData()
{
// StoreData is called when the BasicManager is destroyed or
// this window is closed.
// => interrupts undesired!
GetEditorWindow().SetSourceInBasic();
}
bool ModulWindow::AllowUndo()
{
return GetEditorWindow().CanModify();
}
void ModulWindow::UpdateData()
{
DBG_ASSERT( XModule().is(), "No Module!" );
// UpdateData is called when the source has changed from outside
// => interrupts undesired!
if ( !XModule().is() )
return;
SetModule( m_xModule->GetSource32() );
if ( GetEditView() )
{
TextSelection aSel = GetEditView()->GetSelection();
setTextEngineText(*GetEditEngine(), m_xModule->GetSource32());
GetEditView()->SetSelection( aSel );
GetEditEngine()->SetModified( false );
MarkDocumentModified( GetDocument() );
}
}
sal_Int32 ModulWindow::countPages( Printer* pPrinter )
{
return FormatAndPrint( pPrinter, -1 );
}
void ModulWindow::printPage( sal_Int32 nPage, Printer* pPrinter )
{
FormatAndPrint( pPrinter, nPage );
}
/* implementation note: this is totally inefficient for the XRenderable interface
usage since the whole "document" will be format for every page. Should this ever
become a problem we should
- format only once for every new printer
- keep an index list for each page which is the starting paragraph
*/
sal_Int32 ModulWindow::FormatAndPrint( Printer* pPrinter, sal_Int32 nPrintPage )
{
AssertValidEditEngine();
MapMode eOldMapMode( pPrinter->GetMapMode() );
vcl::Font aOldFont( pPrinter->GetFont() );
vcl::Font aFont( GetEditEngine()->GetFont() );
aFont.SetAlignment( ALIGN_BOTTOM );
aFont.SetTransparent( true );
aFont.SetFontSize( Size( 0, 360 ) );
pPrinter->SetFont( aFont );
pPrinter->SetMapMode(MapMode(MapUnit::Map100thMM));
OUString aTitle( CreateQualifiedName() );
sal_Int32 nLineHeight = pPrinter->GetTextHeight();
if(nLineHeight == 0)
{
nLineHeight = 1;
}
Size aPaperSz = pPrinter->GetOutputSize();
aPaperSz.AdjustWidth( -(Print::nLeftMargin + Print::nRightMargin) );
aPaperSz.AdjustHeight( -(Print::nTopMargin + Print::nBottomMargin) );
// nLinepPage is not correct if there's a line break
sal_Int32 nLinespPage = aPaperSz.Height()/nLineHeight;
tools::Long nXTextWidth = pPrinter->approximate_digit_width();
sal_Int32 nCharspLine = aPaperSz.Width() / std::max<tools::Long>(nXTextWidth, 1);
const sal_uInt32 nParas = GetEditEngine()->GetParagraphCount();
sal_Int32 nPages = nParas/nLinespPage+1;
sal_Int32 nCurPage = 1;
lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nPrintPage == 0 );
Point aPos( Print::nLeftMargin, Print::nTopMargin );
for ( sal_uInt32 nPara = 0; nPara < nParas; ++nPara )
{
OUString aLine( GetEditEngine()->GetText( nPara ) );
lcl_ConvertTabsToSpaces( aLine );
sal_Int32 nLines = aLine.getLength()/nCharspLine+1;
for (sal_Int32 nLine = 0; nLine < nLines; ++nLine)
{
sal_Int32 nBeginIndex = nLine*nCharspLine;
sal_Int32 nCopyCount = std::min<sal_Int32>(nCharspLine, aLine.getLength()-nBeginIndex);
OUString aTmpLine = aLine.copy(nBeginIndex, nCopyCount);
aPos.AdjustY(nLineHeight );
if ( aPos.Y() > ( aPaperSz.Height() + Print::nTopMargin ) )
{
nCurPage++;
lcl_PrintHeader( pPrinter, nPages, nCurPage, aTitle, nCurPage-1 == nPrintPage );
aPos = Point(Print::nLeftMargin, Print::nTopMargin + nLineHeight);
}
if( nCurPage-1 == nPrintPage )
pPrinter->DrawText( aPos, aTmpLine );
}
aPos.AdjustY(10 ); // nParaSpace
}
pPrinter->SetFont( aOldFont );
pPrinter->SetMapMode( eOldMapMode );
return nCurPage;
}
void ModulWindow::ExecuteCommand (SfxRequest& rReq)
{
AssertValidEditEngine();
switch (rReq.GetSlot())
{
case SID_DELETE:
{
if (!IsReadOnly())
{
KeyEvent aFakeDelete(0, KEY_DELETE);
(void)GetEditView()->KeyInput(aFakeDelete);
}
break;
}
case SID_SELECTALL:
{
TextSelection aSel( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) );
TextView * pView = GetEditView();
pView->SetSelection( aSel );
pView->GetWindow()->GrabFocus();
break;
}
case SID_BASICRUN:
{
BasicRun();
}
break;
case SID_BASICCOMPILE:
{
CompileBasic();
}
break;
case SID_BASICSTEPOVER:
{
BasicStepOver();
}
break;
case SID_BASICSTEPINTO:
{
BasicStepInto();
}
break;
case SID_BASICSTEPOUT:
{
BasicStepOut();
}
break;
case SID_BASICLOAD:
{
LoadBasic();
}
break;
case SID_BASICSAVEAS:
{
SaveBasicSource();
}
break;
case SID_IMPORT_DIALOG:
{
ImportDialog();
}
break;
case SID_BASICIDE_MATCHGROUP:
{
GetEditView()->MatchGroup();
}
break;
case SID_BASICIDE_TOGGLEBRKPNT:
{
BasicToggleBreakPoint();
}
break;
case SID_BASICIDE_MANAGEBRKPNTS:
{
ManageBreakPoints();
}
break;
case SID_BASICIDE_TOGGLEBRKPNTENABLED:
{
BasicToggleBreakPointEnabled();
}
break;
case SID_BASICIDE_ADDWATCH:
{
BasicAddWatch();
}
break;
case SID_BASICIDE_REMOVEWATCH:
{
m_rLayout.BasicRemoveWatch();
}
break;
case SID_CUT:
{
if ( !IsReadOnly() )
{
GetEditView()->Cut();
if (SfxBindings* pBindings = GetBindingsPtr())
pBindings->Invalidate( SID_DOC_MODIFIED );
}
}
break;
case SID_COPY:
{
GetEditView()->Copy();
}
break;
case SID_PASTE:
{
if ( !IsReadOnly() )
{
GetEditView()->Paste();
if (SfxBindings* pBindings = GetBindingsPtr())
pBindings->Invalidate( SID_DOC_MODIFIED );
}
}
break;
case SID_BASICIDE_BRKPNTSCHANGED:
{
GetBreakPointWindow().Invalidate();
}
break;
case SID_SHOWLINES:
{
const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(rReq.GetSlot());
bool bLineNumbers = pItem && pItem->GetValue();
m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
officecfg::Office::BasicIDE::EditorSettings::LineNumbering::set(bLineNumbers, batch);
batch->commit();
}
break;
case SID_BASICIDE_DELETECURRENT:
{
if (QueryDelModule(m_aName, GetFrameWeld()))
{
// tdf#134551 don't delete the window if last module is removed until this block
// is complete
VclPtr<ModulWindow> xKeepRef(this);
if (m_aDocument.removeModule(m_aLibName, m_aName))
MarkDocumentModified(m_aDocument);
}
}
break;
case FID_SEARCH_OFF:
GrabFocus();
break;
case SID_GOTOLINE:
{
GotoLineDialog aGotoDlg(GetFrameWeld());
if (aGotoDlg.run() == RET_OK)
{
if (sal_Int32 const nLine = aGotoDlg.GetLineNumber())
{
TextSelection const aSel(TextPaM(nLine - 1, 0), TextPaM(nLine - 1, 0));
GetEditView()->SetSelection(aSel);
}
}
break;
}
}
}
void ModulWindow::ExecuteGlobal (SfxRequest& rReq)
{
switch (rReq.GetSlot())
{
case SID_SIGNATURE:
{
DocumentSignature aSignature(m_aDocument);
if (aSignature.supportsSignatures())
{
aSignature.signScriptingContent(rReq.GetFrameWeld());
if (SfxBindings* pBindings = GetBindingsPtr())
pBindings->Invalidate(SID_SIGNATURE);
}
}
break;
}
}
void ModulWindow::GetState( SfxItemSet &rSet )
{
SfxWhichIter aIter(rSet);
for ( sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich() )
{
switch ( nWh )
{
case SID_CUT:
{
if ( !GetEditView() || !GetEditView()->HasSelection() )
rSet.DisableItem( nWh );
if ( IsReadOnly() )
rSet.DisableItem( nWh );
}
break;
case SID_COPY:
{
if ( !GetEditView() || !GetEditView()->HasSelection() )
rSet.DisableItem( nWh );
}
break;
case SID_PASTE:
{
if ( !IsPasteAllowed() )
rSet.DisableItem( nWh );
if ( IsReadOnly() )
rSet.DisableItem( nWh );
}
break;
case SID_BASICIDE_STAT_POS:
{
TextView* pView = GetEditView();
if ( pView )
{
TextSelection aSel = pView->GetSelection();
OUString aPos = IDEResId( RID_STR_LINE ) +
" " +
OUString::number(aSel.GetEnd().GetPara()+1) +
", " +
IDEResId( RID_STR_COLUMN ) +
" " +
OUString::number(aSel.GetEnd().GetIndex()+1);
SfxStringItem aItem( SID_BASICIDE_STAT_POS, aPos );
rSet.Put( aItem );
}
}
break;
case SID_BASICIDE_STAT_TITLE:
{
// search for current procedure name (Sub or Function)
TextView* pView = GetEditView();
if ( pView )
{
OUString sProcName;
TextSelection aSel = pView->GetSelection();
sal_uInt32 i = aSel.GetStart().GetPara();
do
{
OUString aCurrLine = GetEditEngine()->GetText( i );
OUString sProcType;
if (GetEditorWindow().GetProcedureName(aCurrLine, sProcType, sProcName))
break;
} while (i--);
OUString aTitle = CreateQualifiedName();
if (!sProcName.isEmpty())
aTitle += "." + sProcName;
if (IsReadOnly())
aTitle += " (" + IDEResId(RID_STR_READONLY) + ")";
SfxStringItem aTitleItem( SID_BASICIDE_STAT_TITLE, aTitle );
rSet.Put( aTitleItem );
}
}
break;
case SID_ATTR_INSERT:
{
TextView* pView = GetEditView();
if ( pView )
{
SfxBoolItem aItem( SID_ATTR_INSERT, pView->IsInsertMode() );
rSet.Put( aItem );
}
}
break;
case SID_SHOWLINES:
{
bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
rSet.Put(SfxBoolItem(nWh, bLineNumbers));
break;
}
case SID_SELECTALL:
{
if ( !GetEditView() )
rSet.DisableItem( nWh );
}
break;
}
}
}
void ModulWindow::DoScroll( Scrollable* pCurScrollBar )
{
if ( ( pCurScrollBar == GetHScrollBar() ) && GetEditView() )
{
// don't scroll with the value but rather use the Thumb-Pos for the VisArea:
tools::Long nDiff = GetEditView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
GetEditView()->Scroll( nDiff, 0 );
GetEditView()->ShowCursor( false );
pCurScrollBar->SetThumbPos( GetEditView()->GetStartDocPos().X() );
}
}
bool ModulWindow::IsModified()
{
return GetEditEngine() && GetEditEngine()->IsModified();
}
OUString ModulWindow::GetSbModuleName()
{
OUString aModuleName;
if ( XModule().is() )
aModuleName = m_xModule->GetName();
return aModuleName;
}
OUString ModulWindow::GetTitle()
{
return GetSbModuleName();
}
void ModulWindow::ShowCursor( bool bOn )
{
if ( GetEditEngine() )
{
TextView* pView = GetEditEngine()->GetActiveView();
if ( pView )
{
if ( bOn )
pView->ShowCursor();
else
pView->HideCursor();
}
}
}
void ModulWindow::AssertValidEditEngine()
{
if ( !GetEditEngine() )
GetEditorWindow().CreateEditEngine();
}
void ModulWindow::Activating ()
{
bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
Show();
}
void ModulWindow::Deactivating()
{
Hide();
}
sal_uInt16 ModulWindow::StartSearchAndReplace( const SvxSearchItem& rSearchItem, bool bFromStart )
{
if (IsSuspended())
return 0;
// one could also relinquish syntaxhighlighting/formatting instead of the stupid replace-everything...
AssertValidEditEngine();
TextView* pView = GetEditView();
TextSelection aSel;
if ( bFromStart )
{
aSel = pView->GetSelection();
if ( !rSearchItem.GetBackward() )
pView->SetSelection( TextSelection() );
else
pView->SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
}
bool const bForward = !rSearchItem.GetBackward();
sal_uInt16 nFound = 0;
if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) ||
( rSearchItem.GetCommand() == SvxSearchCmd::FIND_ALL ) )
{
nFound = pView->Search( rSearchItem.GetSearchOptions() , bForward ) ? 1 : 0;
}
else if ( ( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE ) ||
( rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL ) )
{
if ( !IsReadOnly() )
{
bool const bAll = rSearchItem.GetCommand() == SvxSearchCmd::REPLACE_ALL;
nFound = pView->Replace( rSearchItem.GetSearchOptions() , bAll , bForward );
}
}
if ( bFromStart && !nFound )
pView->SetSelection( aSel );
return nFound;
}
SfxUndoManager* ModulWindow::GetUndoManager()
{
if ( GetEditEngine() )
return &GetEditEngine()->GetUndoManager();
return nullptr;
}
SearchOptionFlags ModulWindow::GetSearchOptions()
{
SearchOptionFlags nOptions = SearchOptionFlags::SEARCH |
SearchOptionFlags::WHOLE_WORDS |
SearchOptionFlags::BACKWARDS |
SearchOptionFlags::REG_EXP |
SearchOptionFlags::EXACT |
SearchOptionFlags::SELECTION |
SearchOptionFlags::SIMILARITY;
if ( !IsReadOnly() )
{
nOptions |= SearchOptionFlags::REPLACE;
nOptions |= SearchOptionFlags::REPLACE_ALL;
}
return nOptions;
}
void ModulWindow::BasicStarted()
{
if ( !XModule().is() )
return;
m_aStatus.bIsRunning = true;
BreakPointList& rList = GetBreakPoints();
if ( rList.size() )
{
rList.ResetHitCount();
rList.SetBreakPointsInBasic( m_xModule.get() );
for (sal_uInt32 nMethod = 0; nMethod < m_xModule->GetMethods()->Count(); nMethod++)
{
SbMethod* pMethod = static_cast<SbMethod*>(m_xModule->GetMethods()->Get(nMethod));
assert(pMethod && "Method not found! (NULL)");
pMethod->SetDebugFlags( pMethod->GetDebugFlags() | BasicDebugFlags::Break );
}
}
}
void ModulWindow::BasicStopped()
{
m_aStatus.bIsRunning = false;
GetBreakPointWindow().SetNoMarker();
}
EntryDescriptor ModulWindow::CreateEntryDescriptor()
{
ScriptDocument aDocument( GetDocument() );
OUString aLibName( GetLibName() );
LibraryLocation eLocation = aDocument.getLibraryLocation( aLibName );
OUString aModName( GetName() );
OUString aLibSubName;
if( m_xBasic.is() && aDocument.isInVBAMode() && XModule().is() )
{
switch( m_xModule->GetModuleType() )
{
case script::ModuleType::DOCUMENT:
{
aLibSubName = IDEResId( RID_STR_DOCUMENT_OBJECTS );
uno::Reference< container::XNameContainer > xLib = aDocument.getOrCreateLibrary( E_SCRIPTS, aLibName );
if( xLib.is() )
{
OUString sObjName;
ModuleInfoHelper::getObjectName( xLib, aModName, sObjName );
if( !sObjName.isEmpty() )
{
aModName += " (" + sObjName + ")";
}
}
break;
}
case script::ModuleType::FORM:
aLibSubName = IDEResId( RID_STR_USERFORMS );
break;
case script::ModuleType::NORMAL:
aLibSubName = IDEResId( RID_STR_NORMAL_MODULES );
break;
case script::ModuleType::CLASS:
aLibSubName = IDEResId( RID_STR_CLASS_MODULES );
break;
}
}
return EntryDescriptor( aDocument, eLocation, aLibName, aLibSubName, aModName, OBJ_TYPE_MODULE );
}
void ModulWindow::SetReadOnly (bool b)
{
if ( GetEditView() )
GetEditView()->SetReadOnly( b );
}
bool ModulWindow::IsReadOnly()
{
return GetEditView() && GetEditView()->IsReadOnly();
}
bool ModulWindow::IsPasteAllowed()
{
bool bPaste = false;
// get clipboard
Reference< datatransfer::clipboard::XClipboard > xClipboard = GetClipboard();
if ( xClipboard.is() )
{
Reference< datatransfer::XTransferable > xTransf = xClipboard->getContents();
if ( xTransf.is() )
{
datatransfer::DataFlavor aFlavor;
SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
if ( xTransf->isDataFlavorSupported( aFlavor ) )
bPaste = true;
}
}
return bPaste;
}
void ModulWindow::OnNewDocument ()
{
bool bLineNumbers = ::officecfg::Office::BasicIDE::EditorSettings::LineNumbering::get();
m_aXEditorWindow->SetLineNumberDisplay(bLineNumbers);
}
OUString ModulWindow::GetHid () const
{
return HID_BASICIDE_MODULWINDOW;
}
ItemType ModulWindow::GetType () const
{
return TYPE_MODULE;
}
bool ModulWindow::HasActiveEditor () const
{
return !IsSuspended();
}
void ModulWindow::UpdateModule ()
{
OUString const aModule = getTextEngineText(*GetEditEngine());
// update module in basic
assert(m_xModule.is());
// update module in module window
SetModule(aModule);
// update module in library
OSL_VERIFY(m_aDocument.updateModule(m_aLibName, m_aName, aModule));
GetEditEngine()->SetModified(false);
MarkDocumentModified(m_aDocument);
}
void ModulWindow::SetEditorColorScheme(OUString aColorScheme)
{
m_sWinColorScheme = aColorScheme;
EditorWindow& rEditWindow = GetEditorWindow();
Wallpaper aBackgroundColor(GetLayout().GetSyntaxBackgroundColor());
rEditWindow.SetBackground(aBackgroundColor);
rEditWindow.GetWindow(GetWindowType::Border)->SetBackground(aBackgroundColor);
// The EditEngine is created only when the module is actually opened for the first time,
// therefore we need to check if it actually exists before updating its syntax highlighting
ExtTextEngine* pEditEngine = GetEditEngine();
if (pEditEngine)
rEditWindow.UpdateSyntaxHighlighting();
}
ModulWindowLayout::ModulWindowLayout (vcl::Window* pParent, ObjectCatalog& rObjectCatalog_) :
Layout(pParent),
pChild(nullptr),
aWatchWindow(VclPtr<WatchWindow>::Create(this)),
aStackWindow(VclPtr<StackWindow>::Create(this)),
rObjectCatalog(rObjectCatalog_)
{
// Get active color scheme from the registry
m_sColorSchemeId = GetShell()->GetColorConfig()->GetCurrentColorSchemeName();
aSyntaxColors.ApplyColorScheme(m_sColorSchemeId, true);
}
ModulWindowLayout::~ModulWindowLayout()
{
disposeOnce();
}
void ModulWindowLayout::dispose()
{
aWatchWindow.disposeAndClear();
aStackWindow.disposeAndClear();
pChild.clear();
Layout::dispose();
}
void ModulWindowLayout::UpdateDebug (bool bBasicStopped)
{
aWatchWindow->UpdateWatches(bBasicStopped);
aStackWindow->UpdateCalls();
}
void ModulWindowLayout::Paint (vcl::RenderContext& rRenderContext, tools::Rectangle const&)
{
rRenderContext.DrawText(Point(), IDEResId(RID_STR_NOMODULE));
}
void ModulWindowLayout::Activating (BaseWindow& rChild)
{
assert(dynamic_cast<ModulWindow*>(&rChild));
pChild = &static_cast<ModulWindow&>(rChild);
aWatchWindow->Show();
aStackWindow->Show();
rObjectCatalog.Show();
rObjectCatalog.SetLayoutWindow(this);
rObjectCatalog.UpdateEntries();
Layout::Activating(rChild);
aSyntaxColors.SetActiveEditor(&pChild->GetEditorWindow());
aSyntaxColors.SetActiveColorSchemeId(m_sColorSchemeId);
}
void ModulWindowLayout::Deactivating ()
{
aSyntaxColors.SetActiveEditor(nullptr);
Layout::Deactivating();
aWatchWindow->Hide();
aStackWindow->Hide();
rObjectCatalog.Hide();
pChild = nullptr;
}
void ModulWindowLayout::GetState (SfxItemSet &rSet, unsigned nWhich)
{
switch (nWhich)
{
case SID_SHOW_PROPERTYBROWSER:
rSet.Put(SfxVisibilityItem(nWhich, false));
break;
case SID_BASICIDE_CHOOSEMACRO:
rSet.Put(SfxVisibilityItem(nWhich, true));
break;
}
}
void ModulWindowLayout::BasicAddWatch (OUString const& rWatchStr)
{
aWatchWindow->AddWatch(rWatchStr);
}
void ModulWindowLayout::BasicRemoveWatch ()
{
aWatchWindow->RemoveSelectedWatch();
}
void ModulWindowLayout::ShowWatchWindow(bool bVisible)
{
aWatchWindow->Show(bVisible);
ArrangeWindows();
}
void ModulWindowLayout::ShowStackWindow(bool bVisible)
{
aStackWindow->Show(bVisible);
ArrangeWindows();
}
void ModulWindowLayout::OnFirstSize (tools::Long const nWidth, tools::Long const nHeight)
{
AddToLeft(&rObjectCatalog, Size(nWidth * 0.20, nHeight * 0.75));
AddToBottom(aWatchWindow.get(), Size(nWidth * 0.67, nHeight * 0.25));
AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25));
}
// Applies the color scheme to the current window and updates color definitions;
// note that other ModulWindow instances are not affected by calling this method
void ModulWindowLayout::ApplyColorSchemeToCurrentWindow(OUString aSchemeId)
{
// Apply new color scheme to the UI
m_sColorSchemeId = aSchemeId;
aSyntaxColors.ApplyColorScheme(m_sColorSchemeId, false);
}
ModulWindowLayout::SyntaxColors::SyntaxColors ()
: pEditor(nullptr)
{
aConfig.AddListener(this);
}
ModulWindowLayout::SyntaxColors::~SyntaxColors ()
{
aConfig.RemoveListener(this);
}
// virtual
void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints)
{
// The color scheme only needs to be applied when configuration changed if the "default" color
// scheme (based on Application Colors) is being used
if (m_sActiveSchemeId == DEFAULT_SCHEME)
ApplyColorScheme(DEFAULT_SCHEME, false);
}
// Applies an entire new color scheme; when bFirst is true, then the checks to see if the color scheme
// has changed are ignored to make sure the color scheme is applied
void ModulWindowLayout::SyntaxColors::ApplyColorScheme(OUString aSchemeId, bool bFirst)
{
const TokenType vTokenTypes[] =
{
TokenType::Unknown,
TokenType::Identifier,
TokenType::Whitespace,
TokenType::Number,
TokenType::String,
TokenType::EOL,
TokenType::Comment,
TokenType::Error,
TokenType::Operator,
TokenType::Keywords
};
m_sActiveSchemeId = aSchemeId;
ColorScheme aColorScheme = GetShell()->GetColorConfig()->GetColorScheme(aSchemeId);
Color aFontColor = aColorScheme.m_aGenericFontColor;
m_aFontColor = aFontColor;
Color aDocColor = aColorScheme.m_aBackgroundColor;
m_aBackgroundColor = aDocColor;
if (!bFirst && pEditor)
{
pEditor->ChangeFontColor(aFontColor);
pEditor->SetBackground(Wallpaper(aDocColor));
pEditor->Invalidate();
}
for (const auto& aToken: vTokenTypes)
{
// Retrieves the new color to be set from the color scheme
Color aNewColor;
switch (aToken)
{
case TokenType::EOL:
case TokenType::Whitespace:
case TokenType::Unknown:
aNewColor = aColorScheme.m_aGenericFontColor;
break;
case TokenType::Identifier:
aNewColor = aColorScheme.m_aIdentifierColor;
break;
case TokenType::Number:
aNewColor = aColorScheme.m_aNumberColor;
break;
case TokenType::String:
aNewColor = aColorScheme.m_aStringColor;
break;
case TokenType::Comment:
aNewColor = aColorScheme.m_aCommentColor;
break;
case TokenType::Error:
aNewColor = aColorScheme.m_aErrorColor;
break;
case TokenType::Operator:
aNewColor = aColorScheme.m_aOperatorColor;
break;
case TokenType::Keywords:
aNewColor = aColorScheme.m_aKeywordColor;
break;
default:
SAL_WARN("basctl.basicide", "Unexpected token type for color scheme");
aNewColor = aColorScheme.m_aGenericFontColor;
}
Color& rCurrentColor = aColors[aToken];
rCurrentColor = aNewColor;
}
// This check is needed because the EditEngine will only exist in the EditorWindow when the
// module is actually opened
if (!bFirst && pEditor)
pEditor->UpdateSyntaxHighlighting();
}
} // namespace basctl
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */