From 1d569b18933b801d76f442ac38a1ae9b73179bed Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Thu, 21 May 2026 12:16:54 +0300 Subject: [PATCH 01/15] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20=D0=BF=D0=BB=D0=B0=D0=B3=D0=B8?= =?UTF-8?q?=D0=BD=20RevitRoundingOfAreas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../publish.RevitRoundingOfAreas.yml | 37 ++++++ .nuke/parameters.RevitRoundingOfAreas.json | 15 +++ RevitPlugins.slnx | 3 + .../Models/PluginConfig.cs | 66 ++++++++++ .../Models/RevitRepository.cs | 41 ++++++ src/RevitRoundingOfAreas/README.md | 12 ++ .../RevitRoundingOfAreas.csproj | 6 + .../RevitRoundingOfAreasCommand.cs | 80 ++++++++++++ .../ViewModels/MainViewModel.cs | 123 ++++++++++++++++++ .../Views/MainWindow.xaml | 77 +++++++++++ .../Views/MainWindow.xaml.cs | 49 +++++++ .../assets/Localization/Language.cs-CZ.xaml | 14 ++ .../assets/Localization/Language.de-DE.xaml | 13 ++ .../assets/Localization/Language.en-GB.xaml | 13 ++ .../assets/Localization/Language.en-US.xaml | 13 ++ .../assets/Localization/Language.es-ES.xaml | 13 ++ .../assets/Localization/Language.fr-FR.xaml | 13 ++ .../assets/Localization/Language.hu-HU.xaml | 13 ++ .../assets/Localization/Language.it-IT.xaml | 13 ++ .../assets/Localization/Language.ja-JP.xaml | 13 ++ .../assets/Localization/Language.ko-KR.xaml | 13 ++ .../assets/Localization/Language.nl-NL.xaml | 13 ++ .../assets/Localization/Language.pl-PL.xaml | 13 ++ .../assets/Localization/Language.pt-BR.xaml | 13 ++ .../assets/Localization/Language.ru-RU.xaml | 13 ++ .../assets/Localization/Language.zh-CHS.xaml | 13 ++ .../assets/Localization/Language.zh-CHT.xaml | 13 ++ 27 files changed, 718 insertions(+) create mode 100644 .github/workflows/publish.RevitRoundingOfAreas.yml create mode 100644 .nuke/parameters.RevitRoundingOfAreas.json create mode 100644 src/RevitRoundingOfAreas/Models/PluginConfig.cs create mode 100644 src/RevitRoundingOfAreas/Models/RevitRepository.cs create mode 100644 src/RevitRoundingOfAreas/README.md create mode 100644 src/RevitRoundingOfAreas/RevitRoundingOfAreas.csproj create mode 100644 src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs create mode 100644 src/RevitRoundingOfAreas/Views/MainWindow.xaml create mode 100644 src/RevitRoundingOfAreas/Views/MainWindow.xaml.cs create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml create mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml diff --git a/.github/workflows/publish.RevitRoundingOfAreas.yml b/.github/workflows/publish.RevitRoundingOfAreas.yml new file mode 100644 index 000000000..b52d46d6a --- /dev/null +++ b/.github/workflows/publish.RevitRoundingOfAreas.yml @@ -0,0 +1,37 @@ +name: publish RevitRoundingOfAreas + +on: + workflow_dispatch: + pull_request: + types: [ closed, synchronize, review_requested ] + branches: [ main, master ] + paths: + - '**RevitRoundingOfAreas**.cs' + - '**RevitRoundingOfAreas**.xaml' + +env: + plugin-name: "RevitRoundingOfAreas" + +jobs: + build: + name: build + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + # Install the .NET workload + - name: Install .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + # Add DevExrepress package source: https://nuget.devexpress.com/ + - name: Add DevExpress package source + run: dotnet nuget add source https://nuget.devexpress.com/api -n DXFeed -u DevExpress -p ${{ secrets.DEVEXPRESS_FEED_AUTHORIZATION_KEY }} + + - name: Run './build.cmd ' + run: ./build.cmd publish --profile ${{ env.plugin-name }} --pull-request-merged ${{ github.event.pull_request.merged }} --extensions-app-token ${{ secrets.EXTENSIONS_APP_TOKEN }} --revit-plugins-app-token ${{ secrets.REVIT_PLUGINS_APP_TOKEN }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.nuke/parameters.RevitRoundingOfAreas.json b/.nuke/parameters.RevitRoundingOfAreas.json new file mode 100644 index 000000000..0e49b3e5b --- /dev/null +++ b/.nuke/parameters.RevitRoundingOfAreas.json @@ -0,0 +1,15 @@ +{ + "$schema": "./build.schema.json", + "Solution": "RevitPlugins.slnx", + "PluginName": "RevitRoundingOfAreas", + "PublishDirectory": "02.AR.extension\\АР.tab\\bin", + "RevitVersions": [ + "Rv2022", + "Rv2023", + "Rv2024" + ], + "IconUrl": "https://icons8.com/icon/79538/decrease-decimal", + "BundleName": "Рассчитать площади (соц. объекты)", + "BundleType": "InvokeButton", + "BundleOutput": "02.AR.extension\\АР.tab\\Квартирография.panel\\Помещения.pulldown" +} diff --git a/RevitPlugins.slnx b/RevitPlugins.slnx index d615afbfa..6cb2eedff 100644 --- a/RevitPlugins.slnx +++ b/RevitPlugins.slnx @@ -187,6 +187,9 @@ + + + diff --git a/src/RevitRoundingOfAreas/Models/PluginConfig.cs b/src/RevitRoundingOfAreas/Models/PluginConfig.cs new file mode 100644 index 000000000..9dbf97b3e --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/PluginConfig.cs @@ -0,0 +1,66 @@ +using dosymep.Bim4Everyone; +using dosymep.Bim4Everyone.ProjectConfigs; +using dosymep.Serializers; + +using pyRevitLabs.Json; + +namespace RevitRoundingOfAreas.Models; + +/// +/// Класс конфигурации плагина. +/// (Если не используется удалить) +/// +internal class PluginConfig : ProjectConfig { + /// + /// Системное свойство конфигурации. (Не трогать) + /// + [JsonIgnore] + public override string ProjectConfigPath { get; set; } + + /// + /// Системное свойство конфигурации. (Не трогать) + /// + [JsonIgnore] + public override IConfigSerializer Serializer { get; set; } + + /// + /// Метод создания конфигурации плагина. + /// + /// + /// Сериализатор конфигурации. + /// Возвращает прочитанную конфигурацию плагина, либо созданный конфиг по умолчанию. + /// + public static PluginConfig GetPluginConfig(IConfigSerializer configSerializer) { + return new ProjectConfigBuilder() + .SetSerializer(configSerializer) + .SetPluginName(nameof(RevitRoundingOfAreas)) + .SetRevitVersion(ModuleEnvironment.RevitVersion) + .SetProjectConfigName(nameof(PluginConfig) + ".json") + .Build(); + } +} + +/// +/// Настройки проекта. +/// В настройках проекта обычно хранится выбор пользователя в основном окне плагина. +/// +/// +/// Проектом по умолчанию является текст до первого нижнего подчеркивания. +/// +/// https://github.com/dosymep/dosymep.Revit/blob/master/src/dosymep.Bim4Everyone/ProjectConfigs/ProjectConfig.cs#L102 +/// Если плагин работает без открытых проектов, +/// то требуется данный класс удалять из проекта, +/// как сделано в плагине RevitServerFolders +/// https://github.com/Bim4Everyone/RevitPlugins/blob/master/src/RevitServerFolders/Models/PluginConfig.cs#L8 +/// +internal class RevitSettings : ProjectSettings { + /// + /// Наименование проекта. Системное свойство. (Не трогать) + /// + public override string ProjectName { get; set; } + + /// + /// Сохраняемое свойство для примера, нужно его заменить своими настройками. + /// + public string SaveProperty { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs new file mode 100644 index 000000000..c785d460e --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -0,0 +1,41 @@ +using Autodesk.Revit.ApplicationServices; +using Autodesk.Revit.DB; +using Autodesk.Revit.UI; + +namespace RevitRoundingOfAreas.Models; + +/// +/// Класс доступа к документу и приложению Revit. +/// +/// +/// В случае если данный класс разрастается, рекомендуется его разделить на несколько. +/// +internal class RevitRepository { + /// + /// Создает экземпляр репозитория. + /// + /// Класс доступа к интерфейсу Revit. + public RevitRepository(UIApplication uiApplication) { + UIApplication = uiApplication; + } + + /// + /// Класс доступа к интерфейсу Revit. + /// + public UIApplication UIApplication { get; } + + /// + /// Класс доступа к интерфейсу документа Revit. + /// + public UIDocument ActiveUIDocument => UIApplication.ActiveUIDocument; + + /// + /// Класс доступа к приложению Revit. + /// + public Application Application => UIApplication.Application; + + /// + /// Класс доступа к документу Revit. + /// + public Document Document => ActiveUIDocument.Document; +} diff --git a/src/RevitRoundingOfAreas/README.md b/src/RevitRoundingOfAreas/README.md new file mode 100644 index 000000000..fb0f804ad --- /dev/null +++ b/src/RevitRoundingOfAreas/README.md @@ -0,0 +1,12 @@ +# RevitRoundingOfAreas (Рассчитать площади (соц. объекты)) +Описание проекта + +# Сборка проекта +``` +nuke compile --profile RevitRoundingOfAreas +``` + +# Публикация проекта +``` +nuke publish --profile RevitRoundingOfAreas +``` diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreas.csproj b/src/RevitRoundingOfAreas/RevitRoundingOfAreas.csproj new file mode 100644 index 000000000..ae3efaefb --- /dev/null +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreas.csproj @@ -0,0 +1,6 @@ + + + true + 12 + + diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs new file mode 100644 index 000000000..11918733f --- /dev/null +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -0,0 +1,80 @@ +using System.Globalization; +using System.Reflection; +using System.Windows; + +using Autodesk.Revit.Attributes; +using Autodesk.Revit.UI; + +using dosymep.Bim4Everyone; +using dosymep.Bim4Everyone.ProjectConfigs; +using dosymep.Bim4Everyone.SimpleServices; +using dosymep.SimpleServices; +using dosymep.WPF.Views; +using dosymep.WpfCore.Ninject; +using dosymep.WpfUI.Core.Ninject; +using dosymep.Xpf.Core.Ninject; + +using Ninject; + +using RevitRoundingOfAreas.Models; +using RevitRoundingOfAreas.ViewModels; +using RevitRoundingOfAreas.Views; + +namespace RevitRoundingOfAreas; + +/// +/// Класс команды Revit плагина. +/// +/// +/// В данном классе должна быть инициализация контейнера плагина и указание названия команды. +/// +[Transaction(TransactionMode.Manual)] +public class RevitRoundingOfAreasCommand : BasePluginCommand { + /// + /// Инициализирует команду плагина. + /// + public RevitRoundingOfAreasCommand() { + PluginName = "RevitRoundingOfAreas"; + } + + /// + /// Метод выполнения основного кода плагина. + /// + /// Интерфейс взаимодействия с Revit. + /// + /// В случаях, когда не используется конфигурация + /// или локализация требуется удалять их использование полностью во всем проекте. + /// + protected override void Execute(UIApplication uiApplication) { + // Создание контейнера зависимостей плагина с сервисами из платформы + using IKernel kernel = uiApplication.CreatePlatformServices(); + + // Настройка доступа к Revit + kernel.Bind() + .ToSelf() + .InSingletonScope(); + + // Настройка конфигурации плагина + kernel.Bind() + .ToMethod(c => PluginConfig.GetPluginConfig(c.Kernel.Get())); + + // Используем сервис обновления тем для WinUI + kernel.UseWpfUIThemeUpdater(); + + // Настройка запуска окна + kernel.BindMainWindow(); + + // Настройка локализации, + // получение имени сборки откуда брать текст + string assemblyName = Assembly.GetExecutingAssembly().GetName().Name; + + // Настройка локализации, + // установка дефолтной локализации "ru-RU" + kernel.UseWpfLocalization( + $"/{assemblyName};component/assets/localization/language.xaml", + CultureInfo.GetCultureInfo("ru-RU")); + + // Вызывает стандартное уведомление + Notification(kernel.Get()); + } +} diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs new file mode 100644 index 000000000..44ce7d756 --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -0,0 +1,123 @@ +using System.Windows.Input; + +using dosymep.SimpleServices; +using dosymep.WPF.Commands; +using dosymep.WPF.ViewModels; + +using RevitRoundingOfAreas.Models; + +namespace RevitRoundingOfAreas.ViewModels; + +/// +/// Основная ViewModel главного окна плагина. +/// +internal class MainViewModel : BaseViewModel { + private readonly PluginConfig _pluginConfig; + private readonly RevitRepository _revitRepository; + private readonly ILocalizationService _localizationService; + + private string _errorText; + private string _saveProperty; + + /// + /// Создает экземпляр основной ViewModel главного окна. + /// + /// Настройки плагина. + /// Класс доступа к интерфейсу Revit. + /// Интерфейс доступа к сервису локализации. + public MainViewModel( + PluginConfig pluginConfig, + RevitRepository revitRepository, + ILocalizationService localizationService) { + + _pluginConfig = pluginConfig; + _revitRepository = revitRepository; + _localizationService = localizationService; + + LoadViewCommand = RelayCommand.Create(LoadView); + AcceptViewCommand = RelayCommand.Create(AcceptView, CanAcceptView); + } + + /// + /// Команда загрузки главного окна. + /// + public ICommand LoadViewCommand { get; } + + /// + /// Команда применения настроек главного окна. (запуск плагина) + /// + /// В случаях, когда используется немодальное окно, требуется данную команду удалять. + public ICommand AcceptViewCommand { get; } + + /// + /// Текст ошибки, который отображается при неверном вводе пользователя. + /// + public string ErrorText { + get => _errorText; + set => RaiseAndSetIfChanged(ref _errorText, value); + } + + /// + /// Свойство для примера. (требуется удалить) + /// + public string SaveProperty { + get => _saveProperty; + set => RaiseAndSetIfChanged(ref _saveProperty, value); + } + + /// + /// Метод загрузки главного окна. + /// + /// В данном методе должна происходить загрузка настроек окна, а так же инициализация полей окна. + private void LoadView() { + LoadConfig(); + } + + /// + /// Метод применения настроек главного окна. (выполнение плагина) + /// + /// + /// В данном методе должны браться настройки пользователя и сохраняться в конфиг, а так же быть основной код плагина. + /// + private void AcceptView() { + SaveConfig(); + } + + /// + /// Метод проверки возможности выполнения команды применения настроек. + /// + /// В случае когда true - команда может выполниться, в случае false - нет. + /// + /// В данном методе происходит валидация ввода пользователя и уведомление его о неверных значениях. + /// В методе проверяемые свойства окна должны быть отсортированы в таком же порядке как в окне (сверху-вниз) + /// + private bool CanAcceptView() { + if(string.IsNullOrEmpty(SaveProperty)) { + ErrorText = _localizationService.GetLocalizedString("MainWindow.HelloCheck"); + return false; + } + + ErrorText = null; + return true; + } + + /// + /// Загрузка настроек плагина. + /// + private void LoadConfig() { + RevitSettings setting = _pluginConfig.GetSettings(_revitRepository.Document); + + SaveProperty = setting?.SaveProperty ?? _localizationService.GetLocalizedString("MainWindow.Hello"); + } + + /// + /// Сохранение настроек плагина. + /// + private void SaveConfig() { + RevitSettings setting = _pluginConfig.GetSettings(_revitRepository.Document) + ?? _pluginConfig.AddSettings(_revitRepository.Document); + + setting.SaveProperty = SaveProperty; + _pluginConfig.SaveProjectConfig(); + } +} diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml new file mode 100644 index 000000000..1918fdfce --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml.cs b/src/RevitRoundingOfAreas/Views/MainWindow.xaml.cs new file mode 100644 index 000000000..d0c42a1ab --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml.cs @@ -0,0 +1,49 @@ +using System.Windows; + +using dosymep.SimpleServices; + +namespace RevitRoundingOfAreas.Views; + +/// +/// Класс главного окна плагина. +/// +public partial class MainWindow { + /// + /// Иницализирует главное окно плагина. + /// + public MainWindow( + ILoggerService loggerService, + ISerializationService serializationService, + ILanguageService languageService, ILocalizationService localizationService, + IUIThemeService uiThemeService, IUIThemeUpdaterService themeUpdaterService) + : base(loggerService, + serializationService, + languageService, localizationService, + uiThemeService, themeUpdaterService) { + InitializeComponent(); + } + + /// + /// Наименование плагина. + /// + /// + /// Используется для сохранения положения окна. + /// + public override string PluginName => nameof(RevitRoundingOfAreas); + + /// + /// Наименование файла конфигурации. + /// + /// + /// Используется для сохранения положения окна. + /// + public override string ProjectConfigName => nameof(MainWindow); + + private void ButtonOk_Click(object sender, RoutedEventArgs e) { + DialogResult = true; + } + + private void ButtonCancel_Click(object sender, RoutedEventArgs e) { + DialogResult = false; + } +} diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml new file mode 100644 index 000000000..60a0456a8 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml @@ -0,0 +1,14 @@ + + + + + Příklad příkazu + Ahoj Revit! + Zadejte hodnotu vlastnosti, kterou chcete uložit. + + + OK + Zrušit + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml new file mode 100644 index 000000000..c1238f13b --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml @@ -0,0 +1,13 @@ + + + + + Beispielbefehl + Hallo Revit! + Geben Sie einen Wert für die zu speichernde Eigenschaft ein. + + OK + Stornierung + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml new file mode 100644 index 000000000..c1863e10d --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml @@ -0,0 +1,13 @@ + + + + + Sample command + Hello Revit! + Enter a value for the property to save. + + OK + Cancel + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml new file mode 100644 index 000000000..e409970b0 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml @@ -0,0 +1,13 @@ + + + + + Sample command + Hello Revit! + Enter a value for the property to save. + + OK + Cancel + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml new file mode 100644 index 000000000..a4cfac0d4 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml @@ -0,0 +1,13 @@ + + + + + Comando de ejemplo + Hola Revit! + Introduzca un valor para la propiedad que desea guardar. + + OK + Cancelar + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml new file mode 100644 index 000000000..7cdef4c06 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml @@ -0,0 +1,13 @@ + + + + + Exemple de commande + Bonjour Revit! + Entrez une valeur pour la propriété à enregistrer. + + OK + Annuler + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml new file mode 100644 index 000000000..ab8d0e3d2 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml @@ -0,0 +1,13 @@ + + + + + Példa parancs + Helló Revit! + Adja meg a menteni kívánt tulajdonság értékét. + + OK + Mégse + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml new file mode 100644 index 000000000..823a11558 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml @@ -0,0 +1,13 @@ + + + + + Comando di esempio + Ciao Revit! + Immettere un valore per la proprietà da salvare. + + OK + Annulla + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml new file mode 100644 index 000000000..5d86d0bf4 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml @@ -0,0 +1,13 @@ + + + + + コマンド例 + こんにちは Revit! + 保存するプロパティの値を入力します。 + + OK + キャンセル + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml new file mode 100644 index 000000000..854bfc2e2 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml @@ -0,0 +1,13 @@ + + + + + 예제 명령 + 안녕하세요 Revit! + 저장할 속성의 값을 입력하세요. + + OK + 취소 + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml new file mode 100644 index 000000000..0be59268d --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml @@ -0,0 +1,13 @@ + + + + + Voorbeeld commando + Hallo Revit! + Voer een waarde in voor de eigenschap die u wilt opslaan. + + OK + Annuleren + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml new file mode 100644 index 000000000..14bf4d9ca --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml @@ -0,0 +1,13 @@ + + + + + Przykładowe polecenie + Cześć Revit! + Wprowadź wartość właściwości do zapisania. + + OK + Anulować + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml new file mode 100644 index 000000000..81c8f520c --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml @@ -0,0 +1,13 @@ + + + + + Comando de exemplo + Olá Revit! + Insira um valor para a propriedade salvar. + + OK + Cancelar + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml new file mode 100644 index 000000000..39d849b89 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -0,0 +1,13 @@ + + + + + Пример команды + Привет, Revit! + Введите значение сохраняемого свойства. + + ОК + Отмена + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml new file mode 100644 index 000000000..3a4155697 --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml @@ -0,0 +1,13 @@ + + + + + 命令示例 + 你好 Revit! + 输入要保存的属性的值。 + + OK + 取消 + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml new file mode 100644 index 000000000..890aa061c --- /dev/null +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml @@ -0,0 +1,13 @@ + + + + + 命令範例 + 你好 Revit! + 輸入要儲存的屬性的值。 + + OK + 取消 + From 5a46e04c5f20d2e6812ca529a8136b45dad63262 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Thu, 21 May 2026 13:07:46 +0300 Subject: [PATCH 02/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D0=B0,=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BB=D0=B8=D1=88=D0=BD=D0=B5=D0=B9=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RevitRoundingOfAreas/README.md | 2 +- .../RevitRoundingOfAreasCommand.cs | 8 ++------ .../assets/Localization/Language.cs-CZ.xaml | 14 -------------- .../assets/Localization/Language.de-DE.xaml | 13 ------------- .../assets/Localization/Language.en-GB.xaml | 13 ------------- .../assets/Localization/Language.en-US.xaml | 4 +--- .../assets/Localization/Language.es-ES.xaml | 13 ------------- .../assets/Localization/Language.fr-FR.xaml | 13 ------------- .../assets/Localization/Language.hu-HU.xaml | 13 ------------- .../assets/Localization/Language.it-IT.xaml | 13 ------------- .../assets/Localization/Language.ja-JP.xaml | 13 ------------- .../assets/Localization/Language.ko-KR.xaml | 13 ------------- .../assets/Localization/Language.nl-NL.xaml | 13 ------------- .../assets/Localization/Language.pl-PL.xaml | 13 ------------- .../assets/Localization/Language.pt-BR.xaml | 13 ------------- .../assets/Localization/Language.ru-RU.xaml | 2 -- .../assets/Localization/Language.zh-CHS.xaml | 13 ------------- .../assets/Localization/Language.zh-CHT.xaml | 13 ------------- 18 files changed, 4 insertions(+), 195 deletions(-) delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml delete mode 100644 src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml diff --git a/src/RevitRoundingOfAreas/README.md b/src/RevitRoundingOfAreas/README.md index fb0f804ad..11648ab3a 100644 --- a/src/RevitRoundingOfAreas/README.md +++ b/src/RevitRoundingOfAreas/README.md @@ -1,5 +1,5 @@ # RevitRoundingOfAreas (Рассчитать площади (соц. объекты)) -Описание проекта +Плагин для автоматического округления системной площади в текстовый параметр. Для социальных объектов # Сборка проекта ``` diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index 11918733f..f8159e503 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -1,6 +1,5 @@ using System.Globalization; using System.Reflection; -using System.Windows; using Autodesk.Revit.Attributes; using Autodesk.Revit.UI; @@ -8,11 +7,8 @@ using dosymep.Bim4Everyone; using dosymep.Bim4Everyone.ProjectConfigs; using dosymep.Bim4Everyone.SimpleServices; -using dosymep.SimpleServices; -using dosymep.WPF.Views; using dosymep.WpfCore.Ninject; using dosymep.WpfUI.Core.Ninject; -using dosymep.Xpf.Core.Ninject; using Ninject; @@ -34,7 +30,7 @@ public class RevitRoundingOfAreasCommand : BasePluginCommand { /// Инициализирует команду плагина. /// public RevitRoundingOfAreasCommand() { - PluginName = "RevitRoundingOfAreas"; + PluginName = "Рассчитать площади (соц. объекты)"; } /// @@ -47,7 +43,7 @@ public RevitRoundingOfAreasCommand() { /// protected override void Execute(UIApplication uiApplication) { // Создание контейнера зависимостей плагина с сервисами из платформы - using IKernel kernel = uiApplication.CreatePlatformServices(); + using var kernel = uiApplication.CreatePlatformServices(); // Настройка доступа к Revit kernel.Bind() diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml deleted file mode 100644 index 60a0456a8..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.cs-CZ.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - Příklad příkazu - Ahoj Revit! - Zadejte hodnotu vlastnosti, kterou chcete uložit. - - - OK - Zrušit - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml deleted file mode 100644 index c1238f13b..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.de-DE.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Beispielbefehl - Hallo Revit! - Geben Sie einen Wert für die zu speichernde Eigenschaft ein. - - OK - Stornierung - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml deleted file mode 100644 index c1863e10d..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.en-GB.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Sample command - Hello Revit! - Enter a value for the property to save. - - OK - Cancel - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml index e409970b0..d8b291b3c 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml @@ -1,8 +1,6 @@ - - + xmlns:system="clr-namespace:System;assembly=mscorlib"> Sample command Hello Revit! diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml deleted file mode 100644 index a4cfac0d4..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.es-ES.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Comando de ejemplo - Hola Revit! - Introduzca un valor para la propiedad que desea guardar. - - OK - Cancelar - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml deleted file mode 100644 index 7cdef4c06..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.fr-FR.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Exemple de commande - Bonjour Revit! - Entrez une valeur pour la propriété à enregistrer. - - OK - Annuler - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml deleted file mode 100644 index ab8d0e3d2..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.hu-HU.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Példa parancs - Helló Revit! - Adja meg a menteni kívánt tulajdonság értékét. - - OK - Mégse - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml deleted file mode 100644 index 823a11558..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.it-IT.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Comando di esempio - Ciao Revit! - Immettere un valore per la proprietà da salvare. - - OK - Annulla - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml deleted file mode 100644 index 5d86d0bf4..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ja-JP.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - コマンド例 - こんにちは Revit! - 保存するプロパティの値を入力します。 - - OK - キャンセル - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml deleted file mode 100644 index 854bfc2e2..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ko-KR.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - 예제 명령 - 안녕하세요 Revit! - 저장할 속성의 값을 입력하세요. - - OK - 취소 - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml deleted file mode 100644 index 0be59268d..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.nl-NL.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Voorbeeld commando - Hallo Revit! - Voer een waarde in voor de eigenschap die u wilt opslaan. - - OK - Annuleren - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml deleted file mode 100644 index 14bf4d9ca..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.pl-PL.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Przykładowe polecenie - Cześć Revit! - Wprowadź wartość właściwości do zapisania. - - OK - Anulować - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml deleted file mode 100644 index 81c8f520c..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.pt-BR.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Comando de exemplo - Olá Revit! - Insira um valor para a propriedade salvar. - - OK - Cancelar - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 39d849b89..db07b9bfa 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -2,8 +2,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> - - Пример команды Привет, Revit! Введите значение сохраняемого свойства. diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml deleted file mode 100644 index 3a4155697..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHS.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - 命令示例 - 你好 Revit! - 输入要保存的属性的值。 - - OK - 取消 - diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml deleted file mode 100644 index 890aa061c..000000000 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.zh-CHT.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - 命令範例 - 你好 Revit! - 輸入要儲存的屬性的值。 - - OK - 取消 - From 47a9ee0d5463463ea45ff99766b084edfeb0439b Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Fri, 22 May 2026 10:35:03 +0300 Subject: [PATCH 03/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=A1=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BB=D0=B0=D1=81?= =?UTF-8?q?=D1=81=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D0=BE=D0=BA=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/RevitRepository.cs | 14 +- .../ViewModels/LevelViewModel.cs | 21 +++ .../Views/Edits/CustomEditControl.xaml | 64 +++++++ .../Views/Edits/CustomEditControl.xaml.cs | 47 +++++ .../Views/Edits/CustomGroupEditControl.xaml | 101 ++++++++++ .../Edits/CustomGroupEditControl.xaml.cs | 112 +++++++++++ .../Views/Edits/ItemControl.xaml | 65 +++++++ .../Views/Edits/ItemControl.xaml.cs | 38 ++++ .../Views/MainWindow.xaml | 177 ++++++++++++++++-- .../assets/Localization/Language.en-US.xaml | 10 +- .../assets/Localization/Language.ru-RU.xaml | 26 ++- 11 files changed, 637 insertions(+), 38 deletions(-) create mode 100644 src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs create mode 100644 src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml create mode 100644 src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml.cs create mode 100644 src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml create mode 100644 src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml.cs create mode 100644 src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml create mode 100644 src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml.cs diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index c785d460e..76e806ff4 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -4,12 +4,6 @@ namespace RevitRoundingOfAreas.Models; -/// -/// Класс доступа к документу и приложению Revit. -/// -/// -/// В случае если данный класс разрастается, рекомендуется его разделить на несколько. -/// internal class RevitRepository { /// /// Создает экземпляр репозитория. @@ -23,19 +17,21 @@ public RevitRepository(UIApplication uiApplication) { /// Класс доступа к интерфейсу Revit. /// public UIApplication UIApplication { get; } - + /// /// Класс доступа к интерфейсу документа Revit. /// public UIDocument ActiveUIDocument => UIApplication.ActiveUIDocument; - + /// /// Класс доступа к приложению Revit. /// public Application Application => UIApplication.Application; - + /// /// Класс доступа к документу Revit. /// public Document Document => ActiveUIDocument.Document; + + } diff --git a/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs new file mode 100644 index 000000000..1cb82b553 --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs @@ -0,0 +1,21 @@ +using Autodesk.Revit.DB; + +using dosymep.WPF.ViewModels; + +namespace RevitRoundingOfAreas.ViewModels; + +internal class LevelViewModel : BaseViewModel { + private string _name; + private bool _isChecked; + + public Level Level { get; set; } + + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } + public bool IsChecked { + get => _isChecked; + set => RaiseAndSetIfChanged(ref _isChecked, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml new file mode 100644 index 000000000..3d96afe1c --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml.cs b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml.cs new file mode 100644 index 000000000..e4275cfa5 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml.cs @@ -0,0 +1,47 @@ +using System.ComponentModel; +using System.Windows; +using System.Windows.Markup; + +using Wpf.Ui.Controls; + +namespace RevitRoundingOfAreas.Views.Edits; + +[DefaultProperty(nameof(EditControl))] +[ContentProperty(nameof(EditControl))] +public partial class CustomEditControl { + public static readonly DependencyProperty IconProperty = DependencyProperty.Register( + nameof(Icon), typeof(IconElement), typeof(CustomEditControl), new PropertyMetadata(default(IconElement))); + + public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( + nameof(Header), typeof(string), typeof(CustomEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register( + nameof(Description), typeof(string), typeof(CustomEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty EditControlProperty = DependencyProperty.Register( + nameof(EditControl), typeof(object), typeof(CustomEditControl), new PropertyMetadata(default(object))); + + public CustomEditControl() { + InitializeComponent(); + } + + public IconElement Icon { + get => (IconElement) GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + public string Header { + get => (string) GetValue(HeaderProperty); + set => SetValue(HeaderProperty, value); + } + + public string Description { + get => (string) GetValue(DescriptionProperty); + set => SetValue(DescriptionProperty, value); + } + + public object EditControl { + get => GetValue(EditControlProperty); + set => SetValue(EditControlProperty, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml b/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml new file mode 100644 index 000000000..2d408dc76 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml.cs b/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml.cs new file mode 100644 index 000000000..48d3a00fe --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/CustomGroupEditControl.xaml.cs @@ -0,0 +1,112 @@ +using System.ComponentModel; +using System.Windows; +using System.Windows.Markup; + +using Wpf.Ui.Controls; + +namespace RevitRoundingOfAreas.Views.Edits; + +[DefaultProperty(nameof(EditControl))] +[ContentProperty(nameof(EditControl))] +public partial class CustomGroupEditControl { + public static readonly DependencyProperty IconProperty = DependencyProperty.Register( + nameof(Icon), typeof(IconElement), typeof(CustomGroupEditControl), new PropertyMetadata(default(IconElement))); + + public static readonly DependencyProperty ExtraIconProperty = DependencyProperty.Register( + nameof(ExtraIcon), typeof(IconElement), typeof(CustomGroupEditControl), new PropertyMetadata(default(IconElement))); + + public static readonly DependencyProperty ExtraTextProperty = DependencyProperty.Register( + nameof(ExtraText), typeof(string), typeof(CustomGroupEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( + nameof(Header), typeof(string), typeof(CustomGroupEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register( + nameof(Description), typeof(string), typeof(CustomGroupEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty EditControlProperty = DependencyProperty.Register( + nameof(EditControl), typeof(object), typeof(CustomGroupEditControl), new PropertyMetadata(default(object))); + + public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register( + nameof(IsChecked), typeof(bool), typeof(CustomGroupEditControl), new PropertyMetadata(true)); + + public static readonly DependencyProperty ToggleSwitchVisibleProperty = DependencyProperty.Register( + nameof(ToggleSwitchVisible), typeof(bool), typeof(CustomGroupEditControl), new PropertyMetadata(false)); + + public static readonly DependencyProperty ExtraIconVisibleProperty = DependencyProperty.Register( + nameof(ExtraIconVisible), typeof(bool), typeof(CustomGroupEditControl), new PropertyMetadata(false)); + + public static readonly DependencyProperty ExtraTextVisibleProperty = DependencyProperty.Register( + nameof(ExtraTextVisible), typeof(bool), typeof(CustomGroupEditControl), new PropertyMetadata(false)); + + public static readonly DependencyProperty SwitchOnContentProperty = DependencyProperty.Register( + nameof(SwitchOnContent), typeof(string), typeof(CustomGroupEditControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty SwitchOffContentProperty = DependencyProperty.Register( + nameof(SwitchOffContent), typeof(string), typeof(CustomGroupEditControl), new PropertyMetadata(default(string))); + + + public CustomGroupEditControl() { + InitializeComponent(); + } + + public IconElement Icon { + get => (IconElement) GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + public IconElement ExtraIcon { + get => (IconElement) GetValue(ExtraIconProperty); + set => SetValue(ExtraIconProperty, value); + } + + public string ExtraText { + get => (string) GetValue(ExtraTextProperty); + set => SetValue(ExtraIconProperty, value); + } + + public string Header { + get => (string) GetValue(HeaderProperty); + set => SetValue(HeaderProperty, value); + } + + public string Description { + get => (string) GetValue(DescriptionProperty); + set => SetValue(DescriptionProperty, value); + } + + public object EditControl { + get => GetValue(EditControlProperty); + set => SetValue(EditControlProperty, value); + } + + public bool IsChecked { + get => (bool) GetValue(IsCheckedProperty); + set => SetValue(IsCheckedProperty, value); + } + + public bool ToggleSwitchVisible { + get => (bool) GetValue(ToggleSwitchVisibleProperty); + set => SetValue(ToggleSwitchVisibleProperty, value); + } + + public string SwitchOnContent { + get => (string) GetValue(SwitchOnContentProperty); + set => SetValue(SwitchOnContentProperty, value); + } + + public string SwitchOffContent { + get => (string) GetValue(SwitchOffContentProperty); + set => SetValue(SwitchOffContentProperty, value); + } + + public bool ExtraIconVisible { + get => (bool) GetValue(ExtraIconVisibleProperty); + set => SetValue(ExtraIconVisibleProperty, value); + } + + public bool ExtraTextVisible { + get => (bool) GetValue(ExtraTextVisibleProperty); + set => SetValue(ExtraTextVisibleProperty, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml b/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml new file mode 100644 index 000000000..2e8b3ac4c --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml.cs b/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml.cs new file mode 100644 index 000000000..e410d36de --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/ItemControl.xaml.cs @@ -0,0 +1,38 @@ +using System.Windows; + +namespace RevitRoundingOfAreas.Views.Edits; + +public partial class ItemControl { + public static readonly DependencyProperty ItemNameProperty = DependencyProperty.Register( + nameof(ItemName), typeof(string), typeof(ItemControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty WarningDescriptionProperty = DependencyProperty.Register( + nameof(WarningDescription), typeof(string), typeof(ItemControl), new PropertyMetadata(default(string))); + + public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register( + nameof(IsChecked), typeof(bool), typeof(ItemControl), new PropertyMetadata(true)); + + public static readonly DependencyProperty HasWarningProperty = DependencyProperty.Register( + nameof(HasWarning), typeof(bool), typeof(ItemControl), new PropertyMetadata(true)); + + public ItemControl() { + InitializeComponent(); + } + + public string ItemName { + get => (string) GetValue(ItemNameProperty); + set => SetValue(ItemNameProperty, value); + } + public string WarningDescription { + get => (string) GetValue(WarningDescriptionProperty); + set => SetValue(WarningDescriptionProperty, value); + } + public bool IsChecked { + get => (bool) GetValue(IsCheckedProperty); + set => SetValue(IsCheckedProperty, value); + } + public bool HasWarning { + get => (bool) GetValue(HasWarningProperty); + set => SetValue(HasWarningProperty, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 1918fdfce..029d6b4fb 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -6,20 +6,22 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:base="clr-namespace:dosymep.WPF.Views" xmlns:local="clr-namespace:RevitRoundingOfAreas.Views" + xmlns:edits="clr-namespace:RevitRoundingOfAreas.Views.Edits" xmlns:vms="clr-namespace:RevitRoundingOfAreas.ViewModels" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:core="clr-namespace:dosymep.WpfUI.Core" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" xmlns:me="clr-namespace:dosymep.WpfCore.MarkupExtensions;assembly=dosymep.WpfCore" + xmlns:views="clr-namespace:RevitRoundingOfAreas.Views" mc:Ignorable="d" Title="{me:LocalizationSource MainWindow.Title}" - Height="500" - Width="700" + Height="550" + Width="1315" - MinHeight="500" - MinWidth="700" + MinHeight="550" + MinWidth="1315" d:DataContext="{d:DesignInstance vms:MainViewModel, IsDesignTimeCreatable=False}"> @@ -27,7 +29,7 @@ - + @@ -35,40 +37,175 @@ - - + + + + + + Grid.ColumnSpan="2" + Icon="{ui:SymbolIcon animalCat24, FontSize=20}" + Title="{me:LocalizationSource MainWindow.Title}" + FontSize="14" + FontWeight="DemiBold" /> + + + + + + + + + + + + + + + + + + + + + - + Grid.Column="1" + VerticalScrollBarVisibility="Auto" + HorizontalScrollBarVisibility="Disabled"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + Text="{Binding ErrorText}" /> + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml index d8b291b3c..3e250bf5b 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml @@ -1,11 +1,11 @@ + xmlns:system="clr-namespace:System;assembly=mscorlib"> - Sample command - Hello Revit! - Enter a value for the property to save. + Calculate areas (social facilities) + Model element processing range + Select how model elements will be processed - OK + Calculate Cancel diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index db07b9bfa..4d3e18d8b 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -2,10 +2,28 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> - Пример команды - Привет, Revit! - Введите значение сохраняемого свойства. + Рассчитать площади (соц. объекты) + Диапазон обработки элементов модели + Выбор варианта обработки элементов модели - ОК + Стадия помещений + Выбор стадии для обрабатываемых помещений + + Параметр для чтения + Параметр, с которого будет считываться площадь + + Параметр для записи + Параметр, в который будет записываться площадь + + Количество знаков после запятой + До которого будет происходить округление + + Уровни помещений + Уровни помещений, которые будут обработаны + Выбрать все уровни + Поиск по имени уровня + Сбросить выбор уровней + + Рассчитать Отмена From ef699f2a1df74b3e9a93fbdf250f647f36be85fd Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Mon, 25 May 2026 12:01:26 +0300 Subject: [PATCH 04/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=97=D0=B0?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=B0=20MaimViewModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/ConfigSettings.cs | 14 ++ .../Models/ParamService.cs | 58 ++++++ src/RevitRoundingOfAreas/Models/PhaseModel.cs | 7 + .../Models/PluginConfig.cs | 32 ++-- .../Models/RevitRepository.cs | 25 +++ .../RevitRoundingOfAreasCommand.cs | 5 + .../ViewModels/DigitViewModel.cs | 13 ++ .../ViewModels/MainViewModel.cs | 177 ++++++++++++++++-- .../ViewModels/ParamViewModel.cs | 14 ++ .../ViewModels/PhaseViewModel.cs | 16 ++ .../Views/MainWindow.xaml | 26 +-- .../assets/Localization/Language.ru-RU.xaml | 12 +- 12 files changed, 342 insertions(+), 57 deletions(-) create mode 100644 src/RevitRoundingOfAreas/Models/ConfigSettings.cs create mode 100644 src/RevitRoundingOfAreas/Models/ParamService.cs create mode 100644 src/RevitRoundingOfAreas/Models/PhaseModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/PhaseViewModel.cs diff --git a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs new file mode 100644 index 000000000..348a83f32 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using dosymep.Bim4Everyone; + +namespace RevitRoundingOfAreas.Models; +internal class ConfigSettings { + public ElementId SelectedPhaseId { get; set; } + public RevitParam SourceParam { get; set; } + public RevitParam TargetParam { get; set; } + public int DigitCount { get; set; } + public List Levels { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/ParamService.cs b/src/RevitRoundingOfAreas/Models/ParamService.cs new file mode 100644 index 000000000..3f2a3f21b --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/ParamService.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using dosymep.Bim4Everyone; +using dosymep.Bim4Everyone.ProjectParams; +using dosymep.Bim4Everyone.SharedParams; +using dosymep.Bim4Everyone.SystemParams; +using dosymep.Revit; + +namespace RevitRoundingOfAreas.Models; +internal class ParamService { + + private readonly RevitRepository _revitRepository; + + public ParamService(RevitRepository revitRepository) { + _revitRepository = revitRepository; + + } + + public List AllRevitParams => GetAllRevitParams(); + + public List GetAllRevitParams() { + var categoryId = new ElementId(BuiltInCategory.OST_Rooms); + var filterableParameters = ParameterFilterUtilities + .GetFilterableParametersInCommon(_revitRepository.Document, [categoryId]); + + if(filterableParameters.Count == 0) { + return []; + } + + List listOfParameters = []; + foreach(var elementId in filterableParameters) { + if(elementId.IsSystemId()) { + var param = elementId.AsBuiltInParameter(); + RevitParam revitParam = SystemParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, param); + if(revitParam.StorageType is StorageType.Double or StorageType.String) { + listOfParameters.Add(revitParam); + } + } else { + var element = _revitRepository.Document.GetElement(elementId); + if(element is SharedParameterElement) { + RevitParam revitParam = SharedParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); + if(revitParam.StorageType is StorageType.Double or StorageType.String) { + listOfParameters.Add(revitParam); + } + } else { + RevitParam revitParam = ProjectParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); + if(revitParam.StorageType is StorageType.Double or StorageType.String) { + listOfParameters.Add(revitParam); + } + } + } + } + + return listOfParameters; + } +} diff --git a/src/RevitRoundingOfAreas/Models/PhaseModel.cs b/src/RevitRoundingOfAreas/Models/PhaseModel.cs new file mode 100644 index 000000000..2ec5834bf --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/PhaseModel.cs @@ -0,0 +1,7 @@ +using Autodesk.Revit.DB; + +namespace RevitRoundingOfAreas.Models; +internal class PhaseModel { + public ElementId ElementId { get; set; } + public string Name { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/PluginConfig.cs b/src/RevitRoundingOfAreas/Models/PluginConfig.cs index 9dbf97b3e..434a2abb7 100644 --- a/src/RevitRoundingOfAreas/Models/PluginConfig.cs +++ b/src/RevitRoundingOfAreas/Models/PluginConfig.cs @@ -1,6 +1,5 @@ using dosymep.Bim4Everyone; using dosymep.Bim4Everyone.ProjectConfigs; -using dosymep.Serializers; using pyRevitLabs.Json; @@ -40,27 +39,24 @@ public static PluginConfig GetPluginConfig(IConfigSerializer configSerializer) { } } -/// -/// Настройки проекта. -/// В настройках проекта обычно хранится выбор пользователя в основном окне плагина. -/// -/// -/// Проектом по умолчанию является текст до первого нижнего подчеркивания. -/// -/// https://github.com/dosymep/dosymep.Revit/blob/master/src/dosymep.Bim4Everyone/ProjectConfigs/ProjectConfig.cs#L102 -/// Если плагин работает без открытых проектов, -/// то требуется данный класс удалять из проекта, -/// как сделано в плагине RevitServerFolders -/// https://github.com/Bim4Everyone/RevitPlugins/blob/master/src/RevitServerFolders/Models/PluginConfig.cs#L8 -/// internal class RevitSettings : ProjectSettings { /// - /// Наименование проекта. Системное свойство. (Не трогать) + /// Наименование проекта. /// public override string ProjectName { get; set; } - + /// - /// Сохраняемое свойство для примера, нужно его заменить своими настройками. + /// Выбранная стадия проекта /// - public string SaveProperty { get; set; } + public ConfigSettings ConfigSettings { get; set; } +} + +internal class SystemPluginConfig { + + // Название стадии по умолчанию + public string DefaultPhaseName => "Основная планировка"; + + // Количество знаков по умолчанию + public int DefaultDigitCount => 1; + } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index 76e806ff4..c3bd3f76a 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -1,3 +1,7 @@ +using System.Collections.Generic; + +using System.Linq; + using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB; using Autodesk.Revit.UI; @@ -34,4 +38,25 @@ public RevitRepository(UIApplication uiApplication) { public Document Document => ActiveUIDocument.Document; + + + + public IEnumerable GetPhaseModels() { + var phases = Document.Phases; + return phases + .Cast() + .Select(phase => new PhaseModel { + ElementId = phase.Id, + Name = phase.Name + }); + } + + public ElementId GetPhaseIdByName(string name) { + return GetPhaseModels() + .FirstOrDefault(phase => phase != null && phase.Name == name) + ?.ElementId + ?? ElementId.InvalidElementId; + } + + } diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index f8159e503..266ff52f0 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -50,6 +50,11 @@ protected override void Execute(UIApplication uiApplication) { .ToSelf() .InSingletonScope(); + // Создание класса с параметрами + kernel.Bind() + .ToSelf() + .InSingletonScope(); + // Настройка конфигурации плагина kernel.Bind() .ToMethod(c => PluginConfig.GetPluginConfig(c.Kernel.Get())); diff --git a/src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs new file mode 100644 index 000000000..e65e5b398 --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs @@ -0,0 +1,13 @@ +using dosymep.WPF.ViewModels; + +namespace RevitRoundingOfAreas.ViewModels; +internal class DigitViewModel : BaseViewModel { + private string _name; + + public int DigitCount { get; set; } + + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } +} diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index 44ce7d756..aa018f717 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -1,5 +1,10 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; using System.Windows.Input; +using Autodesk.Revit.DB; + using dosymep.SimpleServices; using dosymep.WPF.Commands; using dosymep.WPF.ViewModels; @@ -13,12 +18,30 @@ namespace RevitRoundingOfAreas.ViewModels; /// internal class MainViewModel : BaseViewModel { private readonly PluginConfig _pluginConfig; + private readonly SystemPluginConfig _systemPluginConfig; private readonly RevitRepository _revitRepository; + private readonly ParamService _paramService; private readonly ILocalizationService _localizationService; + private ConfigSettings _configSettings; + + private ObservableCollection _phases; + private PhaseViewModel _selectedPhase; + + private ObservableCollection _sourceParams; + private ParamViewModel _selectedSourceParam; + + private ObservableCollection _targetParams; + private ParamViewModel _selectedTargetParam; + + private ObservableCollection _digitCount; + private DigitViewModel _selectedDigitCount; + + + private ObservableCollection _levels; + private string _errorText; - private string _saveProperty; - + /// /// Создает экземпляр основной ViewModel главного окна. /// @@ -27,11 +50,15 @@ internal class MainViewModel : BaseViewModel { /// Интерфейс доступа к сервису локализации. public MainViewModel( PluginConfig pluginConfig, + SystemPluginConfig systemPluginConfig, RevitRepository revitRepository, + ParamService paramService, ILocalizationService localizationService) { - + _pluginConfig = pluginConfig; + _systemPluginConfig = systemPluginConfig; _revitRepository = revitRepository; + _paramService = paramService; _localizationService = localizationService; LoadViewCommand = RelayCommand.Create(LoadView); @@ -42,13 +69,59 @@ public MainViewModel( /// Команда загрузки главного окна. /// public ICommand LoadViewCommand { get; } - + /// /// Команда применения настроек главного окна. (запуск плагина) /// /// В случаях, когда используется немодальное окно, требуется данную команду удалять. public ICommand AcceptViewCommand { get; } + public ObservableCollection Phases { + get => _phases; + set => RaiseAndSetIfChanged(ref _phases, value); + } + + public PhaseViewModel SelectedPhase { + get => _selectedPhase; + set => RaiseAndSetIfChanged(ref _selectedPhase, value); + } + + public ObservableCollection SourceParams { + get => _sourceParams; + set => RaiseAndSetIfChanged(ref _sourceParams, value); + } + + public ParamViewModel SelectedSourceParam { + get => _selectedSourceParam; + set => RaiseAndSetIfChanged(ref _selectedSourceParam, value); + } + + public ObservableCollection TargetParams { + get => _targetParams; + set => RaiseAndSetIfChanged(ref _targetParams, value); + } + + public ParamViewModel SelectedTargetParam { + get => _selectedTargetParam; + set => RaiseAndSetIfChanged(ref _selectedTargetParam, value); + } + + public ObservableCollection DigitCount { + get => _digitCount; + set => RaiseAndSetIfChanged(ref _digitCount, value); + } + + public DigitViewModel SelectedDigitCount { + get => _selectedDigitCount; + set => RaiseAndSetIfChanged(ref _selectedDigitCount, value); + } + + public ObservableCollection Levels { + get => _levels; + set => RaiseAndSetIfChanged(ref _levels, value); + } + + /// /// Текст ошибки, который отображается при неверном вводе пользователя. /// @@ -57,20 +130,73 @@ public string ErrorText { set => RaiseAndSetIfChanged(ref _errorText, value); } - /// - /// Свойство для примера. (требуется удалить) - /// - public string SaveProperty { - get => _saveProperty; - set => RaiseAndSetIfChanged(ref _saveProperty, value); + + // Метод получения коллекции DigitViewModel для DigitCount + private IEnumerable GetDigitViewModels() { + for(int i = 1; i <= 3; i++) { + yield return new DigitViewModel { + DigitCount = i, + Name = i.ToString(), + }; + } + } + + // Метод получения коллекции ParamViewModel для TargetParams + private IEnumerable GetTargetParamViewModels() { + return _paramService.AllRevitParams + .Select(param => new ParamViewModel { + Name = param.Name, + RevitParam = param + }) + .Where(param => param.RevitParam.StorageType is StorageType.String); + } + + // Метод получения коллекции ParamViewModel для SourceParams + private IEnumerable GetSourceParamViewModels() { + return _paramService.AllRevitParams + .Select(param => new ParamViewModel { + Name = param.Name, + RevitParam = param + }) + .Where(param => param.RevitParam.StorageType is StorageType.Double); + } + + // Метод получения коллекции PhaseViewModel для Phases + private IEnumerable GetPhaseViewModels() { + return _revitRepository.GetPhaseModels() + .Select(phase => new PhaseViewModel { + Name = phase.Name, + ElementId = phase.ElementId + }); } + /// - /// Метод загрузки главного окна. + /// Метод загрузки главного окна /// /// В данном методе должна происходить загрузка настроек окна, а так же инициализация полей окна. private void LoadView() { LoadConfig(); + + Phases = new ObservableCollection(GetPhaseViewModels()); + SelectedPhase = Phases + .FirstOrDefault(phase => phase.ElementId == _configSettings.SelectedPhaseId) + ?? Phases.LastOrDefault(); + + SourceParams = new ObservableCollection(GetSourceParamViewModels()); + SelectedSourceParam = SourceParams + .FirstOrDefault(param => param.RevitParam.Id == _configSettings.SourceParam?.Id) + ?? SourceParams.FirstOrDefault(); + + TargetParams = new ObservableCollection(GetTargetParamViewModels()); + SelectedTargetParam = TargetParams + .FirstOrDefault(param => param.RevitParam.Id == _configSettings.TargetParam?.Id) + ?? TargetParams.FirstOrDefault(); + + DigitCount = new ObservableCollection(GetDigitViewModels()); + SelectedDigitCount = DigitCount + .FirstOrDefault(digit => digit.DigitCount == _configSettings.DigitCount) + ?? DigitCount.FirstOrDefault(); } /// @@ -92,11 +218,6 @@ private void AcceptView() { /// В методе проверяемые свойства окна должны быть отсортированы в таком же порядке как в окне (сверху-вниз) /// private bool CanAcceptView() { - if(string.IsNullOrEmpty(SaveProperty)) { - ErrorText = _localizationService.GetLocalizedString("MainWindow.HelloCheck"); - return false; - } - ErrorText = null; return true; } @@ -105,19 +226,35 @@ private bool CanAcceptView() { /// Загрузка настроек плагина. /// private void LoadConfig() { - RevitSettings setting = _pluginConfig.GetSettings(_revitRepository.Document); + var setting = _pluginConfig.GetSettings(_revitRepository.Document); + _configSettings = setting?.ConfigSettings ?? new ConfigSettings(); + ApplyDefaultsConfig(); + } + + // Метод применения дефолтных значений настроек. + private void ApplyDefaultsConfig() { + if(_configSettings.SelectedPhaseId is null || _configSettings.SelectedPhaseId == ElementId.InvalidElementId) { + var phaseId = _revitRepository.GetPhaseIdByName(_systemPluginConfig.DefaultPhaseName); - SaveProperty = setting?.SaveProperty ?? _localizationService.GetLocalizedString("MainWindow.Hello"); + var sourceParam = _paramService.AllRevitParams + .FirstOrDefault(); + + _configSettings.SelectedPhaseId = phaseId; + _configSettings.SourceParam = sourceParam; + } } /// /// Сохранение настроек плагина. /// private void SaveConfig() { - RevitSettings setting = _pluginConfig.GetSettings(_revitRepository.Document) + var setting = _pluginConfig.GetSettings(_revitRepository.Document) ?? _pluginConfig.AddSettings(_revitRepository.Document); - setting.SaveProperty = SaveProperty; + _configSettings.SelectedPhaseId = SelectedPhase.ElementId; + _configSettings.SourceParam = SelectedSourceParam.RevitParam; + + setting.ConfigSettings = _configSettings; _pluginConfig.SaveProjectConfig(); } } diff --git a/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs new file mode 100644 index 000000000..bef8bbabe --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs @@ -0,0 +1,14 @@ +using dosymep.Bim4Everyone; +using dosymep.WPF.ViewModels; + +namespace RevitRoundingOfAreas.ViewModels; +internal class ParamViewModel : BaseViewModel { + private string _name; + + public RevitParam RevitParam { get; set; } + + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } +} diff --git a/src/RevitRoundingOfAreas/ViewModels/PhaseViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/PhaseViewModel.cs new file mode 100644 index 000000000..3bee7900d --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/PhaseViewModel.cs @@ -0,0 +1,16 @@ +using Autodesk.Revit.DB; + +using dosymep.WPF.ViewModels; + +namespace RevitRoundingOfAreas.ViewModels; + +internal class PhaseViewModel : BaseViewModel { + private string _name; + + public ElementId ElementId { get; set; } + + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 029d6b4fb..34fa02831 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -64,33 +64,33 @@ + DisplayMemberPath="Name" /> + Header="{me:LocalizationSource MainWindow.Phase}" + Description="{me:LocalizationSource MainWindow.PhaseDescription}"> + Header="{me:LocalizationSource MainWindow.SourceParam}" + Description="{me:LocalizationSource MainWindow.SourceParamDescription}"> + Header="{me:LocalizationSource MainWindow.TargetParam}" + Description="{me:LocalizationSource MainWindow.TargetParamDescription}"> Диапазон обработки элементов модели Выбор варианта обработки элементов модели - Стадия помещений - Выбор стадии для обрабатываемых помещений + Стадия помещений + Выбор стадии для обрабатываемых помещений - Параметр для чтения - Параметр, с которого будет считываться площадь + Параметр для чтения + Параметр, с которого будет считываться площадь - Параметр для записи - Параметр, в который будет записываться площадь + Параметр для записи + Параметр, в который будет записываться площадь Количество знаков после запятой До которого будет происходить округление From 91ee91f2e4da0db75595463a4bac2d4e15a4d8fa Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Tue, 26 May 2026 00:25:54 +0300 Subject: [PATCH 05/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=94=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0=20View=20=D0=B8=20Vi?= =?UTF-8?q?ewModel,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/ConfigSettings.cs | 6 +- .../Models/Enums/ElementsProviderType.cs | 6 + .../Models/Factories/ProvidersFactory.cs | 26 +++ .../Models/Interfaces/IElementsProvider.cs | 18 ++ .../Models/ParamService.cs | 94 ++++++++--- .../Models/PluginConfig.cs | 21 ++- .../Models/Providers/ElementsProviderAll.cs | 22 +++ .../Providers/ElementsProviderCurrentView.cs | 22 +++ .../Providers/ElementsProviderSelected.cs | 22 +++ .../Models/SpatialElement.cs | 3 + .../ViewModels/MainViewModel.cs | 158 +++++++----------- .../ViewModels/RangeViewModel.cs | 17 ++ .../Views/Edits/CustomEditControl.xaml | 2 +- .../Views/Edits/ModeSwitcherControl.xaml | 152 +++++++++++++++++ .../Views/Edits/ModeSwitcherControl.xaml.cs | 67 ++++++++ .../Views/MainWindow.xaml | 113 ++----------- .../assets/Localization/Language.ru-RU.xaml | 9 + 17 files changed, 533 insertions(+), 225 deletions(-) create mode 100644 src/RevitRoundingOfAreas/Models/Enums/ElementsProviderType.cs create mode 100644 src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs create mode 100644 src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs create mode 100644 src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs create mode 100644 src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs create mode 100644 src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs create mode 100644 src/RevitRoundingOfAreas/Models/SpatialElement.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/RangeViewModel.cs create mode 100644 src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml create mode 100644 src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml.cs diff --git a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs index 348a83f32..afac86988 100644 --- a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs +++ b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs @@ -1,14 +1,14 @@ -using System.Collections.Generic; - using Autodesk.Revit.DB; using dosymep.Bim4Everyone; +using RevitRoundingOfAreas.Models.Enums; + namespace RevitRoundingOfAreas.Models; internal class ConfigSettings { + public ElementsProviderType ElementsProviderType { get; set; } public ElementId SelectedPhaseId { get; set; } public RevitParam SourceParam { get; set; } public RevitParam TargetParam { get; set; } public int DigitCount { get; set; } - public List Levels { get; set; } } diff --git a/src/RevitRoundingOfAreas/Models/Enums/ElementsProviderType.cs b/src/RevitRoundingOfAreas/Models/Enums/ElementsProviderType.cs new file mode 100644 index 000000000..227a39a93 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Enums/ElementsProviderType.cs @@ -0,0 +1,6 @@ +namespace RevitRoundingOfAreas.Models.Enums; +internal enum ElementsProviderType { + AllElementsProvider, + CurrentViewProvider, + SelectedElementsProvider +} diff --git a/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs b/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs new file mode 100644 index 000000000..71581a192 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs @@ -0,0 +1,26 @@ +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Interfaces; +using RevitRoundingOfAreas.Models.Providers; + +namespace RevitRoundingOfAreas.Models.Factories; + +internal class ProvidersFactory { + + private readonly RevitRepository _revitRepository; + + public ProvidersFactory(RevitRepository revitRepository) { + _revitRepository = revitRepository; + } + + /// + /// Метод получения провайдера элементов по Enum + /// + public IElementsProvider GetElementsProvider(ElementsProviderType type) { + return type switch { + ElementsProviderType.AllElementsProvider => new ElementsProviderAll(_revitRepository), + ElementsProviderType.CurrentViewProvider => new ElementsProviderCurrentView(_revitRepository), + ElementsProviderType.SelectedElementsProvider => new ElementsProviderSelected(_revitRepository), + _ => new ElementsProviderAll(_revitRepository) + }; + } +} diff --git a/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs b/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs new file mode 100644 index 000000000..ecdc1b99c --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using RevitRoundingOfAreas.Models.Enums; + +namespace RevitRoundingOfAreas.Models.Interfaces; + +internal interface IElementsProvider { + /// + /// Тип провайдера элементов + /// + ElementsProviderType Type { get; } + /// + /// Метод получения элементов модели по стадиям + /// + List GetSpatialElements(ElementId phaseId); +} diff --git a/src/RevitRoundingOfAreas/Models/ParamService.cs b/src/RevitRoundingOfAreas/Models/ParamService.cs index 3f2a3f21b..0702e5360 100644 --- a/src/RevitRoundingOfAreas/Models/ParamService.cs +++ b/src/RevitRoundingOfAreas/Models/ParamService.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Autodesk.Revit.DB; @@ -9,50 +10,89 @@ using dosymep.Revit; namespace RevitRoundingOfAreas.Models; + internal class ParamService { private readonly RevitRepository _revitRepository; + private readonly SystemPluginConfig _systemPluginConfig; + private readonly ICollection _allParamElementIds; + + public ParamService( + RevitRepository revitRepository, + SystemPluginConfig systemPluginConfig) { - public ParamService(RevitRepository revitRepository) { _revitRepository = revitRepository; + _systemPluginConfig = systemPluginConfig; + + _allParamElementIds = GetAllParamElementIds(); + AllRevitParams = GetAllRevitParams().AsReadOnly(); + + DefaultSourceParam = GetDefaultSourceParam(); + DefaultTargetParam = GetDefaultTargetParam(); } - public List AllRevitParams => GetAllRevitParams(); + public IReadOnlyList AllRevitParams { get; } + public RevitParam DefaultSourceParam { get; } + public RevitParam DefaultTargetParam { get; } - public List GetAllRevitParams() { + private ICollection GetAllParamElementIds() { var categoryId = new ElementId(BuiltInCategory.OST_Rooms); - var filterableParameters = ParameterFilterUtilities + + return ParameterFilterUtilities .GetFilterableParametersInCommon(_revitRepository.Document, [categoryId]); + } - if(filterableParameters.Count == 0) { + private RevitParam GetDefaultSourceParam() { + return AllRevitParams + .OfType() + .FirstOrDefault(x => x.SystemParamId == _systemPluginConfig.SystemRoomAreaParamId); + } + + private RevitParam GetDefaultTargetParam() { + return AllRevitParams + .OfType() + .FirstOrDefault(x => x.Name.Equals(_systemPluginConfig.RoomAreaParam.Name)); + } + + private List GetAllRevitParams() { + if(_allParamElementIds.Count == 0) { return []; } - List listOfParameters = []; - foreach(var elementId in filterableParameters) { - if(elementId.IsSystemId()) { - var param = elementId.AsBuiltInParameter(); - RevitParam revitParam = SystemParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, param); - if(revitParam.StorageType is StorageType.Double or StorageType.String) { - listOfParameters.Add(revitParam); - } - } else { - var element = _revitRepository.Document.GetElement(elementId); - if(element is SharedParameterElement) { - RevitParam revitParam = SharedParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); - if(revitParam.StorageType is StorageType.Double or StorageType.String) { - listOfParameters.Add(revitParam); - } - } else { - RevitParam revitParam = ProjectParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); - if(revitParam.StorageType is StorageType.Double or StorageType.String) { - listOfParameters.Add(revitParam); - } - } + List parameters = []; + + foreach(var elementId in _allParamElementIds) { + var revitParam = CreateRevitParam(elementId); + + if(revitParam is null) { + continue; + } + + if(IsSupportedStorageType(revitParam)) { + parameters.Add(revitParam); } } - return listOfParameters; + return parameters; + } + + private RevitParam CreateRevitParam(ElementId elementId) { + if(elementId.IsSystemId()) { + var builtInParameter = elementId.AsBuiltInParameter(); + return SystemParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, builtInParameter); + } + + var element = _revitRepository.Document.GetElement(elementId); + + return element is null + ? null + : element is SharedParameterElement + ? SharedParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name) + : ProjectParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); + } + + private static bool IsSupportedStorageType(RevitParam revitParam) { + return revitParam.StorageType == StorageType.Double; } } diff --git a/src/RevitRoundingOfAreas/Models/PluginConfig.cs b/src/RevitRoundingOfAreas/Models/PluginConfig.cs index 434a2abb7..9246c0c19 100644 --- a/src/RevitRoundingOfAreas/Models/PluginConfig.cs +++ b/src/RevitRoundingOfAreas/Models/PluginConfig.cs @@ -1,8 +1,13 @@ +using Autodesk.Revit.DB; + using dosymep.Bim4Everyone; using dosymep.Bim4Everyone.ProjectConfigs; +using dosymep.Bim4Everyone.SharedParams; using pyRevitLabs.Json; +using RevitRoundingOfAreas.Models.Enums; + namespace RevitRoundingOfAreas.Models; /// @@ -53,10 +58,24 @@ internal class RevitSettings : ProjectSettings { internal class SystemPluginConfig { + // Режим выбора провайдера элементов по умолчанию + public ElementsProviderType DefaultProvider => ElementsProviderType.AllElementsProvider; + // Название стадии по умолчанию public string DefaultPhaseName => "Основная планировка"; - // Количество знаков по умолчанию + // Количество вариантов знаков по умолчанию + public int DefaultDigitCountRange => 3; + + // Количество знаков по умолчанию public int DefaultDigitCount => 1; + // Системный параметр площади помещений по умолчанию + public BuiltInParameter SystemRoomAreaParamId = BuiltInParameter.ROOM_AREA; + + // Общий параметр площади помещений по умолчанию + public RevitParam RoomAreaParam = SharedParamsConfig.Instance.RoomArea; + + + } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs new file mode 100644 index 000000000..0f4823599 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Interfaces; + +namespace RevitRoundingOfAreas.Models.Providers; + +internal class ElementsProviderAll : IElementsProvider { + private readonly RevitRepository _revitRepository; + + public ElementsProviderAll(RevitRepository revitRepository) { + _revitRepository = revitRepository; + } + + public ElementsProviderType Type => ElementsProviderType.AllElementsProvider; + + public List GetSpatialElements(ElementId phaseId) { + throw new System.NotImplementedException(); + } +} diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs new file mode 100644 index 000000000..ee2d3b716 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Interfaces; + +namespace RevitRoundingOfAreas.Models.Providers; + +internal class ElementsProviderCurrentView : IElementsProvider { + private readonly RevitRepository _revitRepository; + + public ElementsProviderCurrentView(RevitRepository revitRepository) { + _revitRepository = revitRepository; + } + + public ElementsProviderType Type => ElementsProviderType.CurrentViewProvider; + + public List GetSpatialElements(ElementId phaseId) { + throw new System.NotImplementedException(); + } +} diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs new file mode 100644 index 000000000..a1db7950a --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +using Autodesk.Revit.DB; + +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Interfaces; + +namespace RevitRoundingOfAreas.Models.Providers; + +internal class ElementsProviderSelected : IElementsProvider { + private readonly RevitRepository _revitRepository; + + public ElementsProviderSelected(RevitRepository revitRepository) { + _revitRepository = revitRepository; + } + + public ElementsProviderType Type => ElementsProviderType.SelectedElementsProvider; + + public List GetSpatialElements(ElementId phaseId) { + throw new System.NotImplementedException(); + } +} diff --git a/src/RevitRoundingOfAreas/Models/SpatialElement.cs b/src/RevitRoundingOfAreas/Models/SpatialElement.cs new file mode 100644 index 000000000..e617bfc7a --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/SpatialElement.cs @@ -0,0 +1,3 @@ +namespace RevitRoundingOfAreas.Models; +internal class SpatialElement { +} diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index aa018f717..f56be831c 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -10,72 +11,70 @@ using dosymep.WPF.ViewModels; using RevitRoundingOfAreas.Models; +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Factories; namespace RevitRoundingOfAreas.ViewModels; -/// -/// Основная ViewModel главного окна плагина. -/// internal class MainViewModel : BaseViewModel { private readonly PluginConfig _pluginConfig; private readonly SystemPluginConfig _systemPluginConfig; private readonly RevitRepository _revitRepository; private readonly ParamService _paramService; + private readonly ProvidersFactory _providersFactory; private readonly ILocalizationService _localizationService; private ConfigSettings _configSettings; + private ObservableCollection _range; + private RangeViewModel _selectedRange; + private ObservableCollection _phases; private PhaseViewModel _selectedPhase; - private ObservableCollection _sourceParams; + private ObservableCollection _params; private ParamViewModel _selectedSourceParam; - - private ObservableCollection _targetParams; private ParamViewModel _selectedTargetParam; private ObservableCollection _digitCount; private DigitViewModel _selectedDigitCount; - - private ObservableCollection _levels; - private string _errorText; - /// - /// Создает экземпляр основной ViewModel главного окна. - /// - /// Настройки плагина. - /// Класс доступа к интерфейсу Revit. - /// Интерфейс доступа к сервису локализации. public MainViewModel( PluginConfig pluginConfig, SystemPluginConfig systemPluginConfig, RevitRepository revitRepository, ParamService paramService, + ProvidersFactory providersFactory, ILocalizationService localizationService) { _pluginConfig = pluginConfig; _systemPluginConfig = systemPluginConfig; _revitRepository = revitRepository; _paramService = paramService; + _providersFactory = providersFactory; _localizationService = localizationService; LoadViewCommand = RelayCommand.Create(LoadView); AcceptViewCommand = RelayCommand.Create(AcceptView, CanAcceptView); } - /// - /// Команда загрузки главного окна. - /// public ICommand LoadViewCommand { get; } - /// - /// Команда применения настроек главного окна. (запуск плагина) - /// - /// В случаях, когда используется немодальное окно, требуется данную команду удалять. public ICommand AcceptViewCommand { get; } + + public ObservableCollection Range { + get => _range; + set => RaiseAndSetIfChanged(ref _range, value); + } + + public RangeViewModel SelectedRange { + get => _selectedRange; + set => RaiseAndSetIfChanged(ref _selectedRange, value); + } + public ObservableCollection Phases { get => _phases; set => RaiseAndSetIfChanged(ref _phases, value); @@ -86,9 +85,9 @@ public PhaseViewModel SelectedPhase { set => RaiseAndSetIfChanged(ref _selectedPhase, value); } - public ObservableCollection SourceParams { - get => _sourceParams; - set => RaiseAndSetIfChanged(ref _sourceParams, value); + public ObservableCollection Params { + get => _params; + set => RaiseAndSetIfChanged(ref _params, value); } public ParamViewModel SelectedSourceParam { @@ -96,11 +95,6 @@ public ParamViewModel SelectedSourceParam { set => RaiseAndSetIfChanged(ref _selectedSourceParam, value); } - public ObservableCollection TargetParams { - get => _targetParams; - set => RaiseAndSetIfChanged(ref _targetParams, value); - } - public ParamViewModel SelectedTargetParam { get => _selectedTargetParam; set => RaiseAndSetIfChanged(ref _selectedTargetParam, value); @@ -116,24 +110,24 @@ public DigitViewModel SelectedDigitCount { set => RaiseAndSetIfChanged(ref _selectedDigitCount, value); } - public ObservableCollection Levels { - get => _levels; - set => RaiseAndSetIfChanged(ref _levels, value); - } - - - /// - /// Текст ошибки, который отображается при неверном вводе пользователя. - /// public string ErrorText { get => _errorText; set => RaiseAndSetIfChanged(ref _errorText, value); } + // Метод получения коллекции RangeElementsViewModel для RangeElements + private IEnumerable GetRangeViewModels() { + var providers = Enum.GetValues(typeof(ElementsProviderType)).Cast(); + return providers + .Select(provider => new RangeViewModel { + Name = _localizationService.GetLocalizedString($"MainViewModel.{provider}"), + ElementsProvider = _providersFactory.GetElementsProvider(provider) + }); + } // Метод получения коллекции DigitViewModel для DigitCount private IEnumerable GetDigitViewModels() { - for(int i = 1; i <= 3; i++) { + for(int i = 1; i <= _systemPluginConfig.DefaultDigitCountRange; i++) { yield return new DigitViewModel { DigitCount = i, Name = i.ToString(), @@ -141,25 +135,15 @@ private IEnumerable GetDigitViewModels() { } } - // Метод получения коллекции ParamViewModel для TargetParams - private IEnumerable GetTargetParamViewModels() { + // Метод получения коллекции ParamViewModel для Params + private IEnumerable GetParamViewModels() { return _paramService.AllRevitParams .Select(param => new ParamViewModel { Name = param.Name, RevitParam = param - }) - .Where(param => param.RevitParam.StorageType is StorageType.String); + }); } - // Метод получения коллекции ParamViewModel для SourceParams - private IEnumerable GetSourceParamViewModels() { - return _paramService.AllRevitParams - .Select(param => new ParamViewModel { - Name = param.Name, - RevitParam = param - }) - .Where(param => param.RevitParam.StorageType is StorageType.Double); - } // Метод получения коллекции PhaseViewModel для Phases private IEnumerable GetPhaseViewModels() { @@ -170,28 +154,25 @@ private IEnumerable GetPhaseViewModels() { }); } - - /// - /// Метод загрузки главного окна - /// - /// В данном методе должна происходить загрузка настроек окна, а так же инициализация полей окна. private void LoadView() { LoadConfig(); + Range = new ObservableCollection(GetRangeViewModels()); + SelectedRange = Range.FirstOrDefault(range => range.ElementsProvider.Type == _configSettings.ElementsProviderType) + ?? Range.FirstOrDefault(); + Phases = new ObservableCollection(GetPhaseViewModels()); SelectedPhase = Phases .FirstOrDefault(phase => phase.ElementId == _configSettings.SelectedPhaseId) ?? Phases.LastOrDefault(); - SourceParams = new ObservableCollection(GetSourceParamViewModels()); - SelectedSourceParam = SourceParams + Params = new ObservableCollection(GetParamViewModels()); + SelectedSourceParam = Params .FirstOrDefault(param => param.RevitParam.Id == _configSettings.SourceParam?.Id) - ?? SourceParams.FirstOrDefault(); - - TargetParams = new ObservableCollection(GetTargetParamViewModels()); - SelectedTargetParam = TargetParams + ?? Params.FirstOrDefault(); + SelectedTargetParam = Params .FirstOrDefault(param => param.RevitParam.Id == _configSettings.TargetParam?.Id) - ?? TargetParams.FirstOrDefault(); + ?? Params.FirstOrDefault(); DigitCount = new ObservableCollection(GetDigitViewModels()); SelectedDigitCount = DigitCount @@ -199,32 +180,15 @@ private void LoadView() { ?? DigitCount.FirstOrDefault(); } - /// - /// Метод применения настроек главного окна. (выполнение плагина) - /// - /// - /// В данном методе должны браться настройки пользователя и сохраняться в конфиг, а так же быть основной код плагина. - /// private void AcceptView() { SaveConfig(); } - /// - /// Метод проверки возможности выполнения команды применения настроек. - /// - /// В случае когда true - команда может выполниться, в случае false - нет. - /// - /// В данном методе происходит валидация ввода пользователя и уведомление его о неверных значениях. - /// В методе проверяемые свойства окна должны быть отсортированы в таком же порядке как в окне (сверху-вниз) - /// private bool CanAcceptView() { ErrorText = null; return true; } - /// - /// Загрузка настроек плагина. - /// private void LoadConfig() { var setting = _pluginConfig.GetSettings(_revitRepository.Document); _configSettings = setting?.ConfigSettings ?? new ConfigSettings(); @@ -233,28 +197,34 @@ private void LoadConfig() { // Метод применения дефолтных значений настроек. private void ApplyDefaultsConfig() { + if(_configSettings.ElementsProviderType == default) { + _configSettings.ElementsProviderType = _systemPluginConfig.DefaultProvider; + } + if(_configSettings.SelectedPhaseId is null || _configSettings.SelectedPhaseId == ElementId.InvalidElementId) { - var phaseId = _revitRepository.GetPhaseIdByName(_systemPluginConfig.DefaultPhaseName); + _configSettings.SelectedPhaseId = _revitRepository.GetPhaseIdByName(_systemPluginConfig.DefaultPhaseName); + } - var sourceParam = _paramService.AllRevitParams - .FirstOrDefault(); + _configSettings.SourceParam ??= _paramService.DefaultSourceParam; + _configSettings.TargetParam ??= _paramService.DefaultTargetParam; - _configSettings.SelectedPhaseId = phaseId; - _configSettings.SourceParam = sourceParam; + if(_configSettings.DigitCount <= 0) { + _configSettings.DigitCount = _systemPluginConfig.DefaultDigitCount; } } - /// - /// Сохранение настроек плагина. - /// private void SaveConfig() { var setting = _pluginConfig.GetSettings(_revitRepository.Document) - ?? _pluginConfig.AddSettings(_revitRepository.Document); + ?? _pluginConfig.AddSettings(_revitRepository.Document); - _configSettings.SelectedPhaseId = SelectedPhase.ElementId; - _configSettings.SourceParam = SelectedSourceParam.RevitParam; + setting.ConfigSettings = new ConfigSettings { + ElementsProviderType = SelectedRange.ElementsProvider.Type, + SelectedPhaseId = SelectedPhase?.ElementId ?? ElementId.InvalidElementId, + SourceParam = SelectedSourceParam?.RevitParam, + TargetParam = SelectedTargetParam?.RevitParam, + DigitCount = SelectedDigitCount?.DigitCount ?? _systemPluginConfig.DefaultDigitCount + }; - setting.ConfigSettings = _configSettings; _pluginConfig.SaveProjectConfig(); } } diff --git a/src/RevitRoundingOfAreas/ViewModels/RangeViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/RangeViewModel.cs new file mode 100644 index 000000000..2c076ce3e --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/RangeViewModel.cs @@ -0,0 +1,17 @@ +using dosymep.WPF.ViewModels; + +using RevitRoundingOfAreas.Models.Interfaces; + +namespace RevitRoundingOfAreas.ViewModels; + +internal class RangeViewModel : BaseViewModel { + + private string _name; + + public IElementsProvider ElementsProvider { get; set; } + + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml index 3d96afe1c..801d9a3d9 100644 --- a/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml +++ b/src/RevitRoundingOfAreas/Views/Edits/CustomEditControl.xaml @@ -55,7 +55,7 @@ diff --git a/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml b/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml new file mode 100644 index 000000000..8677dc138 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml.cs b/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml.cs new file mode 100644 index 000000000..23854aa81 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Edits/ModeSwitcherControl.xaml.cs @@ -0,0 +1,67 @@ +using System.Collections; +using System.Windows; +using System.Windows.Controls; + +namespace RevitRoundingOfAreas.Views.Edits; + +public partial class ModeSwitcherControl : UserControl { + /// + /// Источник данных. + /// + public static readonly DependencyProperty ItemsSourceProperty = + DependencyProperty.Register( + nameof(ItemsSource), + typeof(IEnumerable), + typeof(ModeSwitcherControl), + new PropertyMetadata(null)); + + /// + /// Выбранный элемент. + /// + public static readonly DependencyProperty SelectedItemProperty = + DependencyProperty.Register( + nameof(SelectedItem), + typeof(object), + typeof(ModeSwitcherControl), + new FrameworkPropertyMetadata( + null, + FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + /// + /// Путь к отображаемому свойству. + /// + public static readonly DependencyProperty DisplayMemberPathProperty = + DependencyProperty.Register( + nameof(DisplayMemberPath), + typeof(string), + typeof(ModeSwitcherControl), + new PropertyMetadata("Name")); + + public ModeSwitcherControl() { + InitializeComponent(); + } + + /// + /// Источник данных. + /// + public IEnumerable ItemsSource { + get => (IEnumerable) GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + + /// + /// Выбранный элемент. + /// + public object SelectedItem { + get => GetValue(SelectedItemProperty); + set => SetValue(SelectedItemProperty, value); + } + + /// + /// Путь к отображаемому свойству. + /// + public string DisplayMemberPath { + get => (string) GetValue(DisplayMemberPathProperty); + set => SetValue(DisplayMemberPathProperty, value); + } +} diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 34fa02831..5470805c8 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -11,17 +11,16 @@ xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:core="clr-namespace:dosymep.WpfUI.Core" xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml" - xmlns:me="clr-namespace:dosymep.WpfCore.MarkupExtensions;assembly=dosymep.WpfCore" - xmlns:views="clr-namespace:RevitRoundingOfAreas.Views" + xmlns:me="clr-namespace:dosymep.WpfCore.MarkupExtensions;assembly=dosymep.WpfCore" mc:Ignorable="d" Title="{me:LocalizationSource MainWindow.Title}" - Height="550" - Width="1315" + Height="540" + Width="950" - MinHeight="550" - MinWidth="1315" + MinHeight="540" + MinWidth="950" d:DataContext="{d:DesignInstance vms:MainViewModel, IsDesignTimeCreatable=False}"> @@ -38,21 +37,15 @@ - - - - - @@ -61,10 +54,10 @@ Icon="{ui:SymbolIcon fullScreenMaximize24}" Header="{me:LocalizationSource MainWindow.RangeElements}" Description="{me:LocalizationSource MainWindow.RangeElementsDescription}"> - + @@ -89,7 +82,7 @@ Header="{me:LocalizationSource MainWindow.TargetParam}" Description="{me:LocalizationSource MainWindow.TargetParamDescription}"> @@ -104,88 +97,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -198,7 +113,7 @@ diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 2e7b82b5a..58fe782f2 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -26,4 +26,13 @@ Рассчитать Отмена + + Все элементы + Выделенные + Видимые на виде + + From b74531060ba50b5dd2fb4df23155a9a55c124092 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Wed, 27 May 2026 15:19:02 +0300 Subject: [PATCH 06/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=98=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE?= =?UTF-8?q?=D1=82=D1=81=D1=82=D1=83=D0=BF=D0=BE=D0=B2=20=D0=BA=D0=BD=D0=BE?= =?UTF-8?q?=D0=BF=D0=BE=D0=BA=20=D0=B2=20=D0=BE=D0=BA=D0=BD=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RevitRoundingOfAreas/Views/MainWindow.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 5470805c8..39463abf7 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -111,7 +111,7 @@ Text="{Binding ErrorText}" /> Date: Wed, 27 May 2026 16:05:43 +0300 Subject: [PATCH 07/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=94=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=B0=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D1=82=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/CheckProjectParams.cs | 35 +++++++++++++++++++ .../RevitRoundingOfAreasCommand.cs | 28 +++++++++++++++ .../assets/Localization/Language.ru-RU.xaml | 8 +++-- 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/RevitRoundingOfAreas/Models/CheckProjectParams.cs diff --git a/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs b/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs new file mode 100644 index 000000000..613c12b7d --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs @@ -0,0 +1,35 @@ +using Autodesk.Revit.ApplicationServices; +using Autodesk.Revit.DB; + +using dosymep.Bim4Everyone.Templates; + +namespace RevitRoundingOfAreas.Models; +internal class CheckProjectParams { + private readonly SystemPluginConfig _systemPluginConfig; + private readonly Application _application; + private readonly Document _document; + private readonly ProjectParameters _projectParameters; + private readonly bool _isChecked = true; + + public CheckProjectParams(SystemPluginConfig systemPluginConfig, Application application, Document document) { + _systemPluginConfig = systemPluginConfig; + _application = application; + _document = document; + _projectParameters = ProjectParameters.Create(_application); + } + + /// + /// Метод проверки загрузки параметров + /// + public bool GetIsChecked() { + return _isChecked; + } + + /// + /// Метод копирования параметров проекта + /// + public CheckProjectParams CopyProjectParams() { + _projectParameters.SetupRevitParams(_document, _systemPluginConfig.RoomAreaParam); + return this; + } +} diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index 266ff52f0..0978e60b5 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -1,5 +1,7 @@ +using System; using System.Globalization; using System.Reflection; +using System.Windows; using Autodesk.Revit.Attributes; using Autodesk.Revit.UI; @@ -7,6 +9,7 @@ using dosymep.Bim4Everyone; using dosymep.Bim4Everyone.ProjectConfigs; using dosymep.Bim4Everyone.SimpleServices; +using dosymep.SimpleServices; using dosymep.WpfCore.Ninject; using dosymep.WpfUI.Core.Ninject; @@ -45,6 +48,11 @@ protected override void Execute(UIApplication uiApplication) { // Создание контейнера зависимостей плагина с сервисами из платформы using var kernel = uiApplication.CreatePlatformServices(); + // Создание системных настроек + kernel.Bind() + .ToSelf() + .InSingletonScope(); + // Настройка доступа к Revit kernel.Bind() .ToSelf() @@ -59,6 +67,7 @@ protected override void Execute(UIApplication uiApplication) { kernel.Bind() .ToMethod(c => PluginConfig.GetPluginConfig(c.Kernel.Get())); + // Используем сервис обновления тем для WinUI kernel.UseWpfUIThemeUpdater(); @@ -75,6 +84,25 @@ protected override void Execute(UIApplication uiApplication) { $"/{assemblyName};component/assets/localization/language.xaml", CultureInfo.GetCultureInfo("ru-RU")); + var messageBoxService = kernel.Get(); + var localizationService = kernel.Get(); + var systemPluginConfig = kernel.Get(); + + // Загрузка параметров проекта + bool isParamChecked = new CheckProjectParams( + systemPluginConfig, uiApplication.Application, uiApplication.ActiveUIDocument.Document) + .CopyProjectParams() + .GetIsChecked(); + + if(!isParamChecked) { + messageBoxService.Show( + localizationService.GetLocalizedString("Common.ParamErrorMessageBody"), + localizationService.GetLocalizedString("Common.ConfigErrorMessageTitle"), + MessageBoxButton.OK, + MessageBoxImage.Exclamation); + throw new OperationCanceledException(); + } + // Вызывает стандартное уведомление Notification(kernel.Get()); } diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 58fe782f2..45865c03c 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -33,6 +33,10 @@ x:Key="MainViewModel.SelectedElementsProvider">Выделенные Видимые на виде - - + + Ошибка загрузки параметров + Ошибка настройки плагина + From a18ec3eeaef3a153c311f0285a3049fd8363c319 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Thu, 28 May 2026 09:21:31 +0300 Subject: [PATCH 08/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=94=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=B0=20=D0=BF=D0=BE=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=BA=D0=B5=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=89?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/Enums/WarningType.cs | 6 ++++ src/RevitRoundingOfAreas/Models/RoomModel.cs | 6 ++++ .../Models/SpatialElement.cs | 4 +++ .../Models/SpatialElementCheckService.cs | 31 +++++++++++++++++++ .../Models/Warnings/WarningElement.cs | 8 +++++ .../Warnings/WarningNotEnclosedElement.cs | 3 ++ .../Warnings/WarningRedundantElement.cs | 3 ++ .../RevitRoundingOfAreasCommand.cs | 7 ++++- .../ViewModels/MainViewModel.cs | 9 +++++- 9 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 src/RevitRoundingOfAreas/Models/Enums/WarningType.cs create mode 100644 src/RevitRoundingOfAreas/Models/RoomModel.cs create mode 100644 src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs create mode 100644 src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs create mode 100644 src/RevitRoundingOfAreas/Models/Warnings/WarningNotEnclosedElement.cs create mode 100644 src/RevitRoundingOfAreas/Models/Warnings/WarningRedundantElement.cs diff --git a/src/RevitRoundingOfAreas/Models/Enums/WarningType.cs b/src/RevitRoundingOfAreas/Models/Enums/WarningType.cs new file mode 100644 index 000000000..bcfc1e195 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Enums/WarningType.cs @@ -0,0 +1,6 @@ +namespace RevitRoundingOfAreas.Models.Enums; +internal enum WarningType { + NotEnclosed, + Redundant, + BrokenContour +} diff --git a/src/RevitRoundingOfAreas/Models/RoomModel.cs b/src/RevitRoundingOfAreas/Models/RoomModel.cs new file mode 100644 index 000000000..1bb46c1ef --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/RoomModel.cs @@ -0,0 +1,6 @@ +using Autodesk.Revit.DB.Architecture; + +namespace RevitRoundingOfAreas.Models; +internal class RoomModel { + public Room Room { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/SpatialElement.cs b/src/RevitRoundingOfAreas/Models/SpatialElement.cs index e617bfc7a..77007ed18 100644 --- a/src/RevitRoundingOfAreas/Models/SpatialElement.cs +++ b/src/RevitRoundingOfAreas/Models/SpatialElement.cs @@ -1,3 +1,7 @@ +using Autodesk.Revit.DB.Architecture; + namespace RevitRoundingOfAreas.Models; + internal class SpatialElement { + public Room Room { get; set; } } diff --git a/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs new file mode 100644 index 000000000..8efbe8913 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +using dosymep.Revit; + +using RevitRoundingOfAreas.Models.Enums; +using RevitRoundingOfAreas.Models.Warnings; + +namespace RevitRoundingOfAreas.Models; +internal class SpatialElementCheckService { + + public IReadOnlyCollection CheckSpatialElements(List spatialElements) { + if(spatialElements.Count == 0) { + return []; + } + List warnings = []; + foreach(var spatialElement in spatialElements) { + if(spatialElement.Room.IsRedundant()) { + warnings.Add(new WarningRedundantElement { + WarningType = WarningType.Redundant, + SpatialElement = spatialElement + }); + } else if(spatialElement.Room.IsNotEnclosed()) { + warnings.Add(new WarningNotEnclosedElement { + WarningType = WarningType.NotEnclosed, + SpatialElement = spatialElement + }); + } + } + return warnings; + } +} diff --git a/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs b/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs new file mode 100644 index 000000000..7cdef0b4f --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs @@ -0,0 +1,8 @@ +using RevitRoundingOfAreas.Models.Enums; + +namespace RevitRoundingOfAreas.Models.Warnings; + +internal class WarningElement { + public WarningType WarningType { get; set; } + public SpatialElement SpatialElement { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/Warnings/WarningNotEnclosedElement.cs b/src/RevitRoundingOfAreas/Models/Warnings/WarningNotEnclosedElement.cs new file mode 100644 index 000000000..53e68696c --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Warnings/WarningNotEnclosedElement.cs @@ -0,0 +1,3 @@ +namespace RevitRoundingOfAreas.Models.Warnings; +internal class WarningNotEnclosedElement : WarningElement { +} diff --git a/src/RevitRoundingOfAreas/Models/Warnings/WarningRedundantElement.cs b/src/RevitRoundingOfAreas/Models/Warnings/WarningRedundantElement.cs new file mode 100644 index 000000000..afbabf923 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Warnings/WarningRedundantElement.cs @@ -0,0 +1,3 @@ +namespace RevitRoundingOfAreas.Models.Warnings; +internal class WarningRedundantElement : WarningElement { +} diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index 0978e60b5..28f661578 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -58,11 +58,16 @@ protected override void Execute(UIApplication uiApplication) { .ToSelf() .InSingletonScope(); - // Создание класса с параметрами + // Настройка доступа к классу параметров kernel.Bind() .ToSelf() .InSingletonScope(); + // Настройка доступа к классу проверок + kernel.Bind() + .ToSelf() + .InSingletonScope(); + // Настройка конфигурации плагина kernel.Bind() .ToMethod(c => PluginConfig.GetPluginConfig(c.Kernel.Get())); diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index f56be831c..1695ba12d 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -22,6 +22,7 @@ internal class MainViewModel : BaseViewModel { private readonly RevitRepository _revitRepository; private readonly ParamService _paramService; private readonly ProvidersFactory _providersFactory; + private readonly SpatialElementCheckService _spatialElementCheckService; private readonly ILocalizationService _localizationService; private ConfigSettings _configSettings; @@ -47,7 +48,8 @@ public MainViewModel( RevitRepository revitRepository, ParamService paramService, ProvidersFactory providersFactory, - ILocalizationService localizationService) { + ILocalizationService localizationService, + SpatialElementCheckService spatialElementCheckService) { _pluginConfig = pluginConfig; _systemPluginConfig = systemPluginConfig; @@ -55,6 +57,7 @@ public MainViewModel( _paramService = paramService; _providersFactory = providersFactory; _localizationService = localizationService; + _spatialElementCheckService = spatialElementCheckService; LoadViewCommand = RelayCommand.Create(LoadView); AcceptViewCommand = RelayCommand.Create(AcceptView, CanAcceptView); @@ -182,6 +185,10 @@ private void LoadView() { private void AcceptView() { SaveConfig(); + var spatialElements = SelectedRange.ElementsProvider.GetSpatialElements(SelectedPhase.ElementId); + var warnings = _spatialElementCheckService.CheckSpatialElements(spatialElements); + + } private bool CanAcceptView() { From 1c5381e02f111a6f306ab37f3d25d25c7371c044 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Thu, 28 May 2026 13:48:55 +0300 Subject: [PATCH 09/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=94=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0=20MainViewModel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/ConfigSettings.cs | 3 - .../Models/Interfaces/IElementsProvider.cs | 2 +- .../Models/Providers/ElementsProviderAll.cs | 2 +- .../Providers/ElementsProviderCurrentView.cs | 2 +- .../Providers/ElementsProviderSelected.cs | 2 +- .../Models/RevitRepository.cs | 31 +++++++- src/RevitRoundingOfAreas/Models/RoomModel.cs | 6 -- .../Models/SpatialElement.cs | 7 -- .../Models/SpatialElementCheckService.cs | 17 +++-- .../Models/SpatialModel.cs | 8 +++ .../Models/Warnings/WarningElement.cs | 2 +- .../ViewModels/MainViewModel.cs | 51 +++++++------ .../Warnings/WarningElementViewModel.cs | 38 ++++++++++ .../Warnings/WarningGroupViewModel.cs | 52 ++++++++++++++ .../ViewModels/Warnings/WarningsViewModel.cs | 72 +++++++++++++++++++ .../assets/Localization/Language.ru-RU.xaml | 14 ++++ 16 files changed, 259 insertions(+), 50 deletions(-) delete mode 100644 src/RevitRoundingOfAreas/Models/RoomModel.cs delete mode 100644 src/RevitRoundingOfAreas/Models/SpatialElement.cs create mode 100644 src/RevitRoundingOfAreas/Models/SpatialModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs create mode 100644 src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs diff --git a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs index afac86988..5a98d9bf1 100644 --- a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs +++ b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs @@ -2,11 +2,8 @@ using dosymep.Bim4Everyone; -using RevitRoundingOfAreas.Models.Enums; - namespace RevitRoundingOfAreas.Models; internal class ConfigSettings { - public ElementsProviderType ElementsProviderType { get; set; } public ElementId SelectedPhaseId { get; set; } public RevitParam SourceParam { get; set; } public RevitParam TargetParam { get; set; } diff --git a/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs b/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs index ecdc1b99c..5d8c50c80 100644 --- a/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs +++ b/src/RevitRoundingOfAreas/Models/Interfaces/IElementsProvider.cs @@ -14,5 +14,5 @@ internal interface IElementsProvider { /// /// Метод получения элементов модели по стадиям /// - List GetSpatialElements(ElementId phaseId); + List GetSpatialElements(ElementId phaseId); } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs index 0f4823599..02ead353f 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs @@ -16,7 +16,7 @@ public ElementsProviderAll(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.AllElementsProvider; - public List GetSpatialElements(ElementId phaseId) { + public List GetSpatialElements(ElementId phaseId) { throw new System.NotImplementedException(); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs index ee2d3b716..9ad8dc893 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs @@ -16,7 +16,7 @@ public ElementsProviderCurrentView(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.CurrentViewProvider; - public List GetSpatialElements(ElementId phaseId) { + public List GetSpatialElements(ElementId phaseId) { throw new System.NotImplementedException(); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs index a1db7950a..57abadb62 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs @@ -16,7 +16,7 @@ public ElementsProviderSelected(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.SelectedElementsProvider; - public List GetSpatialElements(ElementId phaseId) { + public List GetSpatialElements(ElementId phaseId) { throw new System.NotImplementedException(); } } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index c3bd3f76a..3fbdf7d7c 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -4,8 +4,11 @@ using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB; +using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI; +using dosymep.Revit; + namespace RevitRoundingOfAreas.Models; internal class RevitRepository { @@ -37,9 +40,35 @@ public RevitRepository(UIApplication uiApplication) { /// public Document Document => ActiveUIDocument.Document; + public bool HasSelectedRooms() { + var selected = GetSelectedElements(); + return selected != null && selected.Count() != 0 && selected + .Any(element => element is Room); + } + public bool HasRoomsOnCurrentView() { + var viewId = Document.ActiveView.Id; + return new FilteredElementCollector(Document, viewId) + .OfCategory(BuiltInCategory.OST_Rooms) + .WhereElementIsNotElementType() + .Any(); + } + /// + /// Метод выделения элементов в документе + /// + public void SetSelected(ElementId elementId) { + List listElements = [elementId]; + ActiveUIDocument.SetSelectedElements(listElements); + } + + /// + /// Метод получения всех выделенных элементов модели + /// + public IEnumerable GetSelectedElements() { + return ActiveUIDocument.GetSelectedElements(); + } public IEnumerable GetPhaseModels() { var phases = Document.Phases; @@ -57,6 +86,4 @@ public ElementId GetPhaseIdByName(string name) { ?.ElementId ?? ElementId.InvalidElementId; } - - } diff --git a/src/RevitRoundingOfAreas/Models/RoomModel.cs b/src/RevitRoundingOfAreas/Models/RoomModel.cs deleted file mode 100644 index 1bb46c1ef..000000000 --- a/src/RevitRoundingOfAreas/Models/RoomModel.cs +++ /dev/null @@ -1,6 +0,0 @@ -using Autodesk.Revit.DB.Architecture; - -namespace RevitRoundingOfAreas.Models; -internal class RoomModel { - public Room Room { get; set; } -} diff --git a/src/RevitRoundingOfAreas/Models/SpatialElement.cs b/src/RevitRoundingOfAreas/Models/SpatialElement.cs deleted file mode 100644 index 77007ed18..000000000 --- a/src/RevitRoundingOfAreas/Models/SpatialElement.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Autodesk.Revit.DB.Architecture; - -namespace RevitRoundingOfAreas.Models; - -internal class SpatialElement { - public Room Room { get; set; } -} diff --git a/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs index 8efbe8913..57b7b1907 100644 --- a/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs +++ b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using Autodesk.Revit.DB.Architecture; + using dosymep.Revit; using RevitRoundingOfAreas.Models.Enums; @@ -8,21 +10,22 @@ namespace RevitRoundingOfAreas.Models; internal class SpatialElementCheckService { - public IReadOnlyCollection CheckSpatialElements(List spatialElements) { - if(spatialElements.Count == 0) { + public IReadOnlyCollection CheckSpatialElements(List spatialModels) { + if(spatialModels.Count == 0) { return []; } List warnings = []; - foreach(var spatialElement in spatialElements) { - if(spatialElement.Room.IsRedundant()) { + foreach(var spatialModel in spatialModels) { + var room = spatialModel.SpatialElement as Room; + if(room.IsRedundant()) { warnings.Add(new WarningRedundantElement { WarningType = WarningType.Redundant, - SpatialElement = spatialElement + SpatialModel = spatialModel }); - } else if(spatialElement.Room.IsNotEnclosed()) { + } else if(room.IsNotEnclosed()) { warnings.Add(new WarningNotEnclosedElement { WarningType = WarningType.NotEnclosed, - SpatialElement = spatialElement + SpatialModel = spatialModel }); } } diff --git a/src/RevitRoundingOfAreas/Models/SpatialModel.cs b/src/RevitRoundingOfAreas/Models/SpatialModel.cs new file mode 100644 index 000000000..83df94209 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/SpatialModel.cs @@ -0,0 +1,8 @@ +using Autodesk.Revit.DB; + +namespace RevitRoundingOfAreas.Models; + +internal class SpatialModel { + public SpatialElement SpatialElement { get; set; } + public string LevelName { get; set; } +} diff --git a/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs b/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs index 7cdef0b4f..2e1e63e73 100644 --- a/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs +++ b/src/RevitRoundingOfAreas/Models/Warnings/WarningElement.cs @@ -4,5 +4,5 @@ namespace RevitRoundingOfAreas.Models.Warnings; internal class WarningElement { public WarningType WarningType { get; set; } - public SpatialElement SpatialElement { get; set; } + public SpatialModel SpatialModel { get; set; } } diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index 1695ba12d..073776527 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -118,16 +118,6 @@ public string ErrorText { set => RaiseAndSetIfChanged(ref _errorText, value); } - // Метод получения коллекции RangeElementsViewModel для RangeElements - private IEnumerable GetRangeViewModels() { - var providers = Enum.GetValues(typeof(ElementsProviderType)).Cast(); - return providers - .Select(provider => new RangeViewModel { - Name = _localizationService.GetLocalizedString($"MainViewModel.{provider}"), - ElementsProvider = _providersFactory.GetElementsProvider(provider) - }); - } - // Метод получения коллекции DigitViewModel для DigitCount private IEnumerable GetDigitViewModels() { for(int i = 1; i <= _systemPluginConfig.DefaultDigitCountRange; i++) { @@ -147,7 +137,6 @@ private IEnumerable GetParamViewModels() { }); } - // Метод получения коллекции PhaseViewModel для Phases private IEnumerable GetPhaseViewModels() { return _revitRepository.GetPhaseModels() @@ -157,12 +146,21 @@ private IEnumerable GetPhaseViewModels() { }); } + // Метод получения коллекции RangeElementsViewModel для RangeElements + private IEnumerable GetRangeViewModels() { + var providers = Enum.GetValues(typeof(ElementsProviderType)).Cast(); + return providers + .Select(provider => new RangeViewModel { + Name = _localizationService.GetLocalizedString($"MainViewModel.{provider}"), + ElementsProvider = _providersFactory.GetElementsProvider(provider) + }); + } + private void LoadView() { LoadConfig(); Range = new ObservableCollection(GetRangeViewModels()); - SelectedRange = Range.FirstOrDefault(range => range.ElementsProvider.Type == _configSettings.ElementsProviderType) - ?? Range.FirstOrDefault(); + SelectedRange = ResolveDefaultRange() ?? Range.FirstOrDefault(); Phases = new ObservableCollection(GetPhaseViewModels()); SelectedPhase = Phases @@ -183,15 +181,33 @@ private void LoadView() { ?? DigitCount.FirstOrDefault(); } + private RangeViewModel ResolveDefaultRange() { + return _revitRepository.HasSelectedRooms() + ? Range.FirstOrDefault(x => x.ElementsProvider.Type == ElementsProviderType.SelectedElementsProvider) + : _revitRepository.HasRoomsOnCurrentView() + ? Range.FirstOrDefault(x => x.ElementsProvider.Type == ElementsProviderType.CurrentViewProvider) + : Range.FirstOrDefault(x => x.ElementsProvider.Type == ElementsProviderType.AllElementsProvider); + } + private void AcceptView() { SaveConfig(); var spatialElements = SelectedRange.ElementsProvider.GetSpatialElements(SelectedPhase.ElementId); var warnings = _spatialElementCheckService.CheckSpatialElements(spatialElements); - - } private bool CanAcceptView() { + if(SelectedRange != null) { + if(SelectedRange.ElementsProvider.Type == ElementsProviderType.SelectedElementsProvider + && !_revitRepository.HasSelectedRooms()) { + ErrorText = _localizationService.GetLocalizedString("MainViewModel.NoSelection"); + return false; + } + if(SelectedRange.ElementsProvider.Type == ElementsProviderType.CurrentViewProvider + && !_revitRepository.HasRoomsOnCurrentView()) { + ErrorText = _localizationService.GetLocalizedString("MainViewModel.NoRoomsOnView"); + return false; + } + } ErrorText = null; return true; } @@ -204,10 +220,6 @@ private void LoadConfig() { // Метод применения дефолтных значений настроек. private void ApplyDefaultsConfig() { - if(_configSettings.ElementsProviderType == default) { - _configSettings.ElementsProviderType = _systemPluginConfig.DefaultProvider; - } - if(_configSettings.SelectedPhaseId is null || _configSettings.SelectedPhaseId == ElementId.InvalidElementId) { _configSettings.SelectedPhaseId = _revitRepository.GetPhaseIdByName(_systemPluginConfig.DefaultPhaseName); } @@ -225,7 +237,6 @@ private void SaveConfig() { ?? _pluginConfig.AddSettings(_revitRepository.Document); setting.ConfigSettings = new ConfigSettings { - ElementsProviderType = SelectedRange.ElementsProvider.Type, SelectedPhaseId = SelectedPhase?.ElementId ?? ElementId.InvalidElementId, SourceParam = SelectedSourceParam?.RevitParam, TargetParam = SelectedTargetParam?.RevitParam, diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs new file mode 100644 index 000000000..7bfd9e552 --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs @@ -0,0 +1,38 @@ +using System.Windows.Input; + +using Autodesk.Revit.DB; + +using dosymep.WPF.ViewModels; + +using RevitRoundingOfAreas.Models; + +namespace RevitRoundingOfAreas.ViewModels.Warnings; + +internal class WarningElementViewModel : BaseViewModel { + private readonly SpatialModel _spatialModel; + private ElementId _elementId; + private string _name; + private string _levelName; + + public WarningElementViewModel(SpatialModel spatialModel) { + _spatialModel = spatialModel; + ElementId = _spatialModel.SpatialElement.Id; + Name = _spatialModel.SpatialElement.Name; + LevelName = _spatialModel.LevelName; + } + + public ICommand ShowElementCommand { get; set; } + + public ElementId ElementId { + get => _elementId; + set => RaiseAndSetIfChanged(ref _elementId, value); + } + public string Name { + get => _name; + set => RaiseAndSetIfChanged(ref _name, value); + } + public string LevelName { + get => _levelName; + set => RaiseAndSetIfChanged(ref _levelName, value); + } +} diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs new file mode 100644 index 000000000..8728a468a --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Input; + +using dosymep.WPF.ViewModels; + +using RevitRoundingOfAreas.Models.Warnings; + +namespace RevitRoundingOfAreas.ViewModels.Warnings; +internal class WarningGroupViewModel : BaseViewModel { + + private ObservableCollection _warnings; + private string _caption; + private string _description; + private string _warningQuantity; + + public IReadOnlyCollection WarningElements { get; set; } = []; + public ICommand ShowElementCommand { get; set; } + + public ObservableCollection Warnings { + get => _warnings; + set => RaiseAndSetIfChanged(ref _warnings, value); + } + public string Caption { + get => _caption; + set => RaiseAndSetIfChanged(ref _caption, value); + } + public string Description { + get => _description; + set => RaiseAndSetIfChanged(ref _description, value); + } + public string WarningQuantity { + get => _warningQuantity; + set => RaiseAndSetIfChanged(ref _warningQuantity, value); + } + + /// + /// Метод загрузки окна + /// + public void LoadView() { + Warnings = new(GetWarningElementViewModel()); + } + + // Метод получения списка WarningElementViewModel + private IEnumerable GetWarningElementViewModel() { + return WarningElements + .Select(warningElement => new WarningElementViewModel(warningElement.SpatialModel) { + ShowElementCommand = ShowElementCommand + }); + } +} diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs new file mode 100644 index 000000000..cd45c951f --- /dev/null +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows.Input; + +using Autodesk.Revit.DB; + +using dosymep.SimpleServices; +using dosymep.WPF.Commands; +using dosymep.WPF.ViewModels; + +using RevitRoundingOfAreas.Models; +using RevitRoundingOfAreas.Models.Warnings; + +namespace RevitRoundingOfAreas.ViewModels.Warnings; +internal class WarningsViewModel : BaseViewModel { + private readonly ILocalizationService _localizationService; + private readonly RevitRepository _revitRepository; + private ObservableCollection _warningViewModels; + private string _warningQuantity; + + public WarningsViewModel(ILocalizationService localizationService, RevitRepository revitRepository) { + _localizationService = localizationService; + _revitRepository = revitRepository; + + ShowElementCommand = RelayCommand.Create(ShowElement); + } + + public ICommand ShowElementCommand { get; } + public IReadOnlyCollection WarningElementsCollection { get; set; } + + public ObservableCollection WarningViewModels { + get => _warningViewModels; + set => RaiseAndSetIfChanged(ref _warningViewModels, value); + } + public string WarningQuantity { + get => _warningQuantity; + set => RaiseAndSetIfChanged(ref _warningQuantity, value); + } + + /// + /// Метод загрузки окна + /// + public void LoadView() { + WarningViewModels = new ObservableCollection(GetWarningGroupViewModels()); + WarningQuantity = $"({WarningViewModels.Count})"; + } + + // Метод выделения элемента + private void ShowElement(ElementId elementId) { + _revitRepository.SetSelected(elementId); + } + + // Метод формирования списка WarningGroupViewModel + private IEnumerable GetWarningGroupViewModels() { + var regularGroups = WarningElementsCollection + .GroupBy(w => w.WarningType) + .Select(group => { + var vm = new WarningGroupViewModel { + Caption = _localizationService.GetLocalizedString($"WarningsViewModel.{group.Key}"), + Description = _localizationService.GetLocalizedString($"WarningsViewModel.{group.Key}Description"), + WarningElements = group.ToList(), + WarningQuantity = $"({group.Count()})", + ShowElementCommand = ShowElementCommand + }; + vm.LoadView(); + return vm; + }); + + return regularGroups; + } +} diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 45865c03c..67834b505 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -39,4 +39,18 @@ Ошибка настройки плагина + Избыточные зоны + Зоны, находящиеся в одной окруженной области + Не окруженные зоны / Не размещенные зоны + Зоны, не имеющие границ или не размещенные на плане + + Не выделены помещения + Нет помещений на виде + From 12d861733b540a94faac7a0f82b152d85deeb4a9 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Thu, 28 May 2026 18:18:59 +0300 Subject: [PATCH 10/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=A0=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B4=D1=83=D0=BF=D1=80=D0=B5=D0=B6=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/Interfaces/IWindowService.cs | 29 ++ .../Models/Providers/ElementsProviderAll.cs | 2 +- .../Providers/ElementsProviderCurrentView.cs | 2 +- .../Providers/ElementsProviderSelected.cs | 2 +- .../Models/RevitRepository.cs | 103 +++++-- .../Models/WindowService.cs | 33 ++ .../RevitRoundingOfAreasCommand.cs | 13 + .../ViewModels/MainViewModel.cs | 9 + .../Warnings/WarningElementViewModel.cs | 10 +- .../ViewModels/Warnings/WarningsViewModel.cs | 4 +- src/RevitRoundingOfAreas/Views/Styles.xaml | 287 ++++++++++++++++++ .../Views/WarningsWindow.xaml | 163 ++++++++++ .../Views/WarningsWindow.xaml.cs | 35 +++ .../assets/Localization/Language.ru-RU.xaml | 12 + 14 files changed, 674 insertions(+), 30 deletions(-) create mode 100644 src/RevitRoundingOfAreas/Models/Interfaces/IWindowService.cs create mode 100644 src/RevitRoundingOfAreas/Models/WindowService.cs create mode 100644 src/RevitRoundingOfAreas/Views/Styles.xaml create mode 100644 src/RevitRoundingOfAreas/Views/WarningsWindow.xaml create mode 100644 src/RevitRoundingOfAreas/Views/WarningsWindow.xaml.cs diff --git a/src/RevitRoundingOfAreas/Models/Interfaces/IWindowService.cs b/src/RevitRoundingOfAreas/Models/Interfaces/IWindowService.cs new file mode 100644 index 000000000..3f9ef52e7 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/Interfaces/IWindowService.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +using RevitRoundingOfAreas.Models.Warnings; + +namespace RevitRoundingOfAreas.Models.Interfaces; + +internal interface IWindowService { + /// + /// Метод закрытия основного окна + /// + /// + /// В данном методе производится закрытие основного окна при появлении предупреждений + /// + /// + /// Void. + /// + void CloseMainWindow(); + /// + /// Метод открытия окна. + /// + /// + /// В данном методе производится открытие кона предупреждений для отображения WarningElement. + /// + /// Коллекция предупреждений WarningElement. + /// + /// Void. + /// + void ShowWarningWindow(IReadOnlyCollection warningElements); +} diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs index 02ead353f..b609c2288 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs @@ -17,6 +17,6 @@ public ElementsProviderAll(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.AllElementsProvider; public List GetSpatialElements(ElementId phaseId) { - throw new System.NotImplementedException(); + return _revitRepository.GetAllSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs index 9ad8dc893..dc558a03c 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs @@ -17,6 +17,6 @@ public ElementsProviderCurrentView(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.CurrentViewProvider; public List GetSpatialElements(ElementId phaseId) { - throw new System.NotImplementedException(); + return _revitRepository.GetActiveViewSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs index 57abadb62..38e80f749 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs @@ -17,6 +17,6 @@ public ElementsProviderSelected(RevitRepository revitRepository) { public ElementsProviderType Type => ElementsProviderType.SelectedElementsProvider; public List GetSpatialElements(ElementId phaseId) { - throw new System.NotImplementedException(); + return _revitRepository.GetSelectedSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index 3fbdf7d7c..ae87edc95 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -8,44 +8,74 @@ using Autodesk.Revit.UI; using dosymep.Revit; +using dosymep.SimpleServices; namespace RevitRoundingOfAreas.Models; internal class RevitRepository { - /// - /// Создает экземпляр репозитория. - /// - /// Класс доступа к интерфейсу Revit. - public RevitRepository(UIApplication uiApplication) { + private readonly ILocalizationService _localizationService; + + public RevitRepository(UIApplication uiApplication, ILocalizationService localizationService) { UIApplication = uiApplication; + _localizationService = localizationService; } - /// - /// Класс доступа к интерфейсу Revit. - /// public UIApplication UIApplication { get; } + public UIDocument ActiveUIDocument => UIApplication.ActiveUIDocument; + public Application Application => UIApplication.Application; + public Document Document => ActiveUIDocument.Document; /// - /// Класс доступа к интерфейсу документа Revit. + /// Метод получения всех помещений /// - public UIDocument ActiveUIDocument => UIApplication.ActiveUIDocument; + public List GetAllSpatialModels(ElementId phaseId) { + return new FilteredElementCollector(Document) + .OfCategory(BuiltInCategory.OST_Rooms) + .WhereElementIsNotElementType() + .OfType() + .Where(spatial => ValidatePhase(spatial, phaseId)) + .Select(CreateSpatialModel) + .ToList(); + } /// - /// Класс доступа к приложению Revit. + /// Метод получения всех помещений на активном виде /// - public Application Application => UIApplication.Application; + public List GetActiveViewSpatialModels(ElementId phaseId) { + return new FilteredElementCollector(Document, Document.ActiveView.Id) + .OfCategory(BuiltInCategory.OST_Rooms) + .WhereElementIsNotElementType() + .OfType() + .Where(spatial => ValidatePhase(spatial, phaseId)) + .Select(CreateSpatialModel) + .ToList(); + } /// - /// Класс доступа к документу Revit. + /// Метод получения всех выделенных помещений /// - public Document Document => ActiveUIDocument.Document; + public List GetSelectedSpatialModels(ElementId phaseId) { + return !HasSelectedRooms() + ? [] + : GetSelectedElements() + .OfType() + .Where(spatial => ValidatePhase(spatial, phaseId)) + .Select(CreateSpatialModel) + .ToList(); + } + /// + /// Метод проверки, есть ли выделенные помещения + /// public bool HasSelectedRooms() { var selected = GetSelectedElements(); return selected != null && selected.Count() != 0 && selected .Any(element => element is Room); } + /// + /// Метод проверки, есть ли помещения на активном виде + /// public bool HasRoomsOnCurrentView() { var viewId = Document.ActiveView.Id; @@ -55,6 +85,13 @@ public bool HasRoomsOnCurrentView() { .Any(); } + /// + /// Метод получения всех выделенных элементов модели + /// + public IEnumerable GetSelectedElements() { + return ActiveUIDocument.GetSelectedElements(); + } + /// /// Метод выделения элементов в документе /// @@ -64,12 +101,8 @@ public void SetSelected(ElementId elementId) { } /// - /// Метод получения всех выделенных элементов модели - /// - public IEnumerable GetSelectedElements() { - return ActiveUIDocument.GetSelectedElements(); - } - + /// Метод получения стадий проекта + /// public IEnumerable GetPhaseModels() { var phases = Document.Phases; return phases @@ -80,10 +113,40 @@ public IEnumerable GetPhaseModels() { }); } + /// + /// Метод получения стадии по имени + /// public ElementId GetPhaseIdByName(string name) { return GetPhaseModels() .FirstOrDefault(phase => phase != null && phase.Name == name) ?.ElementId ?? ElementId.InvalidElementId; } + + // Создания объекта SpatialModel + public SpatialModel CreateSpatialModel(SpatialElement spatialElement) { + return new SpatialModel { + SpatialElement = spatialElement, + LevelName = GetLevelName(spatialElement) + }; + } + + // Получение уровня помещения + private string GetLevelName(SpatialElement spatialElement) { + if(spatialElement is null) { + _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + } + var levelId = spatialElement.LevelId; + if(levelId is null || levelId == ElementId.InvalidElementId) { + _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + } + return Document.GetElement(levelId)?.Name + ?? _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + } + + // Метод валидации стадии + private bool ValidatePhase(SpatialElement spatialElement, ElementId phaseId) { + var spatialPhaseId = spatialElement.get_Parameter(BuiltInParameter.ROOM_PHASE).AsElementId(); + return spatialPhaseId != ElementId.InvalidElementId && spatialPhaseId == phaseId; + } } diff --git a/src/RevitRoundingOfAreas/Models/WindowService.cs b/src/RevitRoundingOfAreas/Models/WindowService.cs new file mode 100644 index 000000000..e24984205 --- /dev/null +++ b/src/RevitRoundingOfAreas/Models/WindowService.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +using Ninject; +using Ninject.Syntax; + +using RevitRoundingOfAreas.Models.Interfaces; +using RevitRoundingOfAreas.Models.Warnings; +using RevitRoundingOfAreas.ViewModels.Warnings; +using RevitRoundingOfAreas.Views; + +namespace RevitRoundingOfAreas.Models; + +internal class WindowService : IWindowService { + private readonly IResolutionRoot _resolutionRoot; + + public WindowService(IResolutionRoot resolutionRoot) { + _resolutionRoot = resolutionRoot; + } + + public void CloseMainWindow() { + var mainWindow = _resolutionRoot.Get(); + mainWindow.Close(); + } + + public void ShowWarningWindow(IReadOnlyCollection warningElements) { + var warningsVM = _resolutionRoot.Get(); + warningsVM.WarningElementsCollection = warningElements; + var warningsWindow = _resolutionRoot.Get(); + warningsWindow.DataContext = warningsVM; + warningsVM.LoadView(); + warningsWindow.Show(); + } +} diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index 28f661578..1c903e2c5 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Windows; + using Autodesk.Revit.Attributes; using Autodesk.Revit.UI; @@ -16,7 +17,9 @@ using Ninject; using RevitRoundingOfAreas.Models; +using RevitRoundingOfAreas.Models.Interfaces; using RevitRoundingOfAreas.ViewModels; +using RevitRoundingOfAreas.ViewModels.Warnings; using RevitRoundingOfAreas.Views; namespace RevitRoundingOfAreas; @@ -68,10 +71,17 @@ protected override void Execute(UIApplication uiApplication) { .ToSelf() .InSingletonScope(); + // Настройка доступа к сервису по управлению окнами + kernel.Bind() + .To() + .InSingletonScope(); + // Настройка конфигурации плагина kernel.Bind() .ToMethod(c => PluginConfig.GetPluginConfig(c.Kernel.Get())); + // Настройка сервиса окошек сообщений + kernel.UseWpfUIMessageBox(); // Используем сервис обновления тем для WinUI kernel.UseWpfUIThemeUpdater(); @@ -79,6 +89,9 @@ protected override void Execute(UIApplication uiApplication) { // Настройка запуска окна kernel.BindMainWindow(); + // Настройка запуска окна предупреждений + kernel.BindOtherWindow(); + // Настройка локализации, // получение имени сборки откуда брать текст string assemblyName = Assembly.GetExecutingAssembly().GetName().Name; diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index 073776527..498514b56 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -13,6 +13,7 @@ using RevitRoundingOfAreas.Models; using RevitRoundingOfAreas.Models.Enums; using RevitRoundingOfAreas.Models.Factories; +using RevitRoundingOfAreas.Models.Interfaces; namespace RevitRoundingOfAreas.ViewModels; @@ -23,6 +24,7 @@ internal class MainViewModel : BaseViewModel { private readonly ParamService _paramService; private readonly ProvidersFactory _providersFactory; private readonly SpatialElementCheckService _spatialElementCheckService; + private readonly IWindowService _windowService; private readonly ILocalizationService _localizationService; private ConfigSettings _configSettings; @@ -49,6 +51,7 @@ public MainViewModel( ParamService paramService, ProvidersFactory providersFactory, ILocalizationService localizationService, + IWindowService windowService, SpatialElementCheckService spatialElementCheckService) { _pluginConfig = pluginConfig; @@ -57,6 +60,7 @@ public MainViewModel( _paramService = paramService; _providersFactory = providersFactory; _localizationService = localizationService; + _windowService = windowService; _spatialElementCheckService = spatialElementCheckService; LoadViewCommand = RelayCommand.Create(LoadView); @@ -193,6 +197,11 @@ private void AcceptView() { SaveConfig(); var spatialElements = SelectedRange.ElementsProvider.GetSpatialElements(SelectedPhase.ElementId); var warnings = _spatialElementCheckService.CheckSpatialElements(spatialElements); + + if(warnings.Count != 0) { + _windowService.CloseMainWindow(); + _windowService.ShowWarningWindow(warnings); + } } private bool CanAcceptView() { diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs index 7bfd9e552..d52c24f93 100644 --- a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs @@ -16,17 +16,13 @@ internal class WarningElementViewModel : BaseViewModel { public WarningElementViewModel(SpatialModel spatialModel) { _spatialModel = spatialModel; - ElementId = _spatialModel.SpatialElement.Id; Name = _spatialModel.SpatialElement.Name; LevelName = _spatialModel.LevelName; + ElementId = _spatialModel.SpatialElement.Id; } public ICommand ShowElementCommand { get; set; } - public ElementId ElementId { - get => _elementId; - set => RaiseAndSetIfChanged(ref _elementId, value); - } public string Name { get => _name; set => RaiseAndSetIfChanged(ref _name, value); @@ -35,4 +31,8 @@ public string LevelName { get => _levelName; set => RaiseAndSetIfChanged(ref _levelName, value); } + public ElementId ElementId { + get => _elementId; + set => RaiseAndSetIfChanged(ref _elementId, value); + } } diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs index cd45c951f..7f9750181 100644 --- a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningsViewModel.cs @@ -43,7 +43,7 @@ public string WarningQuantity { /// public void LoadView() { WarningViewModels = new ObservableCollection(GetWarningGroupViewModels()); - WarningQuantity = $"({WarningViewModels.Count})"; + WarningQuantity = WarningViewModels.Count.ToString(); } // Метод выделения элемента @@ -60,7 +60,7 @@ private IEnumerable GetWarningGroupViewModels() { Caption = _localizationService.GetLocalizedString($"WarningsViewModel.{group.Key}"), Description = _localizationService.GetLocalizedString($"WarningsViewModel.{group.Key}Description"), WarningElements = group.ToList(), - WarningQuantity = $"({group.Count()})", + WarningQuantity = group.Count().ToString(), ShowElementCommand = ShowElementCommand }; vm.LoadView(); diff --git a/src/RevitRoundingOfAreas/Views/Styles.xaml b/src/RevitRoundingOfAreas/Views/Styles.xaml new file mode 100644 index 000000000..69e6613b9 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/Styles.xaml @@ -0,0 +1,287 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml new file mode 100644 index 000000000..b9a57d5e6 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml.cs b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml.cs new file mode 100644 index 000000000..7f784e503 --- /dev/null +++ b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml.cs @@ -0,0 +1,35 @@ +using dosymep.SimpleServices; + +namespace RevitRoundingOfAreas.Views; +/// +/// Interaction logic for WarningWindow.xaml +/// +public partial class WarningsWindow { + public WarningsWindow( + ILoggerService loggerService, + ISerializationService serializationService, + ILanguageService languageService, ILocalizationService localizationService, + IUIThemeService uiThemeService, IUIThemeUpdaterService themeUpdaterService) + : base(loggerService, + serializationService, + languageService, localizationService, + uiThemeService, themeUpdaterService) { + InitializeComponent(); + } + + /// + /// Наименование плагина. + /// + /// + /// Используется для сохранения положения окна. + /// + public override string PluginName => nameof(RevitRoundingOfAreas); + + /// + /// Наименование файла конфигурации. + /// + /// + /// Используется для сохранения положения окна. + /// + public override string ProjectConfigName => nameof(WarningsWindow); +} diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 67834b505..d886007fc 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -53,4 +53,16 @@ Нет помещений на виде + - Нет уровня - + + Предупреждения + ИД помещения + Имя помещения + Уровень помещения + From 1554939caa3713f1bd36f61b08003ff2908b6c01 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Fri, 29 May 2026 16:38:16 +0300 Subject: [PATCH 11/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=98=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE?= =?UTF-8?q?=D0=BA=D0=BD=D0=B0=20=D0=BF=D1=80=D0=B5=D0=B4=D1=83=D0=BF=D1=80?= =?UTF-8?q?=D0=B5=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RevitRoundingOfAreas/Views/MainWindow.xaml | 2 +- .../Views/WarningsWindow.xaml | 15 ++++++++------- .../assets/Localization/Language.ru-RU.xaml | 4 +++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 39463abf7..5c4212523 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -14,7 +14,7 @@ xmlns:me="clr-namespace:dosymep.WpfCore.MarkupExtensions;assembly=dosymep.WpfCore" mc:Ignorable="d" - Title="{me:LocalizationSource MainWindow.Title}" + Title="{me:LocalizationSource WarningWindow.Title}" Height="540" Width="950" diff --git a/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml index b9a57d5e6..ed5547611 100644 --- a/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/WarningsWindow.xaml @@ -16,6 +16,7 @@ Width="1000" MinHeight="400" MinWidth="1000" + Title="{me:LocalizationSource MainWindow.Title}" d:DataContext="{d:DesignInstance vms:WarningsViewModel, IsDesignTimeCreatable=False}"> @@ -88,19 +89,19 @@ + Text="{DynamicResource WarningWindow.ShowHeader}" /> - @@ -124,7 +125,7 @@ @@ -134,7 +135,7 @@ diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index d886007fc..ecd4e3cce 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -57,7 +57,9 @@ x:Key="RevitRepository.NoLevel"> - Нет уровня - Предупреждения + x:Key="WarningWindow.Title">Рассчитать площади (соц. объекты) - предупреждения + Выделить ИД помещения Date: Tue, 2 Jun 2026 09:42:29 +0300 Subject: [PATCH 12/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=94=D0=BE?= =?UTF-8?q?=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D1=81?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D1=85=20=D0=BC=D0=B5=D1=82=D0=BE?= =?UTF-8?q?=D0=B4=D0=BE=D0=B2=20=D0=BE=D0=BA=D1=80=D1=83=D0=B3=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F,=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/ConfigSettings.cs | 2 +- .../Models/PluginConfig.cs | 10 +- .../Models/RevitRepository.cs | 59 +++++++++- ...DigitViewModel.cs => AccuracyViewModel.cs} | 4 +- .../ViewModels/LevelViewModel.cs | 21 ---- .../ViewModels/MainViewModel.cs | 111 +++++++++++------- .../Views/MainWindow.xaml | 8 +- .../assets/Localization/Language.ru-RU.xaml | 3 + 8 files changed, 132 insertions(+), 86 deletions(-) rename src/RevitRoundingOfAreas/ViewModels/{DigitViewModel.cs => AccuracyViewModel.cs} (70%) delete mode 100644 src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs diff --git a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs index 5a98d9bf1..1d734e583 100644 --- a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs +++ b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs @@ -7,5 +7,5 @@ internal class ConfigSettings { public ElementId SelectedPhaseId { get; set; } public RevitParam SourceParam { get; set; } public RevitParam TargetParam { get; set; } - public int DigitCount { get; set; } + public int Accuracy { get; set; } } diff --git a/src/RevitRoundingOfAreas/Models/PluginConfig.cs b/src/RevitRoundingOfAreas/Models/PluginConfig.cs index 9246c0c19..45617152e 100644 --- a/src/RevitRoundingOfAreas/Models/PluginConfig.cs +++ b/src/RevitRoundingOfAreas/Models/PluginConfig.cs @@ -6,8 +6,6 @@ using pyRevitLabs.Json; -using RevitRoundingOfAreas.Models.Enums; - namespace RevitRoundingOfAreas.Models; /// @@ -57,10 +55,6 @@ internal class RevitSettings : ProjectSettings { } internal class SystemPluginConfig { - - // Режим выбора провайдера элементов по умолчанию - public ElementsProviderType DefaultProvider => ElementsProviderType.AllElementsProvider; - // Название стадии по умолчанию public string DefaultPhaseName => "Основная планировка"; @@ -68,7 +62,7 @@ internal class SystemPluginConfig { public int DefaultDigitCountRange => 3; // Количество знаков по умолчанию - public int DefaultDigitCount => 1; + public int DefaultAccuracy => 1; // Системный параметр площади помещений по умолчанию public BuiltInParameter SystemRoomAreaParamId = BuiltInParameter.ROOM_AREA; @@ -76,6 +70,4 @@ internal class SystemPluginConfig { // Общий параметр площади помещений по умолчанию public RevitParam RoomAreaParam = SharedParamsConfig.Instance.RoomArea; - - } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index ae87edc95..9e6fb0c2b 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; @@ -7,6 +8,7 @@ using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.UI; +using dosymep.Bim4Everyone; using dosymep.Revit; using dosymep.SimpleServices; @@ -25,21 +27,50 @@ public RevitRepository(UIApplication uiApplication, ILocalizationService localiz public Application Application => UIApplication.Application; public Document Document => ActiveUIDocument.Document; + /// + /// Основной метод округления площадей + /// + public void RoundingOfAreas(List spatialModels, RevitParam sourceParam, RevitParam targetParam, int accuracy) { + foreach(var spatialModel in spatialModels) { + double sourceValue = spatialModel.SpatialElement.GetParamValueOrDefault(sourceParam); + + if(sourceValue == default) { + continue; + } + + double roundedValue = RoundWithAccuracy(sourceValue, accuracy); + + if(roundedValue == 0) { + continue; + } + + spatialModel.SpatialElement.SetParamValue(targetParam, ConvertValueToInternalUnits(roundedValue)); + } + } + /// /// Метод получения всех помещений /// - public List GetAllSpatialModels(ElementId phaseId) { + public List GetAllSpatialElements() { return new FilteredElementCollector(Document) .OfCategory(BuiltInCategory.OST_Rooms) .WhereElementIsNotElementType() .OfType() + .ToList(); + } + + /// + /// Метод получения всех помещений SpatialModel + /// + public List GetAllSpatialModels(ElementId phaseId) { + return GetAllSpatialElements() .Where(spatial => ValidatePhase(spatial, phaseId)) .Select(CreateSpatialModel) .ToList(); } /// - /// Метод получения всех помещений на активном виде + /// Метод получения всех помещений SpatialModel на активном виде /// public List GetActiveViewSpatialModels(ElementId phaseId) { return new FilteredElementCollector(Document, Document.ActiveView.Id) @@ -52,7 +83,7 @@ public List GetActiveViewSpatialModels(ElementId phaseId) { } /// - /// Метод получения всех выделенных помещений + /// Метод получения всех выделенных помещений SpatialModel /// public List GetSelectedSpatialModels(ElementId phaseId) { return !HasSelectedRooms() @@ -124,7 +155,7 @@ public ElementId GetPhaseIdByName(string name) { } // Создания объекта SpatialModel - public SpatialModel CreateSpatialModel(SpatialElement spatialElement) { + private SpatialModel CreateSpatialModel(SpatialElement spatialElement) { return new SpatialModel { SpatialElement = spatialElement, LevelName = GetLevelName(spatialElement) @@ -149,4 +180,24 @@ private bool ValidatePhase(SpatialElement spatialElement, ElementId phaseId) { var spatialPhaseId = spatialElement.get_Parameter(BuiltInParameter.ROOM_PHASE).AsElementId(); return spatialPhaseId != ElementId.InvalidElementId && spatialPhaseId == phaseId; } + + // Метод округления числа с заданной точкой после запятой + private double RoundWithAccuracy(double? value, int accuracy) { + return value.HasValue + ? Math.Round( + ConvertValueFromInternalUnits(value.Value), + accuracy, + MidpointRounding.ToEven) + : 0; + } + + // Метод конвертации в миллиметры + private double ConvertValueFromInternalUnits(double value) { + return UnitUtils.ConvertFromInternalUnits(value, UnitTypeId.SquareMeters); + } + + // Метод конвертации в футы + private double ConvertValueToInternalUnits(double value) { + return UnitUtils.ConvertToInternalUnits(value, UnitTypeId.SquareMeters); + } } diff --git a/src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs similarity index 70% rename from src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs rename to src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs index e65e5b398..7617a3230 100644 --- a/src/RevitRoundingOfAreas/ViewModels/DigitViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs @@ -1,10 +1,10 @@ using dosymep.WPF.ViewModels; namespace RevitRoundingOfAreas.ViewModels; -internal class DigitViewModel : BaseViewModel { +internal class AccuracyViewModel : BaseViewModel { private string _name; - public int DigitCount { get; set; } + public int Accuracy { get; set; } public string Name { get => _name; diff --git a/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs deleted file mode 100644 index 1cb82b553..000000000 --- a/src/RevitRoundingOfAreas/ViewModels/LevelViewModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Autodesk.Revit.DB; - -using dosymep.WPF.ViewModels; - -namespace RevitRoundingOfAreas.ViewModels; - -internal class LevelViewModel : BaseViewModel { - private string _name; - private bool _isChecked; - - public Level Level { get; set; } - - public string Name { - get => _name; - set => RaiseAndSetIfChanged(ref _name, value); - } - public bool IsChecked { - get => _isChecked; - set => RaiseAndSetIfChanged(ref _isChecked, value); - } -} diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index 498514b56..1cdb9ae9a 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -6,6 +6,7 @@ using Autodesk.Revit.DB; +using dosymep.Revit; using dosymep.SimpleServices; using dosymep.WPF.Commands; using dosymep.WPF.ViewModels; @@ -26,22 +27,17 @@ internal class MainViewModel : BaseViewModel { private readonly SpatialElementCheckService _spatialElementCheckService; private readonly IWindowService _windowService; private readonly ILocalizationService _localizationService; - private ConfigSettings _configSettings; - private ObservableCollection _range; private RangeViewModel _selectedRange; - private ObservableCollection _phases; private PhaseViewModel _selectedPhase; - - private ObservableCollection _params; + private ObservableCollection _sourceParams; private ParamViewModel _selectedSourceParam; + private ObservableCollection _targetParams; private ParamViewModel _selectedTargetParam; - - private ObservableCollection _digitCount; - private DigitViewModel _selectedDigitCount; - + private ObservableCollection _accuracy; + private AccuracyViewModel _selectedAccuracy; private string _errorText; public MainViewModel( @@ -68,7 +64,6 @@ public MainViewModel( } public ICommand LoadViewCommand { get; } - public ICommand AcceptViewCommand { get; } @@ -76,64 +71,59 @@ public ObservableCollection Range { get => _range; set => RaiseAndSetIfChanged(ref _range, value); } - public RangeViewModel SelectedRange { get => _selectedRange; set => RaiseAndSetIfChanged(ref _selectedRange, value); } - public ObservableCollection Phases { get => _phases; set => RaiseAndSetIfChanged(ref _phases, value); } - public PhaseViewModel SelectedPhase { get => _selectedPhase; set => RaiseAndSetIfChanged(ref _selectedPhase, value); } - - public ObservableCollection Params { - get => _params; - set => RaiseAndSetIfChanged(ref _params, value); + public ObservableCollection SourceParams { + get => _sourceParams; + set => RaiseAndSetIfChanged(ref _sourceParams, value); } - public ParamViewModel SelectedSourceParam { get => _selectedSourceParam; set => RaiseAndSetIfChanged(ref _selectedSourceParam, value); } - + public ObservableCollection TargetParams { + get => _targetParams; + set => RaiseAndSetIfChanged(ref _targetParams, value); + } public ParamViewModel SelectedTargetParam { get => _selectedTargetParam; set => RaiseAndSetIfChanged(ref _selectedTargetParam, value); } - - public ObservableCollection DigitCount { - get => _digitCount; - set => RaiseAndSetIfChanged(ref _digitCount, value); + public ObservableCollection Accuracy { + get => _accuracy; + set => RaiseAndSetIfChanged(ref _accuracy, value); } - - public DigitViewModel SelectedDigitCount { - get => _selectedDigitCount; - set => RaiseAndSetIfChanged(ref _selectedDigitCount, value); + public AccuracyViewModel SelectedAccuracy { + get => _selectedAccuracy; + set => RaiseAndSetIfChanged(ref _selectedAccuracy, value); } - public string ErrorText { get => _errorText; set => RaiseAndSetIfChanged(ref _errorText, value); } // Метод получения коллекции DigitViewModel для DigitCount - private IEnumerable GetDigitViewModels() { + private IEnumerable GetDigitViewModels() { for(int i = 1; i <= _systemPluginConfig.DefaultDigitCountRange; i++) { - yield return new DigitViewModel { - DigitCount = i, + yield return new AccuracyViewModel { + Accuracy = i, Name = i.ToString(), }; } } - // Метод получения коллекции ParamViewModel для Params - private IEnumerable GetParamViewModels() { + // Метод получения коллекции ParamViewModel для SourceParams + private IEnumerable GetSourceParamViewModels() { return _paramService.AllRevitParams .Select(param => new ParamViewModel { Name = param.Name, @@ -141,6 +131,24 @@ private IEnumerable GetParamViewModels() { }); } + // Метод получения коллекции ParamViewModel для TargetParams + private IEnumerable GetTargetParamViewModels() { + return _paramService.AllRevitParams + .Where(revitParam => { + var spatialElements = _revitRepository.GetAllSpatialElements(); + var randomSpatialElement = spatialElements.FirstOrDefault(); + if(randomSpatialElement is null) { + return false; + } + var param = revitParam.GetParam(randomSpatialElement); + return !param.IsReadOnly; + }) + .Select(param => new ParamViewModel { + Name = param.Name, + RevitParam = param + }); + } + // Метод получения коллекции PhaseViewModel для Phases private IEnumerable GetPhaseViewModels() { return _revitRepository.GetPhaseModels() @@ -171,18 +179,20 @@ private void LoadView() { .FirstOrDefault(phase => phase.ElementId == _configSettings.SelectedPhaseId) ?? Phases.LastOrDefault(); - Params = new ObservableCollection(GetParamViewModels()); - SelectedSourceParam = Params + SourceParams = new ObservableCollection(GetSourceParamViewModels()); + SelectedSourceParam = SourceParams .FirstOrDefault(param => param.RevitParam.Id == _configSettings.SourceParam?.Id) - ?? Params.FirstOrDefault(); - SelectedTargetParam = Params + ?? SourceParams.FirstOrDefault(); + + TargetParams = new ObservableCollection(GetTargetParamViewModels()); + SelectedTargetParam = TargetParams .FirstOrDefault(param => param.RevitParam.Id == _configSettings.TargetParam?.Id) - ?? Params.FirstOrDefault(); + ?? TargetParams.FirstOrDefault(); - DigitCount = new ObservableCollection(GetDigitViewModels()); - SelectedDigitCount = DigitCount - .FirstOrDefault(digit => digit.DigitCount == _configSettings.DigitCount) - ?? DigitCount.FirstOrDefault(); + Accuracy = new ObservableCollection(GetDigitViewModels()); + SelectedAccuracy = Accuracy + .FirstOrDefault(accuracy => accuracy.Accuracy == _configSettings.Accuracy) + ?? Accuracy.FirstOrDefault(); } private RangeViewModel ResolveDefaultRange() { @@ -201,7 +211,18 @@ private void AcceptView() { if(warnings.Count != 0) { _windowService.CloseMainWindow(); _windowService.ShowWarningWindow(warnings); + return; } + + string transactionName = _localizationService.GetLocalizedString("MainViewModel.TransactionName"); + using var t = _revitRepository.Document.StartTransaction(transactionName); + _revitRepository.RoundingOfAreas( + spatialElements, + SelectedSourceParam.RevitParam, + SelectedTargetParam.RevitParam, + SelectedAccuracy.Accuracy + ); + t.Commit(); } private bool CanAcceptView() { @@ -236,8 +257,8 @@ private void ApplyDefaultsConfig() { _configSettings.SourceParam ??= _paramService.DefaultSourceParam; _configSettings.TargetParam ??= _paramService.DefaultTargetParam; - if(_configSettings.DigitCount <= 0) { - _configSettings.DigitCount = _systemPluginConfig.DefaultDigitCount; + if(_configSettings.Accuracy <= 0) { + _configSettings.Accuracy = _systemPluginConfig.DefaultAccuracy; } } @@ -249,7 +270,7 @@ private void SaveConfig() { SelectedPhaseId = SelectedPhase?.ElementId ?? ElementId.InvalidElementId, SourceParam = SelectedSourceParam?.RevitParam, TargetParam = SelectedTargetParam?.RevitParam, - DigitCount = SelectedDigitCount?.DigitCount ?? _systemPluginConfig.DefaultDigitCount + Accuracy = SelectedAccuracy?.Accuracy ?? _systemPluginConfig.DefaultAccuracy }; _pluginConfig.SaveProjectConfig(); diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 5c4212523..7004817cb 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -73,7 +73,7 @@ Header="{me:LocalizationSource MainWindow.SourceParam}" Description="{me:LocalizationSource MainWindow.SourceParamDescription}"> @@ -82,7 +82,7 @@ Header="{me:LocalizationSource MainWindow.TargetParam}" Description="{me:LocalizationSource MainWindow.TargetParamDescription}"> @@ -91,8 +91,8 @@ Header="{me:LocalizationSource MainWindow.DigitCount}" Description="{me:LocalizationSource MainWindow.DigitCountDescription}"> diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index ecd4e3cce..69e7c94ec 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -67,4 +67,7 @@ Уровень помещения + Расчёт площадей (соц. объекты) + From 188d20b90e17c75946349186b5bcb2a45218dc42 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Tue, 2 Jun 2026 10:03:31 +0300 Subject: [PATCH 13/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=98=D1=81?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=BA=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Views/MainWindow.xaml | 2 +- .../assets/Localization/Language.en-US.xaml | 47 +++++++++++-- .../assets/Localization/Language.ru-RU.xaml | 69 +++++++------------ 3 files changed, 67 insertions(+), 51 deletions(-) diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 7004817cb..89ef06594 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -39,7 +39,7 @@ diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml index 3e250bf5b..868b85ee6 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.en-US.xaml @@ -2,10 +2,49 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> - Calculate areas (social facilities) - Model element processing range - Select how model elements will be processed - + Calculate Areas (Social Facilities) + Model Element Processing Range + Select how to process model elements + + Room Phase + Select the phase for the rooms to be processed + + Read Parameter + Parameter from which the area will be read + + Write Parameter + Parameter to which the area will be written + + Number of Decimal Places + Number of decimal places to round to + Calculate Cancel + + All elements + Selected + Visible in view + + Area Calculation (Social Facilities) + + Error loading parameters + Plugin configuration error + + Redundant zones + Zones located within the same enclosed area + Unenclosed zones / Unplaced zones + Zones that have no boundaries or are not placed on the plan + + No rooms selected + No rooms on the view + + - No level - + + Calculate Areas (Social Facilities) - Warnings + + Highlight + Room ID + Room name + Room level + diff --git a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml index 69e7c94ec..0ee9a769a 100644 --- a/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml +++ b/src/RevitRoundingOfAreas/assets/Localization/Language.ru-RU.xaml @@ -15,59 +15,36 @@ Параметр для записи Параметр, в который будет записываться площадь - Количество знаков после запятой - До которого будет происходить округление - - Уровни помещений - Уровни помещений, которые будут обработаны - Выбрать все уровни - Поиск по имени уровня - Сбросить выбор уровней + Количество знаков после запятой + До которого будет происходить округление Рассчитать Отмена - Все элементы - Выделенные - Видимые на виде - - Ошибка загрузки параметров - Ошибка настройки плагина - - Избыточные зоны - Зоны, находящиеся в одной окруженной области - Не окруженные зоны / Не размещенные зоны - Зоны, не имеющие границ или не размещенные на плане + Все элементы + Выделенные + Видимые на виде + + Расчёт площадей (соц. объекты) - Не выделены помещения - Нет помещений на виде + Ошибка загрузки параметров + Ошибка настройки плагина - - Нет уровня - + Избыточные зоны + Зоны, находящиеся в одной окруженной области + Не окруженные зоны / Не размещенные зоны + Зоны, не имеющие границ или не размещенные на плане - Рассчитать площади (соц. объекты) - предупреждения - Выделить - ИД помещения - Имя помещения - Уровень помещения + Не выделены помещения + Нет помещений на виде - Расчёт площадей (соц. объекты) + - Нет уровня - + Рассчитать площади (соц. объекты) - предупреждения + + Выделить + ИД помещения + Имя помещения + Уровень помещения + From fd1801f8593e5d8044d4e2d6f35b8f455630df77 Mon Sep 17 00:00:00 2001 From: KozlovPS Date: Tue, 2 Jun 2026 16:43:52 +0300 Subject: [PATCH 14/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=9D=D0=B5?= =?UTF-8?q?=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B9=20=D1=80=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0,=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=D0=B7=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/CheckProjectParams.cs | 17 ++---- .../Models/ConfigSettings.cs | 1 + .../Models/Factories/ProvidersFactory.cs | 17 ++---- .../Models/ParamService.cs | 1 - src/RevitRoundingOfAreas/Models/PhaseModel.cs | 1 + .../Models/PluginConfig.cs | 27 ++++----- .../Models/Providers/ElementsProviderAll.cs | 10 +--- .../Providers/ElementsProviderCurrentView.cs | 10 +--- .../Providers/ElementsProviderSelected.cs | 10 +--- .../Models/RevitRepository.cs | 57 ++++++++----------- .../Models/SpatialElementCheckService.cs | 1 + .../Models/WindowService.cs | 20 +++---- .../RevitRoundingOfAreasCommand.cs | 4 +- .../ViewModels/AccuracyViewModel.cs | 1 + .../ViewModels/MainViewModel.cs | 8 +-- .../ViewModels/ParamViewModel.cs | 1 + .../Warnings/WarningElementViewModel.cs | 8 +-- .../Warnings/WarningGroupViewModel.cs | 2 +- .../Views/MainWindow.xaml | 4 +- 19 files changed, 75 insertions(+), 125 deletions(-) diff --git a/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs b/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs index 613c12b7d..f3d54456d 100644 --- a/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs +++ b/src/RevitRoundingOfAreas/Models/CheckProjectParams.cs @@ -4,19 +4,10 @@ using dosymep.Bim4Everyone.Templates; namespace RevitRoundingOfAreas.Models; -internal class CheckProjectParams { - private readonly SystemPluginConfig _systemPluginConfig; - private readonly Application _application; - private readonly Document _document; - private readonly ProjectParameters _projectParameters; - private readonly bool _isChecked = true; - public CheckProjectParams(SystemPluginConfig systemPluginConfig, Application application, Document document) { - _systemPluginConfig = systemPluginConfig; - _application = application; - _document = document; - _projectParameters = ProjectParameters.Create(_application); - } +internal class CheckProjectParams(SystemPluginConfig systemPluginConfig, Application application, Document document) { + private readonly ProjectParameters _projectParameters = ProjectParameters.Create(application); + private readonly bool _isChecked = true; /// /// Метод проверки загрузки параметров @@ -29,7 +20,7 @@ public bool GetIsChecked() { /// Метод копирования параметров проекта /// public CheckProjectParams CopyProjectParams() { - _projectParameters.SetupRevitParams(_document, _systemPluginConfig.RoomAreaParam); + _projectParameters.SetupRevitParams(document, systemPluginConfig.RoomAreaParam); return this; } } diff --git a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs index 1d734e583..88aa8f624 100644 --- a/src/RevitRoundingOfAreas/Models/ConfigSettings.cs +++ b/src/RevitRoundingOfAreas/Models/ConfigSettings.cs @@ -3,6 +3,7 @@ using dosymep.Bim4Everyone; namespace RevitRoundingOfAreas.Models; + internal class ConfigSettings { public ElementId SelectedPhaseId { get; set; } public RevitParam SourceParam { get; set; } diff --git a/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs b/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs index 71581a192..39f17eaa1 100644 --- a/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs +++ b/src/RevitRoundingOfAreas/Models/Factories/ProvidersFactory.cs @@ -4,23 +4,16 @@ namespace RevitRoundingOfAreas.Models.Factories; -internal class ProvidersFactory { - - private readonly RevitRepository _revitRepository; - - public ProvidersFactory(RevitRepository revitRepository) { - _revitRepository = revitRepository; - } - +internal class ProvidersFactory(RevitRepository revitRepository) { /// /// Метод получения провайдера элементов по Enum /// public IElementsProvider GetElementsProvider(ElementsProviderType type) { return type switch { - ElementsProviderType.AllElementsProvider => new ElementsProviderAll(_revitRepository), - ElementsProviderType.CurrentViewProvider => new ElementsProviderCurrentView(_revitRepository), - ElementsProviderType.SelectedElementsProvider => new ElementsProviderSelected(_revitRepository), - _ => new ElementsProviderAll(_revitRepository) + ElementsProviderType.AllElementsProvider => new ElementsProviderAll(revitRepository), + ElementsProviderType.CurrentViewProvider => new ElementsProviderCurrentView(revitRepository), + ElementsProviderType.SelectedElementsProvider => new ElementsProviderSelected(revitRepository), + _ => new ElementsProviderAll(revitRepository) }; } } diff --git a/src/RevitRoundingOfAreas/Models/ParamService.cs b/src/RevitRoundingOfAreas/Models/ParamService.cs index 0702e5360..9e0f03e98 100644 --- a/src/RevitRoundingOfAreas/Models/ParamService.cs +++ b/src/RevitRoundingOfAreas/Models/ParamService.cs @@ -12,7 +12,6 @@ namespace RevitRoundingOfAreas.Models; internal class ParamService { - private readonly RevitRepository _revitRepository; private readonly SystemPluginConfig _systemPluginConfig; private readonly ICollection _allParamElementIds; diff --git a/src/RevitRoundingOfAreas/Models/PhaseModel.cs b/src/RevitRoundingOfAreas/Models/PhaseModel.cs index 2ec5834bf..7646dd52c 100644 --- a/src/RevitRoundingOfAreas/Models/PhaseModel.cs +++ b/src/RevitRoundingOfAreas/Models/PhaseModel.cs @@ -1,6 +1,7 @@ using Autodesk.Revit.DB; namespace RevitRoundingOfAreas.Models; + internal class PhaseModel { public ElementId ElementId { get; set; } public string Name { get; set; } diff --git a/src/RevitRoundingOfAreas/Models/PluginConfig.cs b/src/RevitRoundingOfAreas/Models/PluginConfig.cs index 45617152e..175585939 100644 --- a/src/RevitRoundingOfAreas/Models/PluginConfig.cs +++ b/src/RevitRoundingOfAreas/Models/PluginConfig.cs @@ -1,3 +1,5 @@ +using System; + using Autodesk.Revit.DB; using dosymep.Bim4Everyone; @@ -8,20 +10,11 @@ namespace RevitRoundingOfAreas.Models; -/// -/// Класс конфигурации плагина. -/// (Если не используется удалить) -/// internal class PluginConfig : ProjectConfig { - /// - /// Системное свойство конфигурации. (Не трогать) - /// + [JsonIgnore] public override string ProjectConfigPath { get; set; } - - /// - /// Системное свойство конфигурации. (Не трогать) - /// + [JsonIgnore] public override IConfigSerializer Serializer { get; set; } @@ -59,15 +52,17 @@ internal class SystemPluginConfig { public string DefaultPhaseName => "Основная планировка"; // Количество вариантов знаков по умолчанию - public int DefaultDigitCountRange => 3; - + public int DefaultAccuracyRange => 3; + // Количество знаков по умолчанию public int DefaultAccuracy => 1; + + // Сторона округления + public MidpointRounding MidpointRounding => MidpointRounding.AwayFromZero; // Системный параметр площади помещений по умолчанию - public BuiltInParameter SystemRoomAreaParamId = BuiltInParameter.ROOM_AREA; + public BuiltInParameter SystemRoomAreaParamId => BuiltInParameter.ROOM_AREA; // Общий параметр площади помещений по умолчанию - public RevitParam RoomAreaParam = SharedParamsConfig.Instance.RoomArea; - + public RevitParam RoomAreaParam => SharedParamsConfig.Instance.RoomArea; } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs index b609c2288..3939df5e7 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderAll.cs @@ -7,16 +7,10 @@ namespace RevitRoundingOfAreas.Models.Providers; -internal class ElementsProviderAll : IElementsProvider { - private readonly RevitRepository _revitRepository; - - public ElementsProviderAll(RevitRepository revitRepository) { - _revitRepository = revitRepository; - } - +internal class ElementsProviderAll(RevitRepository revitRepository) : IElementsProvider { public ElementsProviderType Type => ElementsProviderType.AllElementsProvider; public List GetSpatialElements(ElementId phaseId) { - return _revitRepository.GetAllSpatialModels(phaseId); + return revitRepository.GetAllSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs index dc558a03c..4a473a248 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderCurrentView.cs @@ -7,16 +7,10 @@ namespace RevitRoundingOfAreas.Models.Providers; -internal class ElementsProviderCurrentView : IElementsProvider { - private readonly RevitRepository _revitRepository; - - public ElementsProviderCurrentView(RevitRepository revitRepository) { - _revitRepository = revitRepository; - } - +internal class ElementsProviderCurrentView(RevitRepository revitRepository) : IElementsProvider { public ElementsProviderType Type => ElementsProviderType.CurrentViewProvider; public List GetSpatialElements(ElementId phaseId) { - return _revitRepository.GetActiveViewSpatialModels(phaseId); + return revitRepository.GetActiveViewSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs index 38e80f749..83de7dc0f 100644 --- a/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs +++ b/src/RevitRoundingOfAreas/Models/Providers/ElementsProviderSelected.cs @@ -7,16 +7,10 @@ namespace RevitRoundingOfAreas.Models.Providers; -internal class ElementsProviderSelected : IElementsProvider { - private readonly RevitRepository _revitRepository; - - public ElementsProviderSelected(RevitRepository revitRepository) { - _revitRepository = revitRepository; - } - +internal class ElementsProviderSelected(RevitRepository revitRepository) : IElementsProvider { public ElementsProviderType Type => ElementsProviderType.SelectedElementsProvider; public List GetSpatialElements(ElementId phaseId) { - return _revitRepository.GetSelectedSpatialModels(phaseId); + return revitRepository.GetSelectedSpatialModels(phaseId); } } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index 9e6fb0c2b..9c26dadf0 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -14,18 +14,14 @@ namespace RevitRoundingOfAreas.Models; -internal class RevitRepository { - private readonly ILocalizationService _localizationService; - - public RevitRepository(UIApplication uiApplication, ILocalizationService localizationService) { - UIApplication = uiApplication; - _localizationService = localizationService; - } - - public UIApplication UIApplication { get; } - public UIDocument ActiveUIDocument => UIApplication.ActiveUIDocument; - public Application Application => UIApplication.Application; - public Document Document => ActiveUIDocument.Document; +internal class RevitRepository( + UIApplication uiApplication, + ILocalizationService localizationService, + SystemPluginConfig systemPluginConfig) { + private UIApplication UiApplication { get; } = uiApplication; + private UIDocument ActiveUiDocument => UiApplication.ActiveUIDocument; + public Application Application => UiApplication.Application; + public Document Document => ActiveUiDocument.Document; /// /// Основной метод округления площадей @@ -34,16 +30,15 @@ public void RoundingOfAreas(List spatialModels, RevitParam sourceP foreach(var spatialModel in spatialModels) { double sourceValue = spatialModel.SpatialElement.GetParamValueOrDefault(sourceParam); - if(sourceValue == default) { + if(sourceValue is 0) { continue; } double roundedValue = RoundWithAccuracy(sourceValue, accuracy); - if(roundedValue == 0) { + if(roundedValue is 0) { continue; } - spatialModel.SpatialElement.SetParamValue(targetParam, ConvertValueToInternalUnits(roundedValue)); } } @@ -99,9 +94,9 @@ public List GetSelectedSpatialModels(ElementId phaseId) { /// Метод проверки, есть ли выделенные помещения /// public bool HasSelectedRooms() { - var selected = GetSelectedElements(); - return selected != null && selected.Count() != 0 && selected - .Any(element => element is Room); + var selected = GetSelectedElements().ToArray(); + return selected.Count() != 0 + && selected.Any(element => element is Room); } /// @@ -116,19 +111,12 @@ public bool HasRoomsOnCurrentView() { .Any(); } - /// - /// Метод получения всех выделенных элементов модели - /// - public IEnumerable GetSelectedElements() { - return ActiveUIDocument.GetSelectedElements(); - } - /// /// Метод выделения элементов в документе /// public void SetSelected(ElementId elementId) { List listElements = [elementId]; - ActiveUIDocument.SetSelectedElements(listElements); + ActiveUiDocument.SetSelectedElements(listElements); } /// @@ -153,6 +141,11 @@ public ElementId GetPhaseIdByName(string name) { ?.ElementId ?? ElementId.InvalidElementId; } + + // Метод получения всех выделенных элементов модели + private IEnumerable GetSelectedElements() { + return ActiveUiDocument.GetSelectedElements(); + } // Создания объекта SpatialModel private SpatialModel CreateSpatialModel(SpatialElement spatialElement) { @@ -165,14 +158,14 @@ private SpatialModel CreateSpatialModel(SpatialElement spatialElement) { // Получение уровня помещения private string GetLevelName(SpatialElement spatialElement) { if(spatialElement is null) { - _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + localizationService.GetLocalizedString("RevitRepository.NoLevel"); } - var levelId = spatialElement.LevelId; - if(levelId is null || levelId == ElementId.InvalidElementId) { - _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + var levelId = spatialElement?.LevelId; + if(levelId == ElementId.InvalidElementId) { + localizationService.GetLocalizedString("RevitRepository.NoLevel"); } return Document.GetElement(levelId)?.Name - ?? _localizationService.GetLocalizedString("RevitRepository.NoLevel"); + ?? localizationService.GetLocalizedString("RevitRepository.NoLevel"); } // Метод валидации стадии @@ -187,7 +180,7 @@ private double RoundWithAccuracy(double? value, int accuracy) { ? Math.Round( ConvertValueFromInternalUnits(value.Value), accuracy, - MidpointRounding.ToEven) + systemPluginConfig.MidpointRounding) : 0; } diff --git a/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs index 57b7b1907..f52329a0e 100644 --- a/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs +++ b/src/RevitRoundingOfAreas/Models/SpatialElementCheckService.cs @@ -8,6 +8,7 @@ using RevitRoundingOfAreas.Models.Warnings; namespace RevitRoundingOfAreas.Models; + internal class SpatialElementCheckService { public IReadOnlyCollection CheckSpatialElements(List spatialModels) { diff --git a/src/RevitRoundingOfAreas/Models/WindowService.cs b/src/RevitRoundingOfAreas/Models/WindowService.cs index e24984205..71d93f80e 100644 --- a/src/RevitRoundingOfAreas/Models/WindowService.cs +++ b/src/RevitRoundingOfAreas/Models/WindowService.cs @@ -10,24 +10,18 @@ namespace RevitRoundingOfAreas.Models; -internal class WindowService : IWindowService { - private readonly IResolutionRoot _resolutionRoot; - - public WindowService(IResolutionRoot resolutionRoot) { - _resolutionRoot = resolutionRoot; - } - +internal class WindowService(IResolutionRoot resolutionRoot) : IWindowService { public void CloseMainWindow() { - var mainWindow = _resolutionRoot.Get(); + var mainWindow = resolutionRoot.Get(); mainWindow.Close(); } public void ShowWarningWindow(IReadOnlyCollection warningElements) { - var warningsVM = _resolutionRoot.Get(); - warningsVM.WarningElementsCollection = warningElements; - var warningsWindow = _resolutionRoot.Get(); - warningsWindow.DataContext = warningsVM; - warningsVM.LoadView(); + var warningViewModel = resolutionRoot.Get(); + warningViewModel.WarningElementsCollection = warningElements; + var warningsWindow = resolutionRoot.Get(); + warningsWindow.DataContext = warningViewModel; + warningViewModel.LoadView(); warningsWindow.Show(); } } diff --git a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs index 1c903e2c5..8b2804789 100644 --- a/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs +++ b/src/RevitRoundingOfAreas/RevitRoundingOfAreasCommand.cs @@ -45,7 +45,7 @@ public RevitRoundingOfAreasCommand() { /// Интерфейс взаимодействия с Revit. /// /// В случаях, когда не используется конфигурация - /// или локализация требуется удалять их использование полностью во всем проекте. + /// или локализация, требуется удалять их использование полностью во всем проекте. /// protected override void Execute(UIApplication uiApplication) { // Создание контейнера зависимостей плагина с сервисами из платформы @@ -106,7 +106,7 @@ protected override void Execute(UIApplication uiApplication) { var localizationService = kernel.Get(); var systemPluginConfig = kernel.Get(); - // Загрузка параметров проекта + // Загрузка параметров проекта bool isParamChecked = new CheckProjectParams( systemPluginConfig, uiApplication.Application, uiApplication.ActiveUIDocument.Document) .CopyProjectParams() diff --git a/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs index 7617a3230..c9743e561 100644 --- a/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/AccuracyViewModel.cs @@ -1,6 +1,7 @@ using dosymep.WPF.ViewModels; namespace RevitRoundingOfAreas.ViewModels; + internal class AccuracyViewModel : BaseViewModel { private string _name; diff --git a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs index 1cdb9ae9a..12c9c8d05 100644 --- a/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/MainViewModel.cs @@ -112,9 +112,9 @@ public string ErrorText { set => RaiseAndSetIfChanged(ref _errorText, value); } - // Метод получения коллекции DigitViewModel для DigitCount - private IEnumerable GetDigitViewModels() { - for(int i = 1; i <= _systemPluginConfig.DefaultDigitCountRange; i++) { + // Метод получения коллекции AccuracyViewModel для Accuracy + private IEnumerable GetAccuracyViewModels() { + for(int i = 1; i <= _systemPluginConfig.DefaultAccuracyRange; i++) { yield return new AccuracyViewModel { Accuracy = i, Name = i.ToString(), @@ -189,7 +189,7 @@ private void LoadView() { .FirstOrDefault(param => param.RevitParam.Id == _configSettings.TargetParam?.Id) ?? TargetParams.FirstOrDefault(); - Accuracy = new ObservableCollection(GetDigitViewModels()); + Accuracy = new ObservableCollection(GetAccuracyViewModels()); SelectedAccuracy = Accuracy .FirstOrDefault(accuracy => accuracy.Accuracy == _configSettings.Accuracy) ?? Accuracy.FirstOrDefault(); diff --git a/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs index bef8bbabe..bf4d2f9f4 100644 --- a/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/ParamViewModel.cs @@ -2,6 +2,7 @@ using dosymep.WPF.ViewModels; namespace RevitRoundingOfAreas.ViewModels; + internal class ParamViewModel : BaseViewModel { private string _name; diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs index d52c24f93..a9377cb21 100644 --- a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningElementViewModel.cs @@ -9,16 +9,14 @@ namespace RevitRoundingOfAreas.ViewModels.Warnings; internal class WarningElementViewModel : BaseViewModel { - private readonly SpatialModel _spatialModel; private ElementId _elementId; private string _name; private string _levelName; public WarningElementViewModel(SpatialModel spatialModel) { - _spatialModel = spatialModel; - Name = _spatialModel.SpatialElement.Name; - LevelName = _spatialModel.LevelName; - ElementId = _spatialModel.SpatialElement.Id; + Name = spatialModel.SpatialElement.Name; + LevelName = spatialModel.LevelName; + ElementId = spatialModel.SpatialElement.Id; } public ICommand ShowElementCommand { get; set; } diff --git a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs index 8728a468a..97fbc55f2 100644 --- a/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs +++ b/src/RevitRoundingOfAreas/ViewModels/Warnings/WarningGroupViewModel.cs @@ -8,8 +8,8 @@ using RevitRoundingOfAreas.Models.Warnings; namespace RevitRoundingOfAreas.ViewModels.Warnings; -internal class WarningGroupViewModel : BaseViewModel { +internal class WarningGroupViewModel : BaseViewModel { private ObservableCollection _warnings; private string _caption; private string _description; diff --git a/src/RevitRoundingOfAreas/Views/MainWindow.xaml b/src/RevitRoundingOfAreas/Views/MainWindow.xaml index 89ef06594..617d2328d 100644 --- a/src/RevitRoundingOfAreas/Views/MainWindow.xaml +++ b/src/RevitRoundingOfAreas/Views/MainWindow.xaml @@ -88,8 +88,8 @@ + Header="{me:LocalizationSource MainWindow.Accuracy}" + Description="{me:LocalizationSource MainWindow.AccuracyDescription}"> Date: Wed, 3 Jun 2026 12:26:30 +0300 Subject: [PATCH 15/15] =?UTF-8?q?RevitRoundingOfAreas:=20=D0=9F=D1=80?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B1=D1=80=D0=B8=D0=BA=D0=B8=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D0=BE=D0=B2,=20=D0=BF=D0=BE=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC=D0=B5=D1=82?= =?UTF-8?q?=D1=80=D0=B0=20=D1=81=D0=B5=D1=80=D0=B2=D0=B8=D1=81=D0=B0=D0=BC?= =?UTF-8?q?=D0=B8=20=D0=BF=D0=BB=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/ParamService.cs | 26 +++++-------------- .../Models/RevitRepository.cs | 4 ++- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/src/RevitRoundingOfAreas/Models/ParamService.cs b/src/RevitRoundingOfAreas/Models/ParamService.cs index 9e0f03e98..55059cb30 100644 --- a/src/RevitRoundingOfAreas/Models/ParamService.cs +++ b/src/RevitRoundingOfAreas/Models/ParamService.cs @@ -4,24 +4,26 @@ using Autodesk.Revit.DB; using dosymep.Bim4Everyone; -using dosymep.Bim4Everyone.ProjectParams; using dosymep.Bim4Everyone.SharedParams; +using dosymep.Bim4Everyone.SimpleServices; using dosymep.Bim4Everyone.SystemParams; -using dosymep.Revit; namespace RevitRoundingOfAreas.Models; internal class ParamService { private readonly RevitRepository _revitRepository; private readonly SystemPluginConfig _systemPluginConfig; + private readonly IRevitParamFactory _revitParamFactory; private readonly ICollection _allParamElementIds; public ParamService( RevitRepository revitRepository, - SystemPluginConfig systemPluginConfig) { + SystemPluginConfig systemPluginConfig, + IRevitParamFactory revitParamFactory) { _revitRepository = revitRepository; _systemPluginConfig = systemPluginConfig; + _revitParamFactory = revitParamFactory; _allParamElementIds = GetAllParamElementIds(); @@ -62,7 +64,7 @@ private List GetAllRevitParams() { List parameters = []; foreach(var elementId in _allParamElementIds) { - var revitParam = CreateRevitParam(elementId); + var revitParam = _revitParamFactory.Create(_revitRepository.Document, elementId); if(revitParam is null) { continue; @@ -72,25 +74,9 @@ private List GetAllRevitParams() { parameters.Add(revitParam); } } - return parameters; } - private RevitParam CreateRevitParam(ElementId elementId) { - if(elementId.IsSystemId()) { - var builtInParameter = elementId.AsBuiltInParameter(); - return SystemParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, builtInParameter); - } - - var element = _revitRepository.Document.GetElement(elementId); - - return element is null - ? null - : element is SharedParameterElement - ? SharedParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name) - : ProjectParamsConfig.Instance.CreateRevitParam(_revitRepository.Document, element.Name); - } - private static bool IsSupportedStorageType(RevitParam revitParam) { return revitParam.StorageType == StorageType.Double; } diff --git a/src/RevitRoundingOfAreas/Models/RevitRepository.cs b/src/RevitRoundingOfAreas/Models/RevitRepository.cs index 9c26dadf0..66920121e 100644 --- a/src/RevitRoundingOfAreas/Models/RevitRepository.cs +++ b/src/RevitRoundingOfAreas/Models/RevitRepository.cs @@ -170,7 +170,9 @@ private string GetLevelName(SpatialElement spatialElement) { // Метод валидации стадии private bool ValidatePhase(SpatialElement spatialElement, ElementId phaseId) { - var spatialPhaseId = spatialElement.get_Parameter(BuiltInParameter.ROOM_PHASE).AsElementId(); + var spatialPhaseId = spatialElement.GetParamValueOrDefault( + BuiltInParameter.ROOM_PHASE, + ElementId.InvalidElementId); return spatialPhaseId != ElementId.InvalidElementId && spatialPhaseId == phaseId; }