ide/Global Settings: Initial font selector (Windows support)
authorJerome St-Louis <jerome@ecere.com>
Thu, 4 Aug 2016 09:39:17 +0000 (05:39 -0400)
committerJerome St-Louis <jerome@ecere.com>
Thu, 4 Aug 2016 09:39:17 +0000 (05:39 -0400)
ecere/src/gfx/fontManagement.ec
ide/Makefile
ide/ide.epj
ide/src/IDESettings.ec
ide/src/dialogs/FontPicker.ec [new file with mode: 0644]
ide/src/dialogs/GlobalSettingsDialog.ec
ide/src/ide.ec

index b69d8f0..3673df2 100644 (file)
@@ -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<FaceInfo> 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<FaceInfo> 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<String, FontInfo> fonts = (Map<String, FontInfo>)lParam;
+      MapIterator<String, FontInfo> 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<String, FontInfo> ListAvailableFonts()
+{
+   Map<String, FontInfo> 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;
index 7377d01..b00cfde 100644 (file)
@@ -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
 
index cd859e7..423a44c 100644 (file)
                   "NewProjectDialog.ec",
                   "NodeProperties.ec",
                   "WorkspaceSettings.ec",
-                  "ProjectTabSettings.ec"
+                  "ProjectTabSettings.ec",
+                  "FontPicker.ec"
                ]
             },
             {
index 4b1a783..c6aa844 100644 (file)
@@ -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 (file)
index 0000000..edbcf37
--- /dev/null
@@ -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<float> 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<const String> 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<FontResource> 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<String, FontInfo> 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};
+*/
index 1644ebc..8efa976 100644 (file)
@@ -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)
index 0832c18..d19f88f 100644 (file)
@@ -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);