From 6140362c0fb30227364952a8bbf1dfe6fed6e556 Mon Sep 17 00:00:00 2001 From: Jerome St-Louis Date: Thu, 4 Aug 2016 05:39:17 -0400 Subject: [PATCH] ide/Global Settings: Initial font selector (Windows support) --- ecere/src/gfx/fontManagement.ec | 64 +++++++- ide/Makefile | 10 ++ ide/ide.epj | 3 +- ide/src/IDESettings.ec | 21 +++ ide/src/dialogs/FontPicker.ec | 267 ++++++++++++++++++++++++++++++++ ide/src/dialogs/GlobalSettingsDialog.ec | 29 +++- ide/src/ide.ec | 38 +++++ 7 files changed, 420 insertions(+), 12 deletions(-) create mode 100644 ide/src/dialogs/FontPicker.ec diff --git a/ecere/src/gfx/fontManagement.ec b/ecere/src/gfx/fontManagement.ec index b69d8f0..3673df2 100644 --- a/ecere/src/gfx/fontManagement.ec +++ b/ecere/src/gfx/fontManagement.ec @@ -27,7 +27,7 @@ static int CALLBACK MyFontProc(ENUMLOGFONTEX * font, NEWTEXTMETRICEX *lpntme, in //if(fontType == TRUETYPE_FONTTYPE) { FontData * fontData = (FontData *) lParam; - char * fileName = (char *)lParam; + char * fileName = fontData->fileName; HKEY key; int weight = (fontData->flags.bold) ? FW_BOLD : FW_NORMAL; int italic = (fontData->flags.italic) ? 1 : 0; @@ -304,13 +304,16 @@ public Array ResolveFont(const String faceName, float size, FontFlags #endif while(true) { - FaceInfo faceInfo + if(FileExists(fileName)) { - fileName = CopyString(fileName), - fakeItalic = fakeItalic, - fontID = fontID - }; - fileNames.Add(faceInfo); + FaceInfo faceInfo + { + fileName = CopyString(fileName), + fakeItalic = fakeItalic, + fontID = fontID + }; + fileNames.Add(faceInfo); + } { int c; char ch; @@ -394,9 +397,56 @@ public Array ResolveFont(const String faceName, float size, FontFlags #endif #endif + if(!fileNames.count) + delete fileNames; return fileNames; } +import "AVLTree" + +public struct FontInfo +{ + bool fixedPitch; + bool defaultOrAnsiCharSet; +}; + +#if defined(__WIN32__) +static int CALLBACK fontLister(ENUMLOGFONTEXW * font, NEWTEXTMETRICEX *lpntme, int fontType, LPARAM lParam) +{ + // const String faceName = font->elfLogFont.lfFaceName; + uint16 * faceName = font->elfLogFont.lfFaceName; + String s = UTF16toUTF8(faceName); + if(s[0] != '@') + { + Map fonts = (Map)lParam; + MapIterator it { map = fonts }; + if(!it.Index(s, true)) + it.data = { (font->elfLogFont.lfPitchAndFamily & 3) == FIXED_PITCH, defaultOrAnsiCharSet = (font->elfLogFont.lfCharSet == ANSI_CHARSET || font->elfLogFont.lfCharSet == DEFAULT_CHARSET) }; + } + delete s; + return 1; +} +#endif + +public Map ListAvailableFonts() +{ + Map fonts { }; + +#if defined(__WIN32__) + LOGFONTW logFont = { 0 }; + HDC hdc = GetDC(0); + logFont.lfCharSet = DEFAULT_CHARSET; + + EnumFontFamiliesExW(hdc, &logFont, (void *)fontLister, (LPARAM)fonts, 0); + + ReleaseDC(0, hdc); + +#elif !defined(ECERE_NOFONTCONFIG) + +#endif + return fonts; +} + public FaceInfo ResolveCharFont(const String faceName, float size, FontFlags flags, const String lang, unichar testChar) { FaceInfo info = null; diff --git a/ide/Makefile b/ide/Makefile index 7377d01..b00cfde24 100644 --- a/ide/Makefile +++ b/ide/Makefile @@ -54,6 +54,7 @@ _ECSOURCES = \ src/dialogs/FindInFilesDialog.ec \ src/dialogs/GlobalSettingsDialog.ec \ src/dialogs/NewProjectDialog.ec \ + src/dialogs/FontPicker.ec \ src/dialogs/NodeProperties.ec \ src/dialogs/WorkspaceSettings.ec \ src/dialogs/ProjectTabSettings.ec \ @@ -327,6 +328,9 @@ $(OBJ)NodeProperties.sym: src/dialogs/NodeProperties.ec $(OBJ)WorkspaceSettings.sym: src/dialogs/WorkspaceSettings.ec $(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/WorkspaceSettings.ec -o $(OBJ)WorkspaceSettings.sym +$(OBJ)FontPicker.sym: src/dialogs/FontPicker.ec + $(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/FontPicker.ec -o $(OBJ)FontPicker.sym + $(OBJ)ProjectTabSettings.sym: src/dialogs/ProjectTabSettings.ec $(ECP) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/ProjectTabSettings.ec -o $(OBJ)ProjectTabSettings.sym @@ -462,6 +466,9 @@ $(OBJ)NewProjectDialog.c: src/dialogs/NewProjectDialog.ec $(OBJ)NewProjectDialog $(OBJ)NodeProperties.c: src/dialogs/NodeProperties.ec $(OBJ)NodeProperties.sym | $(SYMBOLS) $(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/NodeProperties.ec -o $(OBJ)NodeProperties.c -symbols $(OBJ) +$(OBJ)FontPicker.c: src/dialogs/FontPicker.ec $(OBJ)FontPicker.sym | $(SYMBOLS) + $(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/FontPicker.ec -o $(OBJ)FontPicker.c -symbols $(OBJ) + $(OBJ)WorkspaceSettings.c: src/dialogs/WorkspaceSettings.ec $(OBJ)WorkspaceSettings.sym | $(SYMBOLS) $(ECC) $(CFLAGS) $(CECFLAGS) $(ECFLAGS) $(PRJ_CFLAGS) -c src/dialogs/WorkspaceSettings.ec -o $(OBJ)WorkspaceSettings.c -symbols $(OBJ) @@ -603,6 +610,9 @@ $(OBJ)NodeProperties.o: $(OBJ)NodeProperties.c $(OBJ)WorkspaceSettings.o: $(OBJ)WorkspaceSettings.c $(CC) $(CFLAGS) $(PRJ_CFLAGS) -c $(OBJ)WorkspaceSettings.c -o $(OBJ)WorkspaceSettings.o +$(OBJ)FontPicker.o: $(OBJ)FontPicker.c + $(CC) $(CFLAGS) $(PRJ_CFLAGS) -c $(OBJ)FontPicker.c -o $(OBJ)FontPicker.o + $(OBJ)ProjectTabSettings.o: $(OBJ)ProjectTabSettings.c $(CC) $(CFLAGS) $(PRJ_CFLAGS) -c $(OBJ)ProjectTabSettings.c -o $(OBJ)ProjectTabSettings.o diff --git a/ide/ide.epj b/ide/ide.epj index cd859e7..423a44c 100644 --- a/ide/ide.epj +++ b/ide/ide.epj @@ -178,7 +178,8 @@ "NewProjectDialog.ec", "NodeProperties.ec", "WorkspaceSettings.ec", - "ProjectTabSettings.ec" + "ProjectTabSettings.ec", + "FontPicker.ec" ] }, { diff --git a/ide/src/IDESettings.ec b/ide/src/IDESettings.ec index 4b1a783..c6aa844 100644 --- a/ide/src/IDESettings.ec +++ b/ide/src/IDESettings.ec @@ -883,6 +883,19 @@ public: isset { return language != null; } } + property const String codeEditorFont + { + set + { + delete codeEditorFont; + codeEditorFont = CopyString(value); + } + get { return codeEditorFont; } + } + + float codeEditorFontSize; + bool showFixedPitchFontsOnly; + private: CompilerConfigs compilerConfigs { }; char * docDir; @@ -896,6 +909,12 @@ private: RecentFiles recentFiles { }; RecentWorkspaces recentProjects { }; + String codeEditorFont; + + showFixedPitchFontsOnly = true; + codeEditorFontSize = 12; + codeEditorFont = CopyString("Courier New"); + ~IDESettings() { compilerConfigs.Free(); @@ -913,6 +932,8 @@ private: delete ideFileDialogLocation; delete ideProjectFileDialogLocation; delete displayDriver; + + delete codeEditorFont; } void ForcePathSeparatorStyle(bool unixStyle) diff --git a/ide/src/dialogs/FontPicker.ec b/ide/src/dialogs/FontPicker.ec new file mode 100644 index 0000000..edbcf37 --- /dev/null +++ b/ide/src/dialogs/FontPicker.ec @@ -0,0 +1,267 @@ +import "ide" + +SyntaxColorScheme colorScheme +{ + keywordColors = [ skyBlue, skyBlue ]; + commentColor = Color { 125, 125, 125 }; + charLiteralColor = Color { 245, 50, 245 }; + stringLiteralColor = Color { 245, 50, 245 }; + preprocessorColor = { 120, 220, 140 }; + numberColor = Color { 0, 192, 192 }; +}; + +Array sizes { [ 6, 7, 8.25f, 9, 10, 10.5f, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 36, 40, 44, 48, 54, 60, 66, 72, 80, 88, 96 ] }; + +Array fonts +{ [ + "Bitstream Vera Sans Mono", + "Consolas", + "Courier New", + "DejaVu Sans Mono", + "Lucida Console", + "Monaco", + "Monoid", + "OCR-A II", + "OCR B MT" + + // "Terminal" +] }; + +const String sampleText = //"The Quick Brown Fox Jumps Over The Lazy Dog"; + "import \"ecere\"\n" + "\n" + "class HelloForm : Window\n" + "{\n" + " caption = $\"My First eC Application\";\n" + " borderStyle = sizable;\n" + " size = { 280, 100 };\n" + " hasClose = true;\n" + " displayDriver = \"OpenGL\";\n" + "\n" + " bool OnKeyDown(Key key, unichar ch)\n" + " {\n" + "\n" + " return true;\n" + " }\n" + "\n" + " Label label\n" + " {\n" + " this, position = { 10, 10 }, font = { \"Arial\", 30 },\n" + " caption = $\"Hello, World!!\"\n" + " };\n" + "};\n" + "\n" + "HelloForm hello { };\n"; + +Array fontResources { }; + +class DisplayedFace : FontResource +{ + void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags) + { + surface.font = font; + faceName.OnDisplay(surface, x, y, width, fieldData, alignment, displayFlags); + } +}; + +class FontPicker : Window +{ + opacity = 0; + /* + background = formColor; + caption = $"Font Picker"; + borderStyle = sizable; + hasMaximize = true; + hasMinimize = true; + hasClose = true; + size = { 664, 426 }; + anchor = { horz = 9, vert = -26 }; + */ + virtual bool Window::NotifyChanged(); + + property float fontSize + { + get { return curFont.size; } + } + property const String faceName + { + get { return curFont.faceName; } + } + + FontResource curFont { "Consolas", 12}; + DataField dfSize { class(float) }; + DropBox dbSize + { + this, size = { 56, 24 }, anchor = { left = 4, bottom = 4 }; + + bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods) + { + curFont.size = row.GetData(dfSize); + for(f : fontResources) + { + RemoveResource(f); + f.size = Min(20, curFont.size); + AddResource(f); + } + listFonts.font = fontResources[0]; + OnLoadGraphics(); + listFonts.OnLoadGraphics(); + listFonts.size = listFonts.size; // Fix for scrollbar? + listFonts.Update(null); + sample.font = curFont; + + modifiedDocument = true; + NotifyChanged(master); + return true; + } + }; + Button cbFixedPitch + { + this, isCheckbox = true, caption = $"Fixed pitch only", anchor = { left = 68, bottom = 8 }; + checked = true; + + bool NotifyClicked(Button button, int x, int y, Modifiers mods) + { + ideSettings.showFixedPitchFontsOnly = button.checked; + OnDestroy(); + OnCreate(); + return true; + } + }; + EditBox sample + { + this, anchor = { left = 0.439024, top = 16, right = 4, bottom = 8 }, font = curFont; + textVertScroll = true; + hasVertScroll = true; + hasHorzScroll = true; + freeCaret = true; + + syntaxHighlighting = true; + syntaxColorScheme = colorScheme; + + foreground = ivory; + selectionText = Color { 30, 40, 50 }; + background = black; + selectionColor = lightYellow; + multiLine = true; + contents = sampleText; + }; + ListBox listFonts + { + this, anchor = { left = 4, top = 16, right = 0.591463, bottom = 30 }, alwaysHighLight = true; + hasVertScroll = true; + dontHideScroll = true; + + bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) + { + if(row) + { + FontResource fr = row.GetData(dfFace); + curFont.faceName = fr.faceName; + + modifiedDocument = true; + NotifyChanged(master); + } + sample.font = curFont; + return true; + } + }; + DataField dfFace { class(DisplayedFace) }; + + bool OnLoadGraphics() + { + int maxH = 12 + 5; + float size = dbSize.GetData(dfSize); + int maxSize = (int)(size * 96 / 72 * 1.5); + for(f : fontResources) + { + Font font = f.font; + int h; + // const String n = f.faceName; + displaySystem.FontExtent(font, "W", 1, null, &h); + h += 5; + + h = font.ascent + font.descent + 5; + if(h > maxSize) h = maxSize; + maxH = Max(maxH, h); + } + listFonts.rowHeight = maxH; + return true; + } + + FontPicker() + { + dbSize.AddField(dfSize); + for(s : sizes) + { + DataRow row = dbSize.AddRow(); + row.SetData(dfSize, s); + if(s == curFont.size) + dbSize.currentRow = row; + } + listFonts.AddField(dfFace); + } + + void OnDestroy() + { + for(f : fontResources) + RemoveResource(f); + listFonts.Clear(); + fontResources.RemoveAll(); + } + + bool OnCreate() + { + Map fonts = ListAvailableFonts(); + DataRow sRow; + float fontSize; + bool fixedPitchOnly = ideSettings.showFixedPitchFontsOnly; + + curFont.faceName = ideSettings.codeEditorFont; + curFont.size = fontSize = ideSettings.codeEditorFontSize; + + cbFixedPitch.checked = fixedPitchOnly; + fontResources.minAllocSize = fonts.GetCount(); + + for(sRow = dbSize.firstRow; sRow; sRow = sRow.next) + { + float s = sRow.GetData(dfSize); + if(fontSize - s < 0.5 || s > fontSize) + { + dbSize.currentRow = sRow; + break; + } + } + + for(f : fonts; f.defaultOrAnsiCharSet && (!fixedPitchOnly || f.fixedPitch)) + { + FontResource fr { &f, curFont.size, window = this }; + DataRow row = listFonts.AddRow(); + incref fr; + row.SetData(dfFace, fr); + if(!strcmp(&f, curFont.faceName)) + listFonts.currentRow = row; + fontResources.Add(fr); + } + delete fonts; + return true; + } +} + +//FontPicker fontPicker { }; + +/* +Color selectionColor = lightYellow; +Color selectionText = Color { 30, 40, 50 }; +Color viewsBackground = Color { 30, 40, 50 }; +Color viewsText = lightGray; +Color outputBackground = black; +Color outputText = lime; +Color projectViewBackground = Color { 30, 40, 50 }; +Color projectViewText = lightGray; +Color codeEditorBG = black; +Color codeEditorFG = ivory; +Color marginColor = Color {24, 24, 24}; +Color selectedMarginColor = Color {64, 64, 64}; +Color lineNumbersColor = Color {160, 160, 160}; +*/ diff --git a/ide/src/dialogs/GlobalSettingsDialog.ec b/ide/src/dialogs/GlobalSettingsDialog.ec index 1644ebc..8efa976 100644 --- a/ide/src/dialogs/GlobalSettingsDialog.ec +++ b/ide/src/dialogs/GlobalSettingsDialog.ec @@ -74,11 +74,19 @@ class GlobalSettingsDialog : Window { if(editorTab.useFreeCaret.checked != ideSettings.useFreeCaret || editorTab.showLineNumbers.checked != ideSettings.showLineNumbers || - editorTab.caretFollowsScrolling.checked != ideSettings.caretFollowsScrolling) + editorTab.caretFollowsScrolling.checked != ideSettings.caretFollowsScrolling || + editorTab.fontPicker.fontSize != ideSettings.codeEditorFontSize || + editorTab.fontPicker.faceName.OnCompare(ideSettings.codeEditorFont) + ) { ideSettings.useFreeCaret = editorTab.useFreeCaret.checked; ideSettings.showLineNumbers = editorTab.showLineNumbers.checked; ideSettings.caretFollowsScrolling = editorTab.caretFollowsScrolling.checked; + ideSettings.codeEditorFont = editorTab.fontPicker.faceName; + ideSettings.codeEditorFontSize = editorTab.fontPicker.fontSize; + + ide.ApplyFont(ideSettings.codeEditorFont, ideSettings.codeEditorFontSize); + editorSettingsChanged = true; } } @@ -226,6 +234,8 @@ class GlobalSettingsDialog : Window virtual void OnGlobalSettingChange(GlobalSettingsChange globalSettingsChange); } +import "FontPicker" + class EditorTab : GlobalSettingsSubTab { background = formColor; @@ -233,19 +243,19 @@ class EditorTab : GlobalSettingsSubTab Button useFreeCaret { - this, text = $"Move code editor caret freely past end of line", position = { 16, 68 }, isCheckbox = true; + this, text = $"Move code editor caret freely past end of line", position = { 16, 58 }, isCheckbox = true; NotifyClicked = NotifyClickedModifiedDocument; }; Button caretFollowsScrolling { - this, text = $"Keep caret visible (move along) when scrolling", position = { 16, 88 }, isCheckbox = true; + this, text = $"Keep caret visible (move along) when scrolling", position = { 16, 78 }, isCheckbox = true; NotifyClicked = NotifyClickedModifiedDocument; }; Button showLineNumbers { - this, text = $"Show line numbers in code editor", position = { 16, 108 }, isCheckbox = true; + this, text = $"Show line numbers in code editor", position = { 16, 98 }, isCheckbox = true; NotifyClicked = NotifyClickedModifiedDocument; }; @@ -254,6 +264,17 @@ class EditorTab : GlobalSettingsSubTab modifiedDocument = true; return true; } + + FontPicker fontPicker + { + this, anchor = { left = 8, right = 8, top = 120, bottom = 8 }; + + bool NotifyChanged() + { + modifiedDocument = true; + return true; + } + }; } static void DrawStipple(Surface surface, Size clientSize) diff --git a/ide/src/ide.ec b/ide/src/ide.ec index 0832c18..d19f88f 100644 --- a/ide/src/ide.ec +++ b/ide/src/ide.ec @@ -444,6 +444,42 @@ class IDEWorkSpace : Window Debugger debugger { }; + void ApplyFont(const String faceName, float size) + { + panelFont.faceName = faceName; + panelFont.size = size; + + codeFont.faceName = faceName; + codeFont.size = size; + + { + CodeEditor ce; + for(ce = (CodeEditor)firstChild; ce; ce = (CodeEditor)ce.next) + if(ce._class == class(CodeEditor)) + { + ce.font = { codeFont.faceName, codeFont.size, codeFont.bold, codeFont.italic }; + ce.editBox.font = ce.font; + ce.OnPostCreate(); + } + } + + threadsView.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + callStackView.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.buildBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.debugBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + outputView.findBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + #ifdef GDB_DEBUG_OUTPUT + outputView.gdbBox.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + #endif +#ifdef GDB_DEBUG_GUI + if(gdbDialog) + { + gdbDialog.tree.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + gdbDialog.output.font = { panelFont.faceName, panelFont.size, panelFont.bold, panelFont.italic }; + } +#endif + } + ProjectView projectView; OutputView outputView @@ -3689,6 +3725,8 @@ class IDEApp : GuiApplication } } + ide.ApplyFont(ideSettings.codeEditorFont, ideSettings.codeEditorFontSize); + ideConfig.compilers.read(settingsContainer); ideConfig.recentFiles.read(settingsContainer); ideConfig.recentWorkspaces.read(settingsContainer); -- 1.8.3.1