From ada63d3cc79fa6b8ddd03cf379a6437fedfa2838 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Mon, 25 Sep 2017 18:14:18 +0300 Subject: [PATCH] rework build configuration and project configuration implementation; fix #277, fix #295 --- dub.json | 2 +- src/dlangide/ui/commands.d | 6 + src/dlangide/ui/frame.d | 130 +++++++++++++++++---- src/dlangide/workspace/project.d | 65 +++++++++-- src/dlangide/workspace/projectsettings.d | 8 ++ src/dlangide/workspace/workspace.d | 22 ++-- src/dlangide/workspace/workspacesettings.d | 16 +++ views/VERSION | 2 +- views/res/i18n/en.ini | 5 +- views/res/i18n/ru.ini | 4 +- 10 files changed, 217 insertions(+), 43 deletions(-) diff --git a/dub.json b/dub.json index cab64d5..a4fd08b 100644 --- a/dub.json +++ b/dub.json @@ -12,7 +12,7 @@ "stringImportPaths": ["views"], "dependencies": { - "dlangui": "==0.9.145", + "dlangui": "==0.9.146", "dsymbol": "~>0.2.9", "dcd": "~>0.9.1" }, diff --git a/src/dlangide/ui/commands.d b/src/dlangide/ui/commands.d index b6f50db..74dcd23 100644 --- a/src/dlangide/ui/commands.d +++ b/src/dlangide/ui/commands.d @@ -31,6 +31,9 @@ enum IDEActions : int { ProjectSettings, RunWithRdmd, + BuildSetConfiguration, + ProjectSetConfiguration, + DebugStart, DebugRestart, DebugStartNoDebug, @@ -117,6 +120,9 @@ const Action ACTION_PROJECT_REFRESH = new Action(IDEActions.RefreshProject, "MEN const Action ACTION_PROJECT_UPDATE_DEPENDENCIES = new Action(IDEActions.UpdateProjectDependencies, "MENU_PROJECT_UPDATE_DEPENDENCIES"c); const Action ACTION_RUN_WITH_RDMD = new Action(IDEActions.RunWithRdmd, "MENU_BUILD_RUN_WITH_RDMD"c, "run-rdmd").disableByDefault(); +const Action ACTION_PROJECT_BUILD_CONFIGURATION = new Action(IDEActions.BuildSetConfiguration, "MENU_BUILD_CONFIGURATION"c).disableByDefault(); +const Action ACTION_PROJECT_CONFIGURATION = new Action(IDEActions.ProjectSetConfiguration, "MENU_PROJECT_CONFIGURATION"c).disableByDefault(); + const Action ACTION_DEBUG_START = new Action(IDEActions.DebugStart, "MENU_DEBUG_START_DEBUGGING"c, "debug-run"c, KeyCode.F5, KeyFlag.Control | KeyFlag.Shift); const Action ACTION_DEBUG_START_NO_DEBUG = new Action(IDEActions.DebugStartNoDebug, "MENU_DEBUG_START_NO_DEBUGGING"c, null, KeyCode.F5, KeyFlag.Control); const Action ACTION_DEBUG_CONTINUE = new Action(IDEActions.DebugContinue, "MENU_DEBUG_CONTINUE"c, "debug-run"); diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index eb2a7a3..9b12c51 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -75,7 +75,7 @@ class BackgroundOperationWatcherTest : BackgroundOperationWatcher { /// DIDE app frame class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeListener, BookmarkListChangeListener { - private ToolBarComboBox projectConfigurationCombo; + private ToolBarComboBox _projectConfigurationCombo; MenuItem mainMenuItems; WorkspacePanel _wsPanel; @@ -698,6 +698,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL return _dockHost; } + private MenuItem _projectConfigurationMenuItem; /// create main menu override protected MainMenu createMainMenu() { @@ -735,9 +736,32 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL projectItem.add(ACTION_PROJECT_SET_STARTUP, ACTION_PROJECT_REFRESH, ACTION_PROJECT_UPDATE_DEPENDENCIES, ACTION_PROJECT_SETTINGS); MenuItem buildItem = new MenuItem(new Action(22, "MENU_BUILD")); + Action configs = ACTION_PROJECT_BUILD_CONFIGURATION.clone; + configs.longParam = -1; + MenuItem buildConfiguration = new MenuItem(configs); + foreach (config; BuildConfiguration.min .. BuildConfiguration.max + 1) { + Action a = ACTION_PROJECT_BUILD_CONFIGURATION.clone; + a.label = ["Debug"d,"Release"d,"Unittest"d][config]; + a.longParam = config; + MenuItem child = new MenuItem(a); + child.type = MenuItemType.Radio; + buildConfiguration.add(child); + } + buildItem.add(buildConfiguration); + + _projectConfigurationMenuItem = new MenuItem(ACTION_PROJECT_CONFIGURATION); + Action defaultConfigAction = ACTION_PROJECT_CONFIGURATION.clone; + defaultConfigAction.label = "default"d; + defaultConfigAction.stringParam = "default"; + MenuItem defaultConfigItem = new MenuItem(defaultConfigAction); + defaultConfigItem.type = MenuItemType.Radio; + buildConfiguration.add(defaultConfigItem); + buildItem.add(_projectConfigurationMenuItem); + buildItem.addSeparator(); + buildItem.add(ACTION_WORKSPACE_BUILD, ACTION_WORKSPACE_REBUILD, ACTION_WORKSPACE_CLEAN, - ACTION_PROJECT_BUILD, ACTION_PROJECT_REBUILD, ACTION_PROJECT_CLEAN, - ACTION_RUN_WITH_RDMD); + ACTION_PROJECT_BUILD, ACTION_PROJECT_REBUILD, ACTION_PROJECT_CLEAN, + ACTION_RUN_WITH_RDMD); MenuItem debugItem = new MenuItem(new Action(23, "MENU_DEBUG")); debugItem.add(ACTION_DEBUG_START, ACTION_DEBUG_START_NO_DEBUG, @@ -800,6 +824,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL } } + private ToolBarComboBox _cbBuildConfiguration; /// create app toolbars override protected ToolBarHost createToolbars() { ToolBarHost res = new ToolBarHost(); @@ -809,25 +834,20 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL tb.addButtons(ACTION_DEBUG_START); - projectConfigurationCombo = new ToolBarComboBox("projectConfig", [ProjectConfiguration.DEFAULT_NAME.to!dstring]);//Updateable - projectConfigurationCombo.itemClick = delegate(Widget source, int index) { - if (currentWorkspace) { - currentWorkspace.setStartupProjectConfiguration(projectConfigurationCombo.selectedItem.to!string); - } - return true; - }; - projectConfigurationCombo.action = ACTION_PROJECT_CONFIGURATIONS; - tb.addControl(projectConfigurationCombo); + _projectConfigurationCombo = new ToolBarComboBox("projectConfig", [ProjectConfiguration.DEFAULT_NAME.to!dstring]);//Updateable + _projectConfigurationCombo.action = ACTION_PROJECT_CONFIGURATIONS; + tb.addControl(_projectConfigurationCombo); - ToolBarComboBox cbBuildConfiguration = new ToolBarComboBox("buildConfig", ["Debug"d, "Release"d, "Unittest"d]); - cbBuildConfiguration.itemClick = delegate(Widget source, int index) { + _cbBuildConfiguration = new ToolBarComboBox("buildConfig", ["Debug"d, "Release"d, "Unittest"d]); + _cbBuildConfiguration.itemClick = delegate(Widget source, int index) { if (currentWorkspace && index < 3) { currentWorkspace.buildConfiguration = [BuildConfiguration.Debug, BuildConfiguration.Release, BuildConfiguration.Unittest][index]; } return true; }; - cbBuildConfiguration.action = ACTION_BUILD_CONFIGURATIONS; - tb.addControl(cbBuildConfiguration); + _cbBuildConfiguration.action = ACTION_BUILD_CONFIGURATIONS; + tb.addControl(_cbBuildConfiguration); + tb.addButtons(ACTION_PROJECT_BUILD, ACTION_SEPARATOR, ACTION_RUN_WITH_RDMD); tb = res.getOrAddToolbar("Edit"); @@ -883,6 +903,20 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL else a.state = ACTION_STATE_DISABLE; return true; + case IDEActions.BuildSetConfiguration: + // enable when project exists + if (currentWorkspace && currentWorkspace.startupProject && !_currentBackgroundOperation) + a.state = currentWorkspace.buildConfiguration == a.longParam ? ACTION_STATE_CHECKED : ACTION_STATE_ENABLED; + else + a.state = ACTION_STATE_DISABLE; + return true; + case IDEActions.ProjectSetConfiguration: + // enable when project exists + if (currentWorkspace && currentWorkspace.startupProject && !_currentBackgroundOperation) + a.state = currentWorkspace.startupProject.projectConfiguration.name == a.stringParam ? ACTION_STATE_CHECKED : ACTION_STATE_ENABLED; + else + a.state = ACTION_STATE_DISABLE; + return true; case IDEActions.RunWithRdmd: // enable when D source file is in current tab if (currentEditor && !_currentBackgroundOperation && currentEditor.id.endsWith(".d")) @@ -977,6 +1011,22 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL window.showMessageBox(UIString.fromId("ABOUT"c) ~ " " ~ DLANGIDE_VERSION, UIString.fromRaw(msg)); return true; + case IDEActions.BuildSetConfiguration: + // set build configuration + if (currentWorkspace && a.longParam >= BuildConfiguration.min && a.longParam <= BuildConfiguration.max) { + if (currentWorkspace.buildConfiguration != a.longParam) { + currentWorkspace.buildConfiguration = cast(BuildConfiguration)a.longParam; + Log.d("Changing build configuration to ", currentWorkspace.buildConfiguration); + _cbBuildConfiguration.selectedItemIndex = currentWorkspace.buildConfiguration; + } + } + return true; + case IDEActions.ProjectSetConfiguration: + if (currentWorkspace && currentWorkspace.startupProject && a.stringParam) { + currentWorkspace.startupProject.projectConfiguration = a.stringParam; + updateProjectConfigurations(); + } + return true; case IDEActions.ProjectFolderOpenItem: ProjectItem item = cast(ProjectItem)a.objectParam; if (item && !item.isFolder) { @@ -1680,9 +1730,14 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL warmUpImportPaths(ws.startupProject); } window.windowCaption(ws.name ~ " - "d ~ frameWindowCaptionSuffix); + _cbBuildConfiguration.enabled = true; + _cbBuildConfiguration.selectedItemIndex = currentWorkspace.buildConfiguration; + updateProjectConfigurations(); } else { + _cbBuildConfiguration.enabled = false; window.windowCaption(frameWindowCaptionSuffix); _wsPanel.hide(); + updateProjectConfigurations(); } } @@ -1755,7 +1810,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL } } - Builder op = new Builder(this, project, _logPanel, currentWorkspace.projectConfiguration, currentWorkspace.buildConfiguration, buildOp, + Builder op = new Builder(this, project, _logPanel, project.projectConfiguration, currentWorkspace.buildConfiguration, buildOp, dubExecutable, dubAdditionalParams, toolchain, arch, @@ -1763,11 +1818,44 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL setBackgroundOperation(op); } - /// updates list of available configurations - void setProjectConfigurations(dstring[] items) { - projectConfigurationCombo.items = items; + void updateProjectConfigurations() { + if (currentWorkspace && currentWorkspace.startupProject) { + if (_projectConfigurationCombo) { + _projectConfigurationCombo.enabled = true; + _projectConfigurationCombo.itemClick.clear(); + dstring[] items = currentWorkspace.startupProject.configurationNames; + _projectConfigurationCombo.items = items; + _projectConfigurationCombo.selectedItemIndex = currentWorkspace.startupProject.projectConfigurationIndex; + _projectConfigurationCombo.itemClick = delegate(Widget source, int index) { + if (currentWorkspace) { + currentWorkspace.setStartupProjectConfiguration(_projectConfigurationCombo.selectedItem.to!string); + } + return true; + }; + } + if (_projectConfigurationMenuItem) { + _projectConfigurationMenuItem.clear(); + foreach (config; currentWorkspace.startupProject.configurations) { + Action a = ACTION_PROJECT_CONFIGURATION.clone; + a.label = config.name.toUTF32; + a.stringParam = config.name; + MenuItem child = new MenuItem(a); + child.type = MenuItemType.Radio; + _projectConfigurationMenuItem.add(child); + } + } + } else { + if (_projectConfigurationCombo) { + _projectConfigurationCombo.itemClick.clear(); + _projectConfigurationCombo.enabled = false; + _projectConfigurationCombo.items = ["default"d]; + } + if (_projectConfigurationMenuItem) { + // TODO + } + } } - + /// handle files dropped to application window void onFilesDropped(string[] filenames) { //Log.d("onFilesDropped(", filenames, ")"); diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index 3834e4f..5950295 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -360,20 +360,23 @@ struct ProjectConfiguration { } /// parsing from setting file - static ProjectConfiguration[string] load(Setting s) + static ProjectConfiguration[] load(Setting s) { - ProjectConfiguration[string] res = [DEFAULT_NAME: DEFAULT]; + ProjectConfiguration[] res; Setting configs = s.objectByPath("configurations"); - if(configs is null || configs.type != SettingType.ARRAY) + if(configs is null || configs.type != SettingType.ARRAY) { + res ~= DEFAULT; return res; - + } + foreach(conf; configs) { if(!conf.isObject) continue; Type t = Type.Default; if(auto typeName = conf.getString("targetType")) t = parseType(typeName); - if (string confName = conf.getString("name")) - res[confName] = ProjectConfiguration(confName, t); + if (string confName = conf.getString("name")) { + res ~= ProjectConfiguration(confName, t); + } } return res; } @@ -395,7 +398,43 @@ class Project : WorkspaceItem { protected string[] _sourcePaths; protected string[] _builderSourcePaths; - protected ProjectConfiguration[string] _configurations; + protected ProjectConfiguration[] _configurations; + protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT; + + @property int projectConfigurationIndex() { + ProjectConfiguration config = projectConfiguration(); + foreach(i, value; _configurations) { + if (value.name == config.name) + return cast(int)i; + } + return 0; + } + + @property ProjectConfiguration projectConfiguration() { + if (_configurations.length == 0) + return ProjectConfiguration.DEFAULT; + string configName = settings.projectConfiguration; + foreach(config; _configurations) { + if (configName == config.name) + return config; + } + return _configurations[0]; + } + + @property void projectConfiguration(ProjectConfiguration config) { + settings.projectConfiguration = config.name; + settings.save(); + } + + @property void projectConfiguration(string configName) { + foreach(name, config; _configurations) { + if (configName == config.name) { + settings.projectConfiguration = config.name; + settings.save(); + return; + } + } + } this(Workspace ws, string fname = null, string dependencyVersion = null) { super(fname); @@ -448,11 +487,21 @@ class Project : WorkspaceItem { @property string dependencyVersion() { return _dependencyVersion; } /// returns project configurations - @property const(ProjectConfiguration[string]) configurations() const + @property const(ProjectConfiguration[]) configurations() const { return _configurations; } + /// returns project configurations + @property dstring[] configurationNames() const + { + dstring[] res; + res.assumeSafeAppend; + foreach(conf; _configurations) + res ~= conf.name.toUTF32; + return res; + } + /// direct access to project file (json) @property SettingsFile content() { return _projectFile; } diff --git a/src/dlangide/workspace/projectsettings.d b/src/dlangide/workspace/projectsettings.d index 6f34cf4..35a1208 100644 --- a/src/dlangide/workspace/projectsettings.d +++ b/src/dlangide/workspace/projectsettings.d @@ -43,6 +43,14 @@ class ProjectSettings : SettingsFile { return res; } + @property string projectConfiguration() { + return buildSettings.getString("configuration", "default"); + } + + @property void projectConfiguration(string newConfiguration) { + buildSettings.setString("configuration", newConfiguration); + } + @property bool buildVerbose() { return buildSettings.getBoolean("verbose", false); } diff --git a/src/dlangide/workspace/workspace.d b/src/dlangide/workspace/workspace.d index 36083cc..1ba6b70 100644 --- a/src/dlangide/workspace/workspace.d +++ b/src/dlangide/workspace/workspace.d @@ -56,8 +56,6 @@ class Workspace : WorkspaceItem { protected WorkspaceSettings _settings; protected IDEFrame _frame; - protected BuildConfiguration _buildConfiguration; - protected ProjectConfiguration _projectConfiguration = ProjectConfiguration.DEFAULT; this(IDEFrame frame, string fname = WORKSPACE_EXTENSION) { super(fname); @@ -82,19 +80,23 @@ class Workspace : WorkspaceItem { @property Project[] projects() { return _projects; } - @property BuildConfiguration buildConfiguration() { return _buildConfiguration; } - @property void buildConfiguration(BuildConfiguration config) { _buildConfiguration = config; } + @property BuildConfiguration buildConfiguration() { + return cast(BuildConfiguration)_settings.buildConfiguration; + } + + @property void buildConfiguration(BuildConfiguration config) { + _settings.buildConfiguration = cast(int)config; + } - @property ProjectConfiguration projectConfiguration() { return _projectConfiguration; } - @property void projectConfiguration(ProjectConfiguration config) { _projectConfiguration = config; } - protected Project _startupProject; @property Project startupProject() { return _startupProject; } @property void startupProject(Project project) { + if (_startupProject is project) + return; _startupProject = project; - _frame.setProjectConfigurations(project.configurations.keys.map!(k => k.to!dstring).array); _settings.startupProjectName = toUTF8(project.name); + _frame.updateProjectConfigurations(); } /// Last opened files in workspace @@ -131,8 +133,8 @@ class Workspace : WorkspaceItem { /// setups currrent project configuration by name void setStartupProjectConfiguration(string conf) { - if(_startupProject && conf in _startupProject.configurations) { - _projectConfiguration = _startupProject.configurations[conf]; + if(_startupProject) { + _startupProject.projectConfiguration = conf; } } diff --git a/src/dlangide/workspace/workspacesettings.d b/src/dlangide/workspace/workspacesettings.d index fa00ea1..11e424f 100644 --- a/src/dlangide/workspace/workspacesettings.d +++ b/src/dlangide/workspace/workspacesettings.d @@ -21,6 +21,17 @@ class WorkspaceSettings : SettingsFile { private WorkspaceFile[] _files; private string _startupProjectName; + private int _buildConfiguration; + + @property int buildConfiguration() { + return _buildConfiguration; + } + @property void buildConfiguration(int config) { + _setting.setInteger("buildConfiguration", config); + _buildConfiguration = config; + save(); + } + @property string startupProjectName() { return _startupProjectName; } @@ -239,6 +250,11 @@ class WorkspaceSettings : SettingsFile { file.row(cast(int)item.getInteger("row")); _files ~= file; } + _buildConfiguration = cast(int)_setting.getInteger("buildConfiguration", 0); + if (_buildConfiguration < 0) + _buildConfiguration = 0; + if (_buildConfiguration > 2) + _buildConfiguration = 2; } override void updateDefaults() { diff --git a/views/VERSION b/views/VERSION index 600d46c..6b6bd60 100644 --- a/views/VERSION +++ b/views/VERSION @@ -1 +1 @@ -v0.7.93 \ No newline at end of file +v0.7.94 \ No newline at end of file diff --git a/views/res/i18n/en.ini b/views/res/i18n/en.ini index 23dfcd0..f40666d 100644 --- a/views/res/i18n/en.ini +++ b/views/res/i18n/en.ini @@ -74,7 +74,8 @@ GO_TO_LINE=Go to line FIND_IN_FILES=Find in files... -MENU_BUILD_CONFIGURATIONS=Build configurations +MENU_BUILD_CONFIGURATIONS=Build types +MENU_BUILD_CONFIGURATION=Build type MENU_BUILD=&Build MENU_BUILD_WORKSPACE_BUILD=Build workspace MENU_BUILD_WORKSPACE_REBUILD=Rebuild workspace @@ -83,6 +84,8 @@ MENU_BUILD_PROJECT_BUILD=Build project MENU_BUILD_PROJECT_REBUILD=Rebuild project MENU_BUILD_PROJECT_CLEAN=Clean project MENU_BUILD_RUN_WITH_RDMD=Run with rdmd +MENU_BUILD_CONFIGURATION=Build type +MENU_PROJECT_CONFIGURATION=Project configuration MENU_DEBUG=&Debug MENU_DEBUG_START_DEBUGGING=Start debugging diff --git a/views/res/i18n/ru.ini b/views/res/i18n/ru.ini index 9758042..c5264f7 100644 --- a/views/res/i18n/ru.ini +++ b/views/res/i18n/ru.ini @@ -74,7 +74,9 @@ GO_TO_LINE=Перейти к строке FIND_IN_FILES=Найти в файлах... -MENU_BUILD_CONFIGURATIONS=Собрать конфигурации +MENU_BUILD_CONFIGURATIONS=Тип сборки +MENU_BUILD_CONFIGURATION=Тип сборки +MENU_PROJECT_CONFIGURATION=Конфигурация проекта MENU_BUILD=&Сборка MENU_BUILD_WORKSPACE_BUILD=Собрать рабочее пространство MENU_BUILD_WORKSPACE_REBUILD=Пересобрать рабочее пространство