diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..63a868c
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,13 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
+
+## [vNext]
+
+## [1.0.0] / YYYY-MM-DD
+- First Release
+
+[vNext]: https://github.com/ricaun-io/ricaun.Revit.UI/compare/1.0.0...HEAD
+[1.0.0]: https://github.com/ricaun-io/ricaun.Revit.UI/compare/1.0.0
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..78898b0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# ricaun.Revit.UI
+
+[![Publish](https://github.com/ricaun-io/ricaun.Revit.UI/actions/workflows/Publish.yml/badge.svg)](https://github.com/ricaun-io/ricaun.Revit.UI/actions)
+[![Develop](https://github.com/ricaun-io/ricaun.Revit.UI/actions/workflows/Develop.yml/badge.svg)](https://github.com/ricaun-io/ricaun.Revit.UI/actions)
+
+---
+
+Copyright © 2021 ricaun
+
diff --git a/ricaun.Revit.UI.sln b/ricaun.Revit.UI.sln
new file mode 100644
index 0000000..1e05a64
--- /dev/null
+++ b/ricaun.Revit.UI.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31911.196
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ricaun.Revit.UI", "ricaun.Revit.UI\ricaun.Revit.UI.csproj", "{2064BA4D-5527-41E9-8B76-0CBFEFA35900}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Project", "Project", "{A81D2950-B5CB-4CDB-B7FE-9132C730C8CC}"
+ ProjectSection(SolutionItems) = preProject
+ ricaun.Revit.UI\CHANGELOG.md = ricaun.Revit.UI\CHANGELOG.md
+ ricaun.Revit.UI\README.md = ricaun.Revit.UI\README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2064BA4D-5527-41E9-8B76-0CBFEFA35900}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2064BA4D-5527-41E9-8B76-0CBFEFA35900}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2064BA4D-5527-41E9-8B76-0CBFEFA35900}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2064BA4D-5527-41E9-8B76-0CBFEFA35900}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E22315E4-8753-4610-B0F8-91367AEA4F9A}
+ EndGlobalSection
+EndGlobal
diff --git a/ricaun.Revit.UI/AutodeskExtension.cs b/ricaun.Revit.UI/AutodeskExtension.cs
new file mode 100644
index 0000000..bf561fb
--- /dev/null
+++ b/ricaun.Revit.UI/AutodeskExtension.cs
@@ -0,0 +1,32 @@
+using Autodesk.Windows;
+using System.Windows;
+using System.Windows.Interop;
+
+namespace ricaun.Revit.UI
+{
+ ///
+ /// AutodeskExtension
+ ///
+ public static class AutodeskExtension
+ {
+ ///
+ /// Set Autodesk.Windows as the Owner of the Window
+ ///
+ ///
+ public static void SetAutodeskOwner(this Window window)
+ {
+ new WindowInteropHelper(window) { Owner = ComponentManager.ApplicationWindow };
+ }
+
+ ///
+ /// Get Autodesk.Windows as the Owner Window
+ ///
+ ///
+ public static Window GetAutodeskOwner()
+ {
+ var owner = ComponentManager.ApplicationWindow;
+ var source = System.Windows.Interop.HwndSource.FromHwnd(owner);
+ return source.RootVisual as Window;
+ }
+ }
+}
diff --git a/ricaun.Revit.UI/BitmapExtension.cs b/ricaun.Revit.UI/BitmapExtension.cs
new file mode 100644
index 0000000..2e009e1
--- /dev/null
+++ b/ricaun.Revit.UI/BitmapExtension.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Windows;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace ricaun.Revit.UI
+{
+ ///
+ /// BitmapExtension
+ ///
+ public static class BitmapExtension
+ {
+ ///
+ /// GetBitmapSource
+ ///
+ ///
+ ///
+ public static BitmapSource GetBitmapSource(this System.Drawing.Bitmap bitmap)
+ {
+ var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
+ bitmap.GetHbitmap(),
+ IntPtr.Zero,
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ return bitmapSource;
+ }
+
+ ///
+ /// GetBitmapSource
+ ///
+ ///
+ ///
+ public static BitmapSource GetBitmapSource(this System.Drawing.Icon icon)
+ {
+ var bitmapSource = Imaging.CreateBitmapSourceFromHIcon(
+ icon.ToBitmap().GetHicon(),
+ Int32Rect.Empty,
+ BitmapSizeOptions.FromEmptyOptions());
+
+ return bitmapSource;
+ }
+
+ ///
+ /// GetBitmapSource
+ ///
+ ///
+ ///
+ public static BitmapSource GetBitmapSource(this System.Drawing.Image image)
+ {
+ var bitmap = new System.Drawing.Bitmap(image);
+ return bitmap.GetBitmapSource();
+ }
+
+ ///
+ /// Transform string base64 to BitmapSource
+ ///
+ ///
+ ///
+ public static BitmapSource GetBitmapSource(this string base64)
+ {
+ var image = System.Drawing.Bitmap.FromStream(new MemoryStream(Convert.FromBase64String(base64)));
+ return image.GetBitmapSource();
+ }
+
+ ///
+ /// Scale
+ ///
+ ///
+ ///
+ ///
+ public static BitmapSource Scale(this BitmapSource bitmapSource, double scale)
+ {
+ return new TransformedBitmap(bitmapSource, new ScaleTransform(scale, scale));
+ }
+ }
+}
diff --git a/ricaun.Revit.UI/LanguageExtension.cs b/ricaun.Revit.UI/LanguageExtension.cs
new file mode 100644
index 0000000..4d6a9be
--- /dev/null
+++ b/ricaun.Revit.UI/LanguageExtension.cs
@@ -0,0 +1,137 @@
+using Autodesk.Revit.ApplicationServices;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace ricaun.Revit.UI
+{
+ ///
+ /// LanguageExtension
+ ///
+ public static class LanguageExtension
+ {
+ ///
+ /// Get Base LanguageType
+ ///
+ ///
+ public static LanguageType GetLanguageType()
+ {
+ return GetCultureInfo().GetLanguageType();
+ }
+
+ ///
+ /// Get LanguageType as CultureInfoName
+ ///
+ ///
+ ///
+ public static string GetCultureInfoName(this LanguageType languageType)
+ {
+ string language = "";
+ switch (languageType)
+ {
+ case LanguageType.Unknown:
+ language = "";
+ break;
+ case LanguageType.English_USA:
+ language = "en-US";
+ break;
+ case LanguageType.German:
+ language = "de-DE";
+ break;
+ case LanguageType.Spanish:
+ language = "es-ES";
+ break;
+ case LanguageType.French:
+ language = "fr-FR";
+ break;
+ case LanguageType.Italian:
+ language = "it-IT";
+ break;
+ case LanguageType.Dutch:
+ language = "nl-BE";
+ break;
+ case LanguageType.Chinese_Simplified:
+ language = "zh-CHS";
+ break;
+ case LanguageType.Chinese_Traditional:
+ language = "zh-CHT";
+ break;
+ case LanguageType.Japanese:
+ language = "ja-JP";
+ break;
+ case LanguageType.Korean:
+ language = "ko-KR";
+ break;
+ case LanguageType.Russian:
+ language = "ru-RU";
+ break;
+ case LanguageType.Czech:
+ language = "cs-CZ";
+ break;
+ case LanguageType.Polish:
+ language = "pl-PL";
+ break;
+ case LanguageType.Hungarian:
+ language = "hu-HU";
+ break;
+ case LanguageType.Brazilian_Portuguese:
+ language = "pt-BR";
+ break;
+ }
+ return language;
+ }
+
+ ///
+ /// Get LanguageType by Culture Key
+ ///
+ ///
+ public static Dictionary GetLanguages()
+ {
+ var languages = new Dictionary();
+
+ languages.Add("en-US", LanguageType.English_USA);
+ languages.Add("de-DE", LanguageType.German);
+ languages.Add("es-ES", LanguageType.Spanish);
+ languages.Add("fr-FR", LanguageType.French);
+ languages.Add("nl-BE", LanguageType.Dutch);
+ languages.Add("zh-CHS", LanguageType.Chinese_Simplified);
+ languages.Add("zh-CHT", LanguageType.Chinese_Traditional);
+ languages.Add("ko-KR", LanguageType.Korean);
+ languages.Add("ru-RU", LanguageType.Russian);
+ languages.Add("cs-CZ", LanguageType.Czech);
+ languages.Add("pl-PL", LanguageType.Polish);
+ languages.Add("hu-HU", LanguageType.Hungarian);
+ languages.Add("pt-BR", LanguageType.Brazilian_Portuguese);
+
+ return languages;
+ }
+
+ ///
+ /// Get CultureInfo LanguageType
+ ///
+ ///
+ ///
+ private static LanguageType GetLanguageType(this CultureInfo cultureInfo)
+ {
+ var languages = GetLanguages();
+
+ LanguageType languageType;
+ var name = cultureInfo.Name;
+ if (languages.TryGetValue(name, out languageType))
+ {
+ return languageType;
+ }
+
+ return LanguageType.English_USA;
+ }
+
+ ///
+ /// Get CurrentUICulture
+ ///
+ ///
+ private static CultureInfo GetCultureInfo()
+ {
+ var cultureInfo = CultureInfo.CurrentUICulture;
+ return cultureInfo;
+ }
+ }
+}
diff --git a/ricaun.Revit.UI/Resources/icon.png b/ricaun.Revit.UI/Resources/icon.png
new file mode 100644
index 0000000..0d07216
Binary files /dev/null and b/ricaun.Revit.UI/Resources/icon.png differ
diff --git a/ricaun.Revit.UI/RibbonPanelExtension.cs b/ricaun.Revit.UI/RibbonPanelExtension.cs
new file mode 100644
index 0000000..f608681
--- /dev/null
+++ b/ricaun.Revit.UI/RibbonPanelExtension.cs
@@ -0,0 +1,238 @@
+using Autodesk.Revit.UI;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ricaun.Revit.UI
+{
+ ///
+ /// RibbonPanelExtension
+ ///
+ public static class RibbonPanelExtension
+ {
+ #region Panel
+ ///
+ /// Create RibbonPanel
+ ///
+ ///
+ ///
+ ///
+ public static RibbonPanel CreatePanel(this UIControlledApplication application, string panelName)
+ {
+ RibbonPanel ribbonManager;
+ try
+ {
+ ribbonManager = application.CreateRibbonPanel(panelName);
+ }
+ catch
+ {
+ ribbonManager = application.CreateRibbonPanel(SafeRibbonPanelName(panelName));
+ ribbonManager.Title = panelName;
+ }
+ return ribbonManager;
+ }
+
+ ///
+ /// Create RibbonPanel
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static RibbonPanel CreatePanel(this UIControlledApplication application, string tabName, string panelName)
+ {
+ RibbonPanel ribbonManager = null;
+ try { application.CreateRibbonTab(tabName); } catch { }
+ try
+ {
+ ribbonManager = application.CreateRibbonPanel(tabName, panelName);
+ }
+ catch
+ {
+ //ribbonManager = application.GetRibbonPanels(tabName).FirstOrDefault(r => r.Name.StartsWith(panelName) && r.Visible);
+ if (ribbonManager == null)
+ {
+ ribbonManager = application.CreateRibbonPanel(tabName, SafeRibbonPanelName(panelName));
+ ribbonManager.Title = panelName;
+ }
+ }
+ return ribbonManager;
+ }
+
+ ///
+ /// Close Setting Visible off
+ ///
+ ///
+ ///
+ public static RibbonPanel Close(this RibbonPanel ribbonPanel)
+ {
+ ribbonPanel.Visible = false;
+ return ribbonPanel;
+ }
+ #endregion
+
+ #region PushButtonData
+ ///
+ /// NewPushButtonData
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static PushButtonData NewPushButtonData(this RibbonPanel ribbonPanel, string text = null) where TExternalCommand : class, IExternalCommand, new()
+ {
+ var commandType = typeof(TExternalCommand);
+ var currentDll = commandType.Assembly.Location;
+ string fullname = commandType.FullName;
+ string targetName = commandType.Name;
+ PushButtonData currentBtn = new PushButtonData(targetName, targetName, currentDll, fullname);
+ if (text != null) currentBtn.Text = text;
+ return currentBtn;
+ }
+ ///
+ /// NewPushButtonData
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static PushButtonData NewPushButtonData(this RibbonPanel ribbonPanel, string text = null) where TExternalCommand : class, IExternalCommand, new() where TAvailability : class, IExternalCommandAvailability, new()
+ {
+ PushButtonData currentBtn = ribbonPanel.NewPushButtonData(text);
+ currentBtn.AvailabilityClassName = typeof(TAvailability).FullName;
+ return currentBtn;
+ }
+ #endregion
+
+ #region
+ ///
+ /// AddPushButton
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static PushButton AddPushButton(this RibbonPanel ribbonPanel, string text = null) where TExternalCommand : class, IExternalCommand, new()
+ {
+ PushButton currentBtn = ribbonPanel.AddItem(ribbonPanel.NewPushButtonData(text)) as PushButton;
+ return currentBtn;
+ }
+ ///
+ /// AddPushButton
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static PushButton AddPushButton(this RibbonPanel ribbonPanel, string text = null) where TExternalCommand : class, IExternalCommand, new() where TAvailability : class, IExternalCommandAvailability, new()
+ {
+ PushButton currentBtn = ribbonPanel.AddPushButton(text);
+ currentBtn.AvailabilityClassName = typeof(TAvailability).FullName;
+ return currentBtn;
+ }
+ #endregion
+
+ #region SplitButton
+
+ ///
+ /// CreateSplitButton
+ ///
+ ///
+ ///
+ ///
+ public static SplitButton CreateSplitButton(this RibbonPanel targetPanel, IList targetPushButtons)
+ {
+ return targetPanel.CreateSplitButton(null, targetPushButtons);
+ }
+
+ ///
+ /// CreateSplitButton
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static SplitButton CreateSplitButton(this RibbonPanel targetPanel, string targetName, IList targetPushButtons)
+ {
+ SplitButton currentSplitButton = null;
+ if (targetPushButtons.Count > 0)
+ {
+ if (targetName == null) targetName = targetPushButtons.FirstOrDefault().Name;
+ try
+ {
+ currentSplitButton = targetPanel.AddItem(new SplitButtonData(targetName, targetName)) as SplitButton;
+ }
+ catch
+ {
+ currentSplitButton = targetPanel.AddItem(new SplitButtonData(SafeButtonName(targetName), targetName)) as SplitButton;
+ }
+
+ foreach (PushButtonData currentPushButton in targetPushButtons)
+ {
+ currentSplitButton.AddPushButton(currentPushButton);
+ }
+ }
+
+ return currentSplitButton;
+ }
+ #endregion
+
+ #region PulldownButton
+
+ ///
+ /// CreatePulldownButton
+ ///
+ ///
+ ///
+ ///
+ public static PulldownButton CreatePulldownButton(this RibbonPanel targetPanel, IList targetPushButtons)
+ {
+ return targetPanel.CreatePulldownButton(null, targetPushButtons);
+ }
+
+ ///
+ /// CreatePulldownButton
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static PulldownButton CreatePulldownButton(this RibbonPanel targetPanel, string targetName, IList targetPushButtons)
+ {
+ PulldownButton currentPulldownButton = null;
+ if (targetPushButtons.Count > 0)
+ {
+ if (targetName == null) targetName = targetPushButtons.FirstOrDefault().Name;
+ try
+ {
+ currentPulldownButton = targetPanel.AddItem(new PulldownButtonData(targetName, targetName)) as PulldownButton;
+ }
+ catch
+ {
+ currentPulldownButton = targetPanel.AddItem(new PulldownButtonData(SafeButtonName(targetName), targetName)) as PulldownButton;
+ }
+ foreach (PushButtonData currentPushButton in targetPushButtons)
+ {
+ currentPulldownButton.AddPushButton(currentPushButton);
+ }
+ }
+ return currentPulldownButton;
+ }
+ #endregion
+
+ #region private
+
+ private static string SafeButtonName(string buttonName)
+ {
+ return $"{buttonName} {System.DateTime.Now.Ticks}";
+ }
+
+ private static string SafeRibbonPanelName(string panelName)
+ {
+ return $"{System.DateTime.Now.Ticks}%{panelName}";
+ }
+
+ #endregion
+ }
+}
diff --git a/ricaun.Revit.UI/ricaun.Revit.UI.csproj b/ricaun.Revit.UI/ricaun.Revit.UI.csproj
new file mode 100644
index 0000000..1fd13da
--- /dev/null
+++ b/ricaun.Revit.UI/ricaun.Revit.UI.csproj
@@ -0,0 +1,130 @@
+
+
+
+
+ net46
+ Library
+ AnyCPU
+ true
+ 9
+ false
+ None
+ Debug;Release
+
+
+
+
+
+
+ 2017
+ net46
+
+
+
+
+ 2018
+ net46
+
+
+
+
+ 2019
+ net47
+
+
+
+
+ 2020
+ net47
+
+
+
+
+ 2021
+ net48
+
+
+
+
+ 2022
+ net48
+
+
+
+
+ 2017
+ net47
+
+
+
+
+
+
+ true
+ bin\Content\$(RevitVersion)
+ Revit$(RevitVersion)
+ MSB3052
+ None
+
+
+
+
+ true
+ bin\Debug\
+ DEBUG;TRACE;Revit$(RevitVersion)
+ Full
+
+
+
+ ricaun.Revit.UI
+ 0.0.1
+ {2064ba4d-5527-41e9-8b76-0cbfefa35900}
+
+
+
+ .$(Version)
+
+
+ .Dev
+
+
+
+ ricaun
+ Luiz Henrique Cassettari
+ $([System.DateTime]::Now.ToString('yyyy'))
+
+
+
+ $(PackageId)$(PackageAssemblyVersion)
+ Revit Package $(PackageId).
+ $(PackageId)
+ Copyright © $(CopyrightYears) $(Company)
+
+
+
+ ricaun-io
+ true
+ https://github.com/$(GitHubRepositoryOwner)/$(PackageId)
+ https://github.com/$(GitHubRepositoryOwner)/$(PackageId)
+ github
+ icon.png
+
+
+
+
+ $(OutputPath)\$(AssemblyName).xml
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file