Commit 54b3be95 authored by Martin Seher's avatar Martin Seher Committed by Milian Wolff
Browse files

Configurable semantic colors

Add a page under _Color Themes -> Highlighting Text Styles -> KDevelop/Semantic Colors_ that allows the configuration of the semantic highlight colors.
- When the _Local colorization intensity_ is bigger than zero then the rainbow colors are used for local variables like before, overwriting the corresponding configured colors
- A _Global colorization intensity_ less then 255 (max) will still cause a blending of the global colors
- _Bold font for declarations_ will make the declarations bold in addition to the bold settings from the config dialog

So a _Local colorization intensity_ of 0 and a _Global colorization intensity_ of 255 should be set when the exact configured colors are desired.

See also:
https://invent.kde.org/kdevelop/kdevelop/uploads/500467bc355906d363e3a76a9044e138/ColorConfig.png

BUG: 395856
parent 6fe94005
Pipeline #197890 passed with stage
in 17 minutes and 38 seconds
......@@ -151,6 +151,7 @@ set(KDevPlatformLanguage_LIB_SRCS
highlighting/colorcache.cpp
highlighting/configurablecolors.cpp
highlighting/codehighlighting.cpp
highlighting/syntax/syntax.qrc
checks/dataaccessrepository.cpp checks/dataaccess.cpp
checks/controlflowgraph.cpp checks/controlflownode.cpp
......
......@@ -230,9 +230,10 @@ void CodeHighlightingInstance::highlightDUChain(DUContext* context, QHash<Declar
QList<Declaration*> takeFreeColors;
bool noRainbow = ICore::self()->languageController()->completionSettings()->localColorizationLevel() == 0;
const auto localDeclarations = context->localDeclarations();
for (Declaration* dec : localDeclarations) {
if (!useRainbowColor(dec)) {
if (noRainbow || !useRainbowColor(dec)) {
highlightDeclaration(dec, QColor(QColor::Invalid));
continue;
}
......@@ -402,10 +403,19 @@ CodeHighlightingInstance::Types CodeHighlightingInstance::typeForDeclaration(Dec
//Determine the class we're in
Declaration* klass = localClassFromCodeContext(context);
if (klass) {
if (klass->internalContext() == dec->context())
type = LocalClassMemberType; //Using Member of the local class
else if (klass->internalContext() && klass->internalContext()->imports(dec->context()))
type = InheritedClassMemberType; //Using Member of an inherited class
if (klass->internalContext() == dec->context()) {
//Using Member of the local class
if (dec->type<KDevelop::FunctionType>())
type = LocalMemberFunctionType;
else
type = LocalClassMemberType;
} else if (klass->internalContext() && klass->internalContext()->imports(dec->context())) {
//Using Member of an inherited clas
if (dec->type<KDevelop::FunctionType>())
type = InheritedMemberFunctionType;
else
type = InheritedClassMemberType;
}
}
}
......
......@@ -35,7 +35,9 @@ struct HighlightingEnumContainer
UnknownType,
//Primary highlighting:
LocalClassMemberType,
LocalMemberFunctionType,
InheritedClassMemberType,
InheritedMemberFunctionType,
LocalVariableType,
//Other highlighting:
......@@ -52,6 +54,7 @@ struct HighlightingEnumContainer
MemberVariableType,
NamespaceVariableType,
GlobalVariableType,
HighlightUsesType,
//Most of these are currently not used:
ArgumentType,
......
......@@ -26,12 +26,60 @@
#include <KTextEditor/Document>
#include <KTextEditor/View>
#include <KTextEditor/ConfigInterface>
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Format>
#define ifDebug(x)
namespace KDevelop {
ColorCache* ColorCache::m_self = nullptr;
HighlightingEnumContainer::Types getHighlightingTypeFromName(const QString& name)
{
if (name == QLatin1String("Class")) {
return CodeHighlightingInstance::ClassType;
} else if (name == QLatin1String("Local Member Variable")) {
return CodeHighlightingInstance::LocalClassMemberType;
} else if (name == QLatin1String("Local Member Function")) {
return CodeHighlightingInstance::LocalMemberFunctionType;
} else if (name == QLatin1String("Inherited Member Variable")) {
return CodeHighlightingInstance::InheritedClassMemberType;
} else if (name == QLatin1String("Inherited Member Function")) {
return CodeHighlightingInstance::InheritedMemberFunctionType;
} else if (name == QLatin1String("Function")) {
return CodeHighlightingInstance::FunctionType;
} else if (name == QLatin1String("Function Argument")) {
return CodeHighlightingInstance::FunctionVariableType;
} else if (name == QLatin1String("Type Alias")) {
return CodeHighlightingInstance::TypeAliasType;
} else if (name == QLatin1String("Forward Declaration")) {
return CodeHighlightingInstance::ForwardDeclarationType;
} else if (name == QLatin1String("Namespace")) {
return CodeHighlightingInstance::NamespaceType;
} else if (name == QLatin1String("Local Variable")) {
return CodeHighlightingInstance::LocalVariableType;
} else if (name == QLatin1String("Global Variable")) {
return CodeHighlightingInstance::GlobalVariableType;
} else if (name == QLatin1String("Member Variable")) {
return CodeHighlightingInstance::MemberVariableType;
} else if (name == QLatin1String("Namespace Variable")) {
return CodeHighlightingInstance::NamespaceVariableType;
} else if (name == QLatin1String("Enumeration")) {
return CodeHighlightingInstance::EnumType;
} else if (name == QLatin1String("Enumerator")) {
return CodeHighlightingInstance::EnumeratorType;
} else if (name == QLatin1String("Macro")) {
return CodeHighlightingInstance::MacroType;
} else if (name == QLatin1String("Macro Function")) {
return CodeHighlightingInstance::MacroFunctionLikeType;
} else if (name == QLatin1String("Highlight Uses")) {
return CodeHighlightingInstance::HighlightUsesType;
} else if (name == QLatin1String("Error Variable")) {
return CodeHighlightingInstance::ErrorVariableType;
}
return CodeHighlightingInstance::UnknownType;
}
ColorCache::ColorCache(QObject* parent)
: QObject(parent)
, m_defaultColors(nullptr)
......@@ -91,12 +139,10 @@ ColorCache* ColorCache::self()
void ColorCache::generateColors()
{
if (m_defaultColors) {
delete m_defaultColors;
if (!m_defaultColors) {
m_defaultColors = new CodeHighlightingColors(this);
}
m_defaultColors = new CodeHighlightingColors(this);
// Primary colors taken from: http://colorbrewer2.org/?type=qualitative&scheme=Paired&n=12
const QColor colors[] = {
{"#b15928"}, {"#ff7f00"}, {"#b2df8a"}, {"#33a02c"}, {"#a6cee3"},
......@@ -188,6 +234,7 @@ void ColorCache::updateColorsFromView(KTextEditor::View* view)
#endif
m_view = view;
bool anyAttrChanged = false;
if (!foreground.isValid()) {
// fallback to colorscheme variant
ifDebug(qCDebug(LANGUAGE) << "updating from scheme"; )
......@@ -195,12 +242,89 @@ void ColorCache::updateColorsFromView(KTextEditor::View* view)
} else if (m_foregroundColor != foreground || m_backgroundColor != background) {
m_foregroundColor = foreground;
m_backgroundColor = background;
anyAttrChanged = true;
}
anyAttrChanged |= updateColorsFromTheme(view->theme());
if (anyAttrChanged) {
ifDebug(qCDebug(LANGUAGE) << "updating from document"; )
update();
}
}
bool ColorCache::updateColorsFromTheme(const KSyntaxHighlighting::Theme& theme)
{
// from ktexteditor/src/syntax/kateextendedattribute.h
static const int SelectedBackground = QTextFormat::UserProperty + 2;
const auto schemeDefinition = m_schemeRepo.definitionForName(QStringLiteral("Semantic Colors"));
const auto formats = schemeDefinition.formats();
const bool blendColors = m_globalColorRatio < 255;
bool anyAttrChanged = false;
for (const auto& format : formats) {
const auto type = getHighlightingTypeFromName(format.name());
const auto attr = m_defaultColors->attribute(type);
auto fg = format.textColor(theme);
auto selFg = format.selectedTextColor(theme);
if (blendColors) {
fg = blendGlobalColor(fg);
selFg = blendGlobalColor(selFg);
}
if (attr->fontBold() != format.isBold(theme)) {
attr->setFontBold(format.isBold(theme));
anyAttrChanged = true;
}
if (attr->fontItalic() != format.isItalic(theme)) {
attr->setFontItalic(format.isItalic(theme));
anyAttrChanged = true;
}
if (attr->fontUnderline() != format.isUnderline(theme)) {
attr->setFontUnderline(format.isUnderline(theme));
anyAttrChanged = true;
}
if (attr->fontStrikeOut() != format.isStrikeThrough(theme)) {
attr->setFontStrikeOut(format.isStrikeThrough(theme));
anyAttrChanged = true;
}
if (attr->foreground().color() != fg) {
attr->setForeground(fg);
anyAttrChanged = true;
}
if (attr->selectedForeground().color() != selFg) {
attr->setSelectedForeground(selFg);
anyAttrChanged = true;
}
if (format.hasBackgroundColor(theme)) {
if (attr->background().color() != format.backgroundColor(theme)) {
attr->setBackground(format.backgroundColor(theme));
anyAttrChanged = true;
}
} else if (type == CodeHighlightingInstance::HighlightUsesType ) {
auto background = QColor(theme.editorColor(KSyntaxHighlighting::Theme::SearchHighlight));
if (attr->background().color() != background) {
attr->setBackground(background);
anyAttrChanged = true;
}
} else if (attr->background() != QBrush()) {
attr->setBackground(QBrush());
anyAttrChanged = true;
}
// from KSyntaxHighlighting::Format::isDefaultTextStyle
if (format.selectedBackgroundColor(theme).rgba() != theme.selectedBackgroundColor(KSyntaxHighlighting::Theme::Normal)) {
if (attr->selectedBackground().color() != format.selectedBackgroundColor(theme)) {
attr->setSelectedBackground(format.selectedBackgroundColor(theme));
anyAttrChanged = true;
}
} else if (attr->hasProperty(SelectedBackground)) {
attr->clearProperty(SelectedBackground);
anyAttrChanged = true;
}
}
return anyAttrChanged;
}
void ColorCache::updateColorsFromScheme()
{
KColorScheme scheme(QPalette::Normal, KColorScheme::View);
......@@ -220,10 +344,14 @@ void ColorCache::updateColorsFromSettings()
int localRatio = ICore::self()->languageController()->completionSettings()->localColorizationLevel();
int globalRatio = ICore::self()->languageController()->completionSettings()->globalColorizationLevel();
bool boldDeclartions = ICore::self()->languageController()->completionSettings()->boldDeclarations();
bool globalRatioChanged = globalRatio != m_globalColorRatio;
if (localRatio != m_localColorRatio || globalRatio != m_globalColorRatio) {
if (localRatio != m_localColorRatio || globalRatioChanged) {
m_localColorRatio = localRatio;
m_globalColorRatio = globalRatio;
if (m_view && globalRatioChanged) {
updateColorsFromTheme(m_view->theme());
}
update();
}
if (boldDeclartions != m_boldDeclarations) {
......
......@@ -11,9 +11,14 @@
#include <QVector>
#include <QColor>
#include <QPointer>
#include <KSyntaxHighlighting/Repository>
#include <language/languageexport.h>
namespace KSyntaxHighlighting {
class Theme;
}
namespace KTextEditor {
class Document;
class View;
......@@ -126,6 +131,8 @@ private:
/// @see generateColors(), updateColorsFromScheme()
void updateColorsFromView(KTextEditor::View* view);
bool updateColorsFromTheme(const KSyntaxHighlighting::Theme& theme);
/// the default colors for the different types
CodeHighlightingColors* m_defaultColors;
......@@ -158,6 +165,8 @@ private:
/// The view we are listening to for setting changes.
QPointer<KTextEditor::View> m_view;
KSyntaxHighlighting::Repository m_schemeRepo;
};
}
......
......@@ -60,7 +60,9 @@ CodeHighlightingColors::CodeHighlightingColors(ColorCache* cache) : Configurable
ADD_COLOR(FunctionType, 0x21005A) //Navy blue
ADD_COLOR(MemberVariableType, 0x443069) //Dark Burple (blue/purple)
ADD_COLOR(LocalClassMemberType, 0xae7d00) //Light orange
ADD_COLOR(LocalMemberFunctionType, 0xae7d00)
ADD_COLOR(InheritedClassMemberType, 0x705000) //Dark orange
ADD_COLOR(InheritedMemberFunctionType, 0x705000)
ADD_COLOR(LocalVariableType, 0x0C4D3C)
ADD_COLOR(FunctionVariableType, 0x300085) //Less dark navy blue
ADD_COLOR(NamespaceVariableType, 0x9F3C5F) //Rose
......@@ -70,5 +72,6 @@ CodeHighlightingColors::CodeHighlightingColors(ColorCache* cache) : Configurable
ADD_COLOR(ForwardDeclarationType, 0x5C5C5C) //Gray
ADD_COLOR(MacroType, 0xA41239)
ADD_COLOR(MacroFunctionLikeType, 0x008080)
ADD_COLOR(HighlightUsesType, 0xffffff)
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "language.dtd">
<language
name="Semantic Colors"
section="KDevelop"
version="1"
kateversion="5.0"
mimetype=""
extensions=""
author="Martin Seher (martin.seher@gmail.com)"
hidden="true"
>
<highlighting>
<contexts>
<context attribute="Class" lineEndContext="#stay" name="Normal">
</context>
</contexts>
<itemDatas>
<itemData name="Class" defStyleNum="dsDataType" spellChecking="false" bold="0" italic="0" />
<itemData name="Local Member Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Local Member Function" defStyleNum="dsFunction" spellChecking="false" />
<itemData name="Inherited Member Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Inherited Member Function" defStyleNum="dsFunction" spellChecking="false" />
<itemData name="Function" defStyleNum="dsFunction" spellChecking="false" />
<itemData name="Function Argument" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Type Alias" defStyleNum="dsDataType" spellChecking="false" bold="0" italic="0" />
<itemData name="Forward Declaration" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Namespace" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Local Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Global Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Member Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Namespace Variable" defStyleNum="dsVariable" spellChecking="false" />
<itemData name="Enumeration" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Enumerator" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Macro" defStyleNum="dsPreprocessor" spellChecking="false" />
<itemData name="Macro Function" defStyleNum="dsPreprocessor" spellChecking="false" />
<itemData name="Highlight Uses" defStyleNum="dsNormal" spellChecking="false" />
<itemData name="Error Variable" defStyleNum="dsError" spellChecking="false" />
</itemDatas>
</highlighting>
</language>
<!-- kate: indent-width 2; tab-width 2; -->
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/org.kde.syntax-highlighting/syntax-addons">
<file>kdevelop-semantic-colors.xml</file>
</qresource>
</RCC>
......@@ -42,6 +42,8 @@
#include <language/interfaces/iquickopen.h>
#include <language/highlighting/colorcache.h>
#include <language/highlighting/configurablecolors.h>
#include <language/highlighting/codehighlighting.h>
#include <language/duchain/duchain.h>
#include <language/duchain/ducontext.h>
......@@ -712,17 +714,10 @@ void ContextBrowserPlugin::clearMouseHover()
m_mouseHoverDocument.clear();
}
Attribute::Ptr ContextBrowserPlugin::highlightedUseAttribute(KTextEditor::View* view) const
Attribute::Ptr ContextBrowserPlugin::highlightedUseAttribute() const
{
if (!m_highlightAttribute) {
m_highlightAttribute = Attribute::Ptr(new Attribute());
m_highlightAttribute->setDefaultStyle(KTextEditor::dsNormal);
m_highlightAttribute->setForeground(m_highlightAttribute->selectedForeground());
m_highlightAttribute->setBackgroundFillWhitespace(true);
auto iface = qobject_cast<KTextEditor::ConfigInterface*>(view);
auto background = iface->configValue(QStringLiteral("search-highlight-color")).value<QColor>();
m_highlightAttribute->setBackground(background);
m_highlightAttribute = ColorCache::self()->defaultColors()->attribute(CodeHighlightingInstance::HighlightUsesType);
}
return m_highlightAttribute;
}
......@@ -732,9 +727,9 @@ void ContextBrowserPlugin::colorSetupChanged()
m_highlightAttribute = Attribute::Ptr();
}
Attribute::Ptr ContextBrowserPlugin::highlightedSpecialObjectAttribute(KTextEditor::View* view) const
Attribute::Ptr ContextBrowserPlugin::highlightedSpecialObjectAttribute() const
{
return highlightedUseAttribute(view);
return highlightedUseAttribute();
}
void ContextBrowserPlugin::addHighlight(View* view, KDevelop::Declaration* decl)
......@@ -750,7 +745,7 @@ void ContextBrowserPlugin::addHighlight(View* view, KDevelop::Declaration* decl)
// Highlight the declaration
highlights.highlights << decl->createRangeMoving();
highlights.highlights.back()->setAttribute(highlightedUseAttribute(view));
highlights.highlights.back()->setAttribute(highlightedUseAttribute());
highlights.highlights.back()->setZDepth(highlightingZDepth);
// Highlight uses
......@@ -761,7 +756,7 @@ void ContextBrowserPlugin::addHighlight(View* view, KDevelop::Declaration* decl)
const auto& documentUses = fileIt.value();
for (auto& use : documentUses) {
highlights.highlights << PersistentMovingRange::Ptr(new PersistentMovingRange(use, document));
highlights.highlights.back()->setAttribute(highlightedUseAttribute(view));
highlights.highlights.back()->setAttribute(highlightedUseAttribute());
highlights.highlights.back()->setZDepth(highlightingZDepth);
}
}
......@@ -769,7 +764,7 @@ void ContextBrowserPlugin::addHighlight(View* view, KDevelop::Declaration* decl)
if (auto* def = FunctionDefinition::definition(decl)) {
highlights.highlights << def->createRangeMoving();
highlights.highlights.back()->setAttribute(highlightedUseAttribute(view));
highlights.highlights.back()->setAttribute(highlightedUseAttribute());
highlights.highlights.back()->setZDepth(highlightingZDepth);
}
}
......@@ -859,7 +854,7 @@ void ContextBrowserPlugin::updateForView(View* view)
if (allowHighlight) {
highlights.highlights <<
PersistentMovingRange::Ptr(new PersistentMovingRange(specialRange, IndexedString(url)));
highlights.highlights.back()->setAttribute(highlightedSpecialObjectAttribute(view));
highlights.highlights.back()->setAttribute(highlightedSpecialObjectAttribute());
highlights.highlights.back()->setZDepth(highlightingZDepth);
}
if (updateBrowserView)
......
......@@ -108,8 +108,8 @@ public:
void showUses(const KDevelop::DeclarationPointer& declaration) override;
KTextEditor::Attribute::Ptr highlightedUseAttribute(KTextEditor::View* view) const;
KTextEditor::Attribute::Ptr highlightedSpecialObjectAttribute(KTextEditor::View* view) const;
KTextEditor::Attribute::Ptr highlightedUseAttribute() const;
KTextEditor::Attribute::Ptr highlightedSpecialObjectAttribute() const;
public Q_SLOTS:
void showUsesDelayed(const KDevelop::DeclarationPointer& declaration);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment