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>
diff --git a/basctl/Library_basctl.mk b/basctl/Library_basctl.mk
index bbd9a00..13d3bce 100644
--- a/basctl/Library_basctl.mk
+++ b/basctl/Library_basctl.mk
@@ -99,6 +99,8 @@ $(eval $(call gb_Library_add_exception_objects,basctl,\
	basctl/source/basicide/macrodlg \
	basctl/source/basicide/moduldl2 \
	basctl/source/basicide/moduldlg \
	basctl/source/basicide/BasicColorConfig \
	basctl/source/basicide/ColorSchemeDialog \
	basctl/source/basicide/ObjectCatalog \
	basctl/source/basicide/sbxitem \
	basctl/source/basicide/scriptdocument \
diff --git a/basctl/UIConfig_basicide.mk b/basctl/UIConfig_basicide.mk
index 2c23fbf..217ea6c 100644
--- a/basctl/UIConfig_basicide.mk
+++ b/basctl/UIConfig_basicide.mk
@@ -37,6 +37,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/BasicIDE,\
	basctl/uiconfig/basicide/ui/basicmacrodialog \
	basctl/uiconfig/basicide/ui/breakpointmenus \
	basctl/uiconfig/basicide/ui/codecomplete \
	basctl/uiconfig/basicide/ui/colorscheme \
	basctl/uiconfig/basicide/ui/combobox \
	basctl/uiconfig/basicide/ui/defaultlanguage \
	basctl/uiconfig/basicide/ui/deletelangdialog \
diff --git a/basctl/inc/strings.hrc b/basctl/inc/strings.hrc
index 324b6ba..44efc2f 100644
--- a/basctl/inc/strings.hrc
+++ b/basctl/inc/strings.hrc
@@ -114,6 +114,15 @@
#define RID_STR_MODULE_READONLY             NC_("RID_STR_READONLY_WARNING", "This module is read-only and cannot be edited.")
#define RID_STR_DIALOG_READONLY             NC_("RID_STR_READONLY_WARNING", "This dialog is read-only and cannot be edited.")

// Color scheme names
#define RID_STR_COLORSCHEME_DEFAULT         NC_("RID_STR_COLORSCHEME_DEFAULT", "Default")
#define RID_STR_COLORSCHEME_LIGHT           NC_("RID_STR_COLORSCHEME_LIGHT", "%PRODUCTNAME Light")
#define RID_STR_COLORSCHEME_DARK            NC_("RID_STR_COLORSCHEME_DARK", "%PRODUCTNAME Dark")
#define RID_STR_COLORSCHEME_BREEZE_LIGHT    NC_("RID_STR_COLORSCHEME_BREEZE_LIGHT", "Breeze Light")
#define RID_STR_COLORSCHEME_BREEZE_DARK     NC_("RID_STR_COLORSCHEME_BREEZE_DARK", "Breeze Dark")
#define RID_STR_COLORSCHEME_SOLARIZED_DARK  NC_("RID_STR_COLORSCHEME_SOLARIZED_DARK", "Solarized Dark")
#define RID_STR_COLORSCHEME_SOLARIZED_LIGHT NC_("RID_STR_COLORSCHEME_SOLARIZED_LIGHT", "Solarized Light")

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/sdi/baside.sdi b/basctl/sdi/baside.sdi
index 9e7229c..40ddd8b 100644
--- a/basctl/sdi/baside.sdi
+++ b/basctl/sdi/baside.sdi
@@ -343,6 +343,12 @@ shell basctl_Shell
        StateMethod = GetState;
    ]

    SID_BASICIDE_COLOR_SCHEME_DLG
    [
        ExecMethod  = ExecuteGlobal;
        StateMethod = GetState;
    ]

    SID_ATTR_ZOOMSLIDER
    [
        ExecMethod      = ExecuteGlobal;
diff --git a/basctl/source/basicide/BasicColorConfig.cxx b/basctl/source/basicide/BasicColorConfig.cxx
new file mode 100644
index 0000000..1a650fd
--- /dev/null
+++ b/basctl/source/basicide/BasicColorConfig.cxx
@@ -0,0 +1,114 @@
/* -*- 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 <tools/solar.h>
#include <BasicColorConfig.hxx>
#include <officecfg/Office/BasicIDE.hxx>

#include <sal/log.hxx>

namespace basctl
{
BasicColorConfig::BasicColorConfig()
    : ConfigItem("Office.BasicIDE/IDEColorSchemes")
{
    // Innitially the active color scheme is the one defined in the registry
    m_sCurrentColorScheme = officecfg::Office::BasicIDE::EditorSettings::ColorScheme::get();

    // Initialize all available scheme names
    m_aSchemeNames = GetNodeNames("");
}

BasicColorConfig::~BasicColorConfig() {}

void BasicColorConfig::Notify(const css::uno::Sequence<OUString>&) {}

void BasicColorConfig::ImplCommit() {}

ColorScheme BasicColorConfig::GetColorScheme(const OUString& rScheme)
{
    // If the default scheme is being requested or the scheme does not exist, return the Application Colors scheme
    if (rScheme == DEFAULT_SCHEME || comphelper::findValue(m_aSchemeNames, rScheme) == -1)
    {
        return GetAutomaticColorScheme();
    }

    std::vector<OUString> aVecPropNames = {
        OUString(rScheme + "/GenericColor/Color"),   OUString(rScheme + "/IdentifierColor/Color"),
        OUString(rScheme + "/NumberColor/Color"),    OUString(rScheme + "/StringColor/Color"),
        OUString(rScheme + "/CommentColor/Color"),   OUString(rScheme + "/ErrorColor/Color"),
        OUString(rScheme + "/OperatorColor/Color"),  OUString(rScheme + "/KeywordColor/Color"),
        OUString(rScheme + "/BackgroundColor/Color")
    };

    css::uno::Sequence<OUString> aPropNames(aVecPropNames.size());
    OUString* pPropNames = aPropNames.getArray();
    for (sal_uLong i = 0; i < aVecPropNames.size(); i++)
    {
        pPropNames[i] = aVecPropNames[i];
    }
    css::uno::Sequence<css::uno::Any> aColors = GetProperties(aPropNames);

    ColorScheme aColorScheme;
    aColorScheme.m_sSchemeName = rScheme;
    aColorScheme.m_bIsDefault = comphelper::findValue(m_aDefaultSchemes, rScheme) != -1;
    aColors[0] >>= aColorScheme.m_aGenericFontColor;
    aColors[1] >>= aColorScheme.m_aIdentifierColor;
    aColors[2] >>= aColorScheme.m_aNumberColor;
    aColors[3] >>= aColorScheme.m_aStringColor;
    aColors[4] >>= aColorScheme.m_aCommentColor;
    aColors[5] >>= aColorScheme.m_aErrorColor;
    aColors[6] >>= aColorScheme.m_aOperatorColor;
    aColors[7] >>= aColorScheme.m_aKeywordColor;
    aColors[8] >>= aColorScheme.m_aBackgroundColor;

    return aColorScheme;
}

ColorScheme BasicColorConfig::GetAutomaticColorScheme()
{
    ColorScheme aScheme = { DEFAULT_SCHEME,
                            false,
                            aColorConfig.GetColorValue(svtools::FONTCOLOR).nColor,
                            aColorConfig.GetColorValue(svtools::BASICIDENTIFIER).nColor,
                            aColorConfig.GetColorValue(svtools::BASICNUMBER).nColor,
                            aColorConfig.GetColorValue(svtools::BASICSTRING).nColor,
                            aColorConfig.GetColorValue(svtools::BASICCOMMENT).nColor,
                            aColorConfig.GetColorValue(svtools::BASICERROR).nColor,
                            aColorConfig.GetColorValue(svtools::BASICOPERATOR).nColor,
                            aColorConfig.GetColorValue(svtools::BASICKEYWORD).nColor,
                            aColorConfig.GetColorValue(svtools::BASICEDITOR).nColor };
    return aScheme;
}

OUString& BasicColorConfig::GetCurrentColorSchemeName()
{
    // Always return from the registry to get the most up-to-date value
    m_sCurrentColorScheme = officecfg::Office::BasicIDE::EditorSettings::ColorScheme::get();
    return m_sCurrentColorScheme;
}

TranslateId BasicColorConfig::GetSchemeTranslateId(const OUString& rScheme)
{
    return m_aTranslateIdsMap.find(rScheme)->second;
}

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/source/basicide/ColorSchemeDialog.cxx b/basctl/source/basicide/ColorSchemeDialog.cxx
new file mode 100644
index 0000000..7ae4cf3
--- /dev/null
+++ b/basctl/source/basicide/ColorSchemeDialog.cxx
@@ -0,0 +1,148 @@
/* -*- 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 <basidesh.hxx>
#include <iderdll.hxx>
#include <ColorSchemeDialog.hxx>
#include <strings.hrc>
#include <vcl/weld.hxx>
#include <vcl/settings.hxx>
#include <tools/debug.hxx>
#include "baside2.hxx"
#include <officecfg/Office/BasicIDE.hxx>
#include <BasicColorConfig.hxx>
#include <memory>

namespace basctl
{
ColorSchemeDialog::ColorSchemeDialog(weld::Window* pParent,
                                     VclPtr<ModulWindowLayout> pModulWinLayout)
    : GenericDialogController(pParent, "modules/BasicIDE/ui/colorscheme.ui", "ColorSchemeDialog")
    , m_pModulWinLayout(pModulWinLayout)
    , m_xSchemeList(m_xBuilder->weld_tree_view("schemelist"))
    , m_xUseAppCollors(m_xBuilder->weld_radio_button("opt_appcolors"))
    , m_xUseScheme(m_xBuilder->weld_radio_button("opt_usescheme"))
    , m_xOk(m_xBuilder->weld_button("btn_ok"))
{
    m_pColorConfig = GetShell()->GetColorConfig();
    m_sSelectedSchemeId = m_pColorConfig->GetCurrentColorSchemeName();

    m_xSchemeList->set_size_request(m_xSchemeList->get_approximate_digit_width() * 30,
                                    m_xSchemeList->get_height_rows(10));
    m_xSchemeList->set_selection_mode(SelectionMode::Single);

    Init();
}

ColorSchemeDialog::~ColorSchemeDialog() {}

void ColorSchemeDialog::Init()
{
    m_xOk->connect_clicked(LINK(this, ColorSchemeDialog, BtnOkHdl));
    m_xUseAppCollors->connect_toggled(LINK(this, ColorSchemeDialog, OptionHdl));
    m_xUseScheme->connect_toggled(LINK(this, ColorSchemeDialog, OptionHdl));
    m_xSchemeList->connect_changed(LINK(this, ColorSchemeDialog, SelectHdl));

    // Populate the list with available color schemes
    for (auto const& rName : m_pColorConfig->GetColorSchemeNames())
    {
        // Default schemes (preinstalled with LO) have TranslateIds
        if (m_pColorConfig->IsDefaultScheme(rName))
        {
            m_xSchemeList->append(rName, IDEResId(m_pColorConfig->GetSchemeTranslateId(rName)));
        }
        else
        {
            m_xSchemeList->append(rName, rName);
        }
    }
    m_xSchemeList->make_sorted();

    // Set initial selection in the dialog
    m_xUseAppCollors->set_active(true);
    if (m_sSelectedSchemeId == DEFAULT_SCHEME)
    {
        // The "Application Colors" theme is being used
        m_xSchemeList->set_sensitive(false);
    }
    else
    {
        // Check if the scheme exists
        if (comphelper::findValue(m_pColorConfig->GetColorSchemeNames(), m_sSelectedSchemeId) != -1)
        {
            m_xUseScheme->set_active(true);
            m_xSchemeList->select_id(m_sSelectedSchemeId);
        }
        else
        {
            m_xSchemeList->set_sensitive(false);
        }
    }
}

IMPL_LINK_NOARG(ColorSchemeDialog, BtnOkHdl, weld::Button&, void)
{
    // Collect selected theme
    if (m_xUseAppCollors->get_active())
        m_sSelectedSchemeId = DEFAULT_SCHEME;
    else
        m_sSelectedSchemeId = m_xSchemeList->get_selected_id();

    m_xDialog->response(RET_OK);
}

IMPL_LINK_NOARG(ColorSchemeDialog, OptionHdl, weld::Toggleable&, void)
{
    if (m_xUseAppCollors->get_active())
    {
        m_xSchemeList->set_sensitive(false);
        m_pModulWinLayout->ApplyColorSchemeToCurrentWindow(DEFAULT_SCHEME);
        m_sSelectedSchemeId = DEFAULT_SCHEME;
    }

    if (m_xUseScheme->get_active())
    {
        m_xSchemeList->set_sensitive(true);
        // Always select a item to avoid having nothing selected
        if (m_sSelectedSchemeId == DEFAULT_SCHEME)
        {
            // If the default color scheme was selected, then choose first entry in the list
            m_xSchemeList->select_id(m_xSchemeList->get_id(0));
            m_pModulWinLayout->ApplyColorSchemeToCurrentWindow(m_xSchemeList->get_id(0));
        }
        else
        {
            // If a color scheme was active, select it in the list
            m_xSchemeList->select_id(m_sSelectedSchemeId);
            m_pModulWinLayout->ApplyColorSchemeToCurrentWindow(m_sSelectedSchemeId);
        }
    }
}

IMPL_LINK_NOARG(ColorSchemeDialog, SelectHdl, weld::TreeView&, void)
{
    // Apply the selected scheme only for the current ModulWinLayout for preview
    // Only if the user presses OK the scheme will be applied to all ModulWinLayout(s)
    m_sSelectedSchemeId = m_xSchemeList->get_selected_id();
    m_pModulWinLayout->ApplyColorSchemeToCurrentWindow(m_sSelectedSchemeId);
}

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/source/basicide/baside2.cxx b/basctl/source/basicide/baside2.cxx
index b01e5c2..0f892d5 100644
--- a/basctl/source/basicide/baside2.cxx
+++ b/basctl/source/basicide/baside2.cxx
@@ -26,6 +26,7 @@
#include <iderid.hxx>
#include "moduldlg.hxx"
#include <docsignature.hxx>
#include <colorscheme.hxx>
#include <officecfg/Office/BasicIDE.hxx>

#include <helpids.h>
@@ -69,6 +70,7 @@
#include <cassert>
#include <osl/diagnose.h>
#include <officecfg/Office/Common.hxx>
#include <BasicColorConfig.hxx>

namespace basctl
{
@@ -201,6 +203,9 @@ ModulWindow::ModulWindow (ModulWindowLayout* pParent, ScriptDocument const& rDoc
    , m_aXEditorWindow(VclPtr<ComplexEditorWindow>::Create(this))
    , m_aModule(std::move(aModule))
{
    // Active editor color scheme
    m_sWinColorScheme = GetShell()->GetColorConfig()->GetCurrentColorSchemeName();

    m_aXEditorWindow->Show();
    SetBackground();
}
@@ -1428,13 +1433,32 @@ void ModulWindow::UpdateModule ()
    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()
{
@@ -1471,6 +1495,7 @@ void ModulWindowLayout::Activating (BaseWindow& rChild)
    rObjectCatalog.UpdateEntries();
    Layout::Activating(rChild);
    aSyntaxColors.SetActiveEditor(&pChild->GetEditorWindow());
    aSyntaxColors.SetActiveColorSchemeId(m_sColorSchemeId);
}

void ModulWindowLayout::Deactivating ()
@@ -1526,12 +1551,19 @@ void ModulWindowLayout::OnFirstSize (tools::Long const nWidth, tools::Long const
    AddToBottom(aStackWindow.get(), Size(nWidth * 0.33, nHeight * 0.25));
}

ModulWindowLayout::SyntaxColors::SyntaxColors () :
    pEditor(nullptr)
// 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);

    NewConfig(true);
}

ModulWindowLayout::SyntaxColors::~SyntaxColors ()
@@ -1542,62 +1574,87 @@ ModulWindowLayout::SyntaxColors::~SyntaxColors ()
// virtual
void ModulWindowLayout::SyntaxColors::ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints)
{
    NewConfig(false);
    // 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);
}

// when a new configuration has to be set
void ModulWindowLayout::SyntaxColors::NewConfig (bool bFirst)
// 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)
{
    static struct
    const TokenType vTokenTypes[] =
    {
        TokenType eTokenType;
        svtools::ColorConfigEntry eEntry;
    }
    const vIds[] =
    {
        { TokenType::Unknown,     svtools::FONTCOLOR },
        { TokenType::Identifier,  svtools::BASICIDENTIFIER },
        { TokenType::Whitespace,  svtools::FONTCOLOR },
        { TokenType::Number,      svtools::BASICNUMBER },
        { TokenType::String,      svtools::BASICSTRING },
        { TokenType::EOL,         svtools::FONTCOLOR },
        { TokenType::Comment,     svtools::BASICCOMMENT },
        { TokenType::Error,       svtools::BASICERROR },
        { TokenType::Operator,    svtools::BASICOPERATOR },
        { TokenType::Keywords,    svtools::BASICKEYWORD },
        TokenType::Unknown,
        TokenType::Identifier,
        TokenType::Whitespace,
        TokenType::Number,
        TokenType::String,
        TokenType::EOL,
        TokenType::Comment,
        TokenType::Error,
        TokenType::Operator,
        TokenType::Keywords
    };

    Color aDocColor = aConfig.GetColorValue(svtools::BASICEDITOR).nColor;
    if (bFirst || aDocColor != m_aBackgroundColor)
    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)
    {
        m_aBackgroundColor = aDocColor;
        if (!bFirst && pEditor)
        {
            pEditor->SetBackground(Wallpaper(m_aBackgroundColor));
            pEditor->Invalidate();
        }
        pEditor->ChangeFontColor(aFontColor);
        pEditor->SetBackground(Wallpaper(aDocColor));
        pEditor->Invalidate();
    }

    Color aFontColor = aConfig.GetColorValue(svtools::FONTCOLOR).nColor;
    if (bFirst || aFontColor != m_aFontColor)
    for (const auto& aToken: vTokenTypes)
    {
        m_aFontColor = aFontColor;
        if (!bFirst && pEditor)
            pEditor->ChangeFontColor(m_aFontColor);
        // 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;
    }

    bool bChanged = false;
    for (const auto& vId: vIds)
    {
        Color const aColor = aConfig.GetColorValue(vId.eEntry).nColor;
        Color& rMyColor = aColors[vId.eTokenType];
        if (bFirst || aColor != rMyColor)
        {
            rMyColor = aColor;
            bChanged = true;
        }
    }
    if (bChanged && !bFirst && pEditor)
    // This check is needed because the EditEngine will only exist in the EditorWindow when the
    // module is actually opened
    if (!bFirst && pEditor)
        pEditor->UpdateSyntaxHighlighting();
}

diff --git a/basctl/source/basicide/baside2.hxx b/basctl/source/basicide/baside2.hxx
index 116dab2..bb8380b 100644
--- a/basctl/source/basicide/baside2.hxx
+++ b/basctl/source/basicide/baside2.hxx
@@ -24,6 +24,7 @@
#include <layout.hxx>
#include "breakpoint.hxx"
#include "linenumberwindow.hxx"
#include <colorscheme.hxx>

#include <basic/sbmod.hxx>
#include <basic/sbstar.hxx>
@@ -37,6 +38,7 @@
#include <rtl/ustrbuf.hxx>

#include <set>
#include <map>
#include <string_view>

#include <vcl/textdata.hxx>
@@ -290,6 +292,7 @@ private:
    BasicStatus         m_aStatus;
    SbModuleRef         m_xModule;
    OUString            m_aModule;
    OUString            m_sWinColorScheme;

    void                CheckCompileBasic();
    void                BasicExecute();
@@ -392,6 +395,8 @@ public:
    virtual bool HasActiveEditor () const override;

    void UpdateModule ();
    OUString GetEditorColorScheme() { return m_sWinColorScheme; }
    void SetEditorColorScheme(OUString aColorScheme);
};

class ModulWindowLayout: public Layout
@@ -416,6 +421,8 @@ public:
    Color const & GetSyntaxBackgroundColor () const { return aSyntaxColors.GetBackgroundColor(); }
    Color const & GetFontColor () const { return aSyntaxColors.GetFontColor(); }
    Color const & GetSyntaxColor (TokenType eType) const { return aSyntaxColors.GetColor(eType); }
    OUString GetActiveColorSchemeId() { return m_sColorSchemeId; }
    void ApplyColorSchemeToCurrentWindow (OUString aSchemeId);

protected:
    // Window:
@@ -430,6 +437,8 @@ private:
    VclPtr<WatchWindow> aWatchWindow;
    VclPtr<StackWindow> aStackWindow;
    ObjectCatalog& rObjectCatalog;
    // Active color scheme ID
    OUString m_sColorSchemeId;

    // SyntaxColors -- stores Basic syntax highlighting colors
    class SyntaxColors : public utl::ConfigurationListener
@@ -439,25 +448,26 @@ private:
        virtual ~SyntaxColors () override;
    public:
        void SetActiveEditor (EditorWindow* pEditor_) { pEditor = pEditor_; }
        void SetActiveColorSchemeId(OUString aColorSchemeId) { m_sActiveSchemeId = aColorSchemeId; }
    public:
        Color const & GetBackgroundColor () const { return m_aBackgroundColor; };
        Color const & GetFontColor () const { return m_aFontColor; }
        Color const & GetColor(TokenType eType) const { return aColors[eType]; }
        void ApplyColorScheme(OUString aSchemeId, bool bFirst);

    private:
        virtual void ConfigurationChanged (utl::ConfigurationBroadcaster*, ConfigurationHints) override;
        void NewConfig (bool bFirst);

    private:
        Color m_aBackgroundColor;
        Color m_aFontColor;
        OUString m_sActiveSchemeId;
        // the color values (the indexes are TokenType, see comphelper/syntaxhighlight.hxx)
        o3tl::enumarray<TokenType, Color> aColors;
        // the configuration
        svtools::ColorConfig aConfig;
        // the active editor
        VclPtr<EditorWindow> pEditor;

    } aSyntaxColors;
};

diff --git a/basctl/source/basicide/basides1.cxx b/basctl/source/basicide/basides1.cxx
index 4f2918d..507902a 100644
--- a/basctl/source/basicide/basides1.cxx
+++ b/basctl/source/basicide/basides1.cxx
@@ -31,6 +31,7 @@
#include "iderdll2.hxx"
#include <localizationmgr.hxx>
#include <managelang.hxx>
#include <ColorSchemeDialog.hxx>

#include <basic/basmgr.hxx>
#include <com/sun/star/script/ModuleType.hpp>
@@ -59,6 +60,7 @@
#include <svx/zoomsliderctrl.hxx>
#include <svx/zoomslideritem.hxx>
#include <basegfx/utils/zoomtools.hxx>
#include <officecfg/Office/BasicIDE.hxx>

constexpr sal_Int32 TAB_HEIGHT_MARGIN = 10;

@@ -789,6 +791,50 @@ void Shell::ExecuteGlobal( SfxRequest& rReq )
        }
        break;

        case SID_BASICIDE_COLOR_SCHEME_DLG:
        {
            ModulWindowLayout* pMyLayout = dynamic_cast<ModulWindowLayout*>(pLayout.get());
            if (!pMyLayout)
                return;

            OUString curScheme = pMyLayout->GetActiveColorSchemeId();
            auto xDlg = std::make_shared<ColorSchemeDialog>(pCurWin ? pCurWin->GetFrameWeld() : nullptr,
                                                            pMyLayout);
            weld::DialogController::runAsync(xDlg, [xDlg, pMyLayout, curScheme](sal_Int32 nResult){
                OUString sNewScheme(xDlg->GetColorSchemeId());
                // If the user canceled the dialog, restores the original color scheme
                if (nResult != RET_OK)
                {
                    if (curScheme != sNewScheme)
                        pMyLayout->ApplyColorSchemeToCurrentWindow(curScheme);
                }

                // If the user selects OK, apply the color scheme to all open ModulWindow
                if (nResult == RET_OK)
                {
                    // Set the global color scheme in ModulWindowLayout and update definitions in SyntaxColors
                    pMyLayout->ApplyColorSchemeToCurrentWindow(sNewScheme);

                    // Update color scheme for all windows
                    for (auto const& window : GetShell()->GetWindowTable())
                    {
                        ModulWindow* pModuleWindow = dynamic_cast<ModulWindow*>(window.second.get());
                        if (pModuleWindow)
                        {
                            // We need to set the current scheme for each window
                            pModuleWindow->SetEditorColorScheme(sNewScheme);
                        }
                    }

                    // Update registry with the new color scheme ID
                    std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
                    officecfg::Office::BasicIDE::EditorSettings::ColorScheme::set(sNewScheme, batch);
                    batch->commit();
                }
            });
        }
        break;

        case SID_BASICIDE_MANAGE_LANG:
        {
            auto xRequest = std::make_shared<SfxRequest>(rReq);
@@ -1231,6 +1277,13 @@ void Shell::GetState(SfxItemSet &rSet)
            }
            break;

            case SID_BASICIDE_COLOR_SCHEME_DLG:
            {
                if (!dynamic_cast<ModulWindowLayout*>(pLayout.get()))
                    rSet.DisableItem(nWh);
            }
            break;

            case SID_ATTR_ZOOMSLIDER:
            {
                // The zoom slider is only visible in a module window
diff --git a/basctl/source/basicide/basidesh.cxx b/basctl/source/basicide/basidesh.cxx
index d23da94..e64e34e 100644
--- a/basctl/source/basicide/basidesh.cxx
+++ b/basctl/source/basicide/basidesh.cxx
@@ -74,6 +74,7 @@
#include <vcl/settings.hxx>
#include <vcl/svapp.hxx>
#include <cppuhelper/implbase.hxx>
#include <BasicColorConfig.hxx>

namespace basctl
{
@@ -196,6 +197,9 @@ void Shell::Init()
        GetViewFrame().GetWindow().GetSettings().GetStyleSettings().GetWindowColor()
    );

    // Used to access color settings of the Basic code editor
    m_aColorConfig = std::make_shared<BasicColorConfig>();

    pCurWin = nullptr;
    m_aCurDocument = ScriptDocument::getApplicationScriptDocument();
    bCreatingWindow = false;
diff --git a/basctl/source/inc/BasicColorConfig.hxx b/basctl/source/inc/BasicColorConfig.hxx
new file mode 100644
index 0000000..9d66925
--- /dev/null
+++ b/basctl/source/inc/BasicColorConfig.hxx
@@ -0,0 +1,99 @@
/* -*- 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 .
 */

#pragma once

#include <rtl/ustring.hxx>
#include <strings.hrc>
#include <com/sun/star/uno/Sequence.hxx>
#include <comphelper/sequence.hxx>
#include <unotools/configitem.hxx>
#include <svtools/colorcfg.hxx>
#include "colorscheme.hxx"
#include "iderid.hxx"
#include <map>

namespace basctl
{
// Name used to refer to the application color scheme (the one defined in Application Colors)
inline constexpr OUString DEFAULT_SCHEME = u"COLORSCHEME_DEFAULT"_ustr;

typedef std::map<OUString, TranslateId> SchemeTranslateIdMap;

class BasicColorConfig : public utl::ConfigItem
{
private:
    // Name of the color scheme that is currently active
    OUString m_sCurrentColorScheme;

    // Names of all available scheme names
    css::uno::Sequence<OUString> m_aSchemeNames;

    // Names of default color schemes shipped with LibreOffice
    css::uno::Sequence<OUString> m_aDefaultSchemes
        = { "COLORSCHEME_LIBREOFFICE_LIGHT", "COLORSCHEME_LIBREOFFICE_DARK",
            "COLORSCHEME_BREEZE_LIGHT",      "COLORSCHEME_BREEZE_DARK",
            "COLORSCHEME_SOLARIZED_LIGHT",   "COLORSCHEME_SOLARIZED_DARK" };

    // Maps the scheme names to their TranslateId
    SchemeTranslateIdMap m_aTranslateIdsMap = {
        { "COLORSCHEME_LIBREOFFICE_LIGHT", RID_STR_COLORSCHEME_LIGHT },
        { "COLORSCHEME_LIBREOFFICE_DARK", RID_STR_COLORSCHEME_DARK },
        { "COLORSCHEME_BREEZE_LIGHT", RID_STR_COLORSCHEME_BREEZE_LIGHT },
        { "COLORSCHEME_BREEZE_DARK", RID_STR_COLORSCHEME_BREEZE_DARK },
        { "COLORSCHEME_SOLARIZED_LIGHT", RID_STR_COLORSCHEME_SOLARIZED_LIGHT },
        { "COLORSCHEME_SOLARIZED_DARK", RID_STR_COLORSCHEME_SOLARIZED_DARK },
    };

    // Used to get colors defined in the Appliation Colors dialog
    const svtools::ColorConfig aColorConfig;

    virtual void ImplCommit() override;

public:
    BasicColorConfig();
    virtual ~BasicColorConfig() override;

    virtual void Notify(const css::uno::Sequence<OUString>& aPropertyNames) override;

    ColorScheme GetColorScheme(const OUString& rScheme);
    css::uno::Sequence<OUString> GetColorSchemeNames() { return m_aSchemeNames; }

    // Returns the color scheme defined by the current Application Colors
    ColorScheme GetAutomaticColorScheme();

    // Returns the name of the currently active color scheme
    OUString& GetCurrentColorSchemeName();

    // Returns the current color scheme
    ColorScheme GetCurrentColorScheme() { return GetColorScheme(GetCurrentColorSchemeName()); }

    // Returns true if the scheme is a scheme preinstalled with LO
    bool IsDefaultScheme(const OUString& rScheme)
    {
        return comphelper::findValue(m_aDefaultSchemes, rScheme) != -1;
    }

    // Returns the TranslateId of the scheme name
    TranslateId GetSchemeTranslateId(const OUString& rScheme);
};

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/source/inc/ColorSchemeDialog.hxx b/basctl/source/inc/ColorSchemeDialog.hxx
new file mode 100644
index 0000000..6171212
--- /dev/null
+++ b/basctl/source/inc/ColorSchemeDialog.hxx
@@ -0,0 +1,57 @@
/* -*- 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 .
 */

#pragma once

#include <utility>
#include <vcl/weld.hxx>

namespace basctl
{
class ModulWindowLayout;
class BasicColorConfig;

class ColorSchemeDialog : public weld::GenericDialogController
{
private:
    VclPtr<ModulWindowLayout> m_pModulWinLayout;
    OUString m_sSelectedSchemeId;

    std::unique_ptr<weld::TreeView> m_xSchemeList;
    std::unique_ptr<weld::RadioButton> m_xUseAppCollors;
    std::unique_ptr<weld::RadioButton> m_xUseScheme;
    std::unique_ptr<weld::Button> m_xOk;
    std::shared_ptr<BasicColorConfig> m_pColorConfig;

    void Init();

    DECL_LINK(BtnOkHdl, weld::Button&, void);
    DECL_LINK(OptionHdl, weld::Toggleable&, void);
    DECL_LINK(SelectHdl, weld::TreeView&, void);

public:
    ColorSchemeDialog(weld::Window* pParent, VclPtr<ModulWindowLayout> pModulWinLayout);
    virtual ~ColorSchemeDialog() override;

    const OUString& GetColorSchemeId() { return m_sSelectedSchemeId; }
};

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/source/inc/basidesh.hxx b/basctl/source/inc/basidesh.hxx
index f907abe..afaa47c 100644
--- a/basctl/source/inc/basidesh.hxx
+++ b/basctl/source/inc/basidesh.hxx
@@ -54,6 +54,7 @@ class DialogWindowLayout;
class TabBar;
class BaseWindow;
class LocalizationMgr;
class BasicColorConfig;

class Shell :
    public SfxViewShell,
@@ -81,6 +82,9 @@ private:
    VclPtr<TabBar>       pTabBar;           // basctl::TabBar
    bool                 bCreatingWindow;

    // Basic editor color configuration
    std::shared_ptr<BasicColorConfig> m_aColorConfig;

    // layout windows
    VclPtr<ModulWindowLayout>   pModulLayout;
    VclPtr<DialogWindowLayout>  pDialogLayout;
@@ -220,6 +224,8 @@ public:
    void UpdateObjectCatalog () { aObjectCatalog->UpdateEntries(); }

    void RemoveWindow (BaseWindow* pWindow, bool bDestroy, bool bAllowChangeCurWindow = true);

    const std::shared_ptr<BasicColorConfig>& GetColorConfig() const { return m_aColorConfig; }
};

} // namespace basctl
diff --git a/basctl/source/inc/colorscheme.hxx b/basctl/source/inc/colorscheme.hxx
new file mode 100644
index 0000000..5f7514f
--- /dev/null
+++ b/basctl/source/inc/colorscheme.hxx
@@ -0,0 +1,44 @@
/* -*- 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 .
 */

#pragma once

#include <tools/color.hxx>

namespace basctl
{
// Defines a single color scheme
typedef struct
{
    OUString m_sSchemeName;
    bool m_bIsDefault;
    Color m_aGenericFontColor;
    Color m_aIdentifierColor;
    Color m_aNumberColor;
    Color m_aStringColor;
    Color m_aCommentColor;
    Color m_aErrorColor;
    Color m_aOperatorColor;
    Color m_aKeywordColor;
    Color m_aBackgroundColor;
} ColorScheme;

} // namespace basctl

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basctl/uiconfig/basicide/menubar/menubar.xml b/basctl/uiconfig/basicide/menubar/menubar.xml
index fc51057..d649f96 100644
--- a/basctl/uiconfig/basicide/menubar/menubar.xml
+++ b/basctl/uiconfig/basicide/menubar/menubar.xml
@@ -65,6 +65,7 @@
        <menu:menupopup>
            <menu:menuitem menu:id=".uno:AvailableToolbars"/>
            <menu:menuitem menu:id=".uno:StatusBarVisible"/>
            <menu:menuitem menu:id=".uno:BasicColorSchemeDialog"/>
            <menu:menuseparator/>
            <menu:menuitem menu:id=".uno:ShowLines"/>
            <menu:menuitem menu:id=".uno:ShowPropBrowser"/>
diff --git a/basctl/uiconfig/basicide/ui/colorscheme.ui b/basctl/uiconfig/basicide/ui/colorscheme.ui
new file mode 100644
index 0000000..709f946
--- /dev/null
+++ b/basctl/uiconfig/basicide/ui/colorscheme.ui
@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface domain="basctl">
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name id -->
      <column type="gchararray"/>
      <!-- column-name scheme -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkDialog" id="ColorSchemeDialog">
    <property name="can-focus">False</property>
    <property name="border-width">6</property>
    <property name="title" translatable="yes" context="colorscheme|ColorSchemeDialog">Color Scheme</property>
    <property name="resizable">False</property>
    <property name="type-hint">dialog</property>
    <child internal-child="vbox">
      <object class="GtkBox">
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">12</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox">
            <property name="can-focus">False</property>
            <property name="layout-style">end</property>
            <child>
              <object class="GtkButton" id="btn_help">
                <property name="label" translatable="yes" context="stock">_Help</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="use-underline">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn_ok">
                <property name="label" translatable="yes" context="stock">_OK</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="use-underline">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="btn_cancel">
                <property name="label" translatable="yes" context="stock">_Cancel</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <property name="use-underline">True</property>
              </object>
              <packing>
                <property name="expand">True</property>
                <property name="fill">True</property>
                <property name="position">2</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">False</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkFrame" id="options">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="label-xalign">0</property>
            <property name="shadow-type">none</property>
            <child>
              <object class="GtkAlignment">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="left-padding">12</property>
                <child>
                  <object class="GtkBox">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <property name="orientation">vertical</property>
                    <child>
                      <object class="GtkRadioButton" id="opt_appcolors">
                        <property name="label" translatable="yes" context="colorscheme|opt_appcolors">Use Application Colors</property>
                        <property name="visible">True</property>
                        <property name="can-focus">True</property>
                        <property name="receives-default">False</property>
                        <property name="active">True</property>
                        <property name="draw-indicator">True</property>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">True</property>
                        <property name="position">0</property>
                      </packing>
                    </child>
                    <child>
                      <object class="GtkRadioButton" id="opt_usescheme">
                        <property name="label" translatable="yes" context="colorscheme|opt_usescheme">Choose Color Scheme</property>
                        <property name="visible">True</property>
                        <property name="can-focus">True</property>
                        <property name="receives-default">False</property>
                        <property name="active">True</property>
                        <property name="draw-indicator">True</property>
                        <property name="group">opt_appcolors</property>
                      </object>
                      <packing>
                        <property name="expand">False</property>
                        <property name="fill">True</property>
                        <property name="position">1</property>
                      </packing>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child type="label">
              <object class="GtkLabel" id="lb_title">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes" context="colorscheme|lb_title">Basic IDE Color Options</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkFrame">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="margin-start">6</property>
            <property name="margin-end">6</property>
            <property name="margin-top">6</property>
            <property name="margin-bottom">6</property>
            <property name="label-xalign">0</property>
            <property name="shadow-type">none</property>
            <child>
              <object class="GtkAlignment">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="left-padding">12</property>
                <child>
                  <object class="GtkScrolledWindow">
                    <property name="visible">True</property>
                    <property name="can-focus">True</property>
                    <property name="hexpand">True</property>
                    <property name="vexpand">True</property>
                    <property name="shadow-type">in</property>
                    <child>
                      <object class="GtkTreeView" id="schemelist">
                        <property name="visible">True</property>
                        <property name="can-focus">True</property>
                        <property name="hexpand">True</property>
                        <property name="vexpand">True</property>
                        <property name="model">liststore1</property>
                        <property name="headers-visible">False</property>
                        <property name="headers-clickable">False</property>
                        <property name="search-column">0</property>
                        <property name="show-expanders">False</property>
                        <child internal-child="selection">
                          <object class="GtkTreeSelection"/>
                        </child>
                        <child>
                          <object class="GtkTreeViewColumn">
                            <child>
                              <object class="GtkCellRendererText" id="rendertext"/>
                            </child>
                          </object>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child type="label">
              <object class="GtkLabel" id="lb_schemes">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="margin-bottom">6</property>
                <property name="label" translatable="yes" context="colorscheme|lb_schemes">Color Schemes</property>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="-11">btn_help</action-widget>
      <action-widget response="-5">btn_ok</action-widget>
      <action-widget response="-6">btn_cancel</action-widget>
    </action-widgets>
  </object>
</interface>
diff --git a/include/sfx2/sfxsids.hrc b/include/sfx2/sfxsids.hrc
index 3e1775788..4748ff1 100644
--- a/include/sfx2/sfxsids.hrc
+++ b/include/sfx2/sfxsids.hrc
@@ -669,6 +669,7 @@ class SvxZoomItem;
#define SID_BASICIDE_CURRENT_ZOOM           TypedWhichId<SfxStringItem>( SID_BASICIDE_START + 54 )
#define SID_BASICIDE_WATCH                  TypedWhichId<SfxBoolItem>( SID_BASICIDE_START + 55 )
#define SID_BASICIDE_STACK                  TypedWhichId<SfxBoolItem>( SID_BASICIDE_START + 56 )
#define SID_BASICIDE_COLOR_SCHEME_DLG       ( SID_BASICIDE_START + 57 )
#define SID_OPTIONS_TREEDIALOG              ( SID_BASICIDE_START + 862)

// SlotIds for Apps --------------------------------------------------------
diff --git a/officecfg/registry/data/org/openoffice/Office/BasicIDE.xcu b/officecfg/registry/data/org/openoffice/Office/BasicIDE.xcu
index fc40193..0448b55 100644
--- a/officecfg/registry/data/org/openoffice/Office/BasicIDE.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/BasicIDE.xcu
@@ -18,4 +18,288 @@
 -->
 <!DOCTYPE oor:component-data SYSTEM "../../../../component-update.dtd">
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:install="http://openoffice.org/2004/installation" oor:name="BasicIDE" oor:package="org.openoffice.Office">
  <node oor:name="IDEColorSchemes">
    <node oor:name="COLORSCHEME_LIBREOFFICE_LIGHT" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>0</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>32768</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>16711680</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>16711680</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>8421504</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>16711680</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>128</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>128</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>16777215</value>
        </prop>
      </node>
    </node>
    <node oor:name="COLORSCHEME_LIBREOFFICE_DARK" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>16777215</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>14543051</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>16754342</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>16754342</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>15658734</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>16726072</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>11847644</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>11847644</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>0</value>
        </prop>
      </node>
    </node>
    <node oor:name="COLORSCHEME_BREEZE_LIGHT" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>2038811</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>2038811</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>11567104</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>12518147</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>9144455</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>12518147</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>13263050</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>22446</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>16777215</value>
        </prop>
      </node>
    </node>
    <node oor:name="COLORSCHEME_BREEZE_DARK" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>11974316</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>13619134</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>15822859</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>15814479</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>8358783</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>15814479</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>4161624</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>2719383</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>2303529</value>
        </prop>
      </node>
    </node>
    <node oor:name="COLORSCHEME_SOLARIZED_LIGHT" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>6650755</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>6650755</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>3252632</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>3252632</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>9675169</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>14430772</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>8755456</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>8755456</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>16643811</value>
        </prop>
      </node>
    </node>
    <node oor:name="COLORSCHEME_SOLARIZED_DARK" oor:op="replace">
      <node oor:name="GenericColor">
        <prop oor:name="Color">
          <value>8623254</value>
        </prop>
      </node>
      <node oor:name="IdentifierColor">
        <prop oor:name="Color">
          <value>8623254</value>
        </prop>
      </node>
      <node oor:name="NumberColor">
        <prop oor:name="Color">
          <value>2793880</value>
        </prop>
      </node>
      <node oor:name="StringColor">
        <prop oor:name="Color">
          <value>2793880</value>
        </prop>
      </node>
      <node oor:name="CommentColor">
        <prop oor:name="Color">
          <value>5664373</value>
        </prop>
      </node>
      <node oor:name="ErrorColor">
        <prop oor:name="Color">
          <value>14430767</value>
        </prop>
      </node>
      <node oor:name="OperatorColor">
        <prop oor:name="Color">
          <value>8755456</value>
        </prop>
      </node>
      <node oor:name="KeywordColor">
        <prop oor:name="Color">
          <value>8755456</value>
        </prop>
      </node>
      <node oor:name="BackgroundColor">
        <prop oor:name="Color">
          <value>11062</value>
        </prop>
      </node>
    </node>
  </node>
</oor:component-data>
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/BasicIDECommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/BasicIDECommands.xcu
index 739ad7b..9783255 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/BasicIDECommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/BasicIDECommands.xcu
@@ -99,6 +99,14 @@
          <value xml:lang="en-US">Hide</value>
        </prop>
      </node>
      <node oor:name=".uno:BasicColorSchemeDialog" oor:op="replace">
        <prop oor:name="Label" oor:type="xs:string">
          <value xml:lang="en-US">Color Scheme...</value>
        </prop>
        <prop oor:name="Properties" oor:type="xs:int">
          <value>1</value>
        </prop>
      </node>
    </node>
    <node oor:name="Popups">
      <node oor:name=".uno:RunMenu" oor:op="replace">
diff --git a/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs b/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs
index 94f108c..0a17b5f 100644
--- a/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/BasicIDE.xcs
@@ -21,6 +21,103 @@
    <info>
        <desc>Contains configuration for the BASIC IDE.</desc>
    </info>
    <templates>
      <group oor:name="IDEColorScheme">
      <info>
        <desc>Defines the templates for color schemes used in the Basic IDE code editor.</desc>
      </info>
      <group oor:name="GenericColor">
        <info>
          <desc>Specifies the formatting used for unknown tokens.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for unknown tokens.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="IdentifierColor">
        <info>
          <desc>Specifies the formatting used for identifier tokens.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for identifier tokens.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="NumberColor">
        <info>
          <desc>Specifies the formatting used for numbers.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for numbers.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="StringColor">
        <info>
          <desc>Specifies the formatting used for strings.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for strings.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="CommentColor">
        <info>
          <desc>Specifies the formatting used for comments.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for comments.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="ErrorColor">
        <info>
          <desc>Specifies the formatting used for errors.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for errors.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="OperatorColor">
        <info>
          <desc>Specifies the formatting used for operators.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for operators.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="KeywordColor">
        <info>
          <desc>Specifies the formatting used for keywords.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for keywords.</desc>
          </info>
        </prop>
      </group>
      <group oor:name="BackgroundColor">
        <info>
          <desc>Specifies the settings for the editor's background color.</desc>
        </info>
        <prop oor:name="Color" oor:type="xs:int">
          <info>
            <desc>Specifies the color used for the editor's background.</desc>
          </info>
        </prop>
      </group>
    </group>
    </templates>
    <component>
    <group oor:name="Autocomplete">
        <info>
@@ -64,15 +161,26 @@
        </prop>
    </group>
    <group oor:name="EditorSettings">
      <info>
        <desc>Contains user configuration.</desc>
      </info>
      <prop oor:name="LineNumbering" oor:type="xs:boolean" oor:nillable="false">
        <info>
            <desc>Contains user configuration.</desc>
          <desc>Sets the line numbering on/off. Default is true.</desc>
        </info>
        <prop oor:name="LineNumbering" oor:type="xs:boolean" oor:nillable="false">
            <info>
                <desc>Sets the line numbering on/off. Default is true.</desc>
            </info>
            <value>true</value>
        </prop>
        <value>true</value>
      </prop>
      <prop oor:name="ColorScheme" oor:type="xs:string" oor:nillable="false">
        <info>
          <desc>Name of the selected color scheme used in the Basic IDE.</desc>
        </info>
        <value>COLORSCHEME_DEFAULT</value>
      </prop>
    </group>
    <set oor:name="IDEColorSchemes" oor:node-type="IDEColorScheme">
      <info>
        <desc>Lists entries with color settings.</desc>
      </info>
    </set>
    </component>
</oor:component-schema>
diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi
index fad6109..4b52f73 100644
--- a/svx/sdi/svx.sdi
+++ b/svx/sdi/svx.sdi
@@ -11197,6 +11197,23 @@ SfxVoidItem InsertNarrowNobreakSpace FN_INSERT_NNBSP
    GroupId = SfxGroupId::Insert;
]

SfxVoidItem BasicColorSchemeDialog SID_BASICIDE_COLOR_SCHEME_DLG
()
[
    AutoUpdate = FALSE,
    FastCall = FALSE,
    ReadOnlyDoc = TRUE,
    Toggle = FALSE,
    Container = FALSE,
    RecordAbsolute = FALSE,
    RecordPerSet;

    AccelConfig = TRUE,
    MenuConfig = TRUE,
    ToolBoxConfig = TRUE,
    GroupId = SfxGroupId::Controls;
]

SfxVoidItem ManageLanguage SID_BASICIDE_MANAGE_LANG
()
[