sources/Google.Solutions.IapDesktop.Application/Theme/VSTheme.cs (257 lines of code) (raw):
//
// Copyright 2023 Google LLC
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml.Linq;
using WeifenLuo.WinFormsUI.Docking;
using WeifenLuo.WinFormsUI.ThemeVS2015;
namespace Google.Solutions.IapDesktop.Application.Theme
{
/// <summary>
/// Visual Studio theme as defined by a .vstheme file.
/// </summary>
internal class VSTheme : VS2015ThemeBase
{
public bool IsDark { get; }
public VSColorPalette Palette { get; }
private VSTheme(
VSColorPalette palette,
bool isDark) : base(palette)
{
this.Palette = palette;
this.IsDark = isDark;
this.ToolStripRenderer = new VSThemeExtensions.ToolStripRenderer(palette);
this.Extender.FloatWindowFactory = new VSThemeExtensions.FloatWindowFactory();
this.Extender.DockPaneFactory =
new VSThemeExtensions.DockPaneFactory(this.Extender.DockPaneFactory);
}
public static VSTheme GetLightTheme()
{
return FromResource("Light.vstheme.gz", false);
}
public static VSTheme GetDarkTheme()
{
return FromResource("Dark.vstheme.gz", true);
}
/// <summary>
/// Read gzip-compressed VSTheme XML file from embedded resource.
/// </summary>
public static VSTheme FromResource(string resourceName, bool isDark)
{
var assembly = typeof(VSTheme).Assembly;
var qualifiedResourceName = assembly
.GetManifestResourceNames()
.FirstOrDefault(n => n.EndsWith(resourceName));
if (qualifiedResourceName == null)
{
throw new IOException(
$"The theme {resourceName} does not exist");
}
using (var gzipStream = assembly.GetManifestResourceStream(qualifiedResourceName))
using (var stream = new GZipStream(gzipStream, CompressionMode.Decompress))
using (var reader = new StreamReader(stream))
{
return new VSTheme(
new VSColorPalette(XDocument.Load(reader)),
isDark);
}
}
//---------------------------------------------------------------------
// Palette.
//---------------------------------------------------------------------
internal class VSColorPalette : DockPanelColorPalette
{
public ToolWindowInnerTabPalette ToolWindowInnerTabInactive { get; }
public GridHeadingPallette GridHeading { get; }
public WindowPallette Window { get; }
public ButtonPallette Button { get; }
public LabelPalette Label { get; }
public LabelPalette LinkLabel { get; }
public LabelPalette HeaderLabel { get; }
public TextBoxPalette TextBox { get; }
public ComboBoxPalette ComboBox { get; }
public ProgressBarPalette ProgressBar { get; }
public TabControlPalette TabControl { get; }
public StatusBarPallette StatusBar { get; }
public VSColorPalette(XDocument xml) : base(xml)
{
this.ToolWindowInnerTabInactive = new ToolWindowInnerTabPalette()
{
Background = GetColor(xml, "CommonControls", "InnerTabInactiveBackground", "Background"),
Text = GetColor(xml, "CommonControls", "InnerTabInactiveText", "Background"),
};
this.GridHeading = new GridHeadingPallette()
{
Background = GetColor(xml, "Environment", "ToolWindowContentGrid", "Background"),
Text = GetColor(xml, "Environment", "GridHeadingText", "Background")
};
this.Window = new WindowPallette()
{
Background = GetColor(xml, "Environment", "Window", "Background"),
Frame = GetColor(xml, "Environment", "WindowFrame", "Background"),
Text = GetColor(xml, "Environment", "WindowText", "Background")
};
this.Button = new ButtonPallette()
{
Background = GetColor(xml, "CommonControls", "Button", "Background"),
Text = GetColor(xml, "CommonControls", "Button", "Foreground"),
Border = GetColor(xml, "CommonControls", "ButtonBorder", "Background"),
BorderFocused = GetColor(xml, "CommonControls", "ButtonBorderFocused", "Background"),
BorderHover = GetColor(xml, "CommonControls", "ButtonBorderHover", "Background"),
BackgroundHover = GetColor(xml, "CommonControls", "ButtonHover", "Background"),
BackgroundPressed = GetColor(xml, "CommonControls", "ButtonPressed", "Background"),
DropDownGlyphColor = GetColor(xml, "CommonControls", "ComboBoxGlyph", "Background"),
DropDownGlyphDisabledColor = GetColor(xml, "CommonControls", "ComboBoxGlyphDisabled", "Background"),
};
this.Label = new LabelPalette()
{
Text = GetColor(xml, "Environment", "CaptionText", "Background"),
};
this.LinkLabel = new LabelPalette()
{
Text = GetColor(xml, "Environment", "ControlLinkText", "Background"),
};
this.HeaderLabel = new LabelPalette()
{
Text = GetColor(xml, "Environment", "BrandedUITitle", "Background"),
};
this.TextBox = new TextBoxPalette()
{
Text = GetColor(xml, "CommonControls", "TextBoxText", "Background"),
Background = GetColor(xml, "CommonControls", "TextBoxBackground", "Background"),
BackgroundDisabled = GetColor(xml, "CommonControls", "TextBoxBackgroundDisabled", "Background"),
Border = GetColor(xml, "CommonControls", "TextBoxBorder", "Background"),
BorderFocused = GetColor(xml, "CommonControls", "TextBoxBorderFocused", "Background"),
BorderHover = GetColor(xml, "CommonControls", "ButtonBorderHover", "Background"),
};
this.ComboBox = new ComboBoxPalette()
{
Text = GetColor(xml, "CommonControls", "TextBoxText", "Background"),
Background = GetColor(xml, "CommonControls", "ComboBoxBackground", "Background"),
};
this.ProgressBar = new ProgressBarPalette()
{
Background = GetColor(xml, "ProgressBar", "Background", "Background"),
Indicator = GetColor(xml, "ProgressBar", "IndicatorFill", "Background"),
};
this.TabControl = new TabControlPalette()
{
TabBackground = GetColor(xml, "ProjectDesigner", "CategoryTab", "Background"),
TabText = GetColor(xml, "ProjectDesigner", "CategoryTab", "Foreground"),
SelectedTabBackground = GetColor(xml, "ProjectDesigner", "SelectedCategoryTab", "Background"),
SelectedTabText = GetColor(xml, "ProjectDesigner", "SelectedCategoryTab", "Foreground"),
MouseOverTabBackground = GetColor(xml, "ProjectDesigner", "MouseOverCategoryTab", "Background"),
MouseOverTabText = GetColor(xml, "ProjectDesigner", "MouseOverCategoryTab", "Foreground"),
};
this.TabSelectedActiveAccent1 = new TabPalette()
{
Background = GetColor(xml, "Environment", "VizSurfaceDarkGoldDark", "Background"),
Text = this.TabSelectedActive.Text,
Button = this.TabSelectedActive.Button
};
this.TabSelectedActiveAccent2 = new TabPalette()
{
Background = GetColor(xml, "Environment", "VizSurfacePlumDark", "Background"),
Text = this.TabSelectedActive.Text,
Button = this.TabSelectedActive.Button
};
this.TabSelectedActiveAccent3 = new TabPalette()
{
Background = GetColor(xml, "Environment", "VizSurfaceGreenDark", "Background"),
Text = this.TabSelectedActive.Text,
Button = this.TabSelectedActive.Button
};
this.TabSelectedActiveAccent4 = new TabPalette()
{
Background = GetColor(xml, "Environment", "VizSurfaceBrownDark", "Background"),
Text = this.TabSelectedActive.Text,
Button = this.TabSelectedActive.Button
};
this.CommandBarMenuTopLevelHeaderHovered.Border
= GetColor(xml, "Environment", "CommandBarMenuItemMouseOverBorder", "Background");
this.StatusBar = new StatusBarPallette()
{
InactiveBackground = GetColor(xml, "Environment", "StatusBarDefault", "Background"),
InactiveText = GetColor(xml, "Environment", "StatusBarDefault", "Foreground"),
ActiveBackground = GetColor(xml, "Environment", "StatusBarDebugging", "Background"),
ActiveText = GetColor(xml, "Environment", "StatusBarDebugging", "Foreground"),
};
}
protected static Color GetColor(
XDocument xml,
string category,
string name,
string type)
{
var color = xml.Root.Element("Theme")
.Elements("Category").FirstOrDefault(item => item.Attribute("Name").Value == category)?
.Elements("Color").FirstOrDefault(item => item.Attribute("Name").Value == name)?
.Element(type).Attribute("Source").Value;
if (color == null)
{
return Color.Transparent;
}
return ColorTranslator.FromHtml($"#{color}");
}
}
internal struct ToolWindowInnerTabPalette
{
public Color Background { get; set; }
public Color Text { get; set; }
}
internal struct GridHeadingPallette
{
public Color Background { get; set; }
public Color Text { get; set; }
}
internal struct StatusBarPallette
{
public Color InactiveBackground { get; set; }
public Color InactiveText { get; set; }
public Color ActiveBackground { get; set; }
public Color ActiveText { get; set; }
}
internal struct WindowPallette
{
public Color Background { get; set; }
public Color Frame { get; set; }
public Color Text { get; set; }
}
internal struct ButtonPallette
{
public Color Background { get; set; }
public Color Text { get; set; }
public Color Border { get; set; }
public Color BorderFocused { get; set; }
public Color BorderHover { get; set; }
public Color BackgroundHover { get; set; }
public Color BackgroundPressed { get; set; }
public Color DropDownGlyphColor { get; set; }
public Color DropDownGlyphDisabledColor { get; set; }
}
internal struct LabelPalette
{
public Color Text { get; set; }
}
internal struct TextBoxPalette
{
public Color Text { get; set; }
public Color Background { get; set; }
public Color BackgroundDisabled { get; set; }
public Color Border { get; set; }
public Color BorderFocused { get; set; }
public Color BorderHover { get; set; }
}
internal struct ComboBoxPalette
{
public Color Text { get; set; }
public Color Background { get; set; }
}
internal struct ProgressBarPalette
{
public Color Indicator { get; set; }
public Color Background { get; set; }
}
internal struct TabControlPalette
{
public Color TabBackground { get; set; }
public Color TabText { get; set; }
public Color MouseOverTabBackground { get; set; }
public Color MouseOverTabText { get; set; }
public Color SelectedTabBackground { get; set; }
public Color SelectedTabText { get; set; }
}
}
}