diff --git a/.travis.yml b/.travis.yml index 4a49ed1..bf4e0d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,10 +30,10 @@ install: then sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install -y gcc-multilib libgl1-mesa-glx:i386 libfreetype6:i386 libsdl2-2.0-0:i386 + sudo apt-get install -y gcc-multilib libgl1-mesa-glx:i386 libfreetype6:i386 libsdl2-2.0-0:i386 zlib1g-dev:i386 else sudo apt-get update - sudo apt-get install -y libfreetype6 libsdl2-2.0-0 + sudo apt-get install -y libfreetype6 libsdl2-2.0-0 zlib1g-dev fi fi diff --git a/dub.json b/dub.json index 3bd1b2a..026d787 100644 --- a/dub.json +++ b/dub.json @@ -12,14 +12,16 @@ "stringImportPaths": ["views", "views/res", "views/res/i18n", "views/res/mdpi", "views/res/hdpi"], "dependencies": { - "dlangui": "==0.9.88", - "dcd": "~>0.9.0" + "dlangui": "==0.9.99", + "dcd": "~>0.9.1" }, "copyFiles-windows": [ "libs/windows/x86/mago-mi.exe" ], + "libs-linux": ["z"], + "configurations" : [ { "name" : "default" diff --git a/src/dlangide.d b/src/dlangide.d index 8ce8f87..cf4a506 100644 --- a/src/dlangide.d +++ b/src/dlangide.d @@ -88,10 +88,10 @@ extern (C) int UIAppMain(string[] args) { IDEFrame frame = new IDEFrame(window); // Open project, if it specified in command line - if (args.length > 0) + if (args.length > 1) { Action a = ACTION_FILE_OPEN_WORKSPACE.clone(); - a.stringParam = args[0].toAbsolutePath; + a.stringParam = args[1].toAbsolutePath; frame.handleAction(a); // Mark that workspace opened to prevent auto open frame.isOpenedWorkspace(true); diff --git a/src/dlangide/tools/d/dcdinterface.d b/src/dlangide/tools/d/dcdinterface.d index eb6e4f8..c465825 100644 --- a/src/dlangide/tools/d/dcdinterface.d +++ b/src/dlangide/tools/d/dcdinterface.d @@ -4,7 +4,6 @@ import dlangui.core.logger; import dlangui.core.files; import dlangui.platforms.common.platform; import ddebug.common.queue; -import dsymbol.string_interning : internString; import core.thread; @@ -59,7 +58,7 @@ class DCDTask { } void createRequest() { request.sourceCode = cast(ubyte[])_content; - request.fileName = internString(_filename); + request.fileName = _filename; request.cursorPosition = _index; request.importPaths = _importPaths; } @@ -82,25 +81,16 @@ class DCDTask { } } -string[] internStrings(in string[] src) { - if (!src) - return null; - string[] res; - foreach(s; src) - res ~= internString(s); - return res; -} - class ModuleCacheAccessor { import dsymbol.modulecache; //protected ASTAllocator _astAllocator; protected ModuleCache _moduleCache; this(in string[] importPaths) { _moduleCache = ModuleCache(new SharedASTAllocator); - _moduleCache.addImportPaths(internStrings(importPaths)); + _moduleCache.addImportPaths(importPaths); } protected ModuleCache * getModuleCache(in string[] importPaths) { - _moduleCache.addImportPaths(internStrings(importPaths)); + _moduleCache.addImportPaths(importPaths); return &_moduleCache; } } @@ -161,6 +151,7 @@ class DCDInterface : Thread { void threadFunc() { _moduleCache = new ModuleCacheAccessor(null); + getModuleCache(null); Log.d("Starting DCD tasks thread"); while (!_queue.closed()) { DCDTask task; @@ -174,6 +165,7 @@ class DCDInterface : Thread { } } Log.d("Exiting DCD tasks thread"); + destroyModuleCache(); } import dsymbol.modulecache; diff --git a/src/dlangide/ui/dsourceedit.d b/src/dlangide/ui/dsourceedit.d index b1939cf..fbdeb66 100644 --- a/src/dlangide/ui/dsourceedit.d +++ b/src/dlangide/ui/dsourceedit.d @@ -125,6 +125,7 @@ class DSourceEdit : SourceEdit, EditableContentMarksChangeListener { protected ProjectSourceFile _projectSourceFile; @property ProjectSourceFile projectSourceFile() { return _projectSourceFile; } + @property void projectSourceFile(ProjectSourceFile v) { _projectSourceFile = v; } /// load by filename override bool load(string fn) { _projectSourceFile = null; @@ -224,6 +225,14 @@ class DSourceEdit : SourceEdit, EditableContentMarksChangeListener { return _content.save(); } + /// save to the same file + override bool save(string fn) { + bool res = super.save(fn); + //if (res && projectSourceFile) + // projectSourceFile.setFilename(filename); + return res; + } + void insertCompletion(dstring completionText) { TextRange range; TextPosition p = caretPos; diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 045738b..3d0a640 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -46,7 +46,8 @@ import std.path; immutable string HELP_PAGE_URL = "https://github.com/buggins/dlangide/wiki"; // TODO: get version from GIT commit -immutable dstring DLANGIDE_VERSION = "v0.7.42"d; +//version is now stored in file views/VERSION +immutable dstring DLANGIDE_VERSION = toUTF32(import("VERSION")); bool isSupportedSourceTextFileFormat(string filename) { return (filename.endsWith(".d") || filename.endsWith(".di") || filename.endsWith(".dt") || filename.endsWith(".txt") || filename.endsWith(".cpp") || filename.endsWith(".h") || filename.endsWith(".c") @@ -514,6 +515,18 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL _tabs.removeTab(tabId); } + void renameTab(string oldfilename, string newfilename) { + int index = _tabs.tabIndex(newfilename); + if (index >= 0) { + // file is already opened in tab - close it + _tabs.removeTab(newfilename); + } + int oldindex = _tabs.tabIndex(oldfilename); + if (oldindex >= 0) { + _tabs.renameTab(oldindex, newfilename, UIString.fromRaw(newfilename.baseName)); + } + } + /// close all editor tabs void closeAllDocuments() { for (int i = _tabs.tabCount - 1; i >= 0; i--) { @@ -880,8 +893,8 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL } } - FileDialog createFileDialog(UIString caption) { - FileDialog dlg = new FileDialog(caption, window, null); + FileDialog createFileDialog(UIString caption, int fileDialogFlags = DialogFlag.Modal | DialogFlag.Resizable | FileDialogFlag.FileMustExist) { + FileDialog dlg = new FileDialog(caption, window, null, fileDialogFlags); dlg.filetypeIcons[".d"] = "text-d"; dlg.filetypeIcons["dub.json"] = "project-d"; dlg.filetypeIcons["dub.sdl"] = "project-d"; @@ -911,6 +924,41 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL case StandardAction.OpenUrl: platform.openURL(a.stringParam); return true; + case IDEActions.FileSaveAs: + DSourceEdit ed = currentEditor; + UIString caption; + caption = UIString.fromId("HEADER_SAVE_FILE_AS"c); + FileDialog dlg = createFileDialog(caption, DialogFlag.Modal | DialogFlag.Resizable | FileDialogFlag.Save); + dlg.addFilter(FileFilterEntry(UIString.fromId("SOURCE_FILES"c), "*.d;*.dd;*.ddoc;*.di;*.dt;*.dh;*.json;*.sdl;*.xml;*.ini")); + dlg.addFilter(FileFilterEntry(UIString.fromId("ALL_FILES"c), "*.*")); + dlg.path = ed.filename.dirName; + dlg.filename = ed.filename; + dlg.dialogResult = delegate(Dialog d, const Action result) { + if (result.id == ACTION_SAVE.id) { + string oldfilename = ed.filename; + string filename = result.stringParam; + ed.save(filename); + if (oldfilename == filename) + return; + renameTab(oldfilename, filename); + ed.id = filename; + ed.setSyntaxSupport(); + if( filename.endsWith(".d") || filename.endsWith(".di") ) + ed.editorTool = new DEditorTool(this); + else + ed.editorTool = new DefaultEditorTool(this); + //openSourceFile(filename); + refreshWorkspace(); + ProjectSourceFile file = _wsPanel.findSourceFileItem(filename, false); + if (file) { + ed.projectSourceFile = file; + } else + ed.projectSourceFile = null; + _settings.setRecentPath(dlg.path, "FILE_OPEN_PATH"); + } + }; + dlg.show(); + return true; case IDEActions.FileOpen: UIString caption; caption = UIString.fromId("HEADER_OPEN_TEXT_FILE"c); @@ -1308,6 +1356,22 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL FontManager.minAnitialiasedFontSize = settings.minAntialiasedFontSize; Platform.instance.uiLanguage = settings.uiLanguage; Platform.instance.uiTheme = settings.uiTheme; + bool needUpdateTheme = false; + string oldFontFace = currentTheme.fontFace; + string newFontFace = settings.uiFontFace; + if (newFontFace == "Default") + newFontFace = "Helvetica Neue,Verdana,Arial,DejaVu Sans,Liberation Sans,Helvetica,Roboto,Droid Sans"; + int oldFontSize = currentTheme.fontSize; + if (oldFontFace != newFontFace) { + currentTheme.fontFace = newFontFace; + needUpdateTheme = true; + } + if (oldFontSize != settings.uiFontSize) { + currentTheme.fontSize = settings.uiFontSize; + needUpdateTheme = true; + } + if (needUpdateTheme) + Platform.instance.onThemeChanged(); requestLayout(); } diff --git a/src/dlangide/ui/newproject.d b/src/dlangide/ui/newproject.d index f180b35..8c1f181 100644 --- a/src/dlangide/ui/newproject.d +++ b/src/dlangide/ui/newproject.d @@ -513,7 +513,7 @@ extern (C) int UIAppMain(string[] args) { immutable string DUB_JSON_DLANGUI_HELLOWORLD = q{ { "dependencies": { - "dlangui": "~>0.9.24" + "dlangui": "~>0.9.99" } } diff --git a/src/dlangide/ui/settings.d b/src/dlangide/ui/settings.d index 6fb134a..ee7aa42 100644 --- a/src/dlangide/ui/settings.d +++ b/src/dlangide/ui/settings.d @@ -10,6 +10,56 @@ public import dlangide.workspace.projectsettings; public import dlangide.workspace.idesettings; public import dlangide.workspace.workspacesettings; +StringListValue[] createFaceList(bool monospaceFirst) { + StringListValue[] faces; + faces.assumeSafeAppend(); + faces ~= StringListValue("Default", "OPTION_DEFAULT"c); + import dlangui.graphics.fonts; + import std.utf : toUTF32; + FontFaceProps[] allFaces = FontManager.instance.getFaces(); + import std.algorithm.sorting : sort; + auto fontCompMonospaceFirst = function(ref FontFaceProps a, ref FontFaceProps b) { + if (a.family == FontFamily.MonoSpace && b.family != FontFamily.MonoSpace) + return -1; + if (a.family != FontFamily.MonoSpace && b.family == FontFamily.MonoSpace) + return 1; + if (a.face < b.face) + return -1; + if (a.face > b.face) + return 1; + return 0; + }; + auto fontComp = function(ref FontFaceProps a, ref FontFaceProps b) { + if (a.face < b.face) + return -1; + if (a.face > b.face) + return 1; + return 0; + }; + //auto sorted = allFaces.sort!((a, b) => (a.family == FontFamily.MonoSpace && b.family != FontFamily.MonoSpace) || (a.face < b.face)); + auto sorted = sort!((a, b) => (monospaceFirst ? fontCompMonospaceFirst(a, b) : fontComp(a, b)) < 0)(allFaces); + + //allFaces = allFaces.sort!((a, b) => a.family == FontFamily.MonoSpace && b.family == FontFamily.MonoSpace || a.face < b.face); + //for (int i = 0; i < allFaces.length; i++) { + foreach (face; sorted) { + if (face.family == FontFamily.MonoSpace) + faces ~= StringListValue(face.face, "*"d ~ toUTF32(face.face)); + else + faces ~= StringListValue(face.face, toUTF32(face.face)); + } + return faces; +} + +StringListValue[] createIntValueList(int[] values, dstring suffix = ""d) { + import std.conv : to; + StringListValue[] res; + res.assumeSafeAppend(); + foreach(n; values) { + res ~= StringListValue(n, to!dstring(n) ~ suffix); + } + return res; +} + /// create DlangIDE settings pages tree SettingsPage createSettingsPages() { // Root page @@ -30,6 +80,13 @@ SettingsPage createSettingsPages() { StringListValue("es", "MENU_VIEW_LANGUAGE_ES"c), StringListValue("cs", "MENU_VIEW_LANGUAGE_CS"c)]); + // UI font faces + ui.addStringComboBox("interface/uiFontFace", UIString.fromId("OPTION_FONT_FACE"c), + createFaceList(false)); + ui.addIntComboBox("interface/uiFontSize", UIString.fromId("OPTION_FONT_SIZE"c), + createIntValueList([6,7,8,9,10,11,12,14,16,18,20,22,24,26,28,30,32])); + + ui.addIntComboBox("interface/hintingMode", UIString.fromId("OPTION_FONT_HINTING"c), [StringListValue(0, "OPTION_FONT_HINTING_NORMAL"c), StringListValue(1, "OPTION_FONT_HINTING_FORCE"c), StringListValue(2, "OPTION_FONT_HINTING_DISABLED"c), StringListValue(3, "OPTION_FONT_HINTING_LIGHT"c)]); @@ -67,36 +124,8 @@ SettingsPage createSettingsPages() { SettingsPage ed = res.addChild("editors", UIString.fromId("OPTION_EDITORS"c)); SettingsPage texted = ed.addChild("editors/textEditor", UIString.fromId("OPTION_TEXT_EDITORS"c)); - // font faces - StringListValue[] faces; - faces ~= StringListValue("Default", "OPTION_DEFAULT"c); - import dlangui.graphics.fonts; - import std.utf : toUTF32; - FontFaceProps[] allFaces = FontManager.instance.getFaces(); - import std.algorithm.sorting : sort; - auto fontComp = function(ref FontFaceProps a, ref FontFaceProps b) { - if (a.family == FontFamily.MonoSpace && b.family != FontFamily.MonoSpace) - return -1; - if (a.family != FontFamily.MonoSpace && b.family == FontFamily.MonoSpace) - return 1; - if (a.face < b.face) - return -1; - if (a.face > b.face) - return 1; - return 0; - }; - //auto sorted = allFaces.sort!((a, b) => (a.family == FontFamily.MonoSpace && b.family != FontFamily.MonoSpace) || (a.face < b.face)); - auto sorted = sort!((a, b) => fontComp(a, b) < 0)(allFaces); - - //allFaces = allFaces.sort!((a, b) => a.family == FontFamily.MonoSpace && b.family == FontFamily.MonoSpace || a.face < b.face); - //for (int i = 0; i < allFaces.length; i++) { - foreach (face; sorted) { - if (face.family == FontFamily.MonoSpace) - faces ~= StringListValue(face.face, "*"d ~ toUTF32(face.face)); - else - faces ~= StringListValue(face.face, toUTF32(face.face)); - } - texted.addStringComboBox("editors/textEditor/fontFace", UIString.fromId("OPTION_FONT_FACE"c), faces); + // editor font faces + texted.addStringComboBox("editors/textEditor/fontFace", UIString.fromId("OPTION_FONT_FACE"c), createFaceList(true)); texted.addNumberEdit("editors/textEditor/tabSize", UIString.fromId("OPTION_TAB"c), 1, 16, 4); texted.addCheckbox("editors/textEditor/useSpacesForTabs", UIString.fromId("OPTION_USE_SPACES"c)); diff --git a/src/dlangide/workspace/idesettings.d b/src/dlangide/workspace/idesettings.d index d847c2a..f70e6a8 100644 --- a/src/dlangide/workspace/idesettings.d +++ b/src/dlangide/workspace/idesettings.d @@ -30,6 +30,8 @@ class IDESettings : SettingsFile { ui.setIntegerDef("hintingMode", 1); ui.setIntegerDef("minAntialiasedFontSize", 0); ui.setFloatingDef("fontGamma", 0.8); + ui.setStringDef("uiFontFace", "Default"); + ui.setIntegerDef("uiFontSize", 10); version (Windows) { debuggerSettings.setStringDef("executable", "mago-mi"); } else { @@ -124,6 +126,16 @@ class IDESettings : SettingsFile { return this; } + /// UI font face + @property string uiFontFace() { + return uiSettings.getString("uiFontFace", "Default"); + } + + /// UI font size + @property int uiFontSize() { + return pointsToPixels(cast(int)uiSettings.getInteger("uiFontSize", 10)); + } + /// text editor setting, true if need to insert spaces instead of tabs @property bool useSpacesForTabs() { return editorSettings.getBoolean("useSpacesForTabs", true); diff --git a/src/dlangide/workspace/project.d b/src/dlangide/workspace/project.d index a4fef92..fc2db3b 100644 --- a/src/dlangide/workspace/project.d +++ b/src/dlangide/workspace/project.d @@ -227,6 +227,11 @@ class ProjectSourceFile : ProjectItem { @property string projectFilePath() { return project.absoluteToRelativePath(filename); } + + void setFilename(string filename) { + _filename = buildNormalizedPath(filename); + _name = toUTF32(baseName(_filename)); + } } class WorkspaceItem { diff --git a/views/VERSION b/views/VERSION new file mode 100644 index 0000000..7114f72 --- /dev/null +++ b/views/VERSION @@ -0,0 +1 @@ +v0.7.52 \ No newline at end of file diff --git a/views/res/i18n/en.ini b/views/res/i18n/en.ini index 1409152..1f22da7 100644 --- a/views/res/i18n/en.ini +++ b/views/res/i18n/en.ini @@ -119,6 +119,7 @@ HEADER_OPEN_WORKSPACE_OR_PROJECT=Open Workspace or Project HEADER_OPEN_TEXT_FILE=Open Text File HEADER_CLOSE_FILE=Close file HEADER_CLOSE_TAB=Close tab +HEADER_SAVE_FILE_AS=Save File As OPTION_ADD_TO_CURRENT_WORKSPACE=Add to current workspace OPTION_AUTO_OPEN_LAST_PROJECT=Auto open last project @@ -142,6 +143,7 @@ OPTION_FONT_HINTING_FORCE=Force Auto Hint OPTION_FONT_HINTING_NORMAL=Normal OPTION_FONT_HINTING_LIGHT=LIGHT OPTION_FONT_FACE=Font face +OPTION_FONT_SIZE=Font face OPTION_FONT_GAMMA=Font gamma OPTION_GDC_EXECUTABLE=GDC executable OPTION_LANGUAGE=Language diff --git a/views/res/i18n/ru.ini b/views/res/i18n/ru.ini index 504a249..408d04e 100644 --- a/views/res/i18n/ru.ini +++ b/views/res/i18n/ru.ini @@ -119,6 +119,7 @@ HEADER_OPEN_WORKSPACE_OR_PROJECT=Открыть рабочее простран HEADER_OPEN_TEXT_FILE=Открыть текстовый файл HEADER_CLOSE_FILE=Закрыть файл HEADER_CLOSE_TAB=Закрыть вкладку +HEADER_SAVE_FILE_AS=Сохранить как OPTION_ADD_TO_CURRENT_WORKSPACE=Добавить в текущее пр-во OPTION_AUTO_OPEN_LAST_PROJECT=Авт.открывать последний проект