cui/Library_cui.mk                                         |    2 
 cui/UIConfig_cui.mk                                        |    1 
 cui/inc/strings.hrc                                        |  144 ++
 cui/inc/treeopt.hrc                                        |    1 
 cui/qa/unit/data/cui-dialogs-test_4.txt                    |    1 
 cui/source/options/appearance.cxx                          |  719 ++++++++++
 cui/source/options/appearance.hxx                          |  106 +
 cui/source/options/treeopt.cxx                             |    5 
 cui/source/options/treeopthelper.cxx                       |    1 
 cui/uiconfig/ui/appearance.ui                              |  484 +++++++
 desktop/qa/desktop_lib/test_desktop_lib.cxx                |    7 
 include/sfx2/pageids.hxx                                   |    1 
 include/svtools/colorcfg.hxx                               |  153 ++
 include/vcl/settings.hxx                                   |    3 
 include/vcl/themecolors.hxx                                |   19 
 officecfg/registry/data/org/openoffice/Office/UI.xcu       |  466 +++++--
 officecfg/registry/schema/org/openoffice/Office/Common.xcs |   43 
 officecfg/registry/schema/org/openoffice/Office/UI.xcs     |  853 ++++++++++---
 sc/qa/uitest/calc_tests6/tdf116996.py                      |    2 
 sd/qa/unit/tiledrendering/tiledrendering.cxx               |    9 
 sfx2/source/appl/appserv.cxx                               |   12 
 static/CustomTarget_emscripten_fs_image.mk                 |    1 
 svtools/source/config/colorcfg.cxx                         |  353 +++--
 sw/inc/viewsh.hxx                                          |    2 
 sw/qa/extras/tiledrendering/tiledrendering.cxx             |    9 
 sw/qa/uitest/options/tdf131581.py                          |    2 
 sw/source/core/view/viewsh.cxx                             |   22 
 vcl/source/app/settings.cxx                                |   58 
 vcl/unx/gtk3/gtkframe.cxx                                  |    2 
 29 files changed, 2995 insertions(+), 486 deletions(-)

New commits:
commit ddeeca35d9630f2d3d3afb83a2ec8f21458f6e19
Author:     Sahil Gautam <sahil.gautam.ext...@allotropia.de>
AuthorDate: Sun Dec 1 18:49:36 2024 +0530
Commit:     Sahil Gautam <sahil.gautam.ext...@allotropia.de>
CommitDate: Wed Dec 18 16:24:08 2024 +0100

    tdf#163620 [API CHANGE] Add UI for libreoffice themes
    
    Instead of Color, we have Light and  Dark in the registry. So each theme 
extension
    will specify  dark and  light color  values for  each "customizable  
element" like
    DocColor etc. Under appearance we have three radio buttons - 
light/dark/system. If
    system  is selected  then light/dark  colors are  switched based  on the  
system's
    theme.  if  explicitly light/dark  is  selected  - that  color  is  used 
from  the
    registry.
    
    ColorConfigValue now has three entries  nColor, nLightColor, nDarkColor. 
nColor is
    used as a cache for the color being used at the moment. This is to avoid 
otherwise
    expensive  function calls  + hundreds  of modifications  in the  codebase 
just  to
    change nColor. nColor  is cached either when  the theme is loaded  or when 
changes
    are committed in `ColorConfig_Impl::ImplCommit()`.
    
    Now, if  Automatic theme is selected  then themes is disabled  and the 
application
    uses the system  colors. If some other scheme is  selected like 
"CustomTheme" etc,
    then LibreOffice themes/UI color customization is enabled and the theme 
colors are
    used.
    
    Instead of a scroll window, now we have  a combobox for the registry 
entries and a
    single  color dropdown  to select  the  color value.  This color  dropdown 
is  for
    convinience in case the user wants  to change some specific color that's 
bothering
    him. For themeing, theme extensions should be used.
    
    API CHANGE
    + remove Color in favour of Light and Dark
    + AppBackground has additional two - BackgroundType and Bitmap
    + remove officecfg::Office::Common::Misc::Appearnce in favor of
      officecfg::Office::Common::Appearance::ApplicationAppearance
    + move LibreofficeTheme under officecfg::Office::Common::Appearance
    
    UI
    + it looks like https://i.imgur.com/UMxjfuC.png which is a little
      different from how the [mockup] on the ticket describes it, and that's
      because of lack of time due to upcomming feature freeze.
    
    + system/light/dark allow the user to switch between light/dark modes
      based on either the system theme (system) or by manually specifying
      light/dark.
    
    + ui themeing and color customization is disabled when automatic theme
      is selected, and enabled otherwise.
    
    [mockup]: 
https://bug-attachments.documentfoundation.org/attachment.cgi?id=197469
    
    Change-Id: I1a7f70dfe44b81f863814f87e8d46e146c0e3d5a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174835
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    Tested-by: Jenkins
    Reviewed-by: Sahil Gautam <sahil.gautam.ext...@allotropia.de>

diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index ef64e0fea5f6..71a53ef3928d 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -199,6 +199,8 @@ $(eval $(call gb_Library_add_exception_objects,cui,\
     cui/source/options/optpath \
     cui/source/options/optsave \
     cui/source/options/optupdt \
+    $(call gb_Helper_optional,DESKTOP,\
+        cui/source/options/appearance) \
     cui/source/options/sdbcdriverenum \
     cui/source/options/securityoptions \
     cui/source/options/treeopt \
diff --git a/cui/UIConfig_cui.mk b/cui/UIConfig_cui.mk
index 953227c874c0..b78aa328667f 100644
--- a/cui/UIConfig_cui.mk
+++ b/cui/UIConfig_cui.mk
@@ -168,6 +168,7 @@ $(eval $(call gb_UIConfig_add_uifiles,cui,\
        cui/uiconfig/ui/pastespecial \
        cui/uiconfig/ui/patterntabpage \
        cui/uiconfig/ui/percentdialog \
+       cui/uiconfig/ui/appearance \
        cui/uiconfig/ui/pickbulletpage \
        cui/uiconfig/ui/pickgraphicpage \
        cui/uiconfig/ui/picknumberingpage \
diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc
index 96ab2285b4ee..f197e7c7712f 100644
--- a/cui/inc/strings.hrc
+++ b/cui/inc/strings.hrc
@@ -401,6 +401,150 @@
 // Translatable names of color schemes
 #define RID_COLOR_SCHEME_LIBREOFFICE_AUTOMATIC      
NC_("RID_COLOR_SCHEME_LIBREOFFICE_AUTOMATIC", "Automatic")
 
+// Translatable Bitmap Names
+#define BMP_FUZZY_LIGHTGREY                         NC_("BMP_FUZZY_LIGHTGREY", 
"Fuzzy Lightgrey")
+#define BMP_ICE_LIGHT                               NC_("BMP_ICE_LIGHT", "Ice 
Light")
+#define BMP_PAINTED_WHITE                           NC_("BMP_PAINTED_WHITE", 
"Painted White")
+#define BMP_TEXTURE_PAPER                           NC_("BMP_TEXTURE_PAPER", 
"Texture Paper")
+#define BMP_CRUMPLED_PAPER                          NC_("BMP_CRUMPLED_PAPER", 
"Crumpled Paper")
+#define BMP_MARBLE                                  NC_("BMP_MARBLE", "Marble")
+#define BMP_CONCRETE                                NC_("BMP_CONCRETE", 
"Concrete")
+#define BMP_FUZZY_GREY                              NC_("BMP_FUZZY_GREY", 
"Fuzzy Grey")
+#define BMP_FUZZY_DARKGREY                          NC_("BMP_FUZZY_DARKGREY", 
"Fuzzy Darkgrey")
+#define BMP_STONE                                   NC_("BMP_STONE", "Stone")
+#define BMP_WHITE_DIFFUSION                         NC_("BMP_WHITE_DIFFUSION", 
"White Diffusion")
+#define BMP_SAND_LIGHT                              NC_("BMP_SAND_LIGHT", 
"Sand Light")
+#define BMP_SAND                                    NC_("BMP_SAND", "Sand")
+#define BMP_SURFACE                                 NC_("BMP_SURFACE", 
"Surface")
+#define BMP_STUDIO                                  NC_("BMP_STUDIO", "Studio")
+#define BMP_INVOICE_PAPER                           NC_("BMP_INVOICE_PAPER", 
"Invoice Paper")
+#define BMP_PARCHMENT_PAPER                         NC_("BMP_PARCHMENT_PAPER", 
"Parchment Paper")
+#define BMP_CARDBOARD                               NC_("BMP_CARDBOARD", 
"Cardboard")
+#define BMP_FENCE                                   NC_("BMP_FENCE", "Fence")
+#define BMP_WOODEN_FENCE                            NC_("BMP_WOODEN_FENCE", 
"Wooden Fence")
+#define BMP_WOOD                                    NC_("BMP_WOOD", "Wood")
+#define BMP_WOODEN_BOARD                            NC_("BMP_WOODEN_BOARD", 
"Wooden Board")
+#define BMP_PAINTED_WOOD                            NC_("BMP_PAINTED_WOOD", 
"Painted Wood")
+#define BMP_STONES                                  NC_("BMP_STONES", "Stones")
+#define BMP_PEBBLE_LIGHT                            NC_("BMP_PEBBLE_LIGHT", 
"Pebble Light")
+#define BMP_STONE_WALL                              NC_("BMP_STONE_WALL", 
"Stone Wall")
+#define BMP_STONE_GRAY                              NC_("BMP_STONE_GRAY", 
"Stone Gray")
+#define BMP_ROCK_WALL                               NC_("BMP_ROCK_WALL", "Rock 
Wall")
+#define BMP_SURFACE_BLACK                           NC_("BMP_SURFACE_BLACK", 
"Surface Black")
+#define BMP_BRICK_WALL                              NC_("BMP_BRICK_WALL", 
"Brick Wall")
+#define BMP_TILES                                   NC_("BMP_TILES", "Tiles")
+#define BMP_GRAPH_PAPER                             NC_("BMP_GRAPH_PAPER", 
"Graph Paper")
+#define BMP_CLOUD                                   NC_("BMP_CLOUD", "Cloud")
+#define BMP_POOL                                    NC_("BMP_POOL", "Pool")
+#define BMP_SKY                                     NC_("BMP_SKY", "Sky")
+#define BMP_CIRCUIT_BOARD                           NC_("BMP_CIRCUIT_BOARD", 
"Circuit Board")
+#define BMP_COFFEE                                  NC_("BMP_COFFEE", "Coffee")
+#define BMP_COLOR_STRIPES                           NC_("BMP_COLOR_STRIPES", 
"Color Stripes")
+#define BMP_FLORAL                                  NC_("BMP_FLORAL", "Floral")
+#define BMP_LEAF                                    NC_("BMP_LEAF", "Leaf")
+#define BMP_MAPLE_LEAVES                            NC_("BMP_MAPLE_LEAVES", 
"Maple Leaves")
+#define BMP_SPACE                                   NC_("BMP_SPACE", "Space")
+#define BMP_GIRAFFE                                 NC_("BMP_GIRAFFE", 
"Giraffe")
+#define BMP_TIGER                                   NC_("BMP_TIGER", "Tiger")
+#define BMP_ZEBRA                                   NC_("BMP_ZEBRA", "Zebra")
+
+#define LIGHT_COLOR_LBL                             NC_("LIGHT_COLOR_LBL", 
"Light")
+#define DARK_COLOR_LBL                              NC_("DARK_COLOR_LBL", 
"Dark")
+
+// Translated Registry Entries
+#define REG_DOCCOLOR                        NC_("REG_DOCCOLOR", "Document 
background")
+#define REG_DOCBOUNDARIES                   NC_("REG_DOCBOUNDARIES", "Document 
boundaries")
+#define REG_APPBACKGROUND                   NC_("REG_APPBACKGROUND", 
"Application background")
+#define REG_TABLEBOUNDARIES                 NC_("REG_TABLEBOUNDARIES", "Table 
boundaries")
+#define REG_FONTCOLOR                       NC_("REG_FONTCOLOR", "Font color")
+#define REG_LINKS                           NC_("REG_LINKS", "Unvisited links")
+#define REG_LINKSVISITED                    NC_("REG_LINKSVISITED", "Visited 
links")
+#define REG_SPELL                           NC_("REG_SPELL", "Spelling 
mistakes")
+#define REG_GRAMMAR                         NC_("REG_GRAMMAR", "Grammar")
+#define REG_SMARTTAGS                       NC_("REG_SMARTTAGS", "Smart tags")
+#define REG_SHADOW                          NC_("REG_SHADOW", "Shadows")
+#define REG_WRITERTEXTGRID                  NC_("REG_WRITERTEXTGRID", "Writer 
Text grid")
+#define REG_WRITERFIELDSHADINGS             NC_("REG_WRITERFIELDSHADINGS", 
"Writer Field shadings")
+#define REG_WRITERIDXSHADINGS               NC_("REG_WRITERIDXSHADINGS", 
"Writer Index and table shadings")
+#define REG_WRITERDIRECTCURSOR              NC_("REG_WRITERDIRECTCURSOR", 
"Writer Direct cursor")
+#define REG_WRITERSCRIPTINDICATOR           NC_("REG_WRITERSCRIPTINDICATOR", 
"Writer Script indicator")
+#define REG_WRITERSECTIONBOUNDARIES         NC_("REG_WRITERSECTIONBOUNDARIES", 
"Writer Section boundaries")
+#define REG_WRITERHEADERFOOTERMARK          NC_("REG_WRITERHEADERFOOTERMARK", 
"Writer Header and footer delimiter")
+#define REG_WRITERPAGEBREAKS                NC_("REG_WRITERPAGEBREAKS", 
"Writer Page and column breaks")
+#define REG_WRITERNONPRINTCHARS             NC_("REG_WRITERNONPRINTCHARS", 
"Writer Non-printable characters")
+#define REG_HTMLSGML                        NC_("REG_HTMLSGML", "HTML SGML 
syntax highlighting")
+#define REG_HTMLCOMMENT                     NC_("REG_HTMLCOMMENT", "HTML 
Comment highlighting")
+#define REG_HTMLKEYWORD                     NC_("REG_HTMLKEYWORD", "HTML 
Keyword highlighting")
+#define REG_HTMLUNKNOWN                     NC_("REG_HTMLUNKNOWN", "HTML Text 
Highlighting")
+#define REG_CALCGRID                        NC_("REG_CALCGRID", "Calc Grid")
+#define REG_CALCCELLFOCUS                   NC_("REG_CALCCELLFOCUS", "Calc 
Cell focus")
+#define REG_CALCPAGEBREAK                   NC_("REG_CALCPAGEBREAK", "Calc 
Page break")
+#define REG_CALCPAGEBREAKMANUAL             NC_("REG_CALCPAGEBREAKMANUAL", 
"Calc Manual page breaks")
+#define REG_CALCPAGEBREAKAUTOMATIC          NC_("REG_CALCPAGEBREAKAUTOMATIC", 
"Calc Automatic page breaks")
+#define REG_CALCHIDDENCOLROW                NC_("REG_CALCHIDDENCOLROW", "Calc 
Hidden column/row")
+#define REG_CALCTEXTOVERFLOW                NC_("REG_CALCTEXTOVERFLOW", "Calc 
Text overflow indicator")
+#define REG_CALCCOMMENTS                    NC_("REG_CALCCOMMENTS", "Calc 
Comments")
+#define REG_CALCDETECTIVE                   NC_("REG_CALCDETECTIVE", "Calc 
Detective")
+#define REG_CALCDETECTIVEERROR              NC_("REG_CALCDETECTIVEERROR", 
"Calc Detective error")
+#define REG_CALCREFERENCE                   NC_("REG_CALCREFERENCE", "Calc 
References")
+#define REG_CALCNOTESBACKGROUND             NC_("REG_CALCNOTESBACKGROUND", 
"Calc Notes background")
+#define REG_CALCVALUE                       NC_("REG_CALCVALUE", "Calc Values")
+#define REG_CALCFORMULA                     NC_("REG_CALCFORMULA", "Calc 
Formulas")
+#define REG_CALCTEXT                        NC_("REG_CALCTEXT", "Calc Text")
+#define REG_CALCPROTECTEDBACKGROUND         NC_("REG_CALCPROTECTEDBACKGROUND", 
"Calc Protected cells background")
+#define REG_DRAWGRID                        NC_("REG_DRAWGRID", "Draw Grid")
+#define REG_AUTHOR1                         NC_("REG_AUTHOR1", "Author1")
+#define REG_AUTHOR2                         NC_("REG_AUTHOR2", "Author2")
+#define REG_AUTHOR3                         NC_("REG_AUTHOR3", "Author3")
+#define REG_AUTHOR4                         NC_("REG_AUTHOR4", "Author4")
+#define REG_AUTHOR5                         NC_("REG_AUTHOR5", "Author5")
+#define REG_AUTHOR6                         NC_("REG_AUTHOR6", "Author6")
+#define REG_AUTHOR7                         NC_("REG_AUTHOR7", "Author7")
+#define REG_AUTHOR8                         NC_("REG_AUTHOR8", "Author8")
+#define REG_AUTHOR9                         NC_("REG_AUTHOR9", "Author9")
+#define REG_BASICEDITOR                     NC_("REG_BASICEDITOR", "BASIC 
Editor")
+#define REG_BASICIDENTIFIER                 NC_("REG_BASICIDENTIFIER", "BASIC 
Identifier")
+#define REG_BASICCOMMENT                    NC_("REG_BASICCOMMENT", "BASIC 
Comment")
+#define REG_BASICNUMBER                     NC_("REG_BASICNUMBER", "BASIC 
Number")
+#define REG_BASICSTRING                     NC_("REG_BASICSTRING", "BASIC 
String")
+#define REG_BASICOPERATOR                   NC_("REG_BASICOPERATOR", "BASIC 
Operator")
+#define REG_BASICKEYWORD                    NC_("REG_BASICKEYWORD", "BASIC 
Keyword")
+#define REG_BASICERROR                      NC_("REG_BASICERROR", "BASIC 
Error")
+#define REG_SQLIDENTIFIER                   NC_("REG_SQLIDENTIFIER", "SQL 
Identifier")
+#define REG_SQLNUMBER                       NC_("REG_SQLNUMBER", "SQL Number")
+#define REG_SQLSTRING                       NC_("REG_SQLSTRING", "SQL String")
+#define REG_SQLOPERATOR                     NC_("REG_SQLOPERATOR", "SQL 
Operator")
+#define REG_SQLKEYWORD                      NC_("REG_SQLKEYWORD", "SQL 
Keyword")
+#define REG_SQLPARAMETER                    NC_("REG_SQLPARAMETER", "SQL 
Parameter")
+#define REG_SQLCOMMENT                      NC_("REG_SQLCOMMENT", "SQL 
Comment")
+#define REG_WINDOWCOLOR                     NC_("REG_WINDOWCOLOR", "Window 
color")
+#define REG_WINDOWTEXTCOLOR                 NC_("REG_WINDOWTEXTCOLOR", "Window 
text color")
+#define REG_BASECOLOR                       NC_("REG_BASECOLOR", "Base color")
+#define REG_BUTTONCOLOR                     NC_("REG_BUTTONCOLOR", "Button 
color")
+#define REG_BUTTONTEXTCOLOR                 NC_("REG_BUTTONTEXTCOLOR", "Button 
text color")
+#define REG_ACCENTCOLOR                     NC_("REG_ACCENTCOLOR", "Accent 
color")
+#define REG_DISABLEDCOLOR                   NC_("REG_DISABLEDCOLOR", "Disabled 
color")
+#define REG_DISABLEDTEXTCOLOR               NC_("REG_DISABLEDTEXTCOLOR", 
"Disabled text color")
+#define REG_SHADOWCOLOR                     NC_("REG_SHADOWCOLOR", "Shadow 
color")
+#define REG_SEPARATORCOLOR                  NC_("REG_SEPARATORCOLOR", 
"Separator color")
+#define REG_FACECOLOR                       NC_("REG_FACECOLOR", "Face color")
+#define REG_ACTIVECOLOR                     NC_("REG_ACTIVECOLOR", "Active 
color")
+#define REG_ACTIVETEXTCOLOR                 NC_("REG_ACTIVETEXTCOLOR", "Active 
text color")
+#define REG_ACTIVEBORDERCOLOR               NC_("REG_ACTIVEBORDERCOLOR", 
"Active border color")
+#define REG_FIELDCOLOR                      NC_("REG_FIELDCOLOR", "Field 
color")
+#define REG_MENUBARCOLOR                    NC_("REG_MENUBARCOLOR", "Menu bar 
color")
+#define REG_MENUBARTEXTCOLOR                NC_("REG_MENUBARTEXTCOLOR", "Menu 
bar text color")
+#define REG_MENUBARHIGHLIGHTCOLOR           NC_("REG_MENUBARHIGHLIGHTCOLOR", 
"Menu bar highlight color")
+#define REG_MENUBARHIGHLIGHTTEXTCOLOR       
NC_("REG_MENUBARHIGHLIGHTTEXTCOLOR", "Menu bar highlight text color")
+#define REG_MENUCOLOR                       NC_("REG_MENUCOLOR", "Menu color")
+#define REG_MENUTEXTCOLOR                   NC_("REG_MENUTEXTCOLOR", "Menu 
text color")
+#define REG_MENUHIGHLIGHTCOLOR              NC_("REG_MENUHIGHLIGHTCOLOR", 
"Menu highlight color")
+#define REG_MENUHIGHLIGHTTEXTCOLOR          NC_("REG_MENUHIGHLIGHTTEXTCOLOR", 
"Menu highlight text color")
+#define REG_MENUBORDERCOLOR                 NC_("REG_MENUBORDERCOLOR", "Menu 
border color")
+#define REG_INACTIVECOLOR                   NC_("REG_INACTIVECOLOR", "Inactive 
color")
+#define REG_INACTIVETEXTCOLOR               NC_("REG_INACTIVETEXTCOLOR", 
"Inactive text color")
+#define REG_INACTIVEBORDERCOLOR             NC_("REG_INACTIVEBORDERCOLOR", 
"Inactive border color")
+
 // A11Y Options
 #define STR_NO_ALT_OLE                              NC_("STR_NO_ALT_OLE", 
"Check if the OLE object has an alternative name or description.")
 #define STR_NO_ALT_GRAPHIC                          NC_("STR_NO_ALT_GRAPHIC", 
"Check if the Graphic Object has an alternative name or description.")
diff --git a/cui/inc/treeopt.hrc b/cui/inc/treeopt.hrc
index e79a65eabb89..2b17970e9976 100644
--- a/cui/inc/treeopt.hrc
+++ b/cui/inc/treeopt.hrc
@@ -39,6 +39,7 @@ const std::pair<TranslateId, sal_uInt16> 
SID_GENERAL_OPTIONS_RES[] =
     { NC_("SID_GENERAL_OPTIONS_RES", "Paths"),  RID_SFXPAGE_PATH },
     { NC_("SID_GENERAL_OPTIONS_RES", "Fonts"), RID_SVX_FONT_SUBSTITUTION  },
     { NC_("SID_GENERAL_OPTIONS_RES", "Security"), RID_SVXPAGE_INET_SECURITY  },
+    { NC_("SID_GENERAL_OPTIONS_RES", "Appearance"), RID_SVXPAGE_APPEARANCE },
     { NC_("SID_GENERAL_OPTIONS_RES", "Accessibility"), 
RID_SVXPAGE_ACCESSIBILITYCONFIG  },
     { NC_("SID_GENERAL_OPTIONS_RES", "Advanced"), RID_SVXPAGE_OPTIONS_JAVA  },
     { NC_("SID_GENERAL_OPTIONS_RES", "Basic IDE"), 
RID_SVXPAGE_BASICIDE_OPTIONS  },
diff --git a/cui/qa/unit/data/cui-dialogs-test_4.txt 
b/cui/qa/unit/data/cui-dialogs-test_4.txt
index 8d751be0c26b..076b09e0b75b 100644
--- a/cui/qa/unit/data/cui-dialogs-test_4.txt
+++ b/cui/qa/unit/data/cui-dialogs-test_4.txt
@@ -18,6 +18,7 @@ cui/ui/paratabspage.ui
 cui/ui/password.ui
 cui/ui/pastespecial.ui
 cui/ui/percentdialog.ui
+cui/ui/appearance.ui
 cui/ui/pickbulletpage.ui
 cui/ui/pickgraphicpage.ui
 cui/ui/picknumberingpage.ui
diff --git a/cui/source/options/appearance.cxx 
b/cui/source/options/appearance.cxx
new file mode 100644
index 000000000000..e2cc7e8896a7
--- /dev/null
+++ b/cui/source/options/appearance.cxx
@@ -0,0 +1,719 @@
+/* -*- 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/.
+ */
+
+#include "appearance.hxx"
+#include <com/sun/star/uno/Sequence.hxx>
+#include <dialmgr.hxx>
+#include <helpids.h>
+#include <officecfg/Office/Common.hxx>
+#include <sfx2/objsh.hxx>
+#include <strings.hrc>
+#include <svtools/colorcfg.hxx>
+#include <svtools/restartdialog.hxx>
+#include <svx/itemwin.hxx>
+#include <svx/svxids.hrc>
+#include <tools/debug.hxx>
+#include <unotools/resmgr.hxx>
+#include <vcl/svapp.hxx>
+#include <comphelper/dispatchcommand.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <map>
+
+namespace
+{
+struct BitmapData
+{
+    OUString aTranslatedBitmapLabel;
+    OUString aBitmapFileName;
+};
+
+std::vector<BitmapData> m_aBitmapList = {
+    { CuiResId(BMP_FUZZY_LIGHTGREY), "fuzzy-lightgrey.jpg" },
+    { CuiResId(BMP_ICE_LIGHT), "ice-light.jpg" },
+    { CuiResId(BMP_PAINTED_WHITE), "painted-white.jpg" },
+    { CuiResId(BMP_TEXTURE_PAPER), "texture-paper.jpg" },
+    { CuiResId(BMP_CRUMPLED_PAPER), "crumpled-paper.jpg" },
+    { CuiResId(BMP_MARBLE), "marble.jpg" },
+    { CuiResId(BMP_CONCRETE), "concrete.jpg" },
+    { CuiResId(BMP_FUZZY_GREY), "fuzzy-grey.jpg" },
+    { CuiResId(BMP_FUZZY_DARKGREY), "fuzzy-darkgrey.jpg" },
+    { CuiResId(BMP_STONE), "stone.jpg" },
+    { CuiResId(BMP_WHITE_DIFFUSION), "white-diffusion.jpg" },
+    { CuiResId(BMP_SAND_LIGHT), "sand-light.jpg" },
+    { CuiResId(BMP_SAND), "sand.jpg" },
+    { CuiResId(BMP_SURFACE), "surface.jpg" },
+    { CuiResId(BMP_STUDIO), "studio.jpg" },
+    { CuiResId(BMP_INVOICE_PAPER), "invoice-paper.jpg" },
+    { CuiResId(BMP_PARCHMENT_PAPER), "parchment-paper.jpg" },
+    { CuiResId(BMP_CARDBOARD), "cardboard.jpg" },
+    { CuiResId(BMP_FENCE), "fence.jpg" },
+    { CuiResId(BMP_WOODEN_FENCE), "wooden-fence.jpg" },
+    { CuiResId(BMP_WOOD), "wood.jpg" },
+    { CuiResId(BMP_WOODEN_BOARD), "wooden-board.jpg" },
+    { CuiResId(BMP_PAINTED_WOOD), "painted-wood.jpg" },
+    { CuiResId(BMP_STONES), "stones.jpg" },
+    { CuiResId(BMP_PEBBLE_LIGHT), "pebble-light.jpg" },
+    { CuiResId(BMP_STONE_WALL), "stone-wall.jpg" },
+    { CuiResId(BMP_STONE_GRAY), "stone-gray.jpg" },
+    { CuiResId(BMP_ROCK_WALL), "rock-wall.jpg" },
+    { CuiResId(BMP_SURFACE_BLACK), "surface-black.jpg" },
+    { CuiResId(BMP_BRICK_WALL), "brick-wall.png" },
+    { CuiResId(BMP_TILES), "tiles.jpg" },
+    { CuiResId(BMP_GRAPH_PAPER), "graph-paper.png" },
+    { CuiResId(BMP_CLOUD), "cloud.jpg" },
+    { CuiResId(BMP_POOL), "pool.jpg" },
+    { CuiResId(BMP_SKY), "sky.jpg" },
+    { CuiResId(BMP_CIRCUIT_BOARD), "circuit-board.jpg" },
+    { CuiResId(BMP_COFFEE), "coffee.jpg" },
+    { CuiResId(BMP_COLOR_STRIPES), "color-stripes.png" },
+    { CuiResId(BMP_FLORAL), "floral.png" },
+    { CuiResId(BMP_LEAF), "leaf.jpg" },
+    { CuiResId(BMP_MAPLE_LEAVES), "maple-leaves.jpg" },
+    { CuiResId(BMP_SPACE), "space.png" },
+    { CuiResId(BMP_GIRAFFE), "giraffe.png" },
+    { CuiResId(BMP_TIGER), "tiger.jpg" },
+    { CuiResId(BMP_ZEBRA), "zebra.png" },
+};
+
+std::map<ColorConfigEntry, OUString> m_aRegistryEntries
+    = { { DOCCOLOR, CuiResId(REG_DOCCOLOR) },
+        { DOCBOUNDARIES, CuiResId(REG_DOCBOUNDARIES) },
+        { APPBACKGROUND, CuiResId(REG_APPBACKGROUND) },
+        { TABLEBOUNDARIES, CuiResId(REG_TABLEBOUNDARIES) },
+        { FONTCOLOR, CuiResId(REG_FONTCOLOR) },
+        { LINKS, CuiResId(REG_LINKS) },
+        { LINKSVISITED, CuiResId(REG_LINKSVISITED) },
+        { SPELL, CuiResId(REG_SPELL) },
+        { GRAMMAR, CuiResId(REG_GRAMMAR) },
+        { SMARTTAGS, CuiResId(REG_SMARTTAGS) },
+        { SHADOWCOLOR, CuiResId(REG_SHADOW) },
+        { WRITERTEXTGRID, CuiResId(REG_WRITERTEXTGRID) },
+        { WRITERFIELDSHADINGS, CuiResId(REG_WRITERFIELDSHADINGS) },
+        { WRITERIDXSHADINGS, CuiResId(REG_WRITERIDXSHADINGS) },
+        { WRITERDIRECTCURSOR, CuiResId(REG_WRITERDIRECTCURSOR) },
+        { WRITERSCRIPTINDICATOR, CuiResId(REG_WRITERSCRIPTINDICATOR) },
+        { WRITERSECTIONBOUNDARIES, CuiResId(REG_WRITERSECTIONBOUNDARIES) },
+        { WRITERHEADERFOOTERMARK, CuiResId(REG_WRITERHEADERFOOTERMARK) },
+        { WRITERPAGEBREAKS, CuiResId(REG_WRITERPAGEBREAKS) },
+        { WRITERNONPRINTCHARS, CuiResId(REG_WRITERNONPRINTCHARS) },
+        { HTMLSGML, CuiResId(REG_HTMLSGML) },
+        { HTMLCOMMENT, CuiResId(REG_HTMLCOMMENT) },
+        { HTMLKEYWORD, CuiResId(REG_HTMLKEYWORD) },
+        { HTMLUNKNOWN, CuiResId(REG_HTMLUNKNOWN) },
+        { CALCGRID, CuiResId(REG_CALCGRID) },
+        { CALCCELLFOCUS, CuiResId(REG_CALCCELLFOCUS) },
+        { CALCPAGEBREAK, CuiResId(REG_CALCPAGEBREAK) },
+        { CALCPAGEBREAKMANUAL, CuiResId(REG_CALCPAGEBREAKMANUAL) },
+        { CALCPAGEBREAKAUTOMATIC, CuiResId(REG_CALCPAGEBREAKAUTOMATIC) },
+        { CALCHIDDENROWCOL, CuiResId(REG_CALCHIDDENCOLROW) },
+        { CALCTEXTOVERFLOW, CuiResId(REG_CALCTEXTOVERFLOW) },
+        { CALCCOMMENTS, CuiResId(REG_CALCCOMMENTS) },
+        { CALCDETECTIVE, CuiResId(REG_CALCDETECTIVE) },
+        { CALCDETECTIVEERROR, CuiResId(REG_CALCDETECTIVEERROR) },
+        { CALCREFERENCE, CuiResId(REG_CALCREFERENCE) },
+        { CALCNOTESBACKGROUND, CuiResId(REG_CALCNOTESBACKGROUND) },
+        { CALCVALUE, CuiResId(REG_CALCVALUE) },
+        { CALCFORMULA, CuiResId(REG_CALCFORMULA) },
+        { CALCTEXT, CuiResId(REG_CALCTEXT) },
+        { CALCPROTECTEDBACKGROUND, CuiResId(REG_CALCPROTECTEDBACKGROUND) },
+        { DRAWGRID, CuiResId(REG_DRAWGRID) },
+        { AUTHOR1, CuiResId(REG_AUTHOR1) },
+        { AUTHOR2, CuiResId(REG_AUTHOR2) },
+        { AUTHOR3, CuiResId(REG_AUTHOR3) },
+        { AUTHOR4, CuiResId(REG_AUTHOR4) },
+        { AUTHOR5, CuiResId(REG_AUTHOR5) },
+        { AUTHOR6, CuiResId(REG_AUTHOR6) },
+        { AUTHOR7, CuiResId(REG_AUTHOR7) },
+        { AUTHOR8, CuiResId(REG_AUTHOR8) },
+        { AUTHOR9, CuiResId(REG_AUTHOR9) },
+        { BASICEDITOR, CuiResId(REG_BASICEDITOR) },
+        { BASICIDENTIFIER, CuiResId(REG_BASICIDENTIFIER) },
+        { BASICCOMMENT, CuiResId(REG_BASICCOMMENT) },
+        { BASICNUMBER, CuiResId(REG_BASICNUMBER) },
+        { BASICSTRING, CuiResId(REG_BASICSTRING) },
+        { BASICOPERATOR, CuiResId(REG_BASICOPERATOR) },
+        { BASICKEYWORD, CuiResId(REG_BASICKEYWORD) },
+        { BASICERROR, CuiResId(REG_BASICERROR) },
+        { SQLIDENTIFIER, CuiResId(REG_SQLIDENTIFIER) },
+        { SQLNUMBER, CuiResId(REG_SQLNUMBER) },
+        { SQLSTRING, CuiResId(REG_SQLSTRING) },
+        { SQLOPERATOR, CuiResId(REG_SQLOPERATOR) },
+        { SQLKEYWORD, CuiResId(REG_SQLKEYWORD) },
+        { SQLPARAMETER, CuiResId(REG_SQLPARAMETER) },
+        { SQLCOMMENT, CuiResId(REG_SQLCOMMENT) },
+        { WINDOWCOLOR, CuiResId(REG_WINDOWCOLOR) },
+        { WINDOWTEXTCOLOR, CuiResId(REG_WINDOWTEXTCOLOR) },
+        { BASECOLOR, CuiResId(REG_BASECOLOR) },
+        { BUTTONCOLOR, CuiResId(REG_BUTTONCOLOR) },
+        { BUTTONTEXTCOLOR, CuiResId(REG_BUTTONTEXTCOLOR) },
+        { ACCENTCOLOR, CuiResId(REG_ACCENTCOLOR) },
+        { DISABLEDCOLOR, CuiResId(REG_DISABLEDCOLOR) },
+        { DISABLEDTEXTCOLOR, CuiResId(REG_DISABLEDTEXTCOLOR) },
+        { SHADECOLOR, CuiResId(REG_SHADOWCOLOR) },
+        { SEPARATORCOLOR, CuiResId(REG_SEPARATORCOLOR) },
+        { FACECOLOR, CuiResId(REG_FACECOLOR) },
+        { ACTIVECOLOR, CuiResId(REG_ACTIVECOLOR) },
+        { ACTIVETEXTCOLOR, CuiResId(REG_ACTIVETEXTCOLOR) },
+        { ACTIVEBORDERCOLOR, CuiResId(REG_ACTIVEBORDERCOLOR) },
+        { FIELDCOLOR, CuiResId(REG_FIELDCOLOR) },
+        { MENUBARCOLOR, CuiResId(REG_MENUBARCOLOR) },
+        { MENUBARTEXTCOLOR, CuiResId(REG_MENUBARTEXTCOLOR) },
+        { MENUBARHIGHLIGHTCOLOR, CuiResId(REG_MENUBARHIGHLIGHTCOLOR) },
+        { MENUBARHIGHLIGHTTEXTCOLOR, CuiResId(REG_MENUBARHIGHLIGHTTEXTCOLOR) },
+        { MENUCOLOR, CuiResId(REG_MENUCOLOR) },
+        { MENUTEXTCOLOR, CuiResId(REG_MENUTEXTCOLOR) },
+        { MENUHIGHLIGHTCOLOR, CuiResId(REG_MENUHIGHLIGHTCOLOR) },
+        { MENUHIGHLIGHTTEXTCOLOR, CuiResId(REG_MENUHIGHLIGHTTEXTCOLOR) },
+        { MENUBORDERCOLOR, CuiResId(REG_MENUBORDERCOLOR) },
+        { INACTIVECOLOR, CuiResId(REG_INACTIVECOLOR) },
+        { INACTIVETEXTCOLOR, CuiResId(REG_INACTIVETEXTCOLOR) },
+        { INACTIVEBORDERCOLOR, CuiResId(REG_INACTIVEBORDERCOLOR) } };
+}
+
+SvxAppearanceTabPage::SvxAppearanceTabPage(weld::Container* pPage,
+                                           weld::DialogController* pController,
+                                           const SfxItemSet& rSet)
+    : SfxTabPage(pPage, pController, u"cui/ui/appearance.ui"_ustr, 
u"AppearanceTabPage"_ustr, &rSet)
+    , m_bRestartRequired(false)
+    , pColorConfig(new EditableColorConfig)
+    , m_xSchemeList(m_xBuilder->weld_combo_box(u"scheme"_ustr))
+    , m_xMoreThemesBtn(m_xBuilder->weld_button(u"morethemesbtn"_ustr))
+    , m_xAddSchemeBtn(m_xBuilder->weld_button(u"newschemebtn"_ustr))
+    , m_xRemoveSchemeBtn(m_xBuilder->weld_button(u"removeschemebtn"_ustr))
+    , m_xAppearanceSystem(m_xBuilder->weld_radio_button(u"system"_ustr))
+    , m_xAppearanceLight(m_xBuilder->weld_radio_button(u"light"_ustr))
+    , m_xAppearanceDark(m_xBuilder->weld_radio_button(u"dark"_ustr))
+    , m_xColorEntryBtn(m_xBuilder->weld_combo_box(u"registrydropdown"_ustr))
+    , m_xColorChangeBtn((new 
ColorListBox(m_xBuilder->weld_menu_button(u"colorsdropdownbtn"_ustr),
+                                          [this] { return GetFrameWeld(); })))
+    , m_xColorLbl(m_xBuilder->weld_label(u"colorlbl"_ustr))
+    , 
m_xShowInDocumentChkBtn(m_xBuilder->weld_check_button(u"showindocumentchkbtn"_ustr))
+    , m_xColorRadioBtn(m_xBuilder->weld_radio_button(u"colorradiobtn"_ustr))
+    , m_xImageRadioBtn(m_xBuilder->weld_radio_button(u"imageradiobtn"_ustr))
+    , 
m_xStretchedRadioBtn(m_xBuilder->weld_radio_button(u"stretchedradiobtn"_ustr))
+    , m_xTiledRadioBtn(m_xBuilder->weld_radio_button(u"tiledradiobtn"_ustr))
+    , m_xBitmapDropDownBtn(m_xBuilder->weld_combo_box(u"bitmapdropdown"_ustr))
+{
+    InitThemes();
+    InitAppearance();
+    InitCustomization();
+    UpdateControlsState();
+}
+
+void SvxAppearanceTabPage::UpdateControlsState()
+{
+    // in case of AUTOMATIC_COLOR_SCHEME, disable all the controls
+    bool bEnableControls = m_xSchemeList->get_active_id() != 
AUTOMATIC_COLOR_SCHEME;
+    m_xAppearanceSystem->set_sensitive(bEnableControls);
+    m_xAppearanceLight->set_sensitive(bEnableControls);
+    m_xAppearanceDark->set_sensitive(bEnableControls);
+    m_xColorEntryBtn->set_sensitive(bEnableControls);
+    m_xColorChangeBtn->set_sensitive(bEnableControls);
+    m_xShowInDocumentChkBtn->set_sensitive(bEnableControls);
+    m_xColorRadioBtn->set_sensitive(bEnableControls);
+    EnableImageControls(bEnableControls && GetActiveEntry() == 
static_cast<int>(APPBACKGROUND));
+}
+
+void SvxAppearanceTabPage::LoadSchemeList()
+{
+    m_xSchemeList->clear();
+    css::uno::Sequence<OUString> aSchemeNames = pColorConfig->GetSchemeNames();
+    for (size_t i = 0; i < aSchemeNames.size(); ++i)
+    {
+        if (aSchemeNames[i] != AUTOMATIC_COLOR_SCHEME)
+            m_xSchemeList->insert(i, aSchemeNames[i], nullptr, nullptr, 
nullptr);
+    }
+    m_xSchemeList->insert(0, CuiResId(RID_COLOR_SCHEME_LIBREOFFICE_AUTOMATIC),
+                          &AUTOMATIC_COLOR_SCHEME, nullptr, nullptr);
+
+    if (pColorConfig->GetCurrentSchemeName() == AUTOMATIC_COLOR_SCHEME)
+        m_xSchemeList->set_active_id(AUTOMATIC_COLOR_SCHEME);
+    else
+        m_xSchemeList->set_active_text(pColorConfig->GetCurrentSchemeName());
+}
+
+SvxAppearanceTabPage::~SvxAppearanceTabPage()
+{
+    if (m_bRestartRequired)
+        
::svtools::executeRestartDialog(comphelper::getProcessComponentContext(), 
GetFrameWeld(),
+                                        svtools::RESTART_REASON_THEME_CHANGE);
+}
+
+std::unique_ptr<SfxTabPage> SvxAppearanceTabPage::Create(weld::Container* 
pPage,
+                                                         
weld::DialogController* pController,
+                                                         const SfxItemSet* 
rSet)
+{
+    return std::make_unique<SvxAppearanceTabPage>(pPage, pController, *rSet);
+}
+
+OUString SvxAppearanceTabPage::GetAllStrings()
+{
+    OUString sAllStrings;
+    OUString labels[] = { u"libreofficethemeslb"_ustr, u"optionslb"_ustr, 
u"appearancelb"_ustr,
+                          u"itemslb"_ustr, u"colorlb"_ustr };
+
+    for (const auto& label : labels)
+    {
+        if (const auto pString = m_xBuilder->weld_label(label))
+            sAllStrings += pString->get_label() + " ";
+    }
+
+    return sAllStrings.replaceAll("_", "");
+}
+
+bool SvxAppearanceTabPage::FillItemSet(SfxItemSet* /* rSet */)
+{
+    // commit appearance value
+    if (eCurrentAppearanceMode != 
static_cast<Appearance>(MiscSettings::GetAppColorMode()))
+    {
+        
MiscSettings::SetAppColorMode(static_cast<int>(eCurrentAppearanceMode));
+        m_bRestartRequired = true;
+    }
+
+    // commit ColorConfig
+    if (pColorConfig->IsModified())
+        pColorConfig->Commit();
+
+    // commit LibreOfficeTheme, enable it if the current scheme is not 
Automatic
+    if (m_xSchemeList->get_value_changed_from_saved())
+    {
+        bool bIsLibreOfficeThemeEnabled = m_xSchemeList->get_active_id() != 
AUTOMATIC_COLOR_SCHEME;
+        auto pChange(comphelper::ConfigurationChanges::create());
+        
officecfg::Office::Common::Appearance::LibreOfficeTheme::set(bIsLibreOfficeThemeEnabled,
+                                                                     pChange);
+        pChange->commit();
+    }
+
+    return true;
+}
+
+void SvxAppearanceTabPage::Reset(const SfxItemSet* /* rSet */)
+{
+    // reset scheme list
+    LoadSchemeList();
+
+    m_xSchemeList->set_sensitive(
+        
!officecfg::Office::Common::Appearance::ApplicationAppearance::isReadOnly());
+    m_xSchemeList->save_value();
+
+    UpdateRemoveBtnState();
+
+    // reset appearance
+    eCurrentAppearanceMode = 
static_cast<Appearance>(MiscSettings::GetAppColorMode());
+
+    // reset ColorConfig
+    if (pColorConfig)
+    {
+        pColorConfig->ClearModified();
+        pColorConfig->DisableBroadcast();
+    }
+    pColorConfig.reset(new EditableColorConfig);
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, ShowInDocumentHdl, weld::Toggleable&, 
void)
+{
+    // get selected entry index and ColorConfigValue
+    size_t nEntry = GetActiveEntry();
+    ColorConfigValue aCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    // set colorconfig value
+    aCurrentEntryColor.bIsVisible = m_xShowInDocumentChkBtn->get_active();
+    pColorConfig->SetColorValue(static_cast<ColorConfigEntry>(nEntry), 
aCurrentEntryColor);
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, AppearanceChangeHdl, weld::Toggleable&, 
void)
+{
+    if (m_xAppearanceSystem->get_state() == TRISTATE_TRUE)
+        eCurrentAppearanceMode = Appearance::SYSTEM;
+    if (m_xAppearanceLight->get_state() == TRISTATE_TRUE)
+        eCurrentAppearanceMode = Appearance::LIGHT;
+    if (m_xAppearanceDark->get_state() == TRISTATE_TRUE)
+        eCurrentAppearanceMode = Appearance::DARK;
+    // set the extension theme on light/dark
+
+    UpdateColorDropdown();
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, ColorEntryChgHdl, weld::ComboBox&, void)
+{
+    // get selected entry index and ColorConfigValue
+    size_t nEntry = GetActiveEntry();
+    const ColorConfigValue& rCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    // set automatic colors
+    m_xColorChangeBtn->SetAutoDisplayColor(
+        ColorConfig::GetDefaultColor(static_cast<ColorConfigEntry>(nEntry)));
+    // set values for the entry
+    if (IsDarkModeEnabled())
+        m_xColorChangeBtn->SelectEntry(rCurrentEntryColor.nDarkColor);
+    else
+        m_xColorChangeBtn->SelectEntry(rCurrentEntryColor.nLightColor);
+
+    m_xShowInDocumentChkBtn->set_active(rCurrentEntryColor.bIsVisible);
+
+    // load image related settings if supported
+    if (cNames[nEntry].bCanHaveBitmap)
+    {
+        EnableImageControls(true);
+        m_xImageRadioBtn->set_active(rCurrentEntryColor.bUseBitmapBackground);
+        
m_xStretchedRadioBtn->set_active(rCurrentEntryColor.bIsBitmapStretched);
+
+        // bitmap file name to translated label
+        size_t i;
+        for (i = 0; i < m_aBitmapList.size(); ++i)
+        {
+            if (rCurrentEntryColor.sBitmapFileName == 
m_aBitmapList[i].aBitmapFileName)
+                break;
+        }
+
+        // if bitmap not in the list then reset to 0
+        if (i == m_aBitmapList.size())
+            i = 0;
+
+        m_xBitmapDropDownBtn->set_active(i);
+    }
+    else
+    {
+        m_xColorRadioBtn->set_active(true);
+        EnableImageControls(false);
+    }
+
+    // show/hide show in document button
+    if (!cNames[nEntry].bCanBeVisible)
+        m_xShowInDocumentChkBtn->hide();
+    else
+        m_xShowInDocumentChkBtn->show();
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, ColorValueChgHdl, ColorListBox&, void)
+{
+    // get the active entry
+    size_t nEntry = GetActiveEntry();
+    ColorConfigValue aCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    // restart only for the UI colors
+    if (nEntry >= WINDOWCOLOR)
+        m_bRestartRequired = true;
+
+    // set the color in pColorConfig
+    if (IsDarkModeEnabled())
+        aCurrentEntryColor.nDarkColor = 
m_xColorChangeBtn->GetSelectEntryColor();
+    else
+        aCurrentEntryColor.nLightColor = 
m_xColorChangeBtn->GetSelectEntryColor();
+
+    // use nColor for caching the value of color in use. This avoids tidious 
refactoring which IMO
+    // would use function calls to discriminate between colors. those 
functions themself call some virtual functions
+    // making the whole thing super slow (comparatively).
+    aCurrentEntryColor.nColor = m_xColorChangeBtn->GetSelectEntryColor();
+
+    pColorConfig->SetColorValue(static_cast<ColorConfigEntry>(nEntry), 
aCurrentEntryColor);
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, SchemeChangeHdl, weld::ComboBox&, void)
+{
+    if (m_xSchemeList->get_active_id() == AUTOMATIC_COLOR_SCHEME)
+        pColorConfig->LoadScheme(AUTOMATIC_COLOR_SCHEME);
+    else
+        pColorConfig->LoadScheme(m_xSchemeList->get_active_text());
+
+    if (m_xSchemeList->get_value_changed_from_saved())
+        m_bRestartRequired = true;
+
+    UpdateControlsState();
+    UpdateRemoveBtnState();
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, SchemeListToggleHdl, weld::ComboBox&, 
void)
+{
+    LoadSchemeList();
+}
+
+IMPL_LINK(SvxAppearanceTabPage, CheckNameHdl_Impl, AbstractSvxNameDialog&, 
rDialog, bool)
+{
+    OUString sName = rDialog.GetName();
+    return !sName.isEmpty() && m_xSchemeList->find_text(sName) == -1;
+}
+
+IMPL_STATIC_LINK_NOARG(SvxAppearanceTabPage, MoreThemesHdl, weld::Button&, 
void)
+{
+    css::uno::Sequence<css::beans::PropertyValue> aArgs{ 
comphelper::makePropertyValue(
+        u"AdditionsTag"_ustr, u"Themes"_ustr) };
+    comphelper::dispatchCommand(u".uno:AdditionsDialog"_ustr, aArgs);
+}
+
+IMPL_LINK(SvxAppearanceTabPage, AddRemoveSchemeHdl, weld::Button&, rButton, 
void)
+{
+    if (m_xAddSchemeBtn.get() == &rButton)
+    {
+        OUString sName;
+        SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+        ScopedVclPtr<AbstractSvxNameDialog> 
aNameDlg(pFact->CreateSvxNameDialog(
+            GetFrameWeld(), sName, CuiResId(RID_CUISTR_COLOR_CONFIG_SAVE2)));
+        aNameDlg->SetCheckNameHdl(LINK(this, SvxAppearanceTabPage, 
CheckNameHdl_Impl));
+        aNameDlg->SetText(CuiResId(RID_CUISTR_COLOR_CONFIG_SAVE1));
+        aNameDlg->SetHelpId(HID_OPTIONS_COLORCONFIG_SAVE_SCHEME);
+        aNameDlg->SetCheckNameHdl(LINK(this, SvxAppearanceTabPage, 
CheckNameHdl_Impl));
+        if (RET_OK == aNameDlg->Execute())
+        {
+            sName = aNameDlg->GetName();
+            pColorConfig->AddScheme(sName);
+            m_xSchemeList->append_text(sName);
+            m_xSchemeList->set_active_text(sName);
+            SchemeChangeHdl(*m_xSchemeList);
+        }
+    }
+    else
+    {
+        DBG_ASSERT(m_xSchemeList->get_count() > 1, "don't delete the last 
scheme");
+        std::unique_ptr<weld::MessageDialog> 
xQuery(Application::CreateMessageDialog(
+            GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
+            CuiResId(RID_CUISTR_COLOR_CONFIG_DELETE)));
+        xQuery->set_title(CuiResId(RID_CUISTR_COLOR_CONFIG_DELETE_TITLE));
+
+        if (RET_YES == xQuery->run())
+        {
+            OUString sDeleteScheme(m_xSchemeList->get_active_text());
+            m_xSchemeList->remove(m_xSchemeList->get_active());
+            m_xSchemeList->set_active(0);
+            SchemeChangeHdl(*m_xSchemeList);
+            //first select the new scheme and then delete the old one
+            pColorConfig->DeleteScheme(sDeleteScheme);
+        }
+    }
+
+    // disable remove button if only one scheme available
+    // or if the selected theme is AUTOMATIC_COLOR_SCHEME
+    UpdateRemoveBtnState();
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, ColorImageToggleHdl, weld::Toggleable&, 
void)
+{
+    // get the active entry
+    size_t nEntry = GetActiveEntry();
+    ColorConfigValue aCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    aCurrentEntryColor.bUseBitmapBackground = !m_xColorRadioBtn->get_active();
+    pColorConfig->SetColorValue(static_cast<ColorConfigEntry>(nEntry), 
aCurrentEntryColor);
+    m_bRestartRequired = true;
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, StretchedTiledToggleHdl, 
weld::Toggleable&, void)
+{
+    // get the active entry
+    size_t nEntry = GetActiveEntry();
+    ColorConfigValue aCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    aCurrentEntryColor.bIsBitmapStretched = m_xStretchedRadioBtn->get_active();
+
+    pColorConfig->SetColorValue(static_cast<ColorConfigEntry>(nEntry), 
aCurrentEntryColor);
+    m_bRestartRequired = true;
+}
+
+IMPL_LINK_NOARG(SvxAppearanceTabPage, BitmapChangeHdl, weld::ComboBox&, void)
+{
+    // get the active entry
+    size_t nEntry = GetActiveEntry();
+    ColorConfigValue aCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    // save the bitmap file name
+    aCurrentEntryColor.sBitmapFileName
+        = m_aBitmapList[m_xBitmapDropDownBtn->get_active()].aBitmapFileName;
+
+    pColorConfig->SetColorValue(static_cast<ColorConfigEntry>(nEntry), 
aCurrentEntryColor);
+    m_bRestartRequired = true;
+}
+
+void SvxAppearanceTabPage::InitThemes()
+{
+    // init schemes combobox
+    LoadSchemeList();
+
+    m_xSchemeList->connect_changed(LINK(this, SvxAppearanceTabPage, 
SchemeChangeHdl));
+    m_xSchemeList->connect_popup_toggled(LINK(this, SvxAppearanceTabPage, 
SchemeListToggleHdl));
+    m_xAddSchemeBtn->connect_clicked(LINK(this, SvxAppearanceTabPage, 
AddRemoveSchemeHdl));
+    m_xMoreThemesBtn->connect_clicked(LINK(this, SvxAppearanceTabPage, 
MoreThemesHdl));
+    m_xRemoveSchemeBtn->connect_clicked(LINK(this, SvxAppearanceTabPage, 
AddRemoveSchemeHdl));
+
+    UpdateRemoveBtnState();
+}
+
+void SvxAppearanceTabPage::InitAppearance()
+{
+    m_xAppearanceSystem->connect_toggled(LINK(this, SvxAppearanceTabPage, 
AppearanceChangeHdl));
+    m_xAppearanceDark->connect_toggled(LINK(this, SvxAppearanceTabPage, 
AppearanceChangeHdl));
+
+    Appearance nAppearance = 
static_cast<Appearance>(MiscSettings::GetAppColorMode());
+    switch (nAppearance)
+    {
+        case Appearance::SYSTEM:
+            m_xAppearanceSystem->set_state(TRISTATE_TRUE);
+            eCurrentAppearanceMode = Appearance::SYSTEM;
+            break;
+        case Appearance::LIGHT:
+            m_xAppearanceLight->set_state(TRISTATE_TRUE);
+            eCurrentAppearanceMode = Appearance::LIGHT;
+            break;
+        case Appearance::DARK:
+            m_xAppearanceDark->set_state(TRISTATE_TRUE);
+            eCurrentAppearanceMode = Appearance::DARK;
+            break;
+    }
+}
+
+void SvxAppearanceTabPage::InitCustomization()
+{
+    m_xColorEntryBtn->connect_changed(LINK(this, SvxAppearanceTabPage, 
ColorEntryChgHdl));
+    m_xColorChangeBtn->SetSelectHdl(LINK(this, SvxAppearanceTabPage, 
ColorValueChgHdl));
+    m_xShowInDocumentChkBtn->connect_toggled(LINK(this, SvxAppearanceTabPage, 
ShowInDocumentHdl));
+    m_xBitmapDropDownBtn->connect_changed(LINK(this, SvxAppearanceTabPage, 
BitmapChangeHdl));
+
+    m_xColorRadioBtn->connect_toggled(LINK(this, SvxAppearanceTabPage, 
ColorImageToggleHdl));
+    m_xStretchedRadioBtn->connect_toggled(
+        LINK(this, SvxAppearanceTabPage, StretchedTiledToggleHdl));
+
+    FillItemsList();
+
+    m_xColorChangeBtn->SetSlotId(SID_ATTR_CHAR_COLOR);
+    m_xColorEntryBtn->set_active(DOCCOLOR);
+    UpdateColorDropdown();
+
+    
m_xShowInDocumentChkBtn->set_active(pColorConfig->GetColorValue(DOCCOLOR).bIsVisible);
+    m_xShowInDocumentChkBtn->hide();
+
+    // load bitmap names
+    for (size_t i = 0; i < m_aBitmapList.size(); ++i)
+        
m_xBitmapDropDownBtn->append_text(m_aBitmapList[i].aTranslatedBitmapLabel);
+    m_xBitmapDropDownBtn->set_active(0);
+
+    // DOCCOLOR uses color, so image controls are disabled
+    m_xColorRadioBtn->set_active(true);
+    EnableImageControls(false);
+}
+
+// disable remove if only one scheme available or if the selected theme is 
AUTOMATIC_COLOR_SCHEME
+void SvxAppearanceTabPage::UpdateRemoveBtnState()
+{
+    bool bEnableRemoveButton = (m_xSchemeList->get_count() > 1)
+                               && (m_xSchemeList->get_active_id() != 
AUTOMATIC_COLOR_SCHEME);
+    m_xRemoveSchemeBtn->set_sensitive(bEnableRemoveButton);
+}
+
+void SvxAppearanceTabPage::EnableImageControls(bool bEnabled)
+{
+    m_xImageRadioBtn->set_sensitive(bEnabled);
+    m_xStretchedRadioBtn->set_sensitive(bEnabled);
+    m_xTiledRadioBtn->set_sensitive(bEnabled);
+    m_xBitmapDropDownBtn->set_sensitive(bEnabled);
+}
+
+void SvxAppearanceTabPage::UpdateColorDropdown()
+{
+    switch (eCurrentAppearanceMode)
+    {
+        case Appearance::LIGHT:
+            m_xColorLbl->set_label(CuiResId(LIGHT_COLOR_LBL));
+            break;
+        case Appearance::DARK:
+            m_xColorLbl->set_label(CuiResId(DARK_COLOR_LBL));
+            break;
+        case Appearance::SYSTEM:
+        {
+            if (IsDarkModeEnabled())
+                m_xColorLbl->set_label(CuiResId(DARK_COLOR_LBL));
+            else
+                m_xColorLbl->set_label(CuiResId(LIGHT_COLOR_LBL));
+        }
+        break;
+    }
+
+    // update color to light/dark
+    size_t nEntry = GetActiveEntry();
+    const ColorConfigValue& rCurrentEntryColor
+        = pColorConfig->GetColorValue(static_cast<ColorConfigEntry>(nEntry));
+
+    // set automatic colors
+    m_xColorChangeBtn->SetAutoDisplayColor(
+        ColorConfig::GetDefaultColor(static_cast<ColorConfigEntry>(nEntry)));
+    // set values for the entry
+    if (IsDarkModeEnabled())
+        m_xColorChangeBtn->SelectEntry(rCurrentEntryColor.nDarkColor);
+    else
+        m_xColorChangeBtn->SelectEntry(rCurrentEntryColor.nLightColor);
+}
+
+bool SvxAppearanceTabPage::IsDarkModeEnabled()
+{
+    return eCurrentAppearanceMode == Appearance::DARK
+           || (eCurrentAppearanceMode == Appearance::SYSTEM && 
MiscSettings::GetUseDarkMode());
+}
+
+void SvxAppearanceTabPage::FillItemsList()
+{
+    for (size_t i = DOCCOLOR; i <= SHADOWCOLOR; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = WRITERTEXTGRID; i <= WRITERNONPRINTCHARS; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = HTMLSGML; i <= HTMLUNKNOWN; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = CALCGRID; i <= CALCPROTECTEDBACKGROUND; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    m_xColorEntryBtn->append(OUString(cNames[DRAWGRID].cName), 
m_aRegistryEntries[DRAWGRID]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = AUTHOR1; i <= AUTHOR9; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = BASICEDITOR; i <= BASICERROR; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = SQLIDENTIFIER; i <= SQLCOMMENT; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+    m_xColorEntryBtn->append_separator("SeparatorID");
+
+    for (size_t i = WINDOWCOLOR; i <= INACTIVEBORDERCOLOR; ++i)
+        m_xColorEntryBtn->append(OUString(cNames[i].cName),
+                                 
m_aRegistryEntries[static_cast<ColorConfigEntry>(i)]);
+}
+
+size_t SvxAppearanceTabPage::GetActiveEntry()
+{
+    OUString sEntryId = m_xColorEntryBtn->get_active_id();
+    int nEntry = 0;
+    for (; nEntry < ColorConfigEntryCount; ++nEntry)
+    {
+        if (sEntryId == cNames[nEntry].cName)
+            break;
+    }
+    return nEntry;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/options/appearance.hxx 
b/cui/source/options/appearance.hxx
new file mode 100644
index 000000000000..05d9a99b52c5
--- /dev/null
+++ b/cui/source/options/appearance.hxx
@@ -0,0 +1,106 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <svx/colorbox.hxx>
+#include <svx/xflasit.hxx>
+#include <svx/svxdlg.hxx>
+#include <svtools/colorcfg.hxx>
+
+/*
+ * SYSTEM       ==> the application will use either light or dark colors from 
a theme based on
+ *                  whether the system is in light mode or in dark mode
+ *
+ * LIGHT/DARK   ==> light/dark theme colors
+ *
+ * Note that Appearance settings have nothing to do with the themes, these 
just specify which one
+ * of the theme colors (light/dark) should be used and whether the operating 
system should decide
+ * that
+ *
+ * LibreOffice Themes will be enabled if some theme other than Automatic is 
selected.
+ */
+
+using namespace svtools;
+class SvxAppearanceTabPage : public SfxTabPage
+{
+private:
+    enum class Appearance
+    {
+        SYSTEM,
+        LIGHT,
+        DARK,
+    };
+
+    bool m_bRestartRequired;
+    Appearance eCurrentAppearanceMode;
+    std::unique_ptr<EditableColorConfig> pColorConfig;
+
+    std::unique_ptr<weld::ComboBox> m_xSchemeList;
+    std::unique_ptr<weld::Button> m_xMoreThemesBtn;
+    std::unique_ptr<weld::Button> m_xAddSchemeBtn;
+    std::unique_ptr<weld::Button> m_xRemoveSchemeBtn;
+    std::unique_ptr<weld::RadioButton> m_xAppearanceSystem;
+    std::unique_ptr<weld::RadioButton> m_xAppearanceLight;
+    std::unique_ptr<weld::RadioButton> m_xAppearanceDark;
+    std::unique_ptr<weld::ComboBox> m_xColorEntryBtn;
+    std::unique_ptr<ColorListBox> m_xColorChangeBtn;
+    std::unique_ptr<weld::Label> m_xColorLbl;
+    std::unique_ptr<weld::CheckButton> m_xShowInDocumentChkBtn;
+
+    std::unique_ptr<weld::RadioButton> m_xColorRadioBtn;
+    std::unique_ptr<weld::RadioButton> m_xImageRadioBtn;
+    std::unique_ptr<weld::RadioButton> m_xStretchedRadioBtn;
+    std::unique_ptr<weld::RadioButton> m_xTiledRadioBtn;
+
+    std::unique_ptr<weld::ComboBox> m_xBitmapDropDownBtn;
+
+    DECL_LINK(AppearanceChangeHdl, weld::Toggleable&, void);
+    DECL_LINK(ColorEntryChgHdl, weld::ComboBox&, void);
+    DECL_LINK(ColorValueChgHdl, ColorListBox&, void);
+    DECL_LINK(ShowInDocumentHdl, weld::Toggleable&, void);
+    DECL_LINK(SchemeChangeHdl, weld::ComboBox&, void);
+    DECL_LINK(SchemeListToggleHdl, weld::ComboBox&, void);
+    DECL_STATIC_LINK(SvxAppearanceTabPage, MoreThemesHdl, weld::Button&, void);
+    DECL_LINK(AddRemoveSchemeHdl, weld::Button&, void);
+    DECL_LINK(CheckNameHdl_Impl, AbstractSvxNameDialog&, bool);
+    DECL_LINK(ColorImageToggleHdl, weld::Toggleable&, void);
+    DECL_LINK(StretchedTiledToggleHdl, weld::Toggleable&, void);
+    DECL_LINK(BitmapChangeHdl, weld::ComboBox&, void);
+
+    void InitThemes();
+    void InitAppearance();
+    void InitCustomization();
+    void UpdateControlsState();
+    void LoadSchemeList();
+
+    void UpdateRemoveBtnState();
+    void EnableImageControls(bool bEnabled);
+    void UpdateColorDropdown();
+    bool IsDarkModeEnabled();
+    void FillItemsList();
+    size_t GetActiveEntry();
+
+public:
+    SvxAppearanceTabPage(weld::Container* pPage, weld::DialogController* 
pController,
+                         const SfxItemSet& rSet);
+
+    virtual ~SvxAppearanceTabPage() override;
+
+    static std::unique_ptr<SfxTabPage>
+    Create(weld::Container* pPage, weld::DialogController* pController, const 
SfxItemSet* rSet);
+
+    virtual OUString GetAllStrings() override;
+    virtual bool FillItemSet(SfxItemSet* rSet) override;
+    virtual void Reset(const SfxItemSet* rSet) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx
index 7ef78edb7f9e..5fba9b37445e 100644
--- a/cui/source/options/treeopt.cxx
+++ b/cui/source/options/treeopt.cxx
@@ -34,6 +34,7 @@
 #include <treeopt.hrc>
 #include <helpids.h>
 
+#include "appearance.hxx"
 #include "cfgchart.hxx"
 #include "connpoolconfig.hxx"
 #include "connpooloptions.hxx"
@@ -259,6 +260,9 @@ static std::unique_ptr<SfxTabPage> 
CreateGeneralTabPage(sal_uInt16 nId, weld::Co
         case RID_SVXPAGE_INET_PROXY:                fnCreate = 
&SvxProxyTabPage::Create; break;
         case RID_SVXPAGE_INET_SECURITY:             fnCreate = 
&SvxSecurityTabPage::Create; break;
         case RID_SVXPAGE_INET_MAIL:                 fnCreate = 
&SvxEMailTabPage::Create; break;
+#if HAVE_FEATURE_DESKTOP
+        case RID_SVXPAGE_APPEARANCE:                fnCreate = 
&SvxAppearanceTabPage::Create; break;
+#endif
         case RID_OFAPAGE_HTMLOPT:                   fnCreate = 
&OfaHtmlTabPage::Create; break;
         case SID_OPTFILTER_MSOFFICE:                fnCreate = 
&OfaMSFilterTabPage::Create; break;
         case RID_OFAPAGE_MSFILTEROPT2:              fnCreate = 
&OfaMSFilterTabPage2::Create; break;
@@ -305,6 +309,7 @@ constexpr OptionsMapping_Impl OptionsMap_Impl[]
     { u"ProductName"_ustr,        u"Paths"_ustr,                
RID_SFXPAGE_PATH },
     { u"ProductName"_ustr,        u"Fonts"_ustr,                
RID_SVX_FONT_SUBSTITUTION },
     { u"ProductName"_ustr,        u"Security"_ustr,             
RID_SVXPAGE_INET_SECURITY },
+    { u"ProductName"_ustr,        u"Appearance"_ustr,           
RID_SVXPAGE_APPEARANCE },
     { u"ProductName"_ustr,        u"Accessibility"_ustr,        
RID_SVXPAGE_ACCESSIBILITYCONFIG },
     { u"ProductName"_ustr,        u"Java"_ustr,                 
RID_SVXPAGE_OPTIONS_JAVA },
     { u"ProductName"_ustr,        u"BasicIDEOptions"_ustr,      
RID_SVXPAGE_BASICIDE_OPTIONS },
diff --git a/cui/source/options/treeopthelper.cxx 
b/cui/source/options/treeopthelper.cxx
index 294364cafe37..4dde62e5690a 100644
--- a/cui/source/options/treeopthelper.cxx
+++ b/cui/source/options/treeopthelper.cxx
@@ -53,6 +53,7 @@ static PageIdToFileNameMap_Impl FileMap_Impl[] = {
 
     { RID_SVXPAGE_INET_SECURITY, u""_ustr }, // Security
 
+    { RID_SVXPAGE_APPEARANCE, u""_ustr }, // Appearance
     { RID_SVXPAGE_ACCESSIBILITYCONFIG, u""_ustr }, // Accessibility
     { RID_SVXPAGE_OPTIONS_JAVA, u""_ustr }, // Java
     { RID_SVXPAGE_BASICIDE_OPTIONS, u""_ustr }, // BasicIDEOptions
diff --git a/cui/uiconfig/ui/appearance.ui b/cui/uiconfig/ui/appearance.ui
new file mode 100644
index 000000000000..fb47f7663724
--- /dev/null
+++ b/cui/uiconfig/ui/appearance.ui
@@ -0,0 +1,484 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.40.0 -->
+<interface domain="cui">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkImage" id="morethemes_image">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="icon-name">cmd/sc_additionsdialog.png</property>
+  </object>
+  <object class="GtkBox" id="AppearanceTabPage">
+    <property name="visible">True</property>
+    <property name="can-focus">False</property>
+    <property name="border-width">6</property>
+    <property name="orientation">vertical</property>
+    <property name="spacing">12</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <child>
+          <object class="GtkFrame" id="libreofficethemes">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-end">12</property>
+            <property name="label-xalign">0</property>
+            <property name="shadow-type">none</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-start">12</property>
+                <property name="margin-top">6</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="spacing">3</property>
+                    <child>
+                      <object class="GtkComboBoxText" id="scheme">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</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="morethemesbtn">
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="tooltip-text" translatable="yes" 
context="optappearancepage|morethemes">Add more themes.</property>
+                        <property name="image">morethemes_image</property>
+                        <property name="always-show-image">True</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButtonBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-top">12</property>
+                    <property name="layout-style">spread</property>
+                    <child>
+                      <object class="GtkButton" id="newschemebtn">
+                        <property name="label" translatable="yes" 
context="appearancetabpage|newschemebtn">New</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="margin-end">3</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="removeschemebtn">
+                        <property name="label" translatable="yes" 
context="appearancetabpage|removeschemebtn">Remove</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">True</property>
+                        <property name="margin-start">3</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="libreofficethemeslb">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-bottom">6</property>
+                <property name="label" translatable="yes" 
context="appearancetabpage|libreofficethemeslb">LibreOffice Themes</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkFrame" id="options">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-start">12</property>
+                <property name="margin-bottom">6</property>
+                <property name="label-xalign">0</property>
+                <property name="shadow-type">none</property>
+                <child>
+                  <!-- n-columns=2 n-rows=1 -->
+                  <object class="GtkGrid">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-start">12</property>
+                    <property name="margin-top">6</property>
+                    <child>
+                      <object class="GtkLabel" id="appearancelb">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="valign">start</property>
+                        <property name="margin-end">6</property>
+                        <property name="label" translatable="yes" 
context="appearancetabpage|appearancelb">Appearance:</property>
+                        <property name="use-underline">True</property>
+                        <property name="mnemonic-widget">system</property>
+                      </object>
+                      <packing>
+                        <property name="left-attach">0</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                    <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="system">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|system">System</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="light">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|light">Light</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">False</property>
+                            <property name="draw-indicator">True</property>
+                            <property name="group">system</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkRadioButton" id="dark">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|dark">Dark</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">False</property>
+                            <property name="draw-indicator">True</property>
+                            <property name="group">system</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">2</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left-attach">1</property>
+                        <property name="top-attach">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="optionslb">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="appearancetabpage|optionslb">Options</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="items">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-start">12</property>
+                <property name="margin-top">6</property>
+                <property name="label-xalign">0</property>
+                <property name="shadow-type">none</property>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="margin-start">13</property>
+                    <property name="margin-top">6</property>
+                    <property name="orientation">vertical</property>
+                    <property name="spacing">3</property>
+                    <child>
+                      <!-- n-columns=2 n-rows=7 -->
+                      <object class="GtkGrid">
+                        <property name="visible">True</property>
+                        <property name="can-focus">False</property>
+                        <property name="row-spacing">3</property>
+                        <property name="column-spacing">6</property>
+                        <child>
+                          <object class="GtkLabel" id="itemslb">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes" 
context="appearancetabpage|items">Items: </property>
+                            <property name="use-underline">True</property>
+                            <property 
name="mnemonic-widget">registrydropdown</property>
+                          </object>
+                          <packing>
+                            <property name="left-attach">0</property>
+                            <property name="top-attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" 
id="registrydropdown">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="hexpand">False</property>
+                            <child internal-child="accessible">
+                              <object class="AtkObject" 
id="registrydropdown-atkobject">
+                                <property name="AtkObject::accessible-name" 
translatable="yes" 
context="appearancetabpage|registrycolorslist">registrycolorslist</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left-attach">1</property>
+                            <property name="top-attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkRadioButton" id="colorradiobtn">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|colorradiobtn">Color:</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">False</property>
+                            <property name="halign">start</property>
+                            <property name="active">True</property>
+                            <property name="draw-indicator">True</property>
+                            <property name="group">imageradiobtn</property>
+                          </object>
+                          <packing>
+                            <property name="left-attach">0</property>
+                            <property name="top-attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="colorlbl">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="margin-start">18</property>
+                            <property name="label" translatable="no" 
context="appearancetabpage|colorlbl">colorlbl</property>
+                            <property name="use-underline">True</property>
+                            <property 
name="mnemonic-widget">colorsdropdownbtn</property>
+                          </object>
+                          <packing>
+                            <property name="left-attach">0</property>
+                            <property name="top-attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkMenuButton" id="colorsdropdownbtn">
+                            <property name="label" translatable="no" 
context="appearancetabpage|colorsdropdownbtn"></property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="focus-on-click">False</property>
+                            <property name="receives-default">True</property>
+                            <property name="halign">start</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left-attach">1</property>
+                            <property name="top-attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkCheckButton" 
id="showindocumentchkbtn">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|showindocumentchkbtn">Show in Document</property>
+                            <property name="visible">True</property>
+                            <property name="can-focus">True</property>
+                            <property name="receives-default">False</property>
+                            <property name="draw-indicator">True</property>
+                          </object>
+                          <packing>
+                            <property name="left-attach">1</property>
+                            <property name="top-attach">3</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkRadioButton" id="imageradiobtn">
+                            <property name="label" translatable="yes" 
context="appearancetabpage|imageradiobtn">Image:</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="left-attach">0</property>
+                            <property name="top-attach">4</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkComboBoxText" id="bitmapdropdown">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <property name="halign">start</property>
+                            <child internal-child="accessible">
+                              <object class="AtkObject" 
id="bitmapdropdown-atkobject">
+                                <property name="AtkObject::accessible-name" 
translatable="yes" 
context="appearancetabpage|bitmapdropdown">bitmapdropdown</property>
+                              </object>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left-attach">1</property>
+                            <property name="top-attach">5</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="can-focus">False</property>
+                            <child>
+                              <object class="GtkRadioButton" 
id="stretchedradiobtn">
+                                <property name="label" translatable="yes" 
context="appearancetabpage|stretchedradiobtn">Stretched</property>
+                                <property name="visible">True</property>
+                                <property name="can-focus">True</property>
+                                <property 
name="receives-default">False</property>
+                                <property name="draw-indicator">True</property>
+                                <property name="group">tiledradiobtn</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="tiledradiobtn">
+                                <property name="label" translatable="yes" 
context="appearancetabpage|tiledradiobtn">Tiled</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">1</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="left-attach">1</property>
+                            <property name="top-attach">6</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                </child>
+                <child type="label">
+                  <object class="GtkLabel" id="customizationslb">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="appearancetabpage|customizationslb">Customizations</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
+</interface>
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx 
b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 11db3d75398b..7bca2926e948 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -2270,7 +2270,9 @@ void DesktopLOKTest::testPaintPartTileDifferentSchemes()
         svtools::EditableColorConfig aColorConfig;
         svtools::ColorConfigValue aValue;
         aValue.bIsVisible = true;
-        aValue.nColor = aDarkColor;
+        // aValue.nColor is just used for cache. please see Change: 
I1a7f70dfe44b81f863814f87e8d46e146c0e3d5a
+        aValue.nLightColor = aDarkColor;
+        aValue.nDarkColor = aDarkColor;
         aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue);
         aColorConfig.AddScheme(u"Dark"_ustr);
     }
@@ -2280,7 +2282,8 @@ void DesktopLOKTest::testPaintPartTileDifferentSchemes()
         svtools::EditableColorConfig aColorConfig;
         svtools::ColorConfigValue aValue;
         aValue.bIsVisible = true;
-        aValue.nColor = COL_WHITE;
+        aValue.nLightColor = COL_WHITE;
+        aValue.nDarkColor = COL_WHITE;
         aColorConfig.SetColorValue(svtools::DOCCOLOR, aValue);
         aColorConfig.AddScheme(u"Light"_ustr);
     }
diff --git a/include/sfx2/pageids.hxx b/include/sfx2/pageids.hxx
index bd85bbf6bb2e..c9b9feb9476e 100644
--- a/include/sfx2/pageids.hxx
+++ b/include/sfx2/pageids.hxx
@@ -53,6 +53,7 @@
 #define RID_SVXPAGE_ACCESSIBILITYCONFIG     (RID_SVX_START + 250)
 #define RID_SVXPAGE_ASIAN_LAYOUT            (RID_SVX_START + 246)
 #define RID_OPTPAGE_CHART_DEFCOLORS         (RID_SVX_START + 299)
+#define RID_SVXPAGE_APPEARANCE              (RID_SVX_START + 247)
 #define RID_SVXPAGE_BASICIDE_OPTIONS        (RID_SVX_START + 209)
 #define RID_SVXPAGE_LANGTOOL_OPTIONS        (RID_SVX_START + 210)
 #define RID_SVXPAGE_DEEPL_OPTIONS           (RID_SVX_START + 211)
diff --git a/include/svtools/colorcfg.hxx b/include/svtools/colorcfg.hxx
index 5e4e774826d7..c757eeb20abd 100644
--- a/include/svtools/colorcfg.hxx
+++ b/include/svtools/colorcfg.hxx
@@ -130,16 +130,153 @@ enum ColorConfigEntry : int
 constexpr OUString AUTOMATIC_COLOR_SCHEME = 
u"COLOR_SCHEME_LIBREOFFICE_AUTOMATIC"_ustr;
 constexpr size_t THEME_APPLICATION_COLORS_COUNT = ColorConfigEntryCount - 
WINDOWCOLOR;
 
+namespace {
+    struct ColorConfigEntryData_Impl
+    {
+        std::u16string_view cName;
+        bool            bCanBeVisible;
+        bool            bCanHaveBitmap;
+    };
+    const ColorConfigEntryData_Impl cNames[] =
+    {
+        { std::u16string_view(u"DocColor"), false, false },
+        { std::u16string_view(u"DocBoundaries"), false, false },
+        { std::u16string_view(u"AppBackground"), false, true },
+        { std::u16string_view(u"TableBoundaries"), false, false },
+        { std::u16string_view(u"FontColor"), false, false },
+        { std::u16string_view(u"Links"), true, false },
+        { std::u16string_view(u"LinksVisited"), true, false },
+        { std::u16string_view(u"Spell"), false, false },
+        { std::u16string_view(u"Grammar"), false, false },
+        { std::u16string_view(u"SmartTags"), false, false },
+        { std::u16string_view(u"Shadow"), true, false },
+        { std::u16string_view(u"WriterTextGrid"), false, false },
+        { std::u16string_view(u"WriterFieldShadings"), true, false },
+        { std::u16string_view(u"WriterIdxShadings"), true, false },
+        { std::u16string_view(u"WriterDirectCursor"), true, false },
+        { std::u16string_view(u"WriterScriptIndicator"), false, false },
+        { std::u16string_view(u"WriterSectionBoundaries"), false, false },
+        { std::u16string_view(u"WriterHeaderFooterMark"), false, false },
+        { std::u16string_view(u"WriterPageBreaks"), false, false },
+        { std::u16string_view(u"WriterNonPrintChars"), false, false },
+        { std::u16string_view(u"HTMLSGML"), false, false },
+        { std::u16string_view(u"HTMLComment"), false, false },
+        { std::u16string_view(u"HTMLKeyword"), false, false },
+        { std::u16string_view(u"HTMLUnknown"), false, false },
+        { std::u16string_view(u"CalcGrid"), false, false },
+        { std::u16string_view(u"CalcCellFocus"), false, false },
+        { std::u16string_view(u"CalcPageBreak"), false, false },
+        { std::u16string_view(u"CalcPageBreakManual"), false, false },
+        { std::u16string_view(u"CalcPageBreakAutomatic"), false, false },
+        { std::u16string_view(u"CalcHiddenColRow"), true, false },
+        { std::u16string_view(u"CalcTextOverflow"), true, false },
+        { std::u16string_view(u"CalcComments"), false, false },
+        { std::u16string_view(u"CalcDetective"), false, false },
+        { std::u16string_view(u"CalcDetectiveError"), false, false },
+        { std::u16string_view(u"CalcReference"), false, false },
+        { std::u16string_view(u"CalcNotesBackground"), false, false },
+        { std::u16string_view(u"CalcValue"), false, false },
+        { std::u16string_view(u"CalcFormula"), false, false },
+        { std::u16string_view(u"CalcText"), false, false },
+        { std::u16string_view(u"CalcProtectedBackground"), false, false },
+        { std::u16string_view(u"DrawGrid"), true, false },
+        { std::u16string_view(u"Author1"), false, false },
+        { std::u16string_view(u"Author2"), false, false },
+        { std::u16string_view(u"Author3"), false, false },
+        { std::u16string_view(u"Author4"), false, false },
+        { std::u16string_view(u"Author5"), false, false },
+        { std::u16string_view(u"Author6"), false, false },
+        { std::u16string_view(u"Author7"), false, false },
+        { std::u16string_view(u"Author8"), false, false },
+        { std::u16string_view(u"Author9"), false, false },
+        { std::u16string_view(u"BASICEditor"), false, false },
+        { std::u16string_view(u"BASICIdentifier"), false, false },
+        { std::u16string_view(u"BASICComment"), false, false },
+        { std::u16string_view(u"BASICNumber"), false, false },
+        { std::u16string_view(u"BASICString"), false, false },
+        { std::u16string_view(u"BASICOperator"), false, false },
+        { std::u16string_view(u"BASICKeyword"), false, false },
+        { std::u16string_view(u"BASICError"), false, false },
+        { std::u16string_view(u"SQLIdentifier"), false, false },
+        { std::u16string_view(u"SQLNumber"), false, false },
+        { std::u16string_view(u"SQLString"), false, false },
+        { std::u16string_view(u"SQLOperator"), false, false },
+        { std::u16string_view(u"SQLKeyword"), false, false },
+        { std::u16string_view(u"SQLParameter"), false, false },
+        { std::u16string_view(u"SQLComment"), false, false },
+
+        { std::u16string_view(u"WindowColor"), false, false },
+        { std::u16string_view(u"WindowTextColor"), false, false },
+        { std::u16string_view(u"BaseColor"), false, false },
+        { std::u16string_view(u"ButtonColor"), false, false },
+        { std::u16string_view(u"ButtonTextColor"), false, false },
+        { std::u16string_view(u"AccentColor"), false, false },
+        { std::u16string_view(u"DisabledColor"), false, false },
+        { std::u16string_view(u"DisabledTextColor"), false, false },
+        { std::u16string_view(u"ShadowColor"), false, false },
+        { std::u16string_view(u"SeparatorColor"), false, false },
+        { std::u16string_view(u"FaceColor"), false, false },
+        { std::u16string_view(u"ActiveColor"), false, false },
+        { std::u16string_view(u"ActiveTextColor"), false, false },
+        { std::u16string_view(u"ActiveBorderColor"), false, false },
+        { std::u16string_view(u"FieldColor"), false, false },
+        { std::u16string_view(u"MenuBarColor"), false, false },
+        { std::u16string_view(u"MenuBarTextColor"), false, false },
+        { std::u16string_view(u"MenuBarHighlightColor"), false, false },
+        { std::u16string_view(u"MenuBarHighlightTextColor"), false, false },
+        { std::u16string_view(u"MenuColor"), false, false },
+        { std::u16string_view(u"MenuTextColor"), false, false },
+        { std::u16string_view(u"MenuHighlightColor"), false, false },
+        { std::u16string_view(u"MenuHighlightTextColor"), false, false },
+        { std::u16string_view(u"MenuBorderColor"), false, false },
+        { std::u16string_view(u"InactiveColor"), false, false },
+        { std::u16string_view(u"InactiveTextColor"), false, false },
+        { std::u16string_view(u"InactiveBorderColor"), false, false }
+    };
+}
+
 class ColorConfig_Impl;
 struct ColorConfigValue
 {
 
-    bool        bIsVisible; //validity depends on the element type
-    ::Color     nColor;
-    ColorConfigValue() : bIsVisible(false), nColor(0) {}
-    ColorConfigValue(const Color& rColor, bool bVisible) : 
bIsVisible(bVisible), nColor(rColor) {}
-    bool operator !=(const ColorConfigValue& rCmp) const
-        { return nColor != rCmp.nColor || bIsVisible != rCmp.bIsVisible;}
+    bool        bIsVisible; // validity depends on the element type
+    ::Color     nColor; // used as a cache for the current color
+    Color       nLightColor;
+    Color       nDarkColor;
+
+    bool        bUseBitmapBackground;
+    bool        bIsBitmapStretched;
+    OUString    sBitmapFileName;
+
+    ColorConfigValue()
+        : bIsVisible(false)
+        , nColor(0)
+        , nLightColor(0)
+        , nDarkColor(0)
+        , bUseBitmapBackground(false)
+        , bIsBitmapStretched(false)
+    {
+    }
+
+    ColorConfigValue(const Color& rColor, bool bVisible)
+        : bIsVisible(bVisible)
+        , nColor(rColor)
+        , nLightColor(rColor)
+        , nDarkColor(rColor)
+    {
+    }
+
+    bool operator!=(const ColorConfigValue& rCmp) const
+    {
+        return
+            nColor != rCmp.nColor
+            || nLightColor != rCmp.nLightColor
+            || nDarkColor != rCmp.nDarkColor
+            || bIsVisible != rCmp.bIsVisible
+            || bUseBitmapBackground != rCmp.bUseBitmapBackground
+            || bIsBitmapStretched != rCmp.bIsBitmapStretched
+            || sBitmapFileName != rCmp.sBitmapFileName;
+    }
 };
 
 class SAL_WARN_UNUSED SVT_DLLPUBLIC ColorConfig final :
@@ -161,8 +298,8 @@ public:
     static Color            GetDefaultColor(ColorConfigEntry eEntry, int nMod 
= -1);
     static const OUString& GetCurrentSchemeName();
 
-    static void             LoadThemeColorsFromRegistry();
-    static void             SetupTheme();
+    void                    LoadThemeColorsFromRegistry();
+    void                    SetupTheme();
 };
 
 class SVT_DLLPUBLIC EditableColorConfig
diff --git a/include/vcl/settings.hxx b/include/vcl/settings.hxx
index 4ff322954375..4f335a0b02a1 100644
--- a/include/vcl/settings.hxx
+++ b/include/vcl/settings.hxx
@@ -399,7 +399,7 @@ public:
     SAL_DLLPRIVATE const Color&     GetMenuBarRolloverTextColor() const;
 
     void                            SetMenuBarHighlightTextColor( const Color& 
rColor );
-    SAL_DLLPRIVATE const Color&     GetMenuBarHighlightTextColor() const;
+    const Color&                    GetMenuBarHighlightTextColor() const;
 
     void                            SetMenuHighlightColor( const Color& rColor 
);
     const Color&                    GetMenuHighlightColor() const;
@@ -606,6 +606,7 @@ public:
     void                            SetPreferredIconTheme(const OUString&, 
bool bDarkIconTheme = false);
 
     const DialogStyle&              GetDialogStyle() const;
+    const BitmapEx&                 GetAppBackgroundBitmap() const;
 
     // global switch to allow EdgeBlenging; currently possible for ValueSet 
and ListBox
     // when activated there using Get/SetEdgeBlending; default is true
diff --git a/include/vcl/themecolors.hxx b/include/vcl/themecolors.hxx
index fec422adbac9..80f56db5e0e4 100644
--- a/include/vcl/themecolors.hxx
+++ b/include/vcl/themecolors.hxx
@@ -60,6 +60,13 @@ public:
     void SetInactiveBorderColor(const Color& rColor) { m_aInactiveBorderColor 
= rColor; }
     void SetThemeName(const OUString& rName) { m_sThemeName = rName; }
 
+    void SetAppBackBitmapFileName(const OUString& rBitmapStr)
+    {
+        m_aAppBackBitmapFileName = rBitmapStr;
+    }
+    void SetAppBackBitmapStretched(bool bStretched) { m_bStretched = 
bStretched; }
+    void SetAppBackUseBitmap(bool bDrawBitmap) { m_bUseBitmapForAppBack = 
bDrawBitmap; }
+
     const Color& GetWindowColor() const { return m_aWindowColor; }
     const Color& GetWindowTextColor() const { return m_aWindowTextColor; }
     const Color& GetBaseColor() const { return m_aBaseColor; }
@@ -89,6 +96,10 @@ public:
     const Color& GetInactiveBorderColor() const { return 
m_aInactiveBorderColor; }
     const OUString& GetThemeName() const { return m_sThemeName; }
 
+    const OUString& GetAppBackBitmapFileName() const { return 
m_aAppBackBitmapFileName; }
+    bool IsAppBackBitmapStretched() { return m_bStretched; }
+    bool GetAppBackUseBitmap() { return m_bUseBitmapForAppBack; }
+
 private:
     Color m_aWindowColor;
     Color m_aWindowTextColor;
@@ -119,6 +130,14 @@ private:
     Color m_aInactiveBorderColor;
 
     OUString m_sThemeName;
+
+    // using values for now as only one element is bitmap customizable. but as 
the number increases
+    // we might want to replace these colors with structs similar to `struct 
ColorConfigValue`
+    // The actual bitmap object is in StyleSettings because we cannot have non 
primitive objects in
+    // static singleton classes as the order of initialization would be 
undefined.
+    bool m_bStretched = false;
+    bool m_bUseBitmapForAppBack = false;
+    OUString m_aAppBackBitmapFileName = "";
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/officecfg/registry/data/org/openoffice/Office/UI.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI.xcu
index f4e82ec18ecc..90d4d640b8f8 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI.xcu
@@ -140,27 +140,48 @@
       <node oor:name="COLOR_SCHEME_LIBREOFFICE_AUTOMATIC" oor:op="replace">
         <!-- Group_General -->
         <node oor:name="DocColor">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="DocBoundaries">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="AppBackground">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="BackgroundType">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Bitmap">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="TableBoundaries">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="FontColor">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
@@ -168,7 +189,10 @@
           <prop oor:name="IsVisible">
             <value>false</value>
           </prop>
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
@@ -176,22 +200,34 @@
           <prop oor:name="IsVisible">
             <value>false</value>
           </prop>
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="Spell">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="Grammar">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
         <node oor:name="SmartTags">
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
             <value xsi:nil="true"/>
           </prop>
         </node>
@@ -199,12 +235,18 @@
           <prop oor:name="IsVisible">
             <value>true</value>
           </prop>
-          <prop oor:name="Color">
+          <prop oor:name="Light">
+            <value xsi:nil="true"/>
+          </prop>
+          <prop oor:name="Dark">
-e 
... etc. - the rest is truncated

Reply via email to