1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <svtools/colorcfg.hxx>
22 #include <com/sun/star/uno/Any.hxx>
23 #include <com/sun/star/uno/Sequence.hxx>
24 #include <com/sun/star/lang/Locale.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <unotools/configitem.hxx>
28 #include <unotools/confignode.hxx>
29 #include <unotools/configpaths.hxx>
30 #include <com/sun/star/uno/Sequence.h>
31 #include <svl/poolitem.hxx>
32 #include <svl/smplhint.hxx>
33 #include <osl/mutex.hxx>
35 #include "itemholder2.hxx"
38 #include <vcl/wrkwin.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/event.hxx>
42 #include <vcl/settings.hxx>
43 #include <rtl/instance.hxx>
47 using namespace com::sun::star
;
53 static const sal_Char cColor
[] = "/Color";
54 static const sal_Char cColorSchemes
[] = "ColorSchemes/";
55 sal_Int32 nColorRefCount_Impl
= 0;
58 struct ColorMutex_Impl
59 : public rtl::Static
< ::osl::Mutex
, ColorMutex_Impl
> {};
62 ColorConfig_Impl
* ColorConfig::m_pImpl
= NULL
;
64 class ColorConfig_Impl
: public utl::ConfigItem
66 ColorConfigValue m_aConfigValues
[ColorConfigEntryCount
];
68 OUString m_sIsVisible
;
69 OUString m_sLoadedScheme
;
70 bool m_bAutoDetectSystemHC
;
72 uno::Sequence
< OUString
> GetPropertyNames(const OUString
& rScheme
);
74 virtual void ImplCommit() SAL_OVERRIDE
;
77 ColorConfig_Impl(bool bEditMode
= false);
78 virtual ~ColorConfig_Impl();
80 void Load(const OUString
& rScheme
);
81 void CommitCurrentSchemeName();
82 //changes the name of the current scheme but doesn't load it!
83 void SetCurrentSchemeName(const OUString
& rSchemeName
) {m_sLoadedScheme
= rSchemeName
;}
84 virtual void Notify( const uno::Sequence
<OUString
>& aPropertyNames
) SAL_OVERRIDE
;
86 const ColorConfigValue
& GetColorConfigValue(ColorConfigEntry eValue
)
87 {return m_aConfigValues
[eValue
];}
88 void SetColorConfigValue(ColorConfigEntry eValue
,
89 const ColorConfigValue
& rValue
);
91 const OUString
& GetLoadedScheme() const {return m_sLoadedScheme
;}
93 uno::Sequence
< OUString
> GetSchemeNames();
95 bool AddScheme(const OUString
& rNode
);
96 bool RemoveScheme(const OUString
& rNode
);
97 void SetModified(){ConfigItem::SetModified();}
98 void ClearModified(){ConfigItem::ClearModified();}
99 void SettingsChanged();
100 bool GetAutoDetectSystemHC() {return m_bAutoDetectSystemHC
;}
103 DECL_LINK( DataChangedEventListener
, VclWindowEvent
* );
105 void ImplUpdateApplicationSettings();
108 uno::Sequence
< OUString
> ColorConfig_Impl::GetPropertyNames(const OUString
& rScheme
)
110 uno::Sequence
<OUString
> aNames(2 * ColorConfigEntryCount
);
111 OUString
* pNames
= aNames
.getArray();
112 struct ColorConfigEntryData_Impl
114 const sal_Char
* cName
;
116 rtl_TextEncoding eEncoding
;
119 static const ColorConfigEntryData_Impl cNames
[] =
121 { RTL_CONSTASCII_USTRINGPARAM("/DocColor") ,false },
122 { RTL_CONSTASCII_USTRINGPARAM("/DocBoundaries") ,true },
123 { RTL_CONSTASCII_USTRINGPARAM("/AppBackground") ,false },
124 { RTL_CONSTASCII_USTRINGPARAM("/ObjectBoundaries"),true },
125 { RTL_CONSTASCII_USTRINGPARAM("/TableBoundaries") ,true },
126 { RTL_CONSTASCII_USTRINGPARAM("/FontColor") ,false },
127 { RTL_CONSTASCII_USTRINGPARAM("/Links") ,true },
128 { RTL_CONSTASCII_USTRINGPARAM("/LinksVisited") ,true },
129 { RTL_CONSTASCII_USTRINGPARAM("/Spell") ,false },
130 { RTL_CONSTASCII_USTRINGPARAM("/SmartTags") ,false },
131 { RTL_CONSTASCII_USTRINGPARAM("/Shadow") , true },
132 { RTL_CONSTASCII_USTRINGPARAM("/WriterTextGrid") ,false },
133 { RTL_CONSTASCII_USTRINGPARAM("/WriterFieldShadings"),true },
134 { RTL_CONSTASCII_USTRINGPARAM("/WriterIdxShadings") ,true },
135 { RTL_CONSTASCII_USTRINGPARAM("/WriterDirectCursor") ,true },
136 { RTL_CONSTASCII_USTRINGPARAM("/WriterScriptIndicator") ,false },
137 { RTL_CONSTASCII_USTRINGPARAM("/WriterSectionBoundaries") ,true },
138 { RTL_CONSTASCII_USTRINGPARAM("/WriterHeaderFooterMark") ,false },
139 { RTL_CONSTASCII_USTRINGPARAM("/WriterPageBreaks") ,false },
140 { RTL_CONSTASCII_USTRINGPARAM("/HTMLSGML") ,false },
141 { RTL_CONSTASCII_USTRINGPARAM("/HTMLComment") ,false },
142 { RTL_CONSTASCII_USTRINGPARAM("/HTMLKeyword") ,false },
143 { RTL_CONSTASCII_USTRINGPARAM("/HTMLUnknown") ,false },
144 { RTL_CONSTASCII_USTRINGPARAM("/CalcGrid") ,false },
145 { RTL_CONSTASCII_USTRINGPARAM("/CalcPageBreak"), false },
146 { RTL_CONSTASCII_USTRINGPARAM("/CalcPageBreakManual"), false },
147 { RTL_CONSTASCII_USTRINGPARAM("/CalcPageBreakAutomatic"), false },
148 { RTL_CONSTASCII_USTRINGPARAM("/CalcDetective") ,false },
149 { RTL_CONSTASCII_USTRINGPARAM("/CalcDetectiveError") ,false },
150 { RTL_CONSTASCII_USTRINGPARAM("/CalcReference") ,false },
151 { RTL_CONSTASCII_USTRINGPARAM("/CalcNotesBackground") ,false },
152 { RTL_CONSTASCII_USTRINGPARAM("/DrawGrid") ,true },
153 { RTL_CONSTASCII_USTRINGPARAM("/BASICIdentifier"), false },
154 { RTL_CONSTASCII_USTRINGPARAM("/BASICComment") , false },
155 { RTL_CONSTASCII_USTRINGPARAM("/BASICNumber") , false },
156 { RTL_CONSTASCII_USTRINGPARAM("/BASICString") , false },
157 { RTL_CONSTASCII_USTRINGPARAM("/BASICOperator") , false },
158 { RTL_CONSTASCII_USTRINGPARAM("/BASICKeyword") , false },
159 { RTL_CONSTASCII_USTRINGPARAM("/BASICError"), false },
160 { RTL_CONSTASCII_USTRINGPARAM("/SQLIdentifier"), false },
161 { RTL_CONSTASCII_USTRINGPARAM("/SQLNumber"), false },
162 { RTL_CONSTASCII_USTRINGPARAM("/SQLString"), false },
163 { RTL_CONSTASCII_USTRINGPARAM("/SQLOperator"), false },
164 { RTL_CONSTASCII_USTRINGPARAM("/SQLKeyword"), false },
165 { RTL_CONSTASCII_USTRINGPARAM("/SQLParameter"), false },
166 { RTL_CONSTASCII_USTRINGPARAM("/SQLComment"), false }
169 OUString sColor
= cColor
;
170 OUString
sBase(cColorSchemes
);
171 sBase
+= utl::wrapConfigurationElementName(rScheme
);
172 const int nCount
= ColorConfigEntryCount
;
173 for(sal_Int32 i
= 0; i
< 4 * nCount
; i
+= 4)
175 OUString
sBaseName(sBase
);
176 sal_Int32 nPos
= i
/ 4;
177 sBaseName
+= OUString(cNames
[nPos
].cName
, cNames
[nPos
].nLength
, cNames
[nPos
].eEncoding
);
178 pNames
[nIndex
] += sBaseName
;
179 pNames
[nIndex
++] += sColor
;
180 if(cNames
[nPos
].bCanBeVisible
)
182 pNames
[nIndex
] += sBaseName
;
183 pNames
[nIndex
++] += m_sIsVisible
;
186 aNames
.realloc(nIndex
);
190 ColorConfig_Impl::ColorConfig_Impl(bool bEditMode
) :
191 ConfigItem("Office.UI/ColorScheme"),
192 m_bEditMode(bEditMode
),
193 m_sIsVisible("/IsVisible"),
194 m_bAutoDetectSystemHC(true)
198 //try to register on the root node - if possible
199 uno::Sequence
< OUString
> aNames(1);
200 EnableNotification( aNames
);
204 ImplUpdateApplicationSettings();
207 ::Application::AddEventListener( LINK(this, ColorConfig_Impl
, DataChangedEventListener
) );
211 ColorConfig_Impl::~ColorConfig_Impl()
214 ::Application::RemoveEventListener( LINK(this, ColorConfig_Impl
, DataChangedEventListener
) );
217 void ColorConfig_Impl::Load(const OUString
& rScheme
)
219 OUString
sScheme(rScheme
);
220 if(sScheme
.isEmpty())
222 //detect current scheme name
223 uno::Sequence
< OUString
> aCurrent(1);
224 aCurrent
.getArray()[0] = "CurrentColorScheme";
225 uno::Sequence
< uno::Any
> aCurrentVal
= GetProperties( aCurrent
);
226 aCurrentVal
.getConstArray()[0] >>= sScheme
;
228 m_sLoadedScheme
= sScheme
;
230 uno::Sequence
< OUString
> aColorNames
= GetPropertyNames(sScheme
);
231 uno::Sequence
< uno::Any
> aColors
= GetProperties( aColorNames
);
232 const uno::Any
* pColors
= aColors
.getConstArray();
233 const OUString
* pColorNames
= aColorNames
.getConstArray();
234 sal_Int32 nIndex
= 0;
235 for(int i
= 0; i
< 2 * ColorConfigEntryCount
&& aColors
.getLength() > nIndex
; i
+= 2)
237 if(pColors
[nIndex
].hasValue())
238 pColors
[nIndex
] >>= m_aConfigValues
[i
/ 2].nColor
;
240 m_aConfigValues
[i
/2].nColor
= COL_AUTO
;
242 if(nIndex
>= aColors
.getLength())
244 //test for visibility property
245 if(pColorNames
[nIndex
].endsWith(m_sIsVisible
))
246 m_aConfigValues
[i
/ 2].bIsVisible
= Any2Bool(pColors
[nIndex
++]);
248 // fdo#71511: check if we are running in a11y autodetect
250 utl::OConfigurationNode aNode
= utl::OConfigurationTreeRoot::tryCreateWithComponentContext(comphelper::getProcessComponentContext(),OUString("org.openoffice.Office.Common/Accessibility") );
253 uno::Any aValue
= aNode
.getNodeValue(OUString("AutoDetectSystemHC"));
254 aValue
>>= m_bAutoDetectSystemHC
;
259 void ColorConfig_Impl::Notify( const uno::Sequence
<OUString
>& )
261 //loading via notification always uses the default setting
266 void ColorConfig_Impl::ImplCommit()
268 uno::Sequence
< OUString
> aColorNames
= GetPropertyNames(m_sLoadedScheme
);
269 uno::Sequence
< beans::PropertyValue
> aPropValues(aColorNames
.getLength());
270 beans::PropertyValue
* pPropValues
= aPropValues
.getArray();
271 const OUString
* pColorNames
= aColorNames
.getConstArray();
272 sal_Int32 nIndex
= 0;
273 const uno::Type
& rBoolType
= cppu::UnoType
<bool>::get();
274 for(int i
= 0; i
< 2 * ColorConfigEntryCount
&& aColorNames
.getLength() > nIndex
; i
+= 2)
276 pPropValues
[nIndex
].Name
= pColorNames
[nIndex
];
277 //save automatic colors as void value
278 if(COL_AUTO
!= sal::static_int_cast
<ColorData
>(m_aConfigValues
[i
/2].nColor
))
279 pPropValues
[nIndex
].Value
<<= m_aConfigValues
[i
/2].nColor
;
282 if(nIndex
>= aColorNames
.getLength())
284 //test for visibility property
285 if(pColorNames
[nIndex
].endsWith(m_sIsVisible
))
287 pPropValues
[nIndex
].Name
= pColorNames
[nIndex
];
288 pPropValues
[nIndex
].Value
.setValue(&m_aConfigValues
[i
/2].bIsVisible
, rBoolType
);
292 OUString
sNode("ColorSchemes");
293 SetSetProperties(sNode
, aPropValues
);
295 CommitCurrentSchemeName();
298 void ColorConfig_Impl::CommitCurrentSchemeName()
300 //save current scheme name
301 uno::Sequence
< OUString
> aCurrent(1);
302 aCurrent
.getArray()[0] = "CurrentColorScheme";
303 uno::Sequence
< uno::Any
> aCurrentVal(1);
304 aCurrentVal
.getArray()[0] <<= m_sLoadedScheme
;
305 PutProperties(aCurrent
, aCurrentVal
);
308 void ColorConfig_Impl::SetColorConfigValue(ColorConfigEntry eValue
, const ColorConfigValue
& rValue
)
310 if(rValue
!= m_aConfigValues
[eValue
])
312 m_aConfigValues
[eValue
] = rValue
;
317 uno::Sequence
< OUString
> ColorConfig_Impl::GetSchemeNames()
319 return GetNodeNames("ColorSchemes");
322 bool ColorConfig_Impl::AddScheme(const OUString
& rScheme
)
324 if(ConfigItem::AddNode("ColorSchemes", rScheme
))
326 m_sLoadedScheme
= rScheme
;
333 bool ColorConfig_Impl::RemoveScheme(const OUString
& rScheme
)
335 uno::Sequence
< OUString
> aElements(1);
336 aElements
.getArray()[0] = rScheme
;
337 return ClearNodeElements("ColorSchemes", aElements
);
340 void ColorConfig_Impl::SettingsChanged()
342 SolarMutexGuard aVclGuard
;
344 ImplUpdateApplicationSettings();
349 IMPL_LINK( ColorConfig_Impl
, DataChangedEventListener
, VclWindowEvent
*, pEvent
)
351 if ( pEvent
->GetId() == VCLEVENT_APPLICATION_DATACHANGED
)
353 DataChangedEvent
* pData
= static_cast<DataChangedEvent
*>(pEvent
->GetData());
354 if ( (pData
->GetType() == DataChangedEventType::SETTINGS
) &&
355 (pData
->GetFlags() & AllSettingsFlags::STYLE
) )
367 /** updates the font color in the vcl window settings */
368 void ColorConfig_Impl::ImplUpdateApplicationSettings()
370 Application
* pApp
= GetpApp();
373 AllSettings aSettings
= Application::GetSettings();
374 StyleSettings
aStyleSettings( aSettings
.GetStyleSettings() );
376 ColorConfigValue aRet
= GetColorConfigValue(svtools::FONTCOLOR
);
377 if(COL_AUTO
== sal::static_int_cast
<ColorData
>(aRet
.nColor
))
378 aRet
.nColor
= ColorConfig::GetDefaultColor(svtools::FONTCOLOR
).GetColor();
380 Color
aFontColor(aRet
.nColor
);
382 if( aStyleSettings
.GetFontColor() != aFontColor
)
384 aStyleSettings
.SetFontColor( aFontColor
);
386 aSettings
.SetStyleSettings( aStyleSettings
);
387 Application::SetSettings( aSettings
);
394 ColorConfig::ColorConfig()
396 ::osl::MutexGuard
aGuard( ColorMutex_Impl::get() );
399 m_pImpl
= new ColorConfig_Impl
;
400 svtools::ItemHolder2::holdConfigItem(E_COLORCFG
);
402 ++nColorRefCount_Impl
;
403 m_pImpl
->AddListener(this);
406 ColorConfig::~ColorConfig()
408 ::osl::MutexGuard
aGuard( ColorMutex_Impl::get() );
409 m_pImpl
->RemoveListener(this);
410 if(!--nColorRefCount_Impl
)
417 Color
ColorConfig::GetDefaultColor(ColorConfigEntry eEntry
)
419 static const sal_Int32 aAutoColors
[] =
421 COL_WHITE
, // DOCCOLOR
422 0xc0c0c0, // DOCBOUNDARIES
423 0xDFDFDE, // APPBACKGROUND
424 COL_LIGHTGRAY
, // OBJECTBOUNDARIES
425 COL_LIGHTGRAY
, // TABLEBOUNDARIES
426 COL_BLACK
, // FONTCOLOR
428 0x0000cc, // LINKSVISITED
429 COL_LIGHTRED
, // SPELL
430 COL_LIGHTMAGENTA
,// SMARTTAGS
431 COL_GRAY
, // SHADOWCOLOR
432 COL_LIGHTGRAY
, // WRITERTEXTGRID
433 COL_LIGHTGRAY
, // WRITERFIELDSHADIN
434 COL_LIGHTGRAY
, // WRITERIDXSHADINGS
435 0, // WRITERDIRECTCURSOR
436 COL_GREEN
, //WRITERSCRIPTINDICATOR
437 COL_LIGHTGRAY
, //WRITERSECTIONBOUNDARIES
438 0x0369a3, //WRITERHEADERFOOTERMARK,
439 COL_BLUE
, //WRITERPAGEBREAKS,
440 COL_LIGHTBLUE
, // HTMLSGML
441 COL_LIGHTGREEN
, // HTMLCOMMENT
442 COL_LIGHTRED
, // HTMLKEYWORD
443 COL_GRAY
, // HTMLUNKNOWN
444 COL_LIGHTGRAY
, // CALCGRID
445 COL_BLUE
, //CALCPAGEBREAK
446 0x2300dc, //CALCPAGEBREAKMANUAL
447 COL_GRAY
, //CALCPAGEBREAKAUTOMATIC
448 COL_LIGHTBLUE
, // CALCDETECTIVE
449 COL_LIGHTRED
, // CALCDETECTIVEERROR
450 0xef0fff, // CALCREFERENCE
451 0xffffc0, // CALCNOTESBACKGROUND
452 COL_LIGHTGRAY
, // DRAWGRID
453 COL_GREEN
, // BASICIDENTIFIER,
454 COL_GRAY
,// BASICCOMMENT ,
455 COL_LIGHTRED
,// BASICNUMBER ,
456 COL_LIGHTRED
,// BASICSTRING ,
457 COL_BLUE
, // BASICOPERATOR ,
458 COL_BLUE
, // BASICKEYWORD ,
459 COL_RED
, //BASICERROR
460 0x009900, // SQLIDENTIFIER
461 0x000000, // SQLNUMBER
462 0xCE7B00, // SQLSTRING
463 0x000000, // SQLOPERATOR
464 0x0000E6, // SQLKEYWORD
465 0x259D9D, // SQLPARAMTER
466 0x969696,// SQLCOMMENT
472 aRet
= Application::GetSettings().GetStyleSettings().GetWorkspaceColor();
476 aRet
= Application::GetSettings().GetStyleSettings().GetLinkColor();
480 aRet
= Application::GetSettings().GetStyleSettings().GetVisitedLinkColor();
484 aRet
= aAutoColors
[eEntry
];
486 // fdo#71511: if in autodetected a11y HC mode, do pull background color from theme
487 if(m_pImpl
&& m_pImpl
->GetAutoDetectSystemHC())
492 aRet
= Application::GetSettings().GetStyleSettings().GetWindowColor();
495 aRet
= Application::GetSettings().GetStyleSettings().GetWindowTextColor();
504 ColorConfigValue
ColorConfig::GetColorValue(ColorConfigEntry eEntry
, bool bSmart
) const
506 ColorConfigValue aRet
= m_pImpl
->GetColorConfigValue(eEntry
);
509 if(COL_AUTO
== sal::static_int_cast
<ColorData
>(aRet
.nColor
))
510 aRet
.nColor
= ColorConfig::GetDefaultColor(eEntry
).GetColor();
516 void ColorConfig::Reload()
518 m_pImpl
->Load(OUString());
521 EditableColorConfig::EditableColorConfig() :
522 m_pImpl(new ColorConfig_Impl
),
525 m_pImpl
->BlockBroadcasts(true);
528 EditableColorConfig::~EditableColorConfig()
530 m_pImpl
->BlockBroadcasts(false);
532 m_pImpl
->SetModified();
533 if(m_pImpl
->IsModified())
538 uno::Sequence
< OUString
> EditableColorConfig::GetSchemeNames() const
540 return m_pImpl
->GetSchemeNames();
543 void EditableColorConfig::DeleteScheme(const OUString
& rScheme
)
545 m_pImpl
->RemoveScheme(rScheme
);
548 void EditableColorConfig::AddScheme(const OUString
& rScheme
)
550 m_pImpl
->AddScheme(rScheme
);
553 bool EditableColorConfig::LoadScheme(const OUString
& rScheme
)
556 m_pImpl
->SetModified();
557 if(m_pImpl
->IsModified())
560 m_pImpl
->Load(rScheme
);
561 //the name of the loaded scheme has to be committed separately
562 m_pImpl
->CommitCurrentSchemeName();
566 const OUString
& EditableColorConfig::GetCurrentSchemeName()const
568 return m_pImpl
->GetLoadedScheme();
571 // Changes the name of the current scheme but doesn't load it!
572 void EditableColorConfig::SetCurrentSchemeName(const OUString
& rScheme
)
574 m_pImpl
->SetCurrentSchemeName(rScheme
);
575 m_pImpl
->CommitCurrentSchemeName();
578 const ColorConfigValue
& EditableColorConfig::GetColorValue(
579 ColorConfigEntry eEntry
)const
581 return m_pImpl
->GetColorConfigValue(eEntry
);
584 void EditableColorConfig::SetColorValue(
585 ColorConfigEntry eEntry
, const ColorConfigValue
& rValue
)
587 m_pImpl
->SetColorConfigValue(eEntry
, rValue
);
588 m_pImpl
->ClearModified();
592 void EditableColorConfig::SetModified()
597 void EditableColorConfig::Commit()
600 m_pImpl
->SetModified();
601 if(m_pImpl
->IsModified())
606 void EditableColorConfig::DisableBroadcast()
608 m_pImpl
->BlockBroadcasts(true);
611 void EditableColorConfig::EnableBroadcast()
613 m_pImpl
->BlockBroadcasts(false);
619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */