├── docs ├── images │ ├── run.png │ ├── compile.png │ ├── runPy.png │ ├── EadgythIcon.png │ ├── opensettings.png │ ├── ExampleProject.png │ ├── GrayBackground.png │ ├── opensettingsPy.png │ ├── SimpleEditorView.png │ ├── projectsettings.png │ ├── projectsettingsPy.png │ ├── DarkBlueBackground.png │ └── DarkGrayBackground.png ├── _config.yml ├── help │ └── styles.css └── index.md ├── src └── eg │ ├── syntax │ ├── PHPHighlighter.java │ ├── PerlHighlighter.java │ ├── CSharpHighlighter.java │ ├── XMLHighlighter.java │ ├── HTMLHighlighter.java │ ├── HeredocSearch.java │ ├── RHighlighter.java │ ├── QuoteOperatorSearch.java │ ├── PythonHighlighter.java │ ├── JavascriptHighlighter.java │ ├── SyntaxHighlighter.java │ ├── Highlighter.java │ ├── JavaHighlighter.java │ ├── StringMap.java │ ├── SyntaxConstants.java │ └── CSSHighlighter.java │ ├── ui │ ├── icons │ │ ├── EadIcons │ │ │ ├── large │ │ │ │ ├── run.png │ │ │ │ ├── compile.png │ │ │ │ ├── enterCMD.png │ │ │ │ ├── runCons.png │ │ │ │ ├── changeProj.png │ │ │ │ └── EadgythIcon.png │ │ │ └── small │ │ │ │ ├── run.png │ │ │ │ ├── compile.png │ │ │ │ ├── enterCMD.png │ │ │ │ ├── runCons.png │ │ │ │ ├── changeProj.png │ │ │ │ └── EadgythIcon.png │ │ └── Tango │ │ │ ├── large │ │ │ ├── edit-cut.png │ │ │ ├── edit-clear.png │ │ │ ├── edit-copy.png │ │ │ ├── edit-paste.png │ │ │ ├── edit-redo.png │ │ │ ├── edit-undo.png │ │ │ ├── dialog-error.png │ │ │ ├── document-open.png │ │ │ ├── document-save.png │ │ │ ├── process-stop.png │ │ │ ├── view-refresh.png │ │ │ ├── dialog-warning.png │ │ │ ├── document-close.png │ │ │ ├── dialog-information.png │ │ │ ├── format-indent-less.png │ │ │ └── format-indent-more.png │ │ │ └── small │ │ │ ├── edit-cut.png │ │ │ ├── edit-clear.png │ │ │ ├── edit-copy.png │ │ │ ├── edit-paste.png │ │ │ ├── edit-redo.png │ │ │ ├── edit-undo.png │ │ │ ├── folder-new.png │ │ │ ├── dialog-error.png │ │ │ ├── document-open.png │ │ │ ├── document-save.png │ │ │ ├── process-stop.png │ │ │ ├── view-refresh.png │ │ │ ├── dialog-warning.png │ │ │ ├── document-close.png │ │ │ ├── dialog-information.png │ │ │ ├── format-indent-less.png │ │ │ └── format-indent-more.png │ ├── tabpane │ │ ├── TabClosing.java │ │ ├── ExtTabbedPaneUI.java │ │ └── ExtTabbedPane.java │ ├── IconBuilder.java │ ├── menu │ │ ├── HelpMenu.java │ │ ├── FormatMenu.java │ │ ├── LanguageMenu.java │ │ ├── MenuBar.java │ │ ├── FileMenu.java │ │ └── ViewMenu.java │ ├── EditToolPanel.java │ ├── ConsolePanel.java │ ├── filetree │ │ ├── PopupMenu.java │ │ └── TreePanel.java │ ├── IconFiles.java │ ├── InfoWin.java │ ├── StatusBar.java │ ├── ToolBar.java │ └── FontSettingWin.java │ ├── FileOpener.java │ ├── LanguageChanger.java │ ├── document │ ├── TextChange.java │ ├── EditingStateReadable.java │ ├── styledtext │ │ ├── PrintableText.java │ │ ├── StyledText.java │ │ ├── Attributes.java │ │ └── EditableText.java │ ├── LineNumbers.java │ └── CurrentLanguage.java │ ├── FunctionalAction.java │ ├── edittools │ ├── EditTools.java │ └── AddableEditTool.java │ ├── projects │ ├── ProjectTypes.java │ ├── ProjectCommands.java │ ├── ProjectSelector.java │ ├── GenericProject.java │ ├── HtmlProject.java │ ├── RProject.java │ ├── PythonProject.java │ ├── PerlProject.java │ └── Configurable.java │ ├── Languages.java │ ├── BusyFunction.java │ ├── utils │ ├── SystemParams.java │ ├── FileUtils.java │ ├── LinesFinder.java │ ├── Dialogs.java │ └── ScreenParams.java │ ├── javatools │ ├── FilesFinder.java │ ├── Libraries.java │ └── LibModules.java │ ├── Eadgyth.java │ ├── ViewSetter.java │ ├── TaskRunner.java │ └── FileChooser.java ├── .gitattributes ├── LICENSE └── README.md /docs/images/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/run.png -------------------------------------------------------------------------------- /docs/images/compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/compile.png -------------------------------------------------------------------------------- /docs/images/runPy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/runPy.png -------------------------------------------------------------------------------- /docs/images/EadgythIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/EadgythIcon.png -------------------------------------------------------------------------------- /docs/images/opensettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/opensettings.png -------------------------------------------------------------------------------- /docs/images/ExampleProject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/ExampleProject.png -------------------------------------------------------------------------------- /docs/images/GrayBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/GrayBackground.png -------------------------------------------------------------------------------- /docs/images/opensettingsPy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/opensettingsPy.png -------------------------------------------------------------------------------- /docs/images/SimpleEditorView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/SimpleEditorView.png -------------------------------------------------------------------------------- /docs/images/projectsettings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/projectsettings.png -------------------------------------------------------------------------------- /docs/images/projectsettingsPy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/projectsettingsPy.png -------------------------------------------------------------------------------- /src/eg/syntax/PHPHighlighter.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/syntax/PHPHighlighter.java -------------------------------------------------------------------------------- /docs/images/DarkBlueBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/DarkBlueBackground.png -------------------------------------------------------------------------------- /docs/images/DarkGrayBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/docs/images/DarkGrayBackground.png -------------------------------------------------------------------------------- /src/eg/syntax/PerlHighlighter.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/syntax/PerlHighlighter.java -------------------------------------------------------------------------------- /src/eg/syntax/CSharpHighlighter.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/syntax/CSharpHighlighter.java -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/run.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/run.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-cut.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-cut.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/compile.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/enterCMD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/enterCMD.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/runCons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/runCons.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/compile.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/enterCMD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/enterCMD.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/runCons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/runCons.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-clear.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-copy.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-paste.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-redo.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/edit-undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/edit-undo.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-clear.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-copy.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-paste.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-redo.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/edit-undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/edit-undo.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/folder-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/folder-new.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/changeProj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/changeProj.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/changeProj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/changeProj.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/dialog-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/dialog-error.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/document-open.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/document-save.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/process-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/process-stop.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/view-refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/view-refresh.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/dialog-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/dialog-error.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/document-open.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/document-save.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/process-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/process-stop.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/view-refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/view-refresh.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/large/EadgythIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/large/EadgythIcon.png -------------------------------------------------------------------------------- /src/eg/ui/icons/EadIcons/small/EadgythIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/EadIcons/small/EadgythIcon.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/dialog-warning.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/document-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/document-close.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/dialog-warning.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/document-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/document-close.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/dialog-information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/dialog-information.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/format-indent-less.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/format-indent-less.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/large/format-indent-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/large/format-indent-more.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/dialog-information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/dialog-information.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/format-indent-less.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/format-indent-less.png -------------------------------------------------------------------------------- /src/eg/ui/icons/Tango/small/format-indent-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eadgyth/Programming-Editor/HEAD/src/eg/ui/icons/Tango/small/format-indent-more.png -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - jekyll-seo-tag 3 | theme: jekyll-theme-slate 4 | title: Eadgyth Programming Editor 5 | description: A text editor and basic code editor written in Java. Write and run code in Java, C#, Perl, Python, R or HTML 6 | -------------------------------------------------------------------------------- /src/eg/FileOpener.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * The interface to open a file 7 | */ 8 | @FunctionalInterface 9 | public interface FileOpener { 10 | 11 | /** 12 | * Opens a file 13 | * 14 | * @param f the file 15 | */ 16 | public void open(File f); 17 | } 18 | -------------------------------------------------------------------------------- /src/eg/LanguageChanger.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | /** 4 | * The interface to change the language 5 | */ 6 | @FunctionalInterface 7 | public interface LanguageChanger { 8 | 9 | /** 10 | * Changes the language 11 | * 12 | * @param lang a language in {@link Languages} 13 | */ 14 | public void change(Languages lang); 15 | } 16 | -------------------------------------------------------------------------------- /src/eg/document/TextChange.java: -------------------------------------------------------------------------------- 1 | package eg.document; 2 | 3 | /** 4 | * The interface for controlling the updating done in 5 | * EditorUpdating for possibly multiline text changes 6 | */ 7 | @FunctionalInterface 8 | public interface TextChange { 9 | 10 | /** 11 | * Makes a text change 12 | */ 13 | public void edit(); 14 | } 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /src/eg/ui/tabpane/TabClosing.java: -------------------------------------------------------------------------------- 1 | package eg.ui.tabpane; 2 | 3 | /** 4 | * The interface to close a tab at a given index. The 5 | * implementation checks if closing is possible and calls 6 | * JTabbedPane.removeTabAt(int) as needed 7 | */ 8 | @FunctionalInterface 9 | public interface TabClosing { 10 | 11 | /** 12 | * Closes a tab at the specified index if closing is 13 | * possible 14 | * 15 | * @param index the index 16 | */ 17 | public void close(int index); 18 | } 19 | -------------------------------------------------------------------------------- /src/eg/ui/IconBuilder.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import javax.swing.ImageIcon; 4 | import java.net.URL; 5 | 6 | /** 7 | * The creation of an icon 8 | */ 9 | public class IconBuilder { 10 | 11 | /** 12 | * Creates an ImageIcon 13 | * 14 | * @param path the path of the file that contains the icon 15 | * @return ImageIcon 16 | */ 17 | public ImageIcon createIcon(String path) { 18 | URL imgURL = getClass().getResource(path); 19 | if (imgURL != null) { 20 | return new ImageIcon(imgURL); 21 | } 22 | else { 23 | throw new IllegalArgumentException( 24 | "No image file was found in the specified path"); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/eg/syntax/XMLHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for xml 7 | */ 8 | public class XMLHighlighter implements Highlighter { 9 | 10 | @Override 11 | public void highlight(SyntaxSearcher s, Attributes attr) { 12 | s.setMarkupSection(); 13 | s.resetAttributes(); 14 | s.markup(false); 15 | } 16 | 17 | @Override 18 | public boolean isValid(String text, int pos, int condition) { 19 | return true; 20 | } 21 | 22 | @Override 23 | public int behindLineCmntMark(String text, int pos) { 24 | return -1; 25 | } 26 | 27 | @Override 28 | public int inBlockCmntMarks(String text, int pos) { 29 | return -1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/eg/FunctionalAction.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.awt.event.ActionListener; 4 | 5 | import java.awt.event.ActionEvent; 6 | import javax.swing.AbstractAction; 7 | import javax.swing.Icon; 8 | 9 | /** 10 | * The action whose actionPerformed method uses 11 | * the ActionListener specified in the constructor 12 | */ 13 | @SuppressWarnings("serial") 14 | public class FunctionalAction extends AbstractAction { 15 | 16 | private final transient ActionListener al; 17 | 18 | /** 19 | * @param name the name for the action, null to ignore 20 | * @param icon the icon for the control, null to ignore 21 | * @param al the ActionListener 22 | */ 23 | public FunctionalAction(String name, Icon icon, ActionListener al) { 24 | super(name, icon); 25 | this.al = al; 26 | } 27 | 28 | @Override 29 | public void actionPerformed(ActionEvent e) { 30 | al.actionPerformed(e); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/eg/edittools/EditTools.java: -------------------------------------------------------------------------------- 1 | package eg.edittools; 2 | 3 | /** 4 | * Constants that identify implementations of AddableEditTool 5 | */ 6 | public enum EditTools { 7 | 8 | FINDER("Find/replace", "Finder"), 9 | EXCHANGE_EDITOR("Notes", "ExchangeEditor"); 10 | 11 | private final String display; 12 | private final String className; 13 | 14 | /** 15 | * Returns the display value associated with this constants 16 | * 17 | * @return the display value 18 | */ 19 | public String display() { 20 | return display; 21 | } 22 | 23 | /** 24 | * Returns, for this constants, the name of the classes that implement 25 | * AddableEditTool 26 | * 27 | * @return the class name 28 | */ 29 | public String className() { 30 | return className; 31 | } 32 | 33 | // 34 | //--private--/ 35 | // 36 | 37 | private EditTools(String display, String className) { 38 | this.display = display; 39 | this.className = className; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Malte Bussiek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/eg/syntax/HTMLHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for HTML (or PHP) 7 | */ 8 | public class HTMLHighlighter implements Highlighter { 9 | 10 | private final JavascriptHighlighter js = new JavascriptHighlighter(); 11 | private final CSSHighlighter css = new CSSHighlighter(); 12 | private final PHPHighlighter php = new PHPHighlighter(); 13 | 14 | @Override 15 | public void highlight(SyntaxSearcher s, Attributes attr) { 16 | s.setMarkupSection(); 17 | s.resetAttributes(); 18 | s.markup(true); 19 | s.innerSections("", true, css); 20 | s.innerSections("", false, php); 21 | s.innerSections("", true, js); 22 | } 23 | 24 | @Override 25 | public boolean isValid(String text, int pos, int condition) { 26 | return true; 27 | } 28 | 29 | @Override 30 | public int behindLineCmntMark(String text, int pos) { 31 | return -1; 32 | } 33 | 34 | @Override 35 | public int inBlockCmntMarks(String text, int pos) { 36 | return -1; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /docs/help/styles.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: sans-serif; 3 | } 4 | p { 5 | font-size: 0.95em; 6 | margin-left: 20px; 7 | margin-right: 50px; 8 | } 9 | h1, h2, h3, h4 { 10 | margin-left: 20px; 11 | } 12 | nav.left { 13 | position: fixed; 14 | float: left; 15 | width: 300px; 16 | margin: 0; 17 | padding: 0.5em; 18 | font-size: 0.95em; 19 | overflow: hidden; 20 | } 21 | a { 22 | text-decoration: none; 23 | } 24 | div.top { 25 | height: 100px; 26 | padding: 1em; 27 | background-color:#55bfec; 28 | } 29 | ol li { 30 | font-size: 0.95em; 31 | margin-top: 0.5em; 32 | margin-right: 50px; 33 | } 34 | ul li { 35 | font-size: 0.95em; 36 | margin-top: 1em; 37 | margin-right: 10px; 38 | } 39 | hr { 40 | height: 5px; 41 | color:#55bfec; 42 | background-color:#55bfec; 43 | border: none; 44 | } 45 | article.right { 46 | margin-left: 300px; 47 | border-left: 1px solid gray; 48 | padding: 1em; 49 | overflow: auto; 50 | } 51 | article ul li { 52 | margin-top: 0.5em; 53 | } 54 | table { 55 | font-size: 0.90em; 56 | margin-left: 20px; 57 | border-collapse: collapse; 58 | } 59 | td, th { 60 | border: 2px solid #55bfec; 61 | padding: 5px; 62 | } 63 | -------------------------------------------------------------------------------- /src/eg/document/EditingStateReadable.java: -------------------------------------------------------------------------------- 1 | package eg.document; 2 | 3 | /** 4 | * The interface to read parameters for the state of the document 5 | * while it is edited 6 | */ 7 | public interface EditingStateReadable { 8 | 9 | /** 10 | * Updates the state which indicates that the document has been 11 | * changed 12 | * 13 | * @param b true if changed; false otherwise 14 | */ 15 | public void updateChangedState(boolean b); 16 | 17 | /** 18 | * Updates the state which indicates if edits can be redone and/or 19 | * undone 20 | * 21 | * @param canUndo true if edits can be undone; false otherwise 22 | * @param canRedo true if edits can be redone; false otherwise 23 | */ 24 | public void updateUndoableState(boolean canUndo, boolean canRedo); 25 | 26 | /** 27 | * Updates the state which indicates if text is selected 28 | * 29 | * @param b true if text is selected; false otherwise 30 | */ 31 | public void updateSelectionState(boolean b); 32 | 33 | /** 34 | * Updates the number of the line and the column where the cursor is 35 | * located 36 | * 37 | * @param line the line number 38 | * @param col the column number 39 | */ 40 | public void updateCursorState(int line, int col); 41 | } 42 | -------------------------------------------------------------------------------- /src/eg/syntax/HeredocSearch.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | /** 4 | * The interface for the search of heredoc elements 5 | */ 6 | public interface HeredocSearch { 7 | 8 | /** 9 | * Returns the position of the next identifier for a heredoc 10 | * 11 | * @param text the text 12 | * @param start the position where the search starts 13 | * @return the position of the identifier; -1 if not found 14 | */ 15 | public int nextHeredoc(String text, int start); 16 | 17 | /** 18 | * Returns the heredoc tag 19 | * 20 | * @param text the text 21 | * @param pos the position of the identifier for the heredoc 22 | * @param lineEnd the position of the end of the line where 23 | * the tag is searcher for 24 | * @return the tag; the empty string if no or an invalid tag is 25 | * found 26 | */ 27 | public String heredocTag(String text, int pos, int lineEnd); 28 | 29 | /** 30 | * Returns if the heredoc end is valid 31 | * 32 | * @param text the text 33 | * @param end the position of the possible terminator tag 34 | * @param tagLength the length of the tag 35 | * @return true if valid; false otherwise 36 | */ 37 | public boolean validHeredocEnd(String text, int end, int tagLength); 38 | } 39 | -------------------------------------------------------------------------------- /src/eg/syntax/RHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for R 7 | */ 8 | public class RHighlighter implements Highlighter { 9 | 10 | private static final String[] KEYWORDS = { 11 | "break", 12 | "else", 13 | "FALSE", "for", "function", 14 | "if", "in", "inf", 15 | "NA", "NA_integer", "NA_real", "Na_complex", "NaN", "Na_character", 16 | "next", "NULL", 17 | "repeat", 18 | "TRUE", 19 | "while" 20 | }; 21 | 22 | private static final String[] LINE_CMNT_MARKS = { 23 | SyntaxConstants.HASH 24 | }; 25 | 26 | @Override 27 | public void highlight(SyntaxSearcher s, Attributes attr) { 28 | s.resetAttributes(); 29 | s.quote(false); 30 | s.lineComments(LINE_CMNT_MARKS); 31 | s.keywords(KEYWORDS, null, attr.redPlain); 32 | s.braces(); 33 | s.brackets(); 34 | } 35 | 36 | @Override 37 | public boolean isValid(String text, int pos, int condition) { 38 | return true; 39 | } 40 | 41 | @Override 42 | public int behindLineCmntMark(String text, int pos) { 43 | return SyntaxUtils.behindMark(text, SyntaxConstants.HASH, pos); 44 | } 45 | 46 | @Override 47 | public int inBlockCmntMarks(String text, int pos) { 48 | return -1; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/eg/syntax/QuoteOperatorSearch.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | /** 4 | * The interface for the search of possibly multiline quoted 5 | * sections that are defined by a preceeding identifier (symbol 6 | * or keyword) and certain delimiters. 7 | */ 8 | public interface QuoteOperatorSearch { 9 | 10 | /** 11 | * Returns the position of the next identifier for a quote 12 | * operator 13 | * 14 | * @param text the text 15 | * @param pos the position where the search starts 16 | * @return the position of the identifier; -1 if not found 17 | */ 18 | public int nextQuoteOperator(String text, int pos); 19 | 20 | /** 21 | * Returns the length of the identifier 22 | * 23 | * @param text the text 24 | * @param pos the position of the identifier 25 | * @return the length; 0 to indicate that the identifier is 26 | * invalid in the given text context 27 | */ 28 | public int quoteIdentifierLength(String text, int pos); 29 | 30 | /** 31 | * Returns the length of the quotation including any possible 32 | * delimiters 33 | * 34 | * @param text the text 35 | * @param pos the position following the identifier 36 | * @return the length; 0 to indicate that no valid quote 37 | * follows the identifier 38 | */ 39 | public int quoteLength(String text, int pos); 40 | } 41 | -------------------------------------------------------------------------------- /src/eg/ui/menu/HelpMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import javax.swing.JMenu; 4 | import javax.swing.JMenuItem; 5 | 6 | import java.awt.Desktop; 7 | 8 | import java.io.IOException; 9 | 10 | import java.net.URI; 11 | import java.net.URISyntaxException; 12 | 13 | /** 14 | * The menu for help actions 15 | */ 16 | public class HelpMenu { 17 | 18 | private final JMenu menu = new JMenu("?"); 19 | private final JMenuItem showHelpItm = new JMenuItem("Open help site"); 20 | private final JMenuItem aboutItm = new JMenuItem("About"); 21 | 22 | public HelpMenu() { 23 | menu.add(showHelpItm); 24 | menu.add(aboutItm); 25 | aboutItm.addActionListener(e -> new eg.ui.InfoWin()); 26 | showHelpItm.addActionListener(e -> showHelpSite()); 27 | } 28 | 29 | /** 30 | * Returns this menu 31 | * 32 | * @return the menu 33 | */ 34 | public JMenu getMenu() { 35 | return menu; 36 | } 37 | 38 | private void showHelpSite() { 39 | openWebSite("https://eadgyth.github.io/Programming-Editor/Help.html"); 40 | } 41 | 42 | private void openWebSite(String url) { 43 | try { 44 | if (Desktop.isDesktopSupported()) { 45 | Desktop.getDesktop().browse(new URI(url)); 46 | } 47 | } 48 | catch (IOException | URISyntaxException e) { 49 | eg.utils.FileUtils.log(e); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/eg/projects/ProjectTypes.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | /** 4 | * Constants for project types 5 | */ 6 | public enum ProjectTypes { 7 | /** 8 | * Constant for a Java project; 9 | * value returned by {@link display()} is Java */ 10 | JAVA("Java"), 11 | /** 12 | * Constant for a C# project 13 | * value returned by {@link display()} is C# */ 14 | CSHARP("C#"), 15 | /** 16 | * Constant for an HTML project; 17 | * value returned by {@link display()} is HTML */ 18 | HTML("HTML"), 19 | /** 20 | * Constant for a Perl project; 21 | * value returned by {@link display()} is Perl */ 22 | PERL("Perl"), 23 | /** 24 | * Constant for a Python project; 25 | * value returned by {@link display()} is Python */ 26 | PYTHON("Python"), 27 | /** 28 | * Constant for an R project; 29 | * value returned by {@link display()} is R */ 30 | R("R"), 31 | /** 32 | * Constant for a generic project; 33 | * value returned by {@link display()} is Custom */ 34 | GENERIC("Custom commands"); 35 | 36 | /** 37 | * Returns the display value associated with a project category 38 | * 39 | * @return the display value 40 | */ 41 | public String display() { 42 | return display; 43 | } 44 | 45 | private final String display; 46 | 47 | private ProjectTypes(String display) { 48 | this.display = display; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/eg/ui/EditToolPanel.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import java.awt.BorderLayout; 4 | import java.awt.Component; 5 | 6 | import javax.swing.JPanel; 7 | 8 | /** 9 | * Defines the panel to which a variable Component can 10 | * be added. The component is added in the center of a JPanel with 11 | * a BorderLayout. 12 | */ 13 | public class EditToolPanel { 14 | 15 | private final JPanel content; 16 | 17 | public EditToolPanel() { 18 | content = UIComponents.grayBorderedPanel(); 19 | content.setLayout(new BorderLayout()); 20 | } 21 | 22 | /** 23 | * Gets this JPanel which a Component can be added to 24 | * 25 | * @return the JPanel 26 | */ 27 | public JPanel content() { 28 | return content; 29 | } 30 | 31 | /** 32 | * Adds a component. A previously added component is replaced 33 | * 34 | * @param c the Component 35 | */ 36 | public void addComponent(Component c) { 37 | if (c == null) { 38 | throw new IllegalArgumentException("c is null"); 39 | } 40 | BorderLayout layout = (BorderLayout) content.getLayout(); 41 | Component cPrev = layout.getLayoutComponent(BorderLayout.CENTER); 42 | if (cPrev == c) { 43 | return; 44 | } 45 | if (cPrev != null) { 46 | content.remove(cPrev); 47 | } 48 | content.add(c, BorderLayout.CENTER); 49 | content.revalidate(); 50 | content.repaint(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/eg/projects/ProjectCommands.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | import eg.Projects.ProjectActionsUpdate; 4 | 5 | /** 6 | * The interface that defines the commands to compile, run and build 7 | * a project 8 | */ 9 | public interface ProjectCommands extends Configurable { 10 | 11 | /** 12 | * Enables the controls in the UI that invoke the commands used by 13 | * the project 14 | * 15 | * @param update the ProjectActionsUpdate 16 | */ 17 | public void enable(ProjectActionsUpdate update); 18 | 19 | /** 20 | * Compiles source files 21 | */ 22 | public default void compile() { 23 | throw new UnsupportedOperationException( 24 | "Compiling source files is not supported"); 25 | } 26 | 27 | /** 28 | * Runs the project 29 | */ 30 | public default void run() { 31 | throw new UnsupportedOperationException( 32 | "Running the project is not supported"); 33 | } 34 | 35 | /** 36 | * Runs the project using the specified file 37 | * 38 | * @param filepath the full filepath 39 | */ 40 | public default void run(String filepath) { 41 | throw new UnsupportedOperationException( 42 | "Running the project is not supported"); 43 | } 44 | 45 | /** 46 | * Creates a build of the project. 47 | * It is not defined what a "build" is 48 | */ 49 | public default void build() { 50 | throw new UnsupportedOperationException( 51 | "Creating a build is not supported"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/eg/projects/ProjectSelector.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | import eg.TaskRunner; 4 | 5 | /** 6 | * The selection and creation of a ProjectCommands 7 | * object based on the project type 8 | */ 9 | public class ProjectSelector { 10 | 11 | private final TaskRunner runner; 12 | 13 | /** 14 | * @param runner the reference to TaskRunner 15 | */ 16 | public ProjectSelector(TaskRunner runner) { 17 | this.runner = runner; 18 | } 19 | 20 | /** 21 | * Returns a new ProjectCommands 22 | * 23 | * @param projType the project type 24 | * @return the ProjectCommands 25 | */ 26 | public ProjectCommands createProject(ProjectTypes projType) { 27 | ProjectCommands newProj = null; 28 | switch (projType) { 29 | case CSHARP: 30 | newProj = new CSharpProject(runner); 31 | break; 32 | case JAVA: 33 | newProj = new JavaProject(runner); 34 | break; 35 | case HTML: 36 | newProj = new HtmlProject(); 37 | break; 38 | case PERL: 39 | newProj = new PerlProject(runner); 40 | break; 41 | case PYTHON: 42 | newProj = new PythonProject(runner); 43 | break; 44 | case R: 45 | newProj = new RProject(runner); 46 | break; 47 | case GENERIC: 48 | newProj = new GenericProject(runner); 49 | break; 50 | } 51 | return newProj; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/eg/Languages.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | /** 4 | * Constants for languages 5 | */ 6 | public enum Languages { 7 | 8 | NORMAL_TEXT("Normal text"), 9 | C_SHARP("C#"), 10 | CSS("CSS"), 11 | HTML("HTML"), 12 | JAVA("Java"), 13 | JAVASCRIPT("Javascript"), 14 | PERL("Perl"), 15 | PHP_MIXED("PHP (embedded)"), 16 | PHP_PURE("PHP (pure)"), 17 | PYTHON("Python"), 18 | R("R"), 19 | XML("XML"); 20 | 21 | /** 22 | * Returns the Language constant with the name given 23 | * by the specified String (calling Enum.valueOf(String)) 24 | * or NORMAL_TEXT if the name does not match a Languages 25 | * constant. 26 | * 27 | * @param s the String 28 | * @return the Language or NORMAL_TEXT if no enum 29 | * type with the name in s is present 30 | */ 31 | public static Languages initialLanguage(String s) { 32 | try { 33 | return Languages.valueOf(s); 34 | } 35 | catch (IllegalArgumentException e) { 36 | return Languages.NORMAL_TEXT; 37 | } 38 | catch (NullPointerException e) { 39 | eg.utils.FileUtils.log(e); 40 | return Languages.NORMAL_TEXT; 41 | } 42 | } 43 | 44 | /** 45 | * Returns the display value associated with a language 46 | * constant 47 | * 48 | * @return the display value 49 | */ 50 | public String display() { 51 | return display; 52 | } 53 | 54 | private final String display; 55 | 56 | private Languages(String display) { 57 | this.display = display; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/eg/syntax/PythonHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for Python 7 | */ 8 | public class PythonHighlighter implements Highlighter { 9 | 10 | private static final String[] KEYWORDS = { 11 | "and", "as", "assert", "async", "await", 12 | "break", 13 | "class", "continue", 14 | "def", "del", 15 | "elif", "else", "except", 16 | "False", "finally", "for", "from", 17 | "global", 18 | "if", "import", "in", "is", 19 | "lambda", 20 | "None", "nonlocal", "not", 21 | "or", 22 | "pass", 23 | "raise", "return", 24 | "True", "try", 25 | "while", "with", 26 | "yield" 27 | }; 28 | 29 | private static final String[] LINE_CMNT_MARKS = { 30 | SyntaxConstants.HASH 31 | }; 32 | 33 | @Override 34 | public void highlight(SyntaxSearcher s, Attributes attr) { 35 | s.resetAttributes(); 36 | s.tripleQuoteTextBlocks(true); 37 | s.quote(true); 38 | s.lineComments(LINE_CMNT_MARKS); 39 | s.keywords(KEYWORDS, null, attr.redPlain); 40 | s.brackets(); 41 | s.braces(); 42 | } 43 | 44 | @Override 45 | public boolean isValid(String text, int pos, int condition) { 46 | return true; 47 | } 48 | 49 | @Override 50 | public int behindLineCmntMark(String text, int pos) { 51 | return SyntaxUtils.behindMark(text, SyntaxConstants.HASH, pos); 52 | } 53 | 54 | @Override 55 | public int inBlockCmntMarks(String text, int pos) { 56 | return -1; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/eg/projects/GenericProject.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | //--Eadgyth--/ 4 | import eg.TaskRunner; 5 | import eg.Projects.ProjectActionsUpdate; 6 | 7 | /** 8 | * Represents a project to define custom system commands to 9 | * compile, run or build a project 10 | */ 11 | public final class GenericProject extends AbstractProject implements ProjectCommands { 12 | 13 | private final TaskRunner runner; 14 | 15 | /** 16 | * @param runner the TaskRunner 17 | */ 18 | public GenericProject(TaskRunner runner) { 19 | super(ProjectTypes.GENERIC, null, null); 20 | this.runner = runner; 21 | } 22 | 23 | @Override 24 | public void buildSettingsWindow() { 25 | inputOptions.addCustomCommandInput() 26 | .buildWindow(); 27 | } 28 | 29 | @Override 30 | public void enable(ProjectActionsUpdate update) { 31 | if (!customCompileCmd().isEmpty()) { 32 | update.enableCompile(); 33 | } 34 | if (!customRunCmd().isEmpty()) { 35 | update.enableRun(false); 36 | } 37 | if (!customBuildCmd().isEmpty()) { 38 | update.enableBuild(null); 39 | } 40 | } 41 | 42 | @Override 43 | protected void setCommandParameters() { 44 | // not used 45 | } 46 | 47 | @Override 48 | public void compile() { 49 | runner.runSystemCommand(customCompileCmd()); 50 | } 51 | 52 | @Override 53 | public void run() { 54 | runner.runSystemCommand(customRunCmd()); 55 | } 56 | 57 | @Override 58 | public void build() { 59 | runner.runSystemCommand(customBuildCmd()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/eg/BusyFunction.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | import java.awt.Cursor; 6 | import java.awt.EventQueue; 7 | 8 | import java.awt.event.MouseAdapter; 9 | 10 | import javax.swing.JPanel; 11 | import javax.swing.JFrame; 12 | 13 | //--Eadgyth--/ 14 | import eg.utils.FileUtils; 15 | 16 | /** 17 | * The execution of a task during which a wait cursor is displayed 18 | */ 19 | public class BusyFunction { 20 | 21 | private final JPanel glass = new JPanel(new java.awt.GridLayout(1,1)); 22 | 23 | /** 24 | * @param f the top level JFrame 25 | */ 26 | public BusyFunction(JFrame f) { 27 | glass.setOpaque(false); 28 | glass.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 29 | glass.addMouseListener(new MouseAdapter() {}); 30 | f.setGlassPane(glass); 31 | } 32 | 33 | /** 34 | * Executes the specified Runnable at the end of 35 | * pending EDT events and blocks until completion. 36 | * The task is run by java.awt.EventQueue.invokeAndWait method. 37 | * 38 | * @param r the Runnable 39 | */ 40 | public void execute(Runnable r) { 41 | glass.setVisible(true); 42 | new Thread(() -> { 43 | try { 44 | EventQueue.invokeAndWait(r); 45 | } 46 | catch (InterruptedException | InvocationTargetException e) { 47 | FileUtils.log(e); 48 | Thread.currentThread().interrupt(); 49 | } 50 | finally { 51 | EventQueue.invokeLater(() -> glass.setVisible(false)); 52 | } 53 | }).start(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/eg/document/styledtext/PrintableText.java: -------------------------------------------------------------------------------- 1 | package eg.document.styledtext; 2 | 3 | import java.awt.Font; 4 | 5 | import java.awt.print.PrinterException; 6 | 7 | import javax.swing.JTextPane; 8 | 9 | import javax.swing.text.DefaultStyledDocument; 10 | 11 | //--Eadgyth--/ 12 | import eg.BackgroundTheme; 13 | import eg.utils.FileUtils; 14 | import eg.utils.ScreenParams; 15 | 16 | /** 17 | * The printable styled text 18 | */ 19 | public class PrintableText extends StyledText { 20 | 21 | private static final BackgroundTheme THEME = BackgroundTheme.whiteTheme(); 22 | private static final Attributes ATTR = new Attributes(THEME); 23 | 24 | private final JTextPane printArea; 25 | private final String text; 26 | 27 | /** 28 | * @param text the text to style and to print 29 | * @param font the font 30 | */ 31 | public PrintableText(String text, Font font) { 32 | super(new DefaultStyledDocument(), THEME.normalText()); 33 | this.text = text; 34 | printArea = new JTextPane(doc); 35 | int size = ScreenParams.invertedScaledSize(font.getSize()); 36 | Font printFont = font.deriveFont((float) size); 37 | printArea.setFont(printFont); 38 | printArea.setText(text); 39 | } 40 | 41 | @Override 42 | public final Attributes attributes() { 43 | return ATTR; 44 | } 45 | 46 | @Override 47 | public final String text() { 48 | return text; 49 | } 50 | 51 | /** 52 | * Prints this styled text 53 | */ 54 | public final void print() { 55 | try { 56 | printArea.print(); 57 | } 58 | catch(PrinterException e) { 59 | FileUtils.log(e); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/eg/projects/HtmlProject.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | import java.awt.Desktop; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | 8 | //--Eadgyth--/ 9 | import eg.utils.FileUtils; 10 | import eg.utils.Dialogs; 11 | import eg.Projects.ProjectActionsUpdate; 12 | 13 | /** 14 | * Represents a coding project in HTML 15 | */ 16 | public final class HtmlProject extends AbstractProject implements ProjectCommands { 17 | 18 | public HtmlProject() { 19 | super(ProjectTypes.HTML, null, null); 20 | } 21 | 22 | @Override 23 | public void buildSettingsWindow() { 24 | inputOptions.buildWindow(); 25 | } 26 | 27 | @Override 28 | public void enable(ProjectActionsUpdate update) { 29 | update.enableRun(true); 30 | } 31 | 32 | /** 33 | * Shows the HTML file that is specified by the filepath in the 34 | * default file browser 35 | * 36 | * @param filepath the filepath 37 | */ 38 | @Override 39 | public void run(String filepath) { 40 | File htmlFile = new File(filepath); 41 | if (!filepath.endsWith(".html") && !filepath.endsWith(".htm")) { 42 | Dialogs.warnMessage("No HTML file is open or in the selected tab."); 43 | return; 44 | } 45 | try { 46 | if (Desktop.isDesktopSupported()) { 47 | Desktop.getDesktop().open(htmlFile); 48 | } 49 | } 50 | catch (IOException | IllegalArgumentException 51 | | UnsupportedOperationException e) { 52 | 53 | FileUtils.log(e); 54 | } 55 | } 56 | 57 | /** 58 | * Not implemented 59 | */ 60 | @Override 61 | protected void setCommandParameters() { 62 | // not used 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/eg/projects/RProject.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | //--Eadgyth--// 4 | import eg.TaskRunner; 5 | import eg.Projects.ProjectActionsUpdate; 6 | 7 | /** 8 | * Represents a programming project in R 9 | */ 10 | public final class RProject extends AbstractProject implements ProjectCommands { 11 | 12 | private final TaskRunner runner; 13 | 14 | private String startCmd = ""; 15 | 16 | /** 17 | * @param runner the reference to TaskRunner 18 | */ 19 | public RProject(TaskRunner runner) { 20 | super(ProjectTypes.R, "R", null); 21 | this.runner = runner; 22 | } 23 | 24 | @Override 25 | public void buildSettingsWindow() { 26 | inputOptions.addSourceDirInput(SRC_DIR_LABEL) 27 | .addFileInput(R_SCRIPT_LABEL, true) 28 | .addCmdOptionsInput() 29 | .addCmdArgsInput() 30 | .buildWindow(); 31 | } 32 | 33 | @Override 34 | public void enable(ProjectActionsUpdate update) { 35 | update.enableRun(true); 36 | } 37 | 38 | @Override 39 | public void run() { 40 | if (!locateSourceFile()) { 41 | return; 42 | } 43 | runner.runSystemCommand(startCmd); 44 | } 45 | 46 | @Override 47 | protected void setCommandParameters() { 48 | StringBuilder sb = new StringBuilder("Rscript "); 49 | if (!cmdOptions().isEmpty()) { 50 | sb.append(cmdOptions()).append(" "); 51 | } 52 | sb.append(relativeSourceFile()); 53 | if (!cmdArgs().isEmpty()) { 54 | sb.append(" ").append(cmdArgs()); 55 | } 56 | startCmd = sb.toString(); 57 | } 58 | 59 | private static final String R_SCRIPT_LABEL = 60 | "Name of R script file"; 61 | 62 | private static final String SRC_DIR_LABEL = 63 | "Subdirectory containing R script (if present)"; 64 | } 65 | -------------------------------------------------------------------------------- /src/eg/projects/PythonProject.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | //--Eadgyth--/ 4 | import eg.TaskRunner; 5 | import eg.Projects.ProjectActionsUpdate; 6 | 7 | /** 8 | * Represents a programming project in Python 9 | */ 10 | public final class PythonProject extends AbstractProject implements ProjectCommands { 11 | 12 | private final TaskRunner runner; 13 | 14 | private String startCmd = ""; 15 | 16 | /** 17 | * @param runner the reference to TaskRunner 18 | */ 19 | public PythonProject(TaskRunner runner) { 20 | super(ProjectTypes.PYTHON, "py", null); 21 | this.runner = runner; 22 | } 23 | 24 | @Override 25 | public void buildSettingsWindow() { 26 | inputOptions.addSourceDirInput(SRC_DIR_LABEL) 27 | .addFileInput(PY_SCRIPT_LABEL, true) 28 | .addCmdOptionsInput() 29 | .addCmdArgsInput() 30 | .buildWindow(); 31 | } 32 | 33 | @Override 34 | public void enable(ProjectActionsUpdate update) { 35 | update.enableRun(true); 36 | } 37 | 38 | @Override 39 | public void run() { 40 | if (!locateSourceFile()) { 41 | return; 42 | } 43 | runner.runSystemCommand(startCmd); 44 | } 45 | 46 | @Override 47 | protected void setCommandParameters() { 48 | StringBuilder sb = new StringBuilder("python -u "); 49 | if (!cmdOptions().isEmpty()) { 50 | sb.append(cmdOptions()).append(" "); 51 | } 52 | sb.append(relativeSourceFile()); 53 | if (!cmdArgs().isEmpty()) { 54 | sb.append(" ").append(cmdArgs()); 55 | } 56 | startCmd = sb.toString(); 57 | } 58 | 59 | private static final String PY_SCRIPT_LABEL = 60 | "Name of Python script file"; 61 | 62 | private static final String SRC_DIR_LABEL = 63 | "Subdirectory containing Python script (if present)"; 64 | } 65 | -------------------------------------------------------------------------------- /src/eg/edittools/AddableEditTool.java: -------------------------------------------------------------------------------- 1 | package eg.edittools; 2 | 3 | import java.awt.Component; 4 | 5 | //--Eadgyth--/ 6 | import eg.FunctionalAction; 7 | import eg.document.EditableDocument; 8 | 9 | /** 10 | * The interface that defines an "edit tool" whose graphical view can 11 | * be added to the EditToolPanel on the right of the 12 | * splite pane in the main window. The graphical view of the edit tool 13 | * is represented by a Component object. 14 | * 15 | * @see eg.ui.EditToolPanel 16 | */ 17 | public interface AddableEditTool { 18 | 19 | /** 20 | * Sets the action for closing the EditToolPanel 21 | * to this closing button. The specified act contains 22 | * the close icon 23 | * 24 | * @param act the action 25 | */ 26 | public void addClosingAction(FunctionalAction act); 27 | 28 | /** 29 | * Returns the current width of this Component. May define 30 | * an initial width that is used when the component is added the first 31 | * time. 32 | * 33 | * @return the width 34 | */ 35 | public int width(); 36 | 37 | /** 38 | * Returns if the width of this Component is resized when 39 | * the width of main window is resized. 40 | * 41 | * @return true to resize, false to maintain the width 42 | */ 43 | public boolean resize(); 44 | 45 | /** 46 | * Gets this Component 47 | * 48 | * @return the Component 49 | */ 50 | public Component content(); 51 | 52 | /** 53 | * Sets the EditableDocument that is currently viewed in 54 | * the main editor 55 | * 56 | * @param edtDoc the {@link EditableDocument} 57 | */ 58 | public void setDocument(EditableDocument edtDoc); 59 | 60 | /** 61 | * Ends the edit tool. Called when the program is exited 62 | */ 63 | public void end(); 64 | } 65 | -------------------------------------------------------------------------------- /src/eg/ui/menu/FormatMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import java.awt.event.ActionListener; 4 | import java.awt.event.KeyEvent; 5 | 6 | import javax.swing.JMenu; 7 | import javax.swing.JMenuItem; 8 | import javax.swing.JCheckBoxMenuItem; 9 | 10 | /** 11 | * The menu for formatting actions 12 | */ 13 | public class FormatMenu { 14 | 15 | private final JMenu menu = new JMenu("Format"); 16 | private final JMenuItem fontItm = new JMenuItem("Font ..."); 17 | private final JCheckBoxMenuItem wordWrapItm 18 | = new JCheckBoxMenuItem("Wordwrap"); 19 | 20 | public FormatMenu() { 21 | assembleMenu(); 22 | } 23 | 24 | /** 25 | * Gets this menu 26 | * 27 | * @return the menu 28 | */ 29 | public JMenu getMenu() { 30 | return menu; 31 | } 32 | 33 | /** 34 | * Sets the listener for actions to open the font 35 | * settings 36 | * 37 | * @param al the ActionListener 38 | */ 39 | public void setFontAction(ActionListener al) { 40 | fontItm.addActionListener(al); 41 | } 42 | 43 | /** 44 | * Sets the listener for actions to enable or diable wordwrap 45 | * 46 | * @param al the ActionListener 47 | */ 48 | public void setChangeWordWrapAct(ActionListener al) { 49 | wordWrapItm.addActionListener(al); 50 | } 51 | 52 | /** 53 | * Returns if the item for setting wordwrap is selected 54 | * 55 | * @return true if enabled, false otherwise 56 | */ 57 | public boolean isWordWrapItmSelected() { 58 | return wordWrapItm.isSelected(); 59 | } 60 | 61 | /** 62 | * Sets the selection state of the item for enabling/disabling 63 | * wordwrap 64 | * 65 | * @param b true to select, false to unselect 66 | */ 67 | public void selectWordWrapItm(boolean b) { 68 | wordWrapItm.setState(b); 69 | } 70 | 71 | // 72 | //--private--/ 73 | // 74 | 75 | private void assembleMenu() { 76 | menu.add(fontItm); 77 | menu.add(wordWrapItm); 78 | menu.setMnemonic(KeyEvent.VK_O); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/eg/ui/menu/LanguageMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import java.awt.event.ActionEvent; 4 | 5 | import javax.swing.ButtonGroup; 6 | import javax.swing.JMenu; 7 | import javax.swing.JRadioButtonMenuItem; 8 | 9 | //--Eadgyth--/ 10 | import eg.Languages; 11 | import eg.LanguageChanger; 12 | 13 | /** 14 | * The menu for actions to change the language 15 | */ 16 | public class LanguageMenu { 17 | 18 | private final JMenu menu = new JMenu("Language"); 19 | private final ButtonGroup group = new ButtonGroup(); 20 | private final JRadioButtonMenuItem[] itm 21 | = new JRadioButtonMenuItem[Languages.values().length]; 22 | 23 | public LanguageMenu() { 24 | init(); 25 | } 26 | 27 | /** 28 | * Gets this menu 29 | * 30 | * @return the menu 31 | */ 32 | public JMenu menu() { 33 | return menu; 34 | } 35 | 36 | /** 37 | * Sets a LanguageChanger to the elements in the 38 | * array of items for actions to select the language 39 | * 40 | * @param lc the {@link LanguageChanger} 41 | */ 42 | public void setChangeLanguageActions(LanguageChanger lc) { 43 | for (JRadioButtonMenuItem item : itm) { 44 | item.addActionListener(e -> setLanguage(e, lc)); 45 | } 46 | } 47 | 48 | /** 49 | * Selects the item for the specified language 50 | * 51 | * @param lang the language 52 | */ 53 | public void selectLanguageItm(Languages lang) { 54 | for (int i = 0; i < itm.length; i++) { 55 | if (lang == Languages.values()[i]) { 56 | itm[i].setSelected(true); 57 | } 58 | } 59 | } 60 | 61 | // 62 | //--private--/ 63 | // 64 | 65 | private void setLanguage(ActionEvent e, LanguageChanger lc) { 66 | for (int i = 0; i < itm.length; i++) { 67 | if (e.getSource() == itm[i]) { 68 | lc.change(Languages.values()[i]); 69 | } 70 | } 71 | } 72 | 73 | private void init() { 74 | for (int i = 0; i < itm.length; i++) { 75 | itm[i] = new JRadioButtonMenuItem(Languages.values()[i].display()); 76 | group.add(itm[i]); 77 | menu.add(itm[i]); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/eg/document/styledtext/StyledText.java: -------------------------------------------------------------------------------- 1 | package eg.document.styledtext; 2 | 3 | import java.awt.Color; 4 | 5 | import javax.swing.text.SimpleAttributeSet; 6 | import javax.swing.text.StyleConstants; 7 | import javax.swing.text.StyledDocument; 8 | 9 | /** 10 | * The styling of the text in a StyledDocument 11 | */ 12 | public abstract class StyledText { 13 | 14 | /** 15 | * The SimpleAttributeSte for normal text */ 16 | protected final SimpleAttributeSet normal = new SimpleAttributeSet(); 17 | /** 18 | * The StyledDocument that contains the text */ 19 | protected final StyledDocument doc; 20 | 21 | /** 22 | * @param doc the document that contains the text 23 | * @param normalText the color for normal text 24 | */ 25 | protected StyledText(StyledDocument doc, Color normalText) { 26 | this.doc = doc; 27 | StyleConstants.setBold(normal, false); 28 | StyleConstants.setForeground(normal, normalText); 29 | doc.setParagraphAttributes(0, doc.getLength(), normal, false); 30 | } 31 | 32 | /** 33 | * Returns this Attributes 34 | * 35 | * @return the Attributes 36 | */ 37 | public abstract Attributes attributes(); 38 | 39 | /** 40 | * Returns the text 41 | * 42 | * @return the text 43 | */ 44 | public abstract String text(); 45 | 46 | /** 47 | * Resets character attributes to the attributes for normal text 48 | * in a section of text 49 | * 50 | * @param pos the position where the section start 51 | * @param length the length of the section 52 | */ 53 | public void resetAttributes(int pos, int length) { 54 | setAttributes(pos, length, normal); 55 | } 56 | 57 | /** 58 | * Sets character attributes in a section of the text 59 | * 60 | * @param pos the position where the section starts 61 | * @param length the length of the section 62 | * @param set the attributes applied to the section; expected 63 | * to be selected from {@link Attributes} 64 | */ 65 | public void setAttributes(int pos, int length, SimpleAttributeSet set) { 66 | doc.setCharacterAttributes(pos, length, set, false); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/eg/utils/SystemParams.java: -------------------------------------------------------------------------------- 1 | package eg.utils; 2 | 3 | import java.io.File; 4 | import java.awt.Toolkit; 5 | 6 | /** 7 | * Static system properties 8 | */ 9 | public class SystemParams { 10 | /** 11 | * True if the OS is Windows, false otherwise */ 12 | public static final boolean IS_WINDOWS; 13 | /** 14 | * The Java version */ 15 | public static final String JAVA_VERSION; 16 | /** 17 | * True if the Java version is higher than 8, false otherwise */ 18 | public static final boolean IS_JAVA_9_OR_HIGHER; 19 | /** 20 | * True if the Java version is higher than 10, false otherwise */ 21 | public static final boolean IS_JAVA_10_OR_HIGHER; 22 | /** 23 | * True if the Java version is 13 or higher, false otherwise */ 24 | public static final boolean IS_JAVA_13_OR_HIGHER; 25 | /** 26 | * The modifier mask for menu shortcuts */ 27 | public static final int MODIFIER_MASK; 28 | /** 29 | * The path to the '.eadgyth' directory in the user home 30 | * directory */ 31 | public static final String EADGYTH_DATA_DIR; 32 | 33 | static { 34 | String os = System.getProperty("os.name").toLowerCase(); 35 | IS_WINDOWS = os.contains("win"); 36 | String userHome = System.getProperty("user.home"); 37 | EADGYTH_DATA_DIR = userHome + File.separator + ".eadgyth"; 38 | JAVA_VERSION = System.getProperty("java.version"); 39 | IS_JAVA_9_OR_HIGHER = !JAVA_VERSION.startsWith("1.8"); 40 | IS_JAVA_10_OR_HIGHER = IS_JAVA_9_OR_HIGHER 41 | && "10".compareTo(JAVA_VERSION) <= 0; 42 | IS_JAVA_13_OR_HIGHER = IS_JAVA_9_OR_HIGHER 43 | && "13".compareTo(JAVA_VERSION) <= 0; 44 | // 45 | // up to Java 9: 46 | MODIFIER_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); 47 | // 48 | // as of Java 10: 49 | //MODIFIER_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMaskEx(); 50 | } 51 | 52 | /** 53 | * Returns if the Eadgyth data directory '.eadgyth' exists 54 | * in the user home directory 55 | * 56 | * @return true if the directory exists, false otherwise 57 | * @see #EADGYTH_DATA_DIR 58 | */ 59 | public static boolean existsEadgythDataDir() { 60 | return new File(EADGYTH_DATA_DIR).exists(); 61 | } 62 | 63 | // 64 | //--private--/ 65 | // 66 | 67 | private SystemParams() {} 68 | } 69 | -------------------------------------------------------------------------------- /src/eg/projects/PerlProject.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | //--Eadgyth--/ 4 | import eg.TaskRunner; 5 | import eg.Projects.ProjectActionsUpdate; 6 | 7 | /** 8 | * Represents a programming project in Perl 9 | */ 10 | public final class PerlProject extends AbstractProject implements ProjectCommands { 11 | 12 | private final TaskRunner runner; 13 | 14 | private String runCmd = ""; 15 | private String compileCmd = ""; 16 | 17 | /** 18 | * @param runner the reference to TaskRunner 19 | */ 20 | public PerlProject(TaskRunner runner) { 21 | super(ProjectTypes.PERL, "pl", null); 22 | this.runner = runner; 23 | } 24 | 25 | @Override 26 | public void buildSettingsWindow() { 27 | inputOptions.addSourceDirInput(SRC_DIR_LABEL) 28 | .addFileInput(PERL_SCRIPT_LABEL, true) 29 | .addCmdOptionsInput() 30 | .addCmdArgsInput() 31 | .buildWindow(); 32 | } 33 | 34 | @Override 35 | public void enable(ProjectActionsUpdate update) { 36 | update.enableRun(true); 37 | update.enableCompile(); 38 | } 39 | 40 | @Override 41 | public void compile() { 42 | if (!locateSourceFile()) { 43 | return; 44 | } 45 | runner.runSystemCommand(compileCmd); 46 | } 47 | 48 | @Override 49 | public void run() { 50 | if (!locateSourceFile()) { 51 | return; 52 | } 53 | runner.runSystemCommand(runCmd); 54 | } 55 | 56 | @Override 57 | protected void setCommandParameters() { 58 | setRunCmd(); 59 | setCompileCmd(); 60 | } 61 | 62 | // 63 | //--private--/ 64 | // 65 | 66 | private void setRunCmd() { 67 | StringBuilder sb = new StringBuilder("perl "); 68 | if (!cmdOptions().isEmpty()) { 69 | sb.append(cmdOptions()).append(" "); 70 | } 71 | sb.append(relativeSourceFile()); 72 | if (!cmdArgs().isEmpty()) { 73 | sb.append(" ").append(cmdArgs()); 74 | } 75 | runCmd = sb.toString(); 76 | } 77 | 78 | private void setCompileCmd() { 79 | StringBuilder sb = new StringBuilder("perl -c "); 80 | sb.append(relativeSourceFile()); 81 | if (!cmdArgs().isEmpty()) { 82 | sb.append(" ").append(cmdArgs()); 83 | } 84 | compileCmd = sb.toString(); 85 | } 86 | 87 | private static final String PERL_SCRIPT_LABEL = 88 | "Name of Perl script file"; 89 | 90 | private static final String SRC_DIR_LABEL = 91 | "Subdirectory containing Perl script (if present)"; 92 | } 93 | -------------------------------------------------------------------------------- /src/eg/ui/ConsolePanel.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import java.awt.BorderLayout; 4 | 5 | import javax.swing.JButton; 6 | import javax.swing.JToolBar; 7 | import javax.swing.JPanel; 8 | import javax.swing.JTextArea; 9 | import javax.swing.JScrollPane; 10 | 11 | import javax.swing.border.LineBorder; 12 | 13 | 14 | //--Eadgyth--/ 15 | import eg.BackgroundTheme; 16 | import eg.FunctionalAction; 17 | import eg.utils.ScreenParams; 18 | 19 | /** 20 | * Defines the panel which contains the text area that functions as the 21 | * console and a toolbar for actions to run commands. 22 | */ 23 | public class ConsolePanel { 24 | 25 | private final JPanel content = UIComponents.grayBorderedPanel(); 26 | private final JButton closeBt = new JButton(); 27 | 28 | private final BackgroundTheme theme; 29 | 30 | /** 31 | * Creates a ConsolePanel 32 | * 33 | * @param theme the BackgroundTheme 34 | */ 35 | public ConsolePanel(BackgroundTheme theme) { 36 | this.theme = theme; 37 | } 38 | 39 | /** 40 | * Initializes the console content 41 | * 42 | * @param area the text area 43 | * @param bts the array of buttons added to the toolbar 44 | * @param tooltips the tooltips 45 | */ 46 | public void initContent(JTextArea area, JButton[] bts, String[] tooltips) { 47 | content.setLayout(new BorderLayout()); 48 | JToolBar toolbar = UIComponents.toolbar(bts, tooltips, closeBt); 49 | content.add(toolbar, BorderLayout.NORTH); 50 | JScrollPane scroll = UIComponents.scrollPane(); 51 | scroll.setViewportView(area); 52 | content.add(scroll, BorderLayout.CENTER); 53 | 54 | area.setFont(ScreenParams.SANSSERIF_PLAIN_8); 55 | area.setBackground(theme.background()); 56 | area.setForeground(theme.normalText()); 57 | area.setSelectionColor(theme.selectionBackground()); 58 | area.setSelectedTextColor(theme.normalText()); 59 | area.setBorder(new LineBorder(theme.background(), 5)); 60 | area.setCaretColor(theme.normalText()); 61 | } 62 | 63 | /** 64 | * Gets this JPanel which contains the text area and the toolbar 65 | * 66 | * @return the JPanel 67 | */ 68 | public JPanel content() { 69 | return content; 70 | } 71 | 72 | /** 73 | * Sets the action for closing the console panel to this 74 | * closing button 75 | * 76 | * @param act the action 77 | */ 78 | public void setClosingAct(FunctionalAction act) { 79 | closeBt.setAction(act); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/eg/syntax/JavascriptHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for Javascript 7 | */ 8 | public class JavascriptHighlighter implements Highlighter { 9 | 10 | private static final String[] LINE_CMNT_MARKS = { 11 | SyntaxConstants.HTML_BLOCK_CMNT_START, SyntaxConstants.HTML_BLOCK_CMNT_END, 12 | SyntaxConstants.DOUBLE_SLASH 13 | }; 14 | 15 | // incomplete 16 | private static final String[] JS_KEYWORDS = { 17 | "abstract", 18 | "boolean", "break", "byte", 19 | "case", "catch", "char", "class", "const", "continue", 20 | "debugger", "default", "delete", "do", "double", 21 | "else", "enum", "export", "extends", 22 | "false", "final", "finally", "float", "for", "function", 23 | "goto", 24 | "if", "implements", "import", "in", "instanceof", "int", "interface", 25 | "let", "long", 26 | "native", "new", "null", 27 | "package", "private", "protected", "public", 28 | "return", 29 | "short", "static", "super", "switch", "synchronized", 30 | "this", "throw", "throws", "transient", "true", "try", "typeof", 31 | "var", "void", "volatile", 32 | "while", "with" 33 | }; 34 | 35 | @Override 36 | public void highlight(SyntaxSearcher s, Attributes attr) { 37 | s.resetAttributes(); 38 | s.quote(true); 39 | s.lineComments(LINE_CMNT_MARKS); 40 | s.keywords(JS_KEYWORDS, null, attr.redPlain); 41 | s.brackets(); 42 | s.braces(); 43 | s.blockComments(SyntaxConstants.SLASH_STAR, SyntaxConstants.STAR_SLASH, false); 44 | } 45 | 46 | @Override 47 | public boolean isValid(String text, int pos, int condition) { 48 | return true; 49 | } 50 | 51 | @Override 52 | public int behindLineCmntMark(String text, int pos) { 53 | int res; 54 | int slash = SyntaxUtils.behindMark(text, SyntaxConstants.DOUBLE_SLASH, pos); 55 | int htmlStartMark = SyntaxUtils.behindMark(text, 56 | SyntaxConstants.HTML_BLOCK_CMNT_START, pos); 57 | 58 | res = htmlStartMark > slash ? htmlStartMark : slash; 59 | int htmlEndMark = SyntaxUtils.behindMark(text, 60 | SyntaxConstants.HTML_BLOCK_CMNT_END, pos); 61 | 62 | res = htmlEndMark > res ? htmlEndMark : res; 63 | return res; 64 | } 65 | 66 | @Override 67 | public int inBlockCmntMarks(String text, int pos) { 68 | return SyntaxUtils.inBlock(text, SyntaxConstants.SLASH_STAR, 69 | SyntaxConstants.STAR_SLASH, pos); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/eg/document/LineNumbers.java: -------------------------------------------------------------------------------- 1 | package eg.document; 2 | 3 | import java.awt.Color; 4 | 5 | import javax.swing.JTextPane; 6 | 7 | import javax.swing.text.BadLocationException; 8 | import javax.swing.text.SimpleAttributeSet; 9 | import javax.swing.text.StyledDocument; 10 | import javax.swing.text.StyleConstants; 11 | 12 | //--Eadgyth--// 13 | import eg.utils.FileUtils; 14 | import eg.utils.LinesFinder; 15 | 16 | /** 17 | * The line numbering 18 | */ 19 | public class LineNumbers { 20 | 21 | private static final Color GRAY = new Color(170, 170, 170); 22 | private static final SimpleAttributeSet SET = new SimpleAttributeSet(); 23 | 24 | private final StyledDocument doc; 25 | private final StringBuilder lineNrBuilder = new StringBuilder(); 26 | 27 | private int nOld = 1; 28 | 29 | static { 30 | StyleConstants.setForeground(SET, GRAY); 31 | StyleConstants.setAlignment(SET, StyleConstants.ALIGN_RIGHT); 32 | } 33 | 34 | /** 35 | * @param lineNrArea the JTextPane that displays line 36 | * numbers 37 | */ 38 | public LineNumbers(JTextPane lineNrArea) { 39 | this.doc = lineNrArea.getStyledDocument(); 40 | doc.setParagraphAttributes(0, doc.getLength(), SET, false); 41 | appendLineNumbers(0, nOld); 42 | } 43 | 44 | /** 45 | * Updates the line numbers for the specified text 46 | * 47 | * @param text the text 48 | */ 49 | public void updateLineNumber(String text) { 50 | int nNew = LinesFinder.lineCount(text); 51 | if (nNew > nOld) { 52 | appendLineNumbers(nOld, nNew); 53 | } 54 | else if (nNew < nOld) { 55 | removeLineNumbers(nOld, nNew); 56 | } 57 | nOld = nNew; 58 | } 59 | 60 | // 61 | //--private--/ 62 | // 63 | 64 | private void appendLineNumbers(int prevLineNr, int lineNr) { 65 | lineNrBuilder.setLength(0); 66 | for (int i = prevLineNr + 1; i <= lineNr; i++) { 67 | lineNrBuilder.append(i).append("\n"); 68 | } 69 | try { 70 | doc.insertString(doc.getLength(), lineNrBuilder.toString(), SET); 71 | } 72 | catch (BadLocationException e) { 73 | FileUtils.log(e); 74 | } 75 | } 76 | 77 | private void removeLineNumbers(int prevLineNr, int lineNr) { 78 | int length = 0; 79 | for (int i = prevLineNr; i > lineNr; i--) { 80 | length += ((int) Math.log10(i) + 1) + 1; 81 | } 82 | try { 83 | doc.remove(doc.getLength() - length, length); 84 | } 85 | catch (BadLocationException e) { 86 | FileUtils.log(e); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/eg/ui/menu/MenuBar.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import javax.swing.JMenu; 4 | import javax.swing.JMenuBar; 5 | 6 | //--Eadgyth--/ 7 | import eg.ui.UIComponents; 8 | 9 | /** 10 | * The menu bar that also has the menus 11 | */ 12 | public class MenuBar { 13 | 14 | private final FileMenu fileMenu = new FileMenu(); 15 | private final LanguageMenu languageMenu = new LanguageMenu(); 16 | private final EditMenu editMenu = new EditMenu(languageMenu); 17 | private final FormatMenu formatMenu = new FormatMenu(); 18 | private final ViewMenu viewMenu = new ViewMenu(); 19 | private final ProjectMenu projectMenu = new ProjectMenu(); 20 | private final HelpMenu helpMenu = new HelpMenu(); 21 | private final JMenuBar mb; 22 | 23 | public MenuBar() { 24 | JMenu[] menus = new JMenu[] { 25 | fileMenu().getMenu(), 26 | editMenu().getMenu(), 27 | formatMenu().getMenu(), 28 | viewMenu().getMenu(), 29 | projectMenu().getMenu(), 30 | helpMenu().getMenu() 31 | }; 32 | mb = UIComponents.menuBar(menus); 33 | mb.setBorderPainted(false); 34 | } 35 | 36 | /** 37 | * Gets this menu bar 38 | * 39 | * @return this menu bar 40 | */ 41 | public JMenuBar menuBar() { 42 | return mb; 43 | } 44 | 45 | /** 46 | * Gets this file menu 47 | * 48 | * @return this {@link FileMenu} 49 | */ 50 | public FileMenu fileMenu() { 51 | return fileMenu; 52 | } 53 | 54 | /** 55 | * Gets this edit menu 56 | * 57 | * @return this {@link EditMenu} 58 | */ 59 | public EditMenu editMenu() { 60 | return editMenu; 61 | } 62 | 63 | /** 64 | * Gets this language menu 65 | * 66 | * @return this language menu 67 | */ 68 | public LanguageMenu languageMenu() { 69 | return languageMenu; 70 | } 71 | 72 | /** 73 | * Gets this format menu 74 | * 75 | * @return this {@link FormatMenu} 76 | */ 77 | public FormatMenu formatMenu() { 78 | return formatMenu; 79 | } 80 | 81 | /** 82 | * Gets this view menu 83 | * 84 | * @return this {@link ViewMenu} 85 | */ 86 | public ViewMenu viewMenu() { 87 | return viewMenu; 88 | } 89 | 90 | /** 91 | * Gets this project menu 92 | * 93 | * @return this {@link ProjectMenu} 94 | */ 95 | public ProjectMenu projectMenu() { 96 | return projectMenu; 97 | } 98 | 99 | /** 100 | * Gets this helpMenu 101 | * 102 | * @return this {@link HelpMenu} 103 | */ 104 | public HelpMenu helpMenu() { 105 | return helpMenu; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/eg/document/styledtext/Attributes.java: -------------------------------------------------------------------------------- 1 | package eg.document.styledtext; 2 | 3 | import javax.swing.text.SimpleAttributeSet; 4 | import javax.swing.text.StyleConstants; 5 | 6 | //--Eadgyth--/ 7 | import eg.BackgroundTheme; 8 | 9 | /** 10 | * Holds character attributes with colors depending on 11 | * the background theme. 12 | */ 13 | public final class Attributes { 14 | 15 | /** 16 | * The red colored, plain style which is a more or less 17 | * pink red depending on the background. 18 | */ 19 | public final SimpleAttributeSet redPlain = new SimpleAttributeSet(); 20 | /** 21 | * The blue colored, plain style which can be rather cyan 22 | * depending on the background 23 | */ 24 | public final SimpleAttributeSet bluePlain = new SimpleAttributeSet(); 25 | /** 26 | * The orange colored, plain style 27 | */ 28 | public final SimpleAttributeSet orangePlain = new SimpleAttributeSet(); 29 | /** 30 | * The purple colored, plain style 31 | */ 32 | public final SimpleAttributeSet purplePlain = new SimpleAttributeSet(); 33 | /** 34 | * The purple colored, bold style 35 | */ 36 | public final SimpleAttributeSet purpleBold = new SimpleAttributeSet(); 37 | /** 38 | * The bold style for brackets. The color is dark blue with 39 | * a white background and a yellow tone with a dark 40 | * background. 41 | * {@see eg.BackgroundTheme#accentedNormalText} 42 | */ 43 | public final SimpleAttributeSet bracketsBold = new SimpleAttributeSet(); 44 | /** 45 | * The color for comments 46 | * {@see eg.BackgroundTheme#commentText} 47 | */ 48 | public final SimpleAttributeSet comment = new SimpleAttributeSet(); 49 | 50 | /** 51 | * @param theme the BackgroundTheme 52 | */ 53 | public Attributes(BackgroundTheme theme) { 54 | 55 | StyleConstants.setForeground(redPlain, theme.redText()); 56 | StyleConstants.setBold(redPlain, false); 57 | 58 | StyleConstants.setForeground(bluePlain, theme.blueText()); 59 | StyleConstants.setBold(bluePlain, false); 60 | 61 | StyleConstants.setForeground(orangePlain, theme.orangeText()); 62 | StyleConstants.setBold(orangePlain, false); 63 | 64 | StyleConstants.setForeground(purplePlain, theme.purpleText()); 65 | StyleConstants.setBold(purplePlain, false); 66 | 67 | StyleConstants.setForeground(purpleBold, theme.purpleText()); 68 | StyleConstants.setBold(purpleBold, true); 69 | 70 | StyleConstants.setForeground(comment, theme.commentText()); 71 | StyleConstants.setBold(comment, false); 72 | 73 | StyleConstants.setForeground(bracketsBold, theme.accentedNormalText()); 74 | StyleConstants.setBold(bracketsBold, true); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/eg/ui/filetree/PopupMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.filetree; 2 | 3 | import java.awt.event.*; 4 | import java.awt.Component; 5 | 6 | import javax.swing.JPopupMenu; 7 | import javax.swing.JMenuItem; 8 | 9 | /** 10 | * A popup menu with menu items for actions that can be selected 11 | * after a file node or a folder node was right clicked.
12 | * 13 | * Created in {@link FileTree} 14 | */ 15 | public class PopupMenu { 16 | 17 | /** 18 | * The constant for indicating that items for file operations are shown */ 19 | public static final int FILE_OPT = 0; 20 | /** 21 | * The constant for indicating that items for folder operations are shown */ 22 | public static final int FOLDER_OPT = 1; 23 | 24 | private final JPopupMenu popMenu = new JPopupMenu(); 25 | private final JMenuItem openItm = new JMenuItem("Open"); 26 | private final JMenuItem deleteItm = new JMenuItem("Delete"); 27 | private final JMenuItem newFolderItm = new JMenuItem("Create new folder"); 28 | 29 | /** 30 | * @param option one of PopupMenu.FILE_OPT and 31 | * popupMenu.FOLDER_OPT 32 | */ 33 | public PopupMenu(int option) { 34 | if (option == FILE_OPT) { 35 | popMenu.add(openItm); 36 | popMenu.add(deleteItm); 37 | } 38 | else { 39 | popMenu.add(newFolderItm); 40 | popMenu.add(deleteItm); 41 | } 42 | } 43 | 44 | /** 45 | * Sets the boolean that specifies if the item for deleting 46 | * actions is enabled (true) or disabled 47 | * 48 | * @param b the boolean value 49 | */ 50 | public void enableDelete(boolean b) { 51 | deleteItm.setEnabled(b); 52 | } 53 | 54 | /** 55 | * Shows the menu at the specified component 56 | * 57 | * @param c the Component 58 | * @param x the x coordinate 59 | * @param y the y coordiante 60 | */ 61 | public void showMenu(Component c, int x, int y) { 62 | popMenu.show(c, x, y); 63 | } 64 | 65 | /** 66 | * Sets the listener for actions to open a file 67 | * 68 | * @param al the ActionListener 69 | */ 70 | public void setOpenAction(ActionListener al) { 71 | openItm.addActionListener(al); 72 | } 73 | 74 | /** 75 | * Sets the listener for deleting actions 76 | * 77 | * @param al the ActionListener 78 | */ 79 | public void setDeleteAct(ActionListener al) { 80 | deleteItm.addActionListener(al); 81 | } 82 | 83 | /** 84 | * Sets the listener for actions to create a new folder 85 | * 86 | * @param al the ActionListener 87 | */ 88 | public void setNewFolderAct(ActionListener al) { 89 | newFolderItm.addActionListener(al); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/eg/javatools/FilesFinder.java: -------------------------------------------------------------------------------- 1 | package eg.javatools; 2 | 3 | import java.util.Arrays; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import java.io.File; 8 | import java.io.FilenameFilter; 9 | 10 | import eg.Prefs; 11 | 12 | /** 13 | * The list of files in a directory and its sub-directories with a given 14 | * file extension 15 | */ 16 | public class FilesFinder { 17 | 18 | private List resultList; 19 | 20 | /** 21 | * Returns a List of all files with the specified 22 | * extension in the specified directory and its sub-directories. 23 | * The file 'ProjectConfig.properties' is alsways excluded. 24 | * 25 | * @param dir the directory 26 | * @param extension the file extension which starts with a period. 27 | * @param excludedDir the directory that is excluded from the search. 28 | * Ignored if equal to dir 29 | * @param excludedFileName the name of a file to be excluded 30 | * @return the List of the files 31 | */ 32 | public List filteredFiles(String dir, String extension, 33 | String excludedDir, String excludedFileName) { 34 | 35 | if (!extension.startsWith(".")) { 36 | throw new IllegalArgumentException( 37 | extension 38 | + " must be specified" 39 | + " with preceding peroid"); 40 | } 41 | File fDir = new File(dir); 42 | if (!fDir.exists() || !fDir.isDirectory()) { 43 | throw new IllegalArgumentException( 44 | dir + " is not a directory"); 45 | } 46 | File fExcl = new File(excludedDir); 47 | String excl = fExcl.getPath().equals(fDir.getPath()) ? "" : fExcl.getPath(); 48 | resultList = new ArrayList<>(); 49 | setFilteredFiles(fDir, extension, excl, excludedFileName); 50 | return resultList; 51 | } 52 | 53 | // 54 | //--private--// 55 | // 56 | 57 | private void setFilteredFiles(File f, String extension, String exclDir, 58 | String exclFileName) { 59 | 60 | FilenameFilter filter = (File dir, String name) 61 | -> name.endsWith(extension) 62 | && !name.equals(exclFileName) 63 | && !name.equals(Prefs.PROJ_CONFIG_FILE); 64 | 65 | File[] list = f.listFiles(); 66 | File[] targets = f.listFiles(filter); 67 | if (list == null || targets == null) { 68 | throw new IllegalArgumentException( 69 | f + " is not a directory"); 70 | } 71 | resultList.addAll(Arrays.asList(targets)); 72 | for (File fInList : list) { 73 | if (fInList.isDirectory() 74 | && (exclDir.isEmpty() || !fInList.getPath().equals(exclDir))) { 75 | 76 | setFilteredFiles(fInList, extension, exclDir, exclFileName); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/eg/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package eg.utils; 2 | 3 | import java.io.File; 4 | import java.io.PrintWriter; 5 | import java.io.IOException; 6 | 7 | import java.util.Date; 8 | 9 | import java.text.SimpleDateFormat; 10 | 11 | /** 12 | * Static methods for file operations 13 | */ 14 | public class FileUtils { 15 | 16 | /** 17 | * Adds the specified extension to the specified string if it does 18 | * not end with this extension already 19 | * 20 | * @param file the string that represents a file 21 | * @param ext the extension 22 | * @return the string with the extension 23 | */ 24 | public static String addExtension(String file, String ext) { 25 | if (file.endsWith(ext)) { 26 | return file; 27 | } 28 | else { 29 | return file + ext; 30 | } 31 | } 32 | 33 | /** 34 | * Returns if a file is writeable and shows a message dialog if not 35 | * 36 | * @param f the file 37 | * @return true if writeable 38 | */ 39 | public static boolean isWriteable(File f) { 40 | File sameName = new File(f.toString()); 41 | boolean isWriteable = !f.exists() || f.renameTo(sameName); 42 | if (!isWriteable) { 43 | Dialogs.errorMessage( 44 | f.getName() 45 | + " cannot be accessed." 46 | + " It may be used by another process.", 47 | null); 48 | } 49 | return isWriteable; 50 | } 51 | 52 | /** 53 | * Writes to the file 'log.txt' in the '.eadgyth' folder the date, 54 | * message and stack trace of an exception. However, a new message 55 | * replaces an older one. 56 | * 57 | * @param e the Exception 58 | */ 59 | public static void log(Exception e) { 60 | File f = new File(SystemParams.EADGYTH_DATA_DIR + "/log.txt"); 61 | String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date()); 62 | String msg = ""; 63 | if (e.getMessage() != null) { 64 | msg = e.getMessage(); 65 | } 66 | else if (msg.isEmpty() && e.getCause() != null) { 67 | msg = e.getCause().toString(); 68 | } 69 | else { 70 | msg = "A problem occured"; 71 | } 72 | try (PrintWriter writer = new PrintWriter(f)) { 73 | writer.println(date); 74 | writer.println("_________________"); 75 | e.printStackTrace(writer); 76 | Dialogs.errorMessage( 77 | "Error: " 78 | + msg 79 | + "\nSee " 80 | + f.toString(), 81 | null); 82 | } 83 | catch (IOException fne) { 84 | Dialogs.errorMessage( 85 | "Error: " 86 | + msg // the message that could not be logged 87 | + "\nNOTE: Could not write to log file", 88 | null); 89 | } 90 | } 91 | 92 | // 93 | //--private--/ 94 | // 95 | 96 | private FileUtils() {} 97 | } 98 | -------------------------------------------------------------------------------- /src/eg/syntax/SyntaxHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | //--Eadgyth--/ 4 | import eg.utils.LinesFinder; 5 | import eg.document.styledtext.StyledText; 6 | import eg.document.styledtext.Attributes; 7 | 8 | /** 9 | * The syntax highlighting 10 | */ 11 | public class SyntaxHighlighter { 12 | 13 | private final SyntaxSearcher searcher; 14 | 15 | private final StyledText txt; 16 | private final Attributes attr; 17 | private Highlighter hl; 18 | 19 | /** 20 | * @param txt the StyledText 21 | */ 22 | public SyntaxHighlighter(StyledText txt) { 23 | this.txt = txt; 24 | attr = txt.attributes(); 25 | searcher = new SyntaxSearcher(txt); 26 | } 27 | 28 | /** 29 | * Sets a Highlighter. 30 | * 31 | * @param hl the Highlighter; null means that this 32 | * SyntaxHighligher is not used (is not checked) 33 | */ 34 | public void setHighlighter(Highlighter hl) { 35 | searcher.setHighlighter(hl); 36 | this.hl = hl; 37 | } 38 | 39 | /** 40 | * Highlights text elements in the entire text 41 | */ 42 | public void highlight() { 43 | searcher.setTextParams(txt.text(), 0, 0); 44 | hl.highlight(searcher, attr); 45 | } 46 | 47 | /** 48 | * Highlights text elements in a section around the position where 49 | * a change happened. The section to upate is initially the line 50 | * that contains the chgPos or two lines if 51 | * isNewline is true. 52 | * 53 | * @param chgPos the position where a change happened 54 | * @param isNewline if the change is a newline character 55 | */ 56 | public void highlight(int chgPos, boolean isNewline) { 57 | int lineStart = LinesFinder.lastNewline(txt.text(), chgPos); 58 | String scn; 59 | if (!isNewline) { 60 | scn = LinesFinder.line(txt.text(), lineStart); 61 | } 62 | else { 63 | int lineEnd = LinesFinder.nextNewline(txt.text(), chgPos + 1); 64 | scn = txt.text().substring(lineStart + 1, lineEnd); 65 | } 66 | searcher.setTextParams(scn, chgPos, lineStart + 1); 67 | hl.highlight(searcher, attr); 68 | } 69 | 70 | /** 71 | * Highlights text elements in a section that may be multiline. 72 | * The section to update initially consists of the completed 73 | * lines that contain change and begins with the line 74 | * that contains chgPos. 75 | * 76 | * @param change the change to the text 77 | * @param chgPos the position where the change starts 78 | */ 79 | public void highlight(String change, int chgPos) { 80 | int linesStart = LinesFinder.lastNewline(txt.text(), chgPos); 81 | int length = chgPos - linesStart + change.length(); 82 | String scn = LinesFinder.lines(txt.text(), linesStart, length); 83 | searcher.setTextParams(scn, chgPos, linesStart + 1); 84 | hl.highlight(searcher, attr); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/eg/syntax/Highlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * The interface to highlight text elements. 7 | *

8 | * Highlighting is done by calling selected 'search methods' in 9 | * {@link SyntaxSearcher} from this 10 | * {@link #highlight(SyntaxSearcher, Attributes)} method. 11 | * However, the sequence of method calls matters. An example 12 | * is:

13 | * {@link SyntaxSearcher#resetAttributes()}
14 | * {@link SyntaxSearcher#quote(boolean)}
15 | * {@link SyntaxSearcher#lineComments(String[])}
16 | * {@link SyntaxSearcher#keywords(String[],char[],SimpleAttributeSet)}
17 | * other highlighting of keywords, symbols ...
18 | * {@link SyntaxSearcher#blockComments(String,String,boolean)}
19 | * For special validation of found text elements a 'condition' may be 20 | * set by calling {@link SyntaxSearcher#setCondition(int)} before one 21 | * or more search methods. The validation is implemented in 22 | * {@link #isValid(String, int, int)}. If changed, the 'condition' must be 23 | * explicetely reset to the default (0) before calling methods that don't 24 | * need any additional validation. 25 | *

26 | * Implementations of {@link #behindLineCmntMark(String, int)} and/or 27 | * {@link #inBlockCmntMarks(String, int)} must ignore if comment marks are 28 | * quoted. 29 | * @see SyntaxUtils#behindMark(String,String,int) 30 | * @see SyntaxUtils#inBlock(String,String,String,int) 31 | */ 32 | public interface Highlighter { 33 | 34 | /** 35 | * Defines the syntax highlighting 36 | * 37 | * @param s the SyntaxSearcher 38 | * @param attr the Attributes that may be set on text elements 39 | */ 40 | public void highlight(SyntaxSearcher s, Attributes attr); 41 | 42 | /** 43 | * Returns if a text element found at the specified position is 44 | * valid 45 | * 46 | * @param text the text 47 | * @param pos the position 48 | * @param condition the condition for validating a text element. 49 | * @return true if valid (or no additional validation is 50 | * necessary); false otherwise 51 | */ 52 | public boolean isValid(String text, int pos, int condition); 53 | 54 | /** 55 | * Returns if the specified position is found behind a line 56 | * comment mark in the same line 57 | * 58 | * @param text the text 59 | * @param pos the position 60 | * @return the position of the last line comment mark; -1 if no 61 | * mark is found or if line comment marks can be ignored 62 | */ 63 | public int behindLineCmntMark(String text, int pos); 64 | 65 | /** 66 | * Returns if the specified position is found between the marks 67 | * that define a block comment 68 | * 69 | * @param text the text 70 | * @param pos the position 71 | * @return the position of the last block comment start; -1 if 72 | * not between comment marks or if block comments can be ignored 73 | */ 74 | public int inBlockCmntMarks(String text, int pos); 75 | } 76 | -------------------------------------------------------------------------------- /src/eg/projects/Configurable.java: -------------------------------------------------------------------------------- 1 | package eg.projects; 2 | 3 | /** 4 | * The interface that defines the configuration of a project. 5 | *

6 | * The configuration depends on a class that defines a window 7 | * where the settings for a project are entered. 8 | */ 9 | public interface Configurable { 10 | 11 | /** 12 | * Builds the content of the settings window depending on the 13 | * input options required by a project 14 | */ 15 | public void buildSettingsWindow(); 16 | 17 | /** 18 | * Opens the settings window 19 | * 20 | * @param dir the directory that may be identical to or contained 21 | * in the (presumed) project directory 22 | */ 23 | public void openSettingsWindow(String dir); 24 | 25 | /** 26 | * Sets the Runnable that is called when the entries 27 | * in the settings window are confirmed 28 | * 29 | * @param r the Runnable invoked by the action 30 | */ 31 | public void setConfiguringAction(Runnable r); 32 | 33 | /** 34 | * Tries to configure a project based on the entries in the 35 | * settings window 36 | * 37 | * @return true if the project could be configured; false 38 | * otherwise 39 | */ 40 | public boolean configure(); 41 | 42 | /** 43 | * Tries to retrieve a stored project configuration 44 | * 45 | * @param dir the directory that may be identical to or contained 46 | * in the directory of a stored project 47 | * @return true if a stored project could be retrieved; false 48 | * otherwise 49 | */ 50 | public boolean retrieve(String dir); 51 | 52 | /** 53 | * Returns the type of the project 54 | * 55 | * @return the type of project 56 | */ 57 | public ProjectTypes projectType(); 58 | 59 | /** 60 | * Returns if the project uses a source file (a script file or 61 | * file with a main entry) that is specified in the settings window. 62 | * 63 | * @return true if a set source file is used; false otherwise 64 | */ 65 | public boolean hasSetSourceFile(); 66 | 67 | /** 68 | * Returns if the specified directory is identical to or contained 69 | * in the project directory 70 | * 71 | * @param dir the directory 72 | * @return true if in the project; false otherwise 73 | */ 74 | public boolean isInProject(String dir); 75 | 76 | /** 77 | * Returns the project directory 78 | * 79 | * @return the directory 80 | */ 81 | public String projectDir(); 82 | 83 | /** 84 | * Returns the last name of the project directory 85 | * 86 | * @return the name 87 | */ 88 | public String projectName(); 89 | 90 | /** 91 | * Returns the directory where executable files are saved. 92 | * This directory is deletable in the project explorer if given 93 | * as relative directory that can be created in the project 94 | * directory. 95 | * 96 | * @return the directory which may not yet exist; the empty 97 | * string if none is given 98 | */ 99 | public String executableDir(); 100 | 101 | /** 102 | * Stores configuration parameters 103 | */ 104 | public void storeConfiguration(); 105 | } 106 | -------------------------------------------------------------------------------- /src/eg/syntax/JavaHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | //--Eadgyth--/ 6 | import eg.utils.SystemParams; 7 | 8 | /** 9 | * Syntax highlighting for Java 10 | */ 11 | public class JavaHighlighter implements Highlighter { 12 | 13 | private static final String[] JAVA_KEYWORDS = { 14 | "abstract", "assert", 15 | "break", "boolean", "Boolean", "byte", 16 | "catch", "case","const","continue", "class", "char", 17 | "default", "do", "double", 18 | "else", "enum", "extends", 19 | "false", "finally", "final", "float", "for", 20 | "if", "implements", "import", "instanceof", "int", "interface", 21 | "long", 22 | "native", "new", "null", 23 | "package", "private", "protected", "public", 24 | "return", 25 | "strictfp", "switch", "synchronized", "short", "static", "super", 26 | "String", 27 | "this", "throw", "throws", "transient", "true", "try", 28 | "void", "volatile", 29 | "while" 30 | }; 31 | 32 | private static final String[] JAVA_9_PLUS_KEYWORDS = { 33 | "exports", "module", "requires" 34 | }; 35 | 36 | private static final String[] JAVA_10_PLUS_KEYWORDS = { 37 | "var" 38 | }; 39 | 40 | private static final String[] JAVA_ANNOTATIONS = { 41 | "@Override", "@Deprecated", "@SuppressWarnings", "@SafeVarargs", 42 | "@FunctionalInterface" 43 | }; 44 | 45 | private static final String[] LINE_CMNT_MARK = { 46 | SyntaxConstants.DOUBLE_SLASH 47 | }; 48 | 49 | private static final int IGNORE_COND = 0; 50 | private static final int VALID_TEXT_BLOCK_COND = 1; 51 | 52 | @Override 53 | public void highlight(SyntaxSearcher s, Attributes attr) { 54 | s.resetAttributes(); 55 | if (SystemParams.IS_JAVA_13_OR_HIGHER) { 56 | s.setCondition(VALID_TEXT_BLOCK_COND); 57 | s.tripleQuoteTextBlocks(false); 58 | s.setCondition(IGNORE_COND); 59 | } 60 | s.quote(true); 61 | s.lineComments(LINE_CMNT_MARK); 62 | s.brackets(); 63 | s.braces(); 64 | s.keywords(JAVA_ANNOTATIONS, null, attr.bluePlain); 65 | s.keywords(JAVA_KEYWORDS, null, attr.redPlain); 66 | if (SystemParams.IS_JAVA_9_OR_HIGHER) { 67 | s.keywords(JAVA_9_PLUS_KEYWORDS, null, attr.redPlain); 68 | } 69 | if (SystemParams.IS_JAVA_10_OR_HIGHER) { 70 | s.keywords(JAVA_10_PLUS_KEYWORDS, null, attr.redPlain); 71 | } 72 | s.blockComments(SyntaxConstants.SLASH_STAR, SyntaxConstants.STAR_SLASH, false); 73 | } 74 | 75 | @Override 76 | public boolean isValid(String text, int pos, int condition) { 77 | if (condition == VALID_TEXT_BLOCK_COND && text.length() > pos + 3) { 78 | int nextNonSpace = SyntaxUtils.nextNonSpace(text, pos + 3, true); 79 | return text.charAt(nextNonSpace) == '\n'; 80 | } 81 | return true; 82 | } 83 | 84 | @Override 85 | public int behindLineCmntMark(String text, int pos) { 86 | return SyntaxUtils.behindMark(text, SyntaxConstants.DOUBLE_SLASH, pos); 87 | } 88 | 89 | @Override 90 | public int inBlockCmntMarks(String text, int pos) { 91 | return SyntaxUtils.inBlock(text, SyntaxConstants.SLASH_STAR, 92 | SyntaxConstants.STAR_SLASH, pos); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/eg/ui/IconFiles.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import javax.swing.ImageIcon; 4 | 5 | //--Eadgyth--// 6 | import eg.Prefs; 7 | 8 | /** 9 | * Static ImageIcons 10 | */ 11 | public class IconFiles { 12 | 13 | private static final IconBuilder ICONS = new IconBuilder(); 14 | private static final String ICONS_DIR = "icons/"; 15 | private static final String TANGO_DIR; 16 | private static final String EAD_DIR; 17 | 18 | static { 19 | Prefs prefs = new Prefs(); 20 | if (ViewSettingWin.ICON_SIZES[1].equals(prefs.property(Prefs.ICON_SIZE_KEY))) { 21 | TANGO_DIR = ICONS_DIR + "Tango/large/"; 22 | EAD_DIR = ICONS_DIR + "EadIcons/large/"; 23 | } 24 | else { 25 | TANGO_DIR = ICONS_DIR + "Tango/small/"; 26 | EAD_DIR = ICONS_DIR + "EadIcons/small/"; 27 | } 28 | } 29 | 30 | // Tango icons 31 | public final static ImageIcon OPEN_ICON 32 | = ICONS.createIcon(TANGO_DIR + "document-open.png"); 33 | public final static ImageIcon CLOSE_ICON 34 | = ICONS.createIcon(TANGO_DIR + "document-close.png"); 35 | public final static ImageIcon SAVE_ICON 36 | = ICONS.createIcon(TANGO_DIR + "document-save.png"); 37 | public final static ImageIcon UNDO_ICON 38 | = ICONS.createIcon(TANGO_DIR + "edit-undo.png"); 39 | public final static ImageIcon REDO_ICON 40 | = ICONS.createIcon(TANGO_DIR + "edit-redo.png"); 41 | public final static ImageIcon CUT_ICON 42 | = ICONS.createIcon(TANGO_DIR + "edit-cut.png"); 43 | public final static ImageIcon COPY_ICON 44 | = ICONS.createIcon(TANGO_DIR + "edit-copy.png"); 45 | public final static ImageIcon PASTE_ICON 46 | = ICONS.createIcon(TANGO_DIR + "edit-paste.png"); 47 | public final static ImageIcon INDENT_ICON 48 | = ICONS.createIcon(TANGO_DIR + "format-indent-more.png"); 49 | public final static ImageIcon OUTDENT_ICON 50 | = ICONS.createIcon(TANGO_DIR + "format-indent-less.png"); 51 | public final static ImageIcon STOP_PROCESS_ICON 52 | = ICONS.createIcon(TANGO_DIR + "process-stop.png"); 53 | public final static ImageIcon CLEAR_ICON 54 | = ICONS.createIcon(TANGO_DIR + "edit-clear.png"); 55 | public final static ImageIcon REFRESH_ICON 56 | = ICONS.createIcon(TANGO_DIR + "view-refresh.png"); 57 | public final static ImageIcon INFO_ICON 58 | = ICONS.createIcon(TANGO_DIR + "dialog-information.png"); 59 | public final static ImageIcon ERROR_ICON 60 | = ICONS.createIcon(TANGO_DIR + "dialog-error.png"); 61 | public final static ImageIcon WARNING_ICON 62 | = ICONS.createIcon(TANGO_DIR + "dialog-warning.png"); 63 | // 64 | // Eadgyth icons 65 | public final static ImageIcon CHANGE_PROJ_ICON 66 | = ICONS.createIcon(EAD_DIR + "changeProj.png" ); 67 | public final static ImageIcon RUN_ICON 68 | = ICONS.createIcon(EAD_DIR + "run.png" ); 69 | public final static ImageIcon RUN_CMD_ICON 70 | = ICONS.createIcon(EAD_DIR + "runCons.png" ); 71 | public final static ImageIcon ENTER_CMD_ICON 72 | = ICONS.createIcon(EAD_DIR + "enterCMD.png" ); 73 | public final static ImageIcon COMPILE_ICON 74 | = ICONS.createIcon(EAD_DIR + "compile.png"); 75 | public final static ImageIcon EADGYTH_ICON_16 76 | = ICONS.createIcon(ICONS_DIR + "EadIcons/small/EadgythIcon.png"); 77 | } 78 | -------------------------------------------------------------------------------- /src/eg/Eadgyth.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.io.File; 4 | 5 | import java.util.Locale; 6 | 7 | import java.awt.EventQueue; 8 | 9 | import javax.swing.UIManager; 10 | import javax.swing.UnsupportedLookAndFeelException; 11 | import javax.swing.border.EmptyBorder; 12 | 13 | //--Eadgyth--/ 14 | import eg.ui.MainWin; 15 | import eg.ui.ViewSettingWin; 16 | import eg.utils.FileUtils; 17 | import eg.utils.SystemParams; 18 | import eg.utils.ScreenParams; 19 | 20 | /** 21 | * Contains the main method 22 | * 23 | * @author Malte Bussiek, m.bussiek@web.de 24 | */ 25 | public class Eadgyth { 26 | 27 | public static void main(String[] arg) { 28 | 29 | Locale.setDefault(Locale.US); 30 | uiManagerSettings(); 31 | createEadgythDataDir(); 32 | Prefs prefs = new Prefs(); 33 | String laf = prefs.property(Prefs.LAF_KEY); 34 | setLaf(laf); 35 | 36 | MainWin mw = new MainWin(); 37 | ViewSettingWin viewSetWin = new ViewSettingWin(); 38 | Formatter f = new Formatter(TabbedDocuments.MAX_TABS, ""); 39 | ViewSetter viewSet = new ViewSetter(mw, viewSetWin, f); 40 | TabbedDocuments tabDocs = new TabbedDocuments(mw, f); 41 | 42 | mw.setFileActions(tabDocs); 43 | mw.setViewSettingWinAction(viewSetWin); 44 | mw.setFormatActions(f); 45 | viewSetWin.setOkAct(e -> { 46 | viewSet.applySettings(); 47 | viewSetWin.setVisible(false); 48 | }); 49 | EventQueue.invokeLater(mw::makeVisible); 50 | } 51 | 52 | private static void uiManagerSettings() { 53 | // 54 | // The dpi scaling is disabled when the Java version is 9+ 55 | // because the positioning of the mouse pointer in text 56 | // is not working properly on a high dpi screen (plus some 57 | // other graphics issues, at least under Windows). The 58 | // following 'if' statement may be commented out to verify 59 | // the problem. Then, the methods 'scaledSize' and 60 | // 'invertedScaledSize' in eg.utils.ScreenParams should be 61 | // modified as mentioned in the comments there. 62 | // 63 | if (SystemParams.IS_JAVA_9_OR_HIGHER) { 64 | System.setProperty("sun.java2d.uiScale", "1.0"); 65 | UIManager.put("OptionPane.messageFont", ScreenParams.SANSSERIF_PLAIN_9); 66 | UIManager.put("OptionPane.font", ScreenParams.SANSSERIF_PLAIN_9); 67 | UIManager.put("Button.font", ScreenParams.SANSSERIF_PLAIN_8); 68 | UIManager.put("ComboBox.font", ScreenParams.SANSSERIF_PLAIN_8); 69 | } 70 | UIManager.put("Button.defaultButtonFollowsFocus", Boolean.TRUE); 71 | UIManager.put("Menu.font", ScreenParams.SANSSERIF_PLAIN_9); 72 | UIManager.put("MenuItem.font", ScreenParams.SANSSERIF_PLAIN_9); 73 | UIManager.put("CheckBoxMenuItem.font", ScreenParams.SANSSERIF_PLAIN_9); 74 | UIManager.put("SplitPaneDivider.border", new EmptyBorder(0, 0, 0, 0)); 75 | UIManager.put("Tree.rowHeight", ScreenParams.scaledSize(13)); 76 | } 77 | 78 | private static void setLaf(String laf) { 79 | if (laf.equals("System")) { 80 | try { 81 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 82 | } 83 | catch (ClassNotFoundException 84 | | IllegalAccessException 85 | | InstantiationException 86 | | UnsupportedLookAndFeelException e) { 87 | 88 | FileUtils.log(e); 89 | } 90 | } 91 | } 92 | 93 | private static void createEadgythDataDir() { 94 | File dir = new File(SystemParams.EADGYTH_DATA_DIR); 95 | dir.mkdir(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/eg/ui/tabpane/ExtTabbedPaneUI.java: -------------------------------------------------------------------------------- 1 | package eg.ui.tabpane; 2 | 3 | import javax.swing.JComponent; 4 | 5 | import java.awt.Graphics; 6 | import java.awt.Insets; 7 | import java.awt.Polygon; 8 | import java.awt.Rectangle; 9 | 10 | import javax.swing.plaf.basic.BasicTabbedPaneUI; 11 | 12 | //--Eadgyth--/ 13 | import eg.BackgroundTheme; 14 | 15 | /** 16 | * The UI for the ExtTabbedPane 17 | */ 18 | public class ExtTabbedPaneUI extends BasicTabbedPaneUI { 19 | 20 | private static final Insets ZERO_INSETS = new Insets(0, 0, 0, 0); 21 | 22 | private final BackgroundTheme theme; 23 | private final int tabHeight; 24 | 25 | private boolean isShowTabs = true; 26 | 27 | /** 28 | * Creates an ExtendedTabbedPaneUI 29 | * 30 | * @param theme the BackgroundTheme 31 | * @param tabHeight the height of the tabbar 32 | */ 33 | public ExtTabbedPaneUI(BackgroundTheme theme, int tabHeight) { 34 | this.theme = theme; 35 | this.tabHeight = tabHeight; 36 | } 37 | 38 | /** 39 | * Sets the boolean that indicates if the tabbar is visible 40 | * 41 | * @param b true to show, false to hide the tabbar 42 | */ 43 | public void setShowTabs(boolean b) { 44 | isShowTabs = b; 45 | } 46 | 47 | @Override 48 | public void paint(Graphics g, JComponent c) { 49 | Rectangle bounds = tabPane.getBounds(); 50 | g.setColor(theme.lightBackground()); 51 | g.fillRect(0, 0, bounds.width, bounds.height); 52 | } 53 | 54 | @Override 55 | protected int calculateMaxTabHeight(int tabPlacement) { 56 | if (isShowTabs) { 57 | return tabHeight; 58 | } 59 | else { 60 | return 0; 61 | } 62 | } 63 | 64 | @Override 65 | protected void paintTabBorder(Graphics g, int tabPlacement, 66 | int tabIndex, int x, int y, int w, int h, boolean isSelected) { 67 | 68 | if (!isShowTabs) { 69 | return; 70 | } 71 | int yy = 0; 72 | if (tabIndex == 0 && x != 0) { 73 | w = w + x; 74 | x = 0; 75 | } 76 | g.setColor(theme.lineBorder()); 77 | g.drawLine(x, yy, x, yy + h); 78 | g.drawLine(x + w, yy, x + w, yy + h); 79 | g.drawLine(x, yy , x + w, yy); 80 | } 81 | 82 | @Override 83 | protected void paintTabBackground(Graphics g, int tabPlacement, 84 | int tabIndex, int x, int y, int w, int h, boolean isSelected) { 85 | 86 | if (!isShowTabs) { 87 | return; 88 | } 89 | int yy = 0; 90 | if (tabIndex == 0 && x != 0) { 91 | w = w + x; 92 | x = 0; 93 | } 94 | Polygon shape = new Polygon(); 95 | shape.addPoint(x, yy); 96 | shape.addPoint(x, yy + h); 97 | shape.addPoint(x + w, yy + h); 98 | shape.addPoint(x + w, yy); 99 | if (isSelected) { 100 | g.setColor(theme.background()); 101 | } 102 | else { 103 | g.setColor(theme.lightBackground()); 104 | } 105 | g.fillPolygon(shape); 106 | } 107 | 108 | @Override 109 | protected int getTabLabelShiftY(int tabPlacement, int tabIndex, 110 | boolean isSelected) { 111 | 112 | return 0; 113 | } 114 | 115 | @Override 116 | protected void paintContentBorder(Graphics g, int tabPlacement, 117 | int selectedIndex) { 118 | 119 | // should not paint 120 | } 121 | 122 | @Override 123 | protected Insets getContentBorderInsets(int tabPlacement) { 124 | return ZERO_INSETS; 125 | } 126 | 127 | @Override 128 | protected Insets getTabAreaInsets(int tabPlacement) { 129 | return ZERO_INSETS; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/eg/document/styledtext/EditableText.java: -------------------------------------------------------------------------------- 1 | package eg.document.styledtext; 2 | 3 | import java.awt.FontMetrics; 4 | 5 | import javax.swing.JTextPane; 6 | 7 | import javax.swing.event.DocumentListener; 8 | 9 | import javax.swing.text.BadLocationException; 10 | import javax.swing.text.StyleConstants; 11 | import javax.swing.text.TabSet; 12 | import javax.swing.text.TabStop; 13 | 14 | //--Eadgyth--/ 15 | import eg.BackgroundTheme; 16 | import eg.utils.FileUtils; 17 | 18 | /** 19 | * The editable styled text contained in the StyledDocument 20 | * that is displayed in a JTextPane 21 | */ 22 | public class EditableText extends StyledText { 23 | 24 | private static final BackgroundTheme THEME = BackgroundTheme.givenTheme(); 25 | private static final Attributes ATTR = new Attributes(THEME); 26 | 27 | private final JTextPane textArea; 28 | 29 | private String text = ""; 30 | 31 | /** 32 | * @param textArea the JTextPane that displays the text 33 | */ 34 | public EditableText(JTextPane textArea) { 35 | super(textArea.getStyledDocument(), THEME.normalText()); 36 | this.textArea = textArea; 37 | } 38 | 39 | @Override 40 | public final Attributes attributes() { 41 | return ATTR; 42 | } 43 | 44 | @Override 45 | public final String text() { 46 | return text; 47 | } 48 | 49 | /** 50 | * Updates this copy of the text contained in the document 51 | */ 52 | public final void updateTextCopy() { 53 | try { 54 | text = doc.getText(0, doc.getLength()); 55 | } 56 | catch (BadLocationException e) { 57 | FileUtils.log(e); 58 | } 59 | } 60 | 61 | /** 62 | * Inserts text 63 | * 64 | * @param pos the insert position 65 | * @param s the string that contains the text 66 | */ 67 | public final void insert(int pos, String s) { 68 | try { 69 | doc.insertString(pos, s, null); 70 | } 71 | catch (BadLocationException e) { 72 | FileUtils.log(e); 73 | } 74 | } 75 | 76 | /** 77 | * Removes text 78 | * 79 | * @param pos the start position of the removal 80 | * @param length the length of the removed text 81 | */ 82 | public final void remove(int pos, int length) { 83 | try { 84 | doc.remove(pos, length); 85 | } 86 | catch (BadLocationException e) { 87 | FileUtils.log(e); 88 | } 89 | } 90 | 91 | /** 92 | * Sets the tab length 93 | * 94 | * @param nSpaces the length in number of spaces; not 0 95 | */ 96 | public final void setTabLength(int nSpaces) { 97 | if (nSpaces == 0) { 98 | throw new IllegalArgumentException( 99 | "The number of spaces cannot not be 0"); 100 | } 101 | FontMetrics fm = textArea.getFontMetrics(textArea.getFont()); 102 | int length = fm.charWidth(' ') * nSpaces; 103 | TabStop[] ts = new TabStop[20]; 104 | for (int i = 0; i < ts.length; i++) { 105 | ts[i] = new TabStop((i + 1) * length); 106 | } 107 | TabSet tabSet = new TabSet(ts); 108 | StyleConstants.setTabSet(normal, tabSet); 109 | doc.setParagraphAttributes(0, doc.getLength(), normal, false); 110 | } 111 | 112 | /** 113 | * Adds a DocumentListener 114 | * 115 | * @param dl the DocumentListener 116 | */ 117 | public final void addDocumentListener(DocumentListener dl) { 118 | doc.addDocumentListener(dl); 119 | } 120 | 121 | /** 122 | * Returns the text area that displays the text 123 | * 124 | * @return the text area 125 | */ 126 | public final JTextPane textArea() { 127 | return textArea; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/eg/ui/InfoWin.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import java.awt.FlowLayout; 4 | import java.awt.BorderLayout; 5 | import java.awt.Color; 6 | 7 | import javax.swing.JFrame; 8 | import javax.swing.JLabel; 9 | import javax.swing.JPanel; 10 | import javax.swing.JButton; 11 | import javax.swing.WindowConstants; 12 | 13 | import javax.swing.border.Border; 14 | import javax.swing.border.EmptyBorder; 15 | 16 | import java.awt.Desktop; 17 | 18 | import java.io.IOException; 19 | 20 | import java.net.URI; 21 | import java.net.URISyntaxException; 22 | 23 | //--Eadgyth--/ 24 | import eg.utils.ScreenParams; 25 | 26 | /** 27 | * The window that shows info about Eadgyth Programming Editor 28 | */ 29 | public class InfoWin { 30 | 31 | private static final String INFO 32 | = "" 33 | + "Programming Editor

" 34 | + "Version: 1.2.0
" 35 | + "Author: Malte Bussiek

" 36 | + "Credits and Acknowledgements:" 37 | + "

    " 38 | + "
  • Tango Desktop Project
  • " 39 | + "
  • Dracula color palette
  • " 40 | + "
  • William Gilreath
  • " 41 | + "

" 42 | + ""; 43 | 44 | private static final String LINK 45 | = "https://eadgyth.github.io/Programming-Editor/"; 46 | 47 | private static final Border EMPTY_BORDER = new EmptyBorder(10, 10, 10, 10); 48 | 49 | private final JFrame frame = new JFrame(); 50 | private final JButton okBt = new JButton("OK"); 51 | private final JButton linkBt = new JButton(); 52 | 53 | public InfoWin() { 54 | okBt.setFocusPainted(false); 55 | okBt.addActionListener(e -> frame.setVisible(false)); 56 | JPanel btPnl = new JPanel(new FlowLayout()); 57 | btPnl.add(okBt); 58 | initLinkBt(); 59 | 60 | JPanel content = new JPanel(new BorderLayout()); 61 | content.setBorder(EMPTY_BORDER); 62 | content.add(textPnl(), BorderLayout.CENTER); 63 | content.add(btPnl, BorderLayout.SOUTH); 64 | 65 | frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 66 | frame.setIconImage(IconFiles.EADGYTH_ICON_16.getImage()); 67 | frame.setTitle("About"); 68 | frame.setContentPane(content); 69 | frame.setResizable(false); 70 | frame.setSize(eg.utils.ScreenParams.scaledDimension(250, 240)); 71 | frame.setLocationRelativeTo(null); 72 | frame.setVisible(true); 73 | } 74 | 75 | private JPanel textPnl() { 76 | JPanel pnl = UIComponents.grayBorderedPanel(); 77 | JPanel textPnl = new JPanel(); 78 | JLabel titleLb = new JLabel("Eadgyth"); 79 | titleLb.setFont(ScreenParams.SANSSERIF_BOLD_11); 80 | JLabel infoLb = new JLabel(INFO); 81 | infoLb.setFont(ScreenParams.SANSSERIF_PLAIN_9); 82 | textPnl.setLayout(new BorderLayout()); 83 | textPnl.setBackground(Color.white); 84 | textPnl.add(titleLb, BorderLayout.NORTH); 85 | textPnl.add(infoLb, BorderLayout.CENTER); 86 | textPnl.add(linkBt, BorderLayout.SOUTH); 87 | pnl.add(textPnl); 88 | pnl.setBackground(Color.white); 89 | return pnl; 90 | } 91 | 92 | private void initLinkBt() { 93 | linkBt.setBorder(null); 94 | linkBt.setFocusable(false); 95 | linkBt.setContentAreaFilled(false); 96 | linkBt.setText("" + LINK + ""); 97 | linkBt.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); 98 | linkBt.setFont(ScreenParams.SANSSERIF_PLAIN_9); 99 | linkBt.setForeground(Color.BLUE); 100 | linkBt.addActionListener(e -> openWebSite()); 101 | } 102 | 103 | private void openWebSite() { 104 | try { 105 | if (Desktop.isDesktopSupported()) { 106 | Desktop.getDesktop().browse(new URI(LINK)); 107 | } 108 | } 109 | catch (IOException | URISyntaxException e) { 110 | eg.utils.FileUtils.log(e); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/eg/syntax/StringMap.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import java.util.List; 4 | import java.util.ArrayList; 5 | 6 | /** 7 | * The mapping of strings 8 | */ 9 | public class StringMap { 10 | 11 | private final List starts = new ArrayList<>(); 12 | private final List ends = new ArrayList<>(); 13 | // 14 | // to remember after reset 15 | private final List types = new ArrayList<>(); 16 | private int prevSize = 0; 17 | private int prevNTested = 0; 18 | private int prevNChecked = 0; 19 | 20 | /** 21 | * Clears the string map for a renewed mapping 22 | */ 23 | public void reset() { 24 | if (types.size() > starts.size()) { 25 | for (int i = types.size() - 1; i >= starts.size(); i--) { 26 | types.remove(i); 27 | } 28 | } 29 | starts.clear(); 30 | ends.clear(); 31 | } 32 | 33 | /** 34 | * Adds the start and end positions of a string 35 | * 36 | * @param start the start 37 | * @param end the end 38 | */ 39 | public void add(int start, int end) { 40 | addImpl(start, end); 41 | } 42 | 43 | /** 44 | * Returns if the number of strings or one of the specified 45 | * paramters has changed after the previous reset 46 | * 47 | * @param nTested the nummber of quote marks tested for validity 48 | * as opening quote marks 49 | * @param nChecked the nummber of valid opening quote marks 50 | * (regardless if it equals the actual number of strings) 51 | * @return if a quote number change occurred 52 | */ 53 | public boolean sizeChange(int nTested, int nChecked) { 54 | boolean b = prevNTested != nTested || prevNChecked != nChecked 55 | || starts.size() != prevSize; 56 | 57 | prevNTested = nTested; 58 | prevNChecked = nChecked; 59 | prevSize = starts.size(); 60 | return b; 61 | } 62 | 63 | /** 64 | * Returns if the type of quote mark, i.e. double quote versus 65 | * single quote, has changed at the ith string. 66 | * 67 | * @param type true for (consistently) one type of quote mark, 68 | * false for the other 69 | * @param i the index 70 | * @return true if the mark changed; false otherwise 71 | */ 72 | public boolean quoteMarkChange(int i, boolean type) { 73 | boolean b = markChangeImpl(i, type); 74 | if (i < types.size()) { 75 | types.set(i, type); 76 | } 77 | else if (i == types.size()) { 78 | types.add(type); 79 | } 80 | return b; 81 | } 82 | 83 | /** 84 | * Returns the current number of strings 85 | * 86 | * @return the size 87 | */ 88 | public int size() { 89 | return starts.size(); 90 | } 91 | 92 | /** 93 | * Returns if the specified position is inside a string 94 | * 95 | * @param pos the position 96 | * @return the start position of the string; -1 if not in a 97 | * string 98 | */ 99 | public int inString(int pos) { 100 | if (starts.isEmpty()) { 101 | return -1; 102 | } 103 | int lastStart = -1; 104 | int nextStart = -1; 105 | for (int i : starts) { 106 | if (i > pos) { 107 | nextStart = i; 108 | break; 109 | } 110 | lastStart = i; 111 | } 112 | int nextEnd = -1; 113 | int lastEnd = -1; 114 | for (int i : ends) { 115 | if (i > pos) { 116 | nextEnd = i; 117 | break; 118 | } 119 | lastEnd = i; 120 | } 121 | if ((lastStart != -1 && lastStart > lastEnd) 122 | && (nextEnd != -1 && (nextStart == -1 || nextEnd < nextStart))) { 123 | 124 | return lastStart; 125 | } 126 | else { 127 | return -1; 128 | } 129 | } 130 | 131 | // 132 | //--private--/ 133 | // 134 | 135 | private void addImpl(int start, int end) { 136 | starts.add(start); 137 | ends.add(end); 138 | } 139 | 140 | private boolean markChangeImpl(int i, boolean doubleQuote) { 141 | if (types.isEmpty() || i >= types.size()) { 142 | return false; 143 | } 144 | return types.get(i) != doubleQuote; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/eg/ViewSetter.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.awt.event.WindowAdapter; 4 | import java.awt.event.WindowEvent; 5 | 6 | //--Eadgyth--/ 7 | import eg.ui.MainWin; 8 | import eg.ui.ViewSettingWin; 9 | 10 | /** 11 | * The applying of view settings made in ViewSettingsWin 12 | */ 13 | public class ViewSetter { 14 | 15 | private final MainWin mw; 16 | private final ViewSettingWin vsw; 17 | private final Formatter f; 18 | private final Prefs prefs = new Prefs(); 19 | 20 | private boolean isShowLineNumbers; 21 | private boolean isShowToolbar; 22 | private boolean isShowStatusbar; 23 | private int themeIndex; 24 | private int iconSizeIndex; 25 | private int lafIndex; 26 | 27 | /** 28 | * @param mw the reference to MainWin 29 | * @param vsw the reference to ViewSettingWin 30 | * @param f the reference to Formatter 31 | */ 32 | public ViewSetter(MainWin mw, ViewSettingWin vsw, Formatter f) { 33 | this.mw = mw; 34 | this.vsw = vsw; 35 | this.f = f; 36 | initSettings(); 37 | vsw.setCancelAct(e -> undoSettings()); 38 | vsw.setDefaultCloseAction(defaultClosing); 39 | } 40 | 41 | /** 42 | * Applies the selections made in ViewSettingWin and sets 43 | * the corresponding properties in Prefs 44 | */ 45 | public void applySettings() { 46 | boolean show; 47 | show = vsw.isShowLineNumbers(); 48 | if (show != isShowLineNumbers) { 49 | f.showLineNumbers(show); 50 | isShowLineNumbers = show; 51 | prefs.setYesNoProperty(Prefs.LINE_NR_KEY, isShowLineNumbers); 52 | } 53 | show = vsw.isShowToolbar(); 54 | if (show != isShowToolbar) { 55 | mw.showToolbar(show); 56 | isShowToolbar = show; 57 | prefs.setYesNoProperty(Prefs.TOOLBAR_KEY, isShowToolbar); 58 | } 59 | show = vsw.isShowStatusbar(); 60 | if (show != isShowStatusbar) { 61 | mw.showStatusbar(show); 62 | isShowStatusbar = show; 63 | prefs.setYesNoProperty(Prefs.STATUSBAR_KEY, isShowStatusbar); 64 | } 65 | int index; 66 | index = vsw.themeIndex(); 67 | if (index != themeIndex) { 68 | themeIndex = index; 69 | prefs.setProperty(Prefs.THEME_KEY, 70 | ViewSettingWin.THEME_OPT[themeIndex]); 71 | } 72 | index = vsw.iconSizeIndex(); 73 | if (index != iconSizeIndex) { 74 | iconSizeIndex = index; 75 | prefs.setProperty(Prefs.ICON_SIZE_KEY, 76 | ViewSettingWin.ICON_SIZES[iconSizeIndex]); 77 | } 78 | index = vsw.lafIndex(); 79 | if (index != lafIndex) { 80 | lafIndex = index; 81 | prefs.setProperty("LaF", ViewSettingWin.LAF_OPT[lafIndex]); 82 | } 83 | } 84 | 85 | // 86 | //--private--/ 87 | // 88 | 89 | private void initSettings() { 90 | isShowLineNumbers = prefs.yesNoProperty(Prefs.LINE_NR_KEY); 91 | vsw.setShowLineNumbers(isShowLineNumbers); 92 | f.showLineNumbers(isShowLineNumbers); 93 | 94 | isShowToolbar = prefs.yesNoProperty(Prefs.TOOLBAR_KEY); 95 | vsw.setShowToolbar(isShowToolbar); 96 | mw.showToolbar(isShowToolbar); 97 | 98 | isShowStatusbar = prefs.yesNoProperty(Prefs.STATUSBAR_KEY); 99 | vsw.setShowStatusbar(isShowStatusbar); 100 | mw.showStatusbar(isShowStatusbar); 101 | 102 | vsw.setIconSize(prefs.property(Prefs.ICON_SIZE_KEY)); 103 | iconSizeIndex = vsw.iconSizeIndex(); 104 | 105 | String laf = prefs.property(Prefs.LAF_KEY); 106 | vsw.setLaf(laf); 107 | lafIndex = vsw.lafIndex(); 108 | 109 | String themeKey = prefs.property(Prefs.THEME_KEY); 110 | vsw.setTheme(themeKey); 111 | themeIndex = vsw.themeIndex(); 112 | } 113 | 114 | private void undoSettings() { 115 | vsw.setShowLineNumbers(isShowLineNumbers); 116 | vsw.setShowToolbar(isShowToolbar); 117 | vsw.setShowStatusbar(isShowStatusbar); 118 | vsw.setTheme(themeIndex); 119 | vsw.setIconSize(iconSizeIndex); 120 | vsw.setLaf(lafIndex); 121 | vsw.setVisible(false); 122 | } 123 | 124 | private final WindowAdapter defaultClosing = new WindowAdapter() { 125 | 126 | @Override 127 | public void windowClosing(WindowEvent we) { 128 | undoSettings(); 129 | } 130 | }; 131 | } 132 | -------------------------------------------------------------------------------- /src/eg/javatools/Libraries.java: -------------------------------------------------------------------------------- 1 | package eg.javatools; 2 | 3 | import java.io.File; 4 | 5 | import java.net.MalformedURLException; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | //--Eadgyth--/ 11 | import eg.utils.FileUtils; 12 | 13 | /** 14 | * Stores configured libraries that can be added to the classpath 15 | */ 16 | public class Libraries { 17 | 18 | private static final String F_SEP = File.separator; 19 | 20 | private final List libs = new ArrayList<>(); 21 | private final List libsAbs = new ArrayList<>(); 22 | private final List libsForJar = new ArrayList<>(); 23 | private final StringBuilder notFound = new StringBuilder(); 24 | 25 | private String joined = ""; 26 | private String joinedAbs = ""; 27 | 28 | private String errMsg = ""; 29 | 30 | /** 31 | * Configures the libraries 32 | * 33 | * @param libraries the list of paths of (putative) libraries 34 | * which may be relative to the project directory or absolute 35 | * @param projectDir the project directory 36 | */ 37 | public void configure(List libraries, String projectDir) { 38 | notFound.setLength(0); 39 | libs.clear(); 40 | libsAbs.clear(); 41 | libsForJar.clear(); 42 | if (!libraries.isEmpty()) { 43 | for (String s : libraries) { 44 | File f = new File(s); 45 | if (f.exists() && f.isAbsolute()) { 46 | libsAbs.add(s); 47 | libs.add(s); 48 | addAbsForJar(f); 49 | } 50 | else { 51 | String absInProj = projectDir + F_SEP + s; 52 | f = new File(absInProj); 53 | if (f.exists()) { 54 | libs.add(s); 55 | libsAbs.add(absInProj); 56 | addRelForJar(f, s); 57 | } 58 | else { 59 | notFound.append("\n").append(s); 60 | } 61 | } 62 | } 63 | } 64 | joined = joinedLibs(libs); 65 | joinedAbs = joinedLibs(libsAbs); 66 | errMsg = notFound.length() == 0 ? "" : 67 | "The following libraries cannot be found:" + notFound.toString(); 68 | } 69 | 70 | /** 71 | * Returns the message that indicates invalid entries 72 | * 73 | * @return the message; the empty string if no invalid entries 74 | * are present 75 | */ 76 | public String errorMessage() { 77 | return errMsg; 78 | } 79 | 80 | /** 81 | * Returns a string in which the libraries are joined with the 82 | * system's path separator 83 | * 84 | * @return the joined libraries; the empty string if none are 85 | * given 86 | */ 87 | public String joined() { 88 | return joined; 89 | } 90 | 91 | /** 92 | * Returns a string in which the libraries are joined with the 93 | * system's path separator and relative paths converted to 94 | * absolute paths. 95 | * 96 | * @return the joined libraries; the empty string if none are 97 | * given 98 | */ 99 | public String joinedAbs() { 100 | return joinedAbs; 101 | } 102 | 103 | /** 104 | * Returns the list that contains the libraries formatted for the 105 | * classpath entry in a manifest file. Relative and absolute paths 106 | * remain unchanged 107 | * 108 | * @return the list; the empty list if no libraries are given 109 | */ 110 | public List forJar() { 111 | return libsForJar; 112 | } 113 | 114 | // 115 | //--private--/ 116 | // 117 | 118 | private String joinedLibs(List l) { 119 | if (l.isEmpty()) { 120 | return ""; 121 | } 122 | else { 123 | return String.join(File.pathSeparator, l); 124 | } 125 | } 126 | 127 | private void addRelForJar(File f, String path) { 128 | String s = path.replace(F_SEP, "/"); 129 | if (f.isFile()) { 130 | libsForJar.add(s); 131 | } 132 | else { 133 | if (s.endsWith("/")) { 134 | libsForJar.add(s); 135 | } 136 | else { 137 | libsForJar.add(s + "/"); 138 | } 139 | } 140 | } 141 | 142 | private void addAbsForJar(File f) { 143 | try { 144 | libsForJar.add(f.toURI().toURL().toString()); 145 | } 146 | catch (MalformedURLException e) { 147 | FileUtils.log(e); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/eg/ui/menu/FileMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import java.awt.event.ActionListener; 4 | import java.awt.event.KeyEvent; 5 | 6 | import javax.swing.JMenu; 7 | import javax.swing.JMenuItem; 8 | import javax.swing.KeyStroke; 9 | 10 | //--Eadgyth-- 11 | import eg.TabbedDocuments; 12 | import eg.ui.IconFiles; 13 | import eg.utils.SystemParams; 14 | 15 | /** 16 | * The menu for file actions 17 | */ 18 | public class FileMenu { 19 | 20 | private final JMenu menu = new JMenu("File"); 21 | private final JMenuItem newFileItm = new JMenuItem("New" ); 22 | private final JMenuItem openItm = new JMenuItem("Open ...", 23 | IconFiles.OPEN_ICON); 24 | private final JMenuItem closeItm = new JMenuItem("Close", 25 | IconFiles.CLOSE_ICON); 26 | private final JMenuItem closeAllItm = new JMenuItem("Close all"); 27 | private final JMenuItem saveItm = new JMenuItem("Save", 28 | IconFiles.SAVE_ICON); 29 | private final JMenuItem saveAllItm = new JMenuItem("Save all"); 30 | private final JMenuItem saveAsItm = new JMenuItem("Save as ..."); 31 | private final JMenuItem saveCopyItm = new JMenuItem("Save copy as ..."); 32 | private final JMenuItem renameItm = new JMenuItem("Rename ..."); 33 | private final JMenuItem printItm = new JMenuItem("Print ..."); 34 | private final JMenuItem exitItm = new JMenuItem("Exit"); 35 | 36 | public FileMenu() { 37 | assembleMenu(); 38 | shortCuts(); 39 | } 40 | 41 | /** 42 | * Gets this menu 43 | * 44 | * @return the menu 45 | */ 46 | public JMenu getMenu() { 47 | return menu; 48 | } 49 | 50 | /** 51 | * Sets listeners for file actions defined in TabbedFiles 52 | * except for the action to exit the program 53 | * 54 | * @param td the reference to {@link TabbedDocuments} 55 | */ 56 | public void setActions(TabbedDocuments td) { 57 | newFileItm.addActionListener(e -> td.openBlankDocument()); 58 | openItm.addActionListener(e -> td.open()); 59 | closeItm.addActionListener(e -> td.close()); 60 | closeAllItm.addActionListener(e -> td.closeAll()); 61 | saveItm.addActionListener(e -> td.save()); 62 | saveAllItm.addActionListener(e -> td.saveAll()); 63 | saveAsItm.addActionListener(e -> td.saveAs()); 64 | saveCopyItm.addActionListener(e -> td.saveCopy()); 65 | renameItm.addActionListener(e -> td.rename()); 66 | printItm.addActionListener(e -> td.print()); 67 | } 68 | 69 | /** 70 | * Sets the listener for the action to exit the program 71 | * 72 | * @param al the ActionListener 73 | */ 74 | public void setExitAction(ActionListener al) { 75 | exitItm.addActionListener(al); 76 | } 77 | 78 | /** 79 | * Enables or disables the item for save actions 80 | * 81 | * @param b true to enable, false to disable 82 | */ 83 | public void enableSaveItm(boolean b) { 84 | saveItm.setEnabled(b); 85 | } 86 | 87 | /** 88 | * Enables or disables the item for rename actions 89 | * 90 | * @param b true to enable, false to disable 91 | */ 92 | public void enableRenameItm(boolean b) { 93 | renameItm.setEnabled(b); 94 | } 95 | 96 | // 97 | //--private--/ 98 | // 99 | 100 | private void assembleMenu() { 101 | menu.add(newFileItm); 102 | menu.add(openItm); 103 | menu.add(closeItm); 104 | menu.add(closeAllItm); 105 | menu.addSeparator(); 106 | menu.add(saveItm); 107 | menu.add(saveAllItm); 108 | menu.add(saveAsItm); 109 | menu.add(saveCopyItm); 110 | menu.add(renameItm); 111 | menu.addSeparator(); 112 | menu.add(printItm); 113 | menu.addSeparator(); 114 | menu.add(exitItm); 115 | menu.setMnemonic(KeyEvent.VK_F); 116 | } 117 | 118 | private void shortCuts() { 119 | newFileItm.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 120 | SystemParams.MODIFIER_MASK)); 121 | openItm.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 122 | SystemParams.MODIFIER_MASK)); 123 | saveItm.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, 124 | SystemParams.MODIFIER_MASK)); 125 | printItm.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, 126 | SystemParams.MODIFIER_MASK)); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/eg/ui/filetree/TreePanel.java: -------------------------------------------------------------------------------- 1 | package eg.ui.filetree; 2 | 3 | import java.awt.Color; 4 | import java.awt.Component; 5 | import java.awt.BorderLayout; 6 | 7 | import javax.swing.JPanel; 8 | import javax.swing.JTree; 9 | import javax.swing.JScrollPane; 10 | import javax.swing.JButton; 11 | import javax.swing.JToolBar; 12 | 13 | import javax.swing.border.LineBorder; 14 | 15 | import javax.swing.filechooser.FileSystemView; 16 | 17 | import javax.swing.tree.DefaultMutableTreeNode; 18 | import javax.swing.tree.DefaultTreeCellRenderer; 19 | import javax.swing.tree.TreeSelectionModel; 20 | 21 | import java.io.File; 22 | 23 | //--Eadgyth--/ 24 | import eg.BackgroundTheme; 25 | import eg.FunctionalAction; 26 | import eg.utils.ScreenParams; 27 | import eg.ui.UIComponents; 28 | 29 | /** 30 | * Defines the panel which contains a tool bar and panel for adding 31 | * a JTree 32 | */ 33 | public class TreePanel { 34 | 35 | private final JPanel content; 36 | private final JPanel holdTree = new JPanel(new BorderLayout()); 37 | private final JScrollPane scroll = UIComponents.scrollPane(); 38 | private final JButton closeBt = new JButton(); 39 | private final BackgroundTheme theme; 40 | 41 | /** 42 | * Creates a TreePanel 43 | * 44 | * @param theme the BackgroundTheme 45 | */ 46 | public TreePanel(BackgroundTheme theme) { 47 | this.theme = theme; 48 | content = UIComponents.grayBorderedPanel(); 49 | init(); 50 | } 51 | 52 | /** 53 | * Gets this JPanel which contains the toolbar and the panel for 54 | * adding the tree 55 | * 56 | * @return the JPanel 57 | */ 58 | public JPanel content() { 59 | return content; 60 | } 61 | 62 | /** 63 | * Sets the specified JTree 64 | * 65 | * @param tree the JTree 66 | */ 67 | public void setTree(JTree tree) { 68 | tree.setRootVisible(true); 69 | tree.setCellRenderer(new TreeRenderer()); 70 | tree.setToggleClickCount(0); 71 | tree.getSelectionModel().setSelectionMode( 72 | TreeSelectionModel.SINGLE_TREE_SELECTION); 73 | 74 | tree.setFocusable(false); 75 | tree.setBackground(theme.background()); 76 | holdTree.add(tree); 77 | holdTree.revalidate(); 78 | } 79 | 80 | /** 81 | * Sets the action for closing the this panel to this closing button 82 | * 83 | * @param act the closing action 84 | */ 85 | public void setClosingAct(FunctionalAction act) { 86 | closeBt.setAction(act); 87 | } 88 | 89 | // 90 | //--private--/ 91 | // 92 | 93 | private void init() { 94 | content.setLayout(new BorderLayout()); 95 | content.add(toolbar(), BorderLayout.NORTH); 96 | content.add(scroll, BorderLayout.CENTER); 97 | holdTree.setBackground(theme.background()); 98 | holdTree.setBorder(new LineBorder(theme.background(), 5)); 99 | scroll.setViewportView(holdTree); 100 | } 101 | 102 | private JToolBar toolbar() { 103 | return UIComponents.toolbar(null, null, closeBt); 104 | } 105 | 106 | @SuppressWarnings("serial") 107 | private class TreeRenderer extends DefaultTreeCellRenderer { 108 | 109 | private final transient FileSystemView fsv = FileSystemView.getFileSystemView(); 110 | 111 | @Override 112 | public Color getBackgroundNonSelectionColor() { 113 | return theme.background(); 114 | } 115 | 116 | @Override 117 | public Color getBackgroundSelectionColor() { 118 | return theme.selectionBackground(); 119 | } 120 | 121 | @Override 122 | public Color getBackground() { 123 | return theme.background(); 124 | } 125 | 126 | @Override 127 | public Component getTreeCellRendererComponent(JTree tree, Object value, 128 | boolean sel, boolean expanded, boolean leaf, int row, 129 | boolean hasFocus) { 130 | 131 | super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, 132 | row, hasFocus); 133 | 134 | setForeground(theme.normalText()); 135 | if (value instanceof DefaultMutableTreeNode) { 136 | value = ((DefaultMutableTreeNode) value).getUserObject(); 137 | if (value instanceof File) { 138 | File f = (File) value; 139 | setIcon(fsv.getSystemIcon(f)); 140 | setFont(ScreenParams.scaledFontToPlain(getFont(), 8)); 141 | setText(f.getName()); 142 | } 143 | } 144 | return this; 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/eg/utils/LinesFinder.java: -------------------------------------------------------------------------------- 1 | package eg.utils; 2 | 3 | /** 4 | * Static methods to search for lines and line parameters 5 | */ 6 | public class LinesFinder { 7 | 8 | private static final char NEW_LINE = '\n'; 9 | 10 | /** 11 | * Returns the content of the line that contains the specified 12 | * position 13 | * 14 | * @param text the text 15 | * @param pos the pos 16 | * @return the line 17 | */ 18 | public static String lineAtPos(String text, int pos) { 19 | int lastNewline = LinesFinder.lastNewline(text, pos); 20 | return line(text, lastNewline); 21 | } 22 | 23 | /** 24 | * Returns the content of the line that follows 25 | * lastNewline 26 | * 27 | * @param text the text 28 | * @param lastNewline the position of the last newline 29 | * @return the line 30 | * @see #lastNewline 31 | */ 32 | public static String line(String text, int lastNewline) { 33 | if (text.length() == 0) { 34 | return text; 35 | } 36 | else { 37 | int start = lastNewline + 1; 38 | int lineEnd = LinesFinder.nextNewline(text, start); 39 | return text.substring(start, lineEnd); 40 | } 41 | } 42 | 43 | /** 44 | * Returns the possibly multiline content that follows 45 | * lastNewline 46 | * 47 | * @param text the text 48 | * @param lastNewline the position of the last newline 49 | * @param length the length of the section that is contained in 50 | * the line or lines 51 | * @return the line or lines 52 | * @see #lastNewline 53 | */ 54 | public static String lines(String text, int lastNewline, int length) { 55 | int linesEnd = LinesFinder.nextNewline(text, lastNewline + length); 56 | return text.substring(lastNewline + 1, linesEnd); 57 | } 58 | 59 | /** 60 | * Returns the position of the last newline before the specified 61 | * position even if a newline is found at the position 62 | * 63 | * @param text the text 64 | * @param pos the position 65 | * @return the last newline position, -1 if the line is the first line 66 | */ 67 | public static int lastNewline(String text, int pos) { 68 | int i = text.lastIndexOf(NEW_LINE, pos); 69 | if (i == pos) { 70 | i = text.lastIndexOf(NEW_LINE, pos - 1); 71 | } 72 | return i; 73 | } 74 | 75 | /** 76 | * Returns the position of the next newline behind the specified 77 | * position 78 | * 79 | * @param text the text 80 | * @param pos the position relative to which the next newline 81 | * is searched 82 | * @return the position of the next newline character. The length 83 | * of text if no newline character is found 84 | */ 85 | public static int nextNewline(String text, int pos) { 86 | int i = text.indexOf(NEW_LINE, pos); 87 | if (i == -1) { 88 | i = text.length(); 89 | } 90 | return i; 91 | } 92 | 93 | /** 94 | * Returns the number of the line that contains the specified position 95 | * 96 | * @param text the text 97 | * @param pos the position 98 | * @return the number 99 | */ 100 | public static int lineNrAtPos(String text, int pos) { 101 | int count = 0; 102 | int i = 0; 103 | while (i != -1) { 104 | i = text.indexOf(NEW_LINE, i); 105 | if (i != -1) { 106 | if (i >= pos) { 107 | break; 108 | } 109 | count++; 110 | i++; 111 | } 112 | } 113 | return count + 1; 114 | } 115 | 116 | /** 117 | * Returns the count of lines in the specified text 118 | * 119 | * @param text the text 120 | * @return the line number 121 | */ 122 | public static int lineCount(String text) { 123 | int count = 1; 124 | int i = 0; 125 | while (i != -1) { 126 | i = text.indexOf(NEW_LINE, i); 127 | if (i != -1) { 128 | count++; 129 | i++; 130 | } 131 | } 132 | return count; 133 | } 134 | 135 | /** 136 | * Returns if the specified text contains at least one 137 | * newline character 138 | * 139 | * @param text the text 140 | * @return the boolean value; true if multiline 141 | */ 142 | public static boolean isMultiline(String text) { 143 | return text.length() > 1 && text.indexOf(NEW_LINE) > -1; 144 | } 145 | 146 | // 147 | //--private--/ 148 | // 149 | 150 | private LinesFinder() {} 151 | } 152 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | I (Malte) started to make a text editor when I started to learn Java for myself and wished 2 | that Notepad had a compile and a run button. I knew that really versatile code editors and 3 | IDEs exist but using them seemed very complicated to me. 4 | 5 | Therefore, a goal is that it is as simple as possible to set up the editor to try out code 6 | from within it and provide at the same time some flexibility to use it for real coding 7 | projects. 8 | 9 | The github repository for the program also contains, well ... "releases" (a record of my 10 | attempts to fix bugs and add useful features). Anyway, there an executable jar file of the 11 | program can be found for trying it out (requires JDK 8 or higher). 12 | 13 | See also 14 | README for requirements. 15 | 16 |
17 |

How to set up Eadgyth to run code?

18 | The program is set up for running source code by defining a "project". This is initially 19 | just a working directory which distinguishes "project files" from "non-project files" and 20 | where commands (built-in or custom) are executed. Setting a project only requires that any 21 | file that is found in the intended project directory is open and in the selected tab 22 | if multiple files are open. This file may also be found in a sub-directory path relative 23 | to the project directory and does not have to be the "main" source file. The same is true 24 | for running a project: it is not necessary that the "main" source file is selected (it 25 | does not even have to be open) but it is necessary that any file of the project is open 26 | (and selected). 27 | 28 | The screenshots below give examples for project settings (the settings dialog is somewhat 29 | modified in newer versions, though). 30 | 31 |
32 |

Example for a 'Hello World' program in Python

33 | This is an example for a 'Hello World' program in Python. The script was saved as hello_world.py 34 | in the directory helloworld which is also the intended project root. The project settings are 35 | opened by selecting 'Settings for...' and choosing the category Python: 36 | 37 | 38 | 39 | In the project settings the name of the project directory and the name of the script are 40 | entered: 41 | 42 | 43 | 44 | 45 | Then, after clicking OK, the script is run by selecting 'Save and run' in the toolbar or 46 | in the 'Project' menu. This opens the console panel which shows the output: 47 | 48 | 49 | 50 |
51 |

Example for a Java program

52 | For Java the settings could be as simple as in the example for Python above: Just have a 53 | Java file with a main method in any direcory which is set as the project directory. 54 | However, this example simulates a Java project with a directory structure that includes a 55 | source directory, an output directory and a main class that belongs to a package: The 56 | 'Hello World' program was saved as HelloWorld.java in the directory ..\helloworld\scr\hello 57 | where 'helloworld' is should be the project directory. 'src' is defined as the source root 58 | directory inside the project and 'hello' is a directory that corresponds to the package 59 | which the source file belongs to. The package name is declared at the top of the code. The 60 | project settings are opened by choosing the category Java: 61 | 62 | 63 | 64 | 65 | The name of the project directory, the name of the source directory and the name of the 66 | Java file (could also be qualified: hello.HelloWorld) are entered. Finally, the name for 67 | a distination directory for a compiled class file (next step) is specified. This directory 68 | does not have to exists initially. 69 | 70 | 71 | 72 | 73 |
NOTE: If a main Java source file is part of a package but is not saved in a 74 | subdirectory (path) that corresponds to the package the qualified name (e.g. 75 | my.package.myprogram.java) must be specified to be able to run the program.
76 |
77 | A project may be viewed in the 'Project explorer'. After a try to compile the program the 78 | console shows the error in the code: 79 | 80 | 81 | 82 | 83 | After correcting the code a new compilation generates the class file hello\HelloWorld.class 84 | in the 'bin' directory and the program can be run: 85 | 86 | 87 | 88 |
89 | Please also have a look at the [Help](./Help.md) which is 90 | also accessible from the '?' menu. 91 | -------------------------------------------------------------------------------- /src/eg/document/CurrentLanguage.java: -------------------------------------------------------------------------------- 1 | package eg.document; 2 | 3 | import java.io.File; 4 | 5 | //--Eadgyth--/ 6 | import eg.Languages; 7 | import eg.syntax.*; 8 | 9 | /** 10 | * The language that is used for a document 11 | */ 12 | public class CurrentLanguage { 13 | 14 | private Languages lang = Languages.NORMAL_TEXT; 15 | 16 | /** 17 | * Sets the specified language 18 | * 19 | * @param lang the language 20 | */ 21 | public void setLanguage(Languages lang) { 22 | this.lang = lang; 23 | } 24 | 25 | /** 26 | * Sets the language based on the type of file 27 | * 28 | * @param file the file 29 | */ 30 | public void setLanguage(String file) { 31 | String ext = fileExtension(file); 32 | switch (ext) { 33 | case "java": 34 | lang = Languages.JAVA; 35 | break; 36 | case "html": case "htm": 37 | lang = Languages.HTML; 38 | break; 39 | case "js": 40 | lang = Languages.JAVASCRIPT; 41 | break; 42 | case "css": 43 | lang = Languages.CSS; 44 | break; 45 | case "cs": 46 | lang = Languages.C_SHARP; 47 | break; 48 | case "php": 49 | if (lang == Languages.PHP_PURE) { 50 | break; 51 | } 52 | else { 53 | lang = Languages.PHP_MIXED; 54 | break; 55 | } 56 | case "pl": case "pm": 57 | lang = Languages.PERL; 58 | break; 59 | case "py": 60 | lang = Languages.PYTHON; 61 | break; 62 | case "R": 63 | lang = Languages.R; 64 | break; 65 | case "xml": case "fxml": 66 | lang = Languages.XML; 67 | break; 68 | default: 69 | lang = Languages.NORMAL_TEXT; 70 | } 71 | } 72 | 73 | /** 74 | * Returns this language 75 | * 76 | * @return the language; default is {@link Languages#NORMAL_TEXT} 77 | */ 78 | public Languages lang() { 79 | if (lang == null) { 80 | throw new IllegalStateException("A language is not set"); 81 | } 82 | return lang; 83 | } 84 | 85 | /** 86 | * Creates a Highlighter for this language 87 | * 88 | * @return the Highlighter; null if no Highlighter is 89 | * available for the language 90 | */ 91 | public Highlighter createHighlighter() { 92 | Highlighter hl = null; 93 | switch(lang) { 94 | case CSS: 95 | hl = new CSSHighlighter(); 96 | break; 97 | case C_SHARP: 98 | hl = new CSharpHighlighter(); 99 | break; 100 | case HTML: 101 | hl = new HTMLHighlighter(); 102 | break; 103 | case JAVA: 104 | hl = new JavaHighlighter(); 105 | break; 106 | case JAVASCRIPT: 107 | hl = new JavascriptHighlighter(); 108 | break; 109 | case PERL: 110 | hl = new PerlHighlighter(); 111 | break; 112 | case PHP_MIXED: 113 | hl = new HTMLHighlighter(); 114 | break; 115 | case PHP_PURE: 116 | hl = new PHPHighlighter(); 117 | break; 118 | case PYTHON: 119 | hl = new PythonHighlighter(); 120 | break; 121 | case R: 122 | hl = new RHighlighter(); 123 | break; 124 | case XML: 125 | hl = new XMLHighlighter(); 126 | break; 127 | case NORMAL_TEXT: 128 | } 129 | return hl; 130 | } 131 | 132 | /** 133 | * Returns if curly-bracket indentation is used in this 134 | * language 135 | * 136 | * @return true for curly-bracket mode, false otherwise 137 | */ 138 | public boolean curlyBracketMode() { 139 | boolean b; 140 | switch (lang) { 141 | case JAVA: 142 | case JAVASCRIPT: 143 | case PERL: 144 | case PHP_PURE: 145 | case CSS: 146 | case C_SHARP: 147 | b = true; 148 | break; 149 | default: 150 | b = false; 151 | } 152 | return b; 153 | } 154 | 155 | // 156 | //--private--/ 157 | // 158 | 159 | private String fileExtension(String file) { 160 | int i = file.lastIndexOf('.') + 1; 161 | int j = file.lastIndexOf(File.separator); 162 | if (i > j) { 163 | return file.substring(i); 164 | } 165 | else { 166 | return ""; 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/eg/ui/StatusBar.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.Dimension; 6 | 7 | import javax.swing.Box; 8 | import javax.swing.BoxLayout; 9 | import javax.swing.JLabel; 10 | import javax.swing.JPanel; 11 | 12 | //--Eadgyth---/ 13 | import eg.BackgroundTheme; 14 | import eg.utils.ScreenParams; 15 | 16 | /** 17 | * Defines the status bar 18 | */ 19 | public class StatusBar { 20 | 21 | private final JPanel content = new JPanel(); 22 | private final JLabel projectLb = new JLabel(); 23 | private final JLabel languageLb = new JLabel(); 24 | private final JLabel cursorPosLb = new JLabel(); 25 | private final JLabel wordwrapLb = new JLabel(); 26 | 27 | private final BackgroundTheme theme; 28 | 29 | /** 30 | * Creates a StatusBar 31 | * 32 | * @param theme the BackgroundTheme 33 | */ 34 | public StatusBar(BackgroundTheme theme) { 35 | this.theme = theme; 36 | init(); 37 | setBackground(); 38 | } 39 | 40 | /** 41 | * Gets this JPanel which represents the status bar 42 | * 43 | * @return the JPanel 44 | */ 45 | public JPanel content() { 46 | return content; 47 | } 48 | 49 | /** 50 | * Displays the language 51 | * 52 | * @param lang the language 53 | */ 54 | public void displayLanguage(String lang) { 55 | languageLb.setText("Language: " + lang); 56 | } 57 | 58 | /** 59 | * Displays the cursor position 60 | * 61 | * @param lineNr the line number 62 | * @param colNr the column number 63 | */ 64 | public void displayCursorPosition(int lineNr, int colNr) { 65 | cursorPosLb.setText("Line " + lineNr + " Col " + colNr); 66 | } 67 | 68 | /** 69 | * Displays if wordwrap is switched on 70 | * 71 | * @param b true if wordwrap is switched on, false otherwise 72 | */ 73 | public void displayWordwrapState(boolean b) { 74 | if (b) { 75 | cursorPosLb.setForeground(Color.GRAY); 76 | wordwrapLb.setText("Word-wrap "); 77 | } 78 | else { 79 | if (theme == null) { 80 | cursorPosLb.setForeground(Color.BLACK); 81 | } 82 | else { 83 | cursorPosLb.setForeground(theme.normalText()); 84 | } 85 | wordwrapLb.setText(""); 86 | } 87 | } 88 | 89 | /** 90 | * Displays the project name 91 | * 92 | * @param projName the name 93 | */ 94 | public void displayProjectName(String projName) { 95 | projectLb.setText("Current project: " + projName); 96 | } 97 | 98 | //--private--/ 99 | 100 | private void init() { 101 | int lbHeight = 15; 102 | Dimension width5 = ScreenParams.scaledDimension(5, lbHeight); 103 | Dimension width20 = ScreenParams.scaledDimension(20, lbHeight); 104 | Dimension width100 = ScreenParams.scaledDimension(100, lbHeight); 105 | Dimension width150 = ScreenParams.scaledDimension(150, lbHeight); 106 | Dimension width200 = ScreenParams.scaledDimension(200, lbHeight); 107 | JLabel[] lbArr = { languageLb, projectLb, cursorPosLb, wordwrapLb }; 108 | setLbFont(lbArr); 109 | setLbWidth(languageLb, width100); 110 | setLbWidth(projectLb, width200); 111 | setLbWidth(cursorPosLb, width150); 112 | content.setLayout(new BoxLayout(content, BoxLayout.LINE_AXIS)); 113 | content.setBorder(UIComponents.grayMatteBorder(0, 1, 1, 1)); 114 | content.add(Box.createRigidArea(width5)); 115 | content.add(languageLb); 116 | content.add(Box.createRigidArea(width20)); 117 | content.add(projectLb); 118 | content.add(Box.createRigidArea(width20)); 119 | content.add(wordwrapLb); 120 | content.add(Box.createRigidArea(width5)); 121 | content.add(cursorPosLb); 122 | projectLb.setText("Current project: none"); 123 | } 124 | 125 | private void setBackground() { 126 | if (!theme.isDark()) { 127 | return; 128 | } 129 | content.setBackground(theme.lightBackground()); 130 | projectLb.setForeground(theme.normalText()); 131 | languageLb.setForeground(theme.normalText()); 132 | wordwrapLb.setForeground(theme.normalText()); 133 | } 134 | 135 | private void setLbFont(JLabel[] lb) { 136 | Font f = lb[0].getFont(); 137 | for (JLabel l : lb) { 138 | l.setFont(ScreenParams.scaledFontToPlain(f, 8)); 139 | } 140 | } 141 | 142 | private void setLbWidth(JLabel lb, Dimension dim) { 143 | lb.setPreferredSize(dim); 144 | lb.setMinimumSize(dim); 145 | lb.setMaximumSize(dim); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/eg/ui/menu/ViewMenu.java: -------------------------------------------------------------------------------- 1 | package eg.ui.menu; 2 | 3 | import java.awt.event.KeyEvent; 4 | import java.awt.event.ActionListener; 5 | 6 | import javax.swing.JMenu; 7 | import javax.swing.JMenuItem; 8 | import javax.swing.JCheckBoxMenuItem; 9 | 10 | /** 11 | * The menu for view actions 12 | */ 13 | public class ViewMenu { 14 | 15 | private final JMenu menu = new JMenu("View"); 16 | 17 | private final JCheckBoxMenuItem consoleItm = new JCheckBoxMenuItem("Console"); 18 | private final JCheckBoxMenuItem fileViewItm 19 | = new JCheckBoxMenuItem("Project explorer"); 20 | 21 | private final JCheckBoxMenuItem tabItm 22 | = new JCheckBoxMenuItem("Files in tabs"); 23 | 24 | private final JMenuItem openSettingsItm 25 | = new JMenuItem("Preferences ..."); 26 | 27 | public ViewMenu() { 28 | assembleMenu(); 29 | } 30 | 31 | /** 32 | * Gets this menu 33 | * 34 | * @return the menu 35 | */ 36 | public JMenu getMenu() { 37 | return menu; 38 | } 39 | 40 | /** 41 | * Sets the listener for actions to open or close the console 42 | * panel 43 | * 44 | * @param al the ActionListener 45 | */ 46 | public void setConsoleItmAction(ActionListener al) { 47 | consoleItm.addActionListener(al); 48 | } 49 | 50 | /** 51 | * Sets the listener for actions to open or close the file view 52 | * panel 53 | * 54 | * @param al the ActionListener 55 | */ 56 | public void setFileViewItmAction(ActionListener al) { 57 | fileViewItm.addActionListener(al); 58 | } 59 | 60 | /** 61 | * Sets the listener for actions to show or hide the tab bar 62 | * 63 | * @param al the ActionListener 64 | */ 65 | public void setTabItmAction(ActionListener al) { 66 | tabItm.addActionListener(al); 67 | } 68 | 69 | /** 70 | * Sets the listener for actions to open the view settings dialog 71 | * 72 | * @param al the ActionListener 73 | */ 74 | public void openSettingWinItmAction(ActionListener al) { 75 | openSettingsItm.addActionListener(al); 76 | } 77 | 78 | /** 79 | * Return if the item for actions to open or close the console is 80 | * selected 81 | * 82 | * @return true if selected 83 | */ 84 | public boolean isConsoleItmSelected() { 85 | return consoleItm.isSelected(); 86 | } 87 | 88 | /** 89 | * Returns if the item for actions to open or close the file view 90 | * is selected 91 | * 92 | * @return true if selected 93 | */ 94 | public boolean isFileViewItmSelected() { 95 | return fileViewItm.isSelected(); 96 | } 97 | 98 | /** 99 | * Returns if the item for actions to to show or or hide the tabbar 100 | * is selected 101 | * 102 | * @return true if selected 103 | */ 104 | public boolean isTabItmSelected() { 105 | return tabItm.isSelected(); 106 | } 107 | 108 | /** 109 | * Performs the action to show or hide the console 110 | * 111 | * @param b true to show, false to hide the console 112 | */ 113 | public void doConsoleItmAct(boolean b) { 114 | if (b != consoleItm.isSelected()) { 115 | consoleItm.doClick(); 116 | } 117 | } 118 | 119 | /** 120 | * Performs the action to hide the file view panel 121 | */ 122 | public void doUnselectFileViewAct() { 123 | if (fileViewItm.isSelected()) { 124 | fileViewItm.doClick(); 125 | } 126 | } 127 | 128 | /** 129 | * Selects or unselects the item for actions to show or hide the tabbar 130 | * 131 | * @param b true to select, false to unselect 132 | */ 133 | public void selectTabsItm(boolean b) { 134 | tabItm.setSelected(b); 135 | } 136 | 137 | /** 138 | * Selects or unselects the item for actions to show or hide the 139 | * file tree 140 | * 141 | * @param b true to select, false to unselect 142 | */ 143 | public void selectFileViewItm(boolean b) { 144 | fileViewItm.setSelected(b); 145 | } 146 | 147 | /** 148 | * Enables or disables the item for actions to show or hide the tabbar 149 | * 150 | * @param b true to enable, false to disable 151 | */ 152 | public void enableTabItm(boolean b) { 153 | tabItm.setEnabled(b); 154 | } 155 | 156 | // 157 | //--private--/ 158 | // 159 | 160 | private void assembleMenu() { 161 | menu.add(consoleItm); 162 | menu.add(fileViewItm); 163 | menu.add(tabItm); 164 | menu.addSeparator(); 165 | menu.add(openSettingsItm); 166 | menu.setMnemonic(KeyEvent.VK_V); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/eg/TaskRunner.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import java.awt.EventQueue; 4 | 5 | //--Eadgyth--/ 6 | import eg.console.*; 7 | import eg.ui.MainWin; 8 | 9 | /** 10 | * The starting of tasks with certain predefined settings and behaviour 11 | * of the UI 12 | */ 13 | public class TaskRunner { 14 | 15 | private final MainWin mw; 16 | private final ProcessStarter proc; 17 | private final Console cons; 18 | private final Runnable fileTreeUpdate; 19 | private final TaskRunner.ConsolePrinter printer; 20 | 21 | /** 22 | * @param mw the MainWin 23 | * @param cons the Console 24 | * @param proc the ProcessStarter 25 | * @param fileTreeUpdate the updating of the file tree 26 | */ 27 | public TaskRunner(MainWin mw, Console cons, ProcessStarter proc, 28 | Runnable fileTreeUpdate) { 29 | 30 | this.mw = mw; 31 | this.proc = proc; 32 | this.fileTreeUpdate = fileTreeUpdate; 33 | this.cons = cons; 34 | printer = new TaskRunner.ConsolePrinter(cons); 35 | } 36 | 37 | /** 38 | * Gets this ConsolePrinter 39 | * 40 | * @return the ConsolePrinter 41 | */ 42 | public ConsolePrinter consolePrinter() { 43 | return printer; 44 | } 45 | 46 | /** 47 | * Runs the specified Runnable in a separate thread. 48 | * The Runnable is supposed to use {@link ConsolePrinter} for 49 | * output to the console. If the console is blocked by another task 50 | * a warning dialog is shown and the thread is not started. 51 | * 52 | * @param r the Runnable 53 | * @param initialMsg the message that is printed to the console 54 | * before the thread is started; maybe null or the empty string 55 | * @param toTop true to move to the top of the console after the 56 | * task is finished 57 | * @see ConsolePrinter 58 | */ 59 | public void runWithConsoleOutput(Runnable r, String initialMsg, boolean toTop) { 60 | if (!cons.setUnlocked()) { 61 | return; 62 | } 63 | mw.showConsole(); 64 | cons.setText(""); 65 | if (initialMsg != null && !initialMsg.isEmpty()) { 66 | cons.appendTextBr(initialMsg); 67 | } 68 | new Thread(() -> { 69 | r.run(); 70 | EventQueue.invokeLater(() -> { 71 | if (toTop) { 72 | cons.setCaret(0); 73 | } 74 | cons.setLocked(); 75 | fileTreeUpdate.run(); 76 | }); 77 | }).start(); 78 | } 79 | 80 | /** 81 | * Runs the specified Runnable at the end of pending EDT events 82 | * and shows the wait cursor during processing 83 | * 84 | * @param r the Runnable 85 | */ 86 | public void runBusy(Runnable r) { 87 | mw.busyFunction().execute(r); 88 | EventQueue.invokeLater(fileTreeUpdate); 89 | } 90 | 91 | /** 92 | * Runs the specified system command with the current project 93 | * directory. 94 | * Method invokes {@link ProcessStarter#startProcess(String)} 95 | * 96 | * @param cmd the system command 97 | */ 98 | public void runSystemCommand(String cmd) { 99 | mw.showConsole(); 100 | proc.startProcess(cmd); 101 | } 102 | 103 | /** 104 | * Runs the specified system command with the current project 105 | * directory. 106 | * Method invokes {@link ProcessStarter#startProcess(String, String)} 107 | * 108 | * @param cmd the system command 109 | * @param startMsg an initial message that describes the command 110 | * in the console 111 | */ 112 | public void runSystemCommand(String cmd, String startMsg) { 113 | mw.showConsole(); 114 | proc.startProcess(cmd, startMsg); 115 | } 116 | 117 | /** 118 | * The printing of output to the console 119 | */ 120 | public static class ConsolePrinter { 121 | 122 | private final Console cons; 123 | 124 | /** 125 | * Prints the specified text without appending a line separator 126 | * 127 | * @param text the text 128 | */ 129 | public void print(String text) { 130 | EventQueue.invokeLater(() -> cons.appendText(text)); 131 | } 132 | 133 | /** 134 | * Prints the specified text with a line separator at the end 135 | * 136 | * @param text the text 137 | */ 138 | public void printLine(String text) { 139 | EventQueue.invokeLater(() -> cons.appendText(text + "\n")); 140 | } 141 | 142 | /** 143 | * Prints a message which is formatted such that it begins with 144 | * two closing angle brackets and ends with the line separator. 145 | * This output is intended for predefined status/error messages. 146 | * 147 | * @param text the text 148 | */ 149 | public void printBr(String text) { 150 | EventQueue.invokeLater(() -> cons.appendTextBr(text)); 151 | } 152 | 153 | // 154 | //--private--/ 155 | // 156 | 157 | private ConsolePrinter(Console cons) { 158 | this.cons = cons; 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/eg/FileChooser.java: -------------------------------------------------------------------------------- 1 | package eg; 2 | 3 | import javax.swing.UIManager; 4 | import javax.swing.JFrame; 5 | import javax.swing.JFileChooser; 6 | import javax.swing.Icon; 7 | 8 | import javax.swing.filechooser.FileView; 9 | import javax.swing.filechooser.FileSystemView; 10 | 11 | import java.io.File; 12 | 13 | /** 14 | * Defines a JFileChooser which can be initialized in 15 | * different ways 16 | */ 17 | public class FileChooser { 18 | 19 | private final JFrame frame = new JFrame(); 20 | private JFileChooser ch = null; 21 | private File currentDir; 22 | 23 | public FileChooser() { 24 | ch = new JFileChooser(); 25 | } 26 | 27 | /** 28 | * @param startingDir the directory initially shown 29 | */ 30 | public FileChooser(String startingDir) { 31 | currentDir = new File(startingDir); 32 | ch = new JFileChooser(currentDir); 33 | } 34 | 35 | /** 36 | * Initializes the chooser to open a file 37 | */ 38 | public void initOpenFileChooser() { 39 | ch.setDialogTitle("Open"); 40 | ch.setApproveButtonText("Open"); 41 | ch.setAcceptAllFileFilterUsed(true); 42 | ch.setFileSelectionMode(JFileChooser.FILES_ONLY); 43 | setIcons(ch); 44 | } 45 | 46 | /** 47 | * Initializes the chooser to save a file 48 | */ 49 | public void initSaveFileChooser() { 50 | ch.setDialogTitle("Save file"); 51 | ch.setAcceptAllFileFilterUsed(true); 52 | setIcons(ch); 53 | } 54 | 55 | /** 56 | * Initializes the chooser to select a file or directory 57 | */ 58 | public void initSelectFileOrDirectoryChooser() { 59 | ch.setDialogTitle("Select file/directory"); 60 | ch.setApproveButtonText("Select"); 61 | ch.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); 62 | setIcons(ch); 63 | } 64 | 65 | /** 66 | * Opens the chooser to select a file to open 67 | * 68 | * @return the file; null if cancel was clicked or the chooser 69 | * window was closed 70 | */ 71 | public File selectedFile() { 72 | File f = null; 73 | int res = ch.showOpenDialog(frame); 74 | if (res == JFileChooser.APPROVE_OPTION) { 75 | f = ch.getSelectedFile(); 76 | currentDir = f.getParentFile(); 77 | ch.setCurrentDirectory(currentDir); 78 | } 79 | return f; 80 | } 81 | 82 | /** 83 | * Opens the chooser to select a file to save 84 | * 85 | * @param presetFile the filename that is shown in the text field 86 | * to specify a file. Can be Null or the empty string 87 | * @return the file; null if cancel was clicked or the chooser 88 | * window was closed 89 | */ 90 | public File selectedFileToSave(String presetFile) { 91 | File f = null; 92 | if (presetFile != null && presetFile.length() > 0) { 93 | File toSet = new File(presetFile); 94 | ch.setSelectedFile(toSet); 95 | } 96 | int res = ch.showSaveDialog(frame); 97 | if (res == JFileChooser.APPROVE_OPTION) { 98 | f = ch.getSelectedFile(); 99 | currentDir = f.getParentFile(); 100 | ch.setCurrentDirectory(currentDir); 101 | } 102 | return f; 103 | } 104 | 105 | /** 106 | * Opens the chooser to select a file or directory 107 | * 108 | * @return the file or directory; null if cancel was clicked or the chooser 109 | * window was closed 110 | */ 111 | public File selectedFileOrDirectory() { 112 | File f = null; 113 | int res = ch.showOpenDialog(frame); 114 | if (res == JFileChooser.APPROVE_OPTION) { 115 | f = ch.getSelectedFile(); 116 | if (f.isFile()) { 117 | currentDir = f.getParentFile(); 118 | } 119 | else { 120 | currentDir = f; 121 | } 122 | ch.setCurrentDirectory(currentDir); 123 | } 124 | return f; 125 | } 126 | 127 | /** 128 | * Sets the directory for the chooser 129 | * 130 | * @param dir the directory 131 | */ 132 | public void setDirectory(String dir) { 133 | File f = new File(dir); 134 | if (currentDir != null && f.equals(currentDir)) { 135 | return; 136 | } 137 | currentDir = f; 138 | ch.setCurrentDirectory(currentDir); 139 | if (ch.getFileSelectionMode() == JFileChooser.FILES_AND_DIRECTORIES) { 140 | ch.setSelectedFile(currentDir); 141 | } 142 | } 143 | 144 | /** 145 | * Returns the directory selected most recently 146 | * 147 | * @return the directory 148 | */ 149 | public String currentDir() { 150 | return currentDir.toString(); 151 | } 152 | 153 | // 154 | //--private--/ 155 | // 156 | 157 | private void setIcons(JFileChooser ch) { 158 | if ("Metal".equals(UIManager.getLookAndFeel().getName())) { 159 | ch.setFileView(new FileView() { 160 | 161 | @Override 162 | public Icon getIcon(File f) { 163 | return FileSystemView.getFileSystemView().getSystemIcon(f); 164 | } 165 | }); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/eg/syntax/SyntaxConstants.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | /** 4 | * Constants for strings and characters used for searching text elements 5 | */ 6 | public class SyntaxConstants { 7 | 8 | /** 9 | * The opening bracket characters (parenthesis, braces, angle, 10 | * square) */ 11 | public static final char[] OPEN_BRACKETS = { 12 | '(', '{', '<', '[' 13 | }; 14 | 15 | /** 16 | * The closing bracket characteres (parenthesis, braces, angle, square; 17 | * same order as in {@link #OPEN_BRACKETS}) */ 18 | public static final char[] CLOSE_BRACKETS = { 19 | ')', '}', '>', ']' 20 | }; 21 | 22 | /** 23 | * The single quote character */ 24 | public static final char SINGLE_QUOTE = '\''; 25 | 26 | /** 27 | * The double quote character */ 28 | public static final char DOUBLE_QUOTE = '\"'; 29 | 30 | /** 31 | * The single quote*/ 32 | public static final String SINGLE_QUOTE_STR = "\'"; 33 | 34 | /** 35 | * The double quote */ 36 | public static final String DOUBLE_QUOTE_STR = "\""; 37 | 38 | /** 39 | * The triple double quotes*/ 40 | public static final String TRI_DOUBLE_QUOTE = "\"\"\""; 41 | 42 | /** 43 | * The triple single quotes */ 44 | public static final String TRI_SINGLE_QUOTE = "\'\'\'"; 45 | 46 | /** 47 | * The slash-star block comment start */ 48 | public static final String SLASH_STAR = "/*"; 49 | 50 | /** 51 | * The star-slash block comment end */ 52 | public static final String STAR_SLASH = "*/"; 53 | 54 | /** 55 | * The double slash line comment start */ 56 | public static final String DOUBLE_SLASH = "//"; 57 | 58 | /** 59 | * The hash sign line comment start */ 60 | public static final String HASH = "#"; 61 | 62 | /** 63 | * The markup block comment start */ 64 | public static final String HTML_BLOCK_CMNT_START = ""; 69 | 70 | /** 71 | * The markup CDATA block start */ 72 | public static final String CDATA_BLOCK_START = ""; 77 | 78 | /** 79 | * The characters that end an XML tag */ 80 | public static final char[] XML_TAG_ENDS = { 81 | '<', '>' 82 | }; 83 | 84 | /** 85 | * The characters that are reserved in XML */ 86 | public static final char[] RES_XML_CHARS = { 87 | '>', '<', '/', ' ', '\n', '&', '\"', '\'', '%', '=', '+', ';', ',', '\\' 88 | }; 89 | 90 | /** 91 | * The HTML tag names 92 | */ 93 | public static final String[] HTML_TAGS = { 94 | "a", "abbr", "address", "applet", "area", "article", "aside", "audio", 95 | "b", "base", "bdi", "bdo", "blockquote", "bold", "body", "br", "button", 96 | "canvas", "caption", "code", "col", "colgroup", "command", 97 | "data", "details", "datalist", "dd", "del", "dfn", "div", "dl", "dt", 98 | "em", "embed", 99 | "fieldset", "figure", "figcaption", "form", "footer", "frame", "frameset", 100 | "head", "header", "html", "hr", 101 | "h1", "h2", "h3", "h4", "h5", "h6", 102 | "i", "iframe", "img", "input", "ins", 103 | "kbd", "keygen", 104 | "label", "legend", "li", "link", 105 | "main", "map", "mark", "math", "menu", "menuitem", "meta", "meter", 106 | "nav", "noframes", "noscript", 107 | "object", "ol", "optgroup", "option", "output", 108 | "p", "param", "pre", "progress", 109 | "rp", "rt", "ruby", 110 | "s", "samp", "script", "section", "select", "small", "source", "span", 111 | "strong", "style", "sub", "summary", "sup", "svg", 112 | "table", "tbody", "textarea", "tfoot", "thead", "time", "title", "td", 113 | "th", "tr", "track", 114 | "ul", 115 | "video", 116 | "wbr", 117 | }; 118 | 119 | /** 120 | * The html attribute keywords */ 121 | public static final String[] HTML_ATTR = { 122 | "accesskey", "abbr", "accept", "accept-charset", "action", "align", "alt", 123 | "archive", "axis", 124 | "bgcolor", "border", 125 | "callpadding", "callspacing", "char", "charset", "checked", "cite", "class", 126 | "classid", "code", "codebase", "codetag", "compact", "content", "coords", 127 | "cols", "colspan", 128 | "data", "datetime", "declare", "defer", "dir", "disabled", 129 | "enctype", 130 | "for", "frame", "frameborder", 131 | "headers", "height", "href", "hreflang", "hspace", "http-equiv", 132 | "id", "ismap", 133 | "label", "longdesc", 134 | "marginheight", "marginwidth", "maxlength", "media", "method", "multiple", 135 | "name", "nohref", "noresize", "noshade", 136 | "onclick", "onload", 137 | "profile", 138 | "readonly", "rel", "rev", "rows", "rowspan", "rules", 139 | "scheme", "scope", "scrolling", "selected", "size", "shape", "src", "source", 140 | "standby", "start", "style", "summary", 141 | "tabindex", "target", "title", "type", 142 | "usemap", 143 | "valign", "value", "valuetype", "vspace", 144 | "width", 145 | "xml:lang", "xml:space", "xmlns", 146 | }; 147 | 148 | private SyntaxConstants() {} 149 | } 150 | -------------------------------------------------------------------------------- /src/eg/ui/ToolBar.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import javax.swing.JToolBar; 4 | import javax.swing.JButton; 5 | 6 | //--Eadgyth--/ 7 | import eg.TabbedDocuments; 8 | import eg.Projects; 9 | import eg.Edit; 10 | import eg.utils.ScreenParams; 11 | 12 | /** 13 | * Defines the main toolbar of the editor 14 | */ 15 | public class ToolBar { 16 | 17 | private final JButton openBt = new JButton(IconFiles.OPEN_ICON); 18 | private final JButton saveBt = new JButton(IconFiles.SAVE_ICON); 19 | private final JButton undoBt = new JButton(IconFiles.UNDO_ICON); 20 | private final JButton redoBt = new JButton(IconFiles.REDO_ICON); 21 | private final JButton cutBt = new JButton(IconFiles.CUT_ICON); 22 | private final JButton copyBt = new JButton(IconFiles.COPY_ICON); 23 | private final JButton pasteBt = new JButton(IconFiles.PASTE_ICON); 24 | private final JButton indentBt = new JButton(IconFiles.INDENT_ICON); 25 | private final JButton outdentBt = new JButton(IconFiles.OUTDENT_ICON); 26 | private final JButton changeProjBt = new JButton(IconFiles.CHANGE_PROJ_ICON); 27 | private final JButton compileBt = new JButton(IconFiles.COMPILE_ICON); 28 | private final JButton runBt = new JButton(IconFiles.RUN_ICON); 29 | 30 | private final JToolBar tb; 31 | 32 | public ToolBar() { 33 | compileBt.setEnabled(false); 34 | runBt.setEnabled(false); 35 | changeProjBt.setEnabled(false); 36 | JButton[] bts = new JButton[] { 37 | openBt, saveBt, 38 | undoBt, redoBt, cutBt, copyBt, pasteBt, indentBt, outdentBt, 39 | compileBt, runBt, changeProjBt 40 | }; 41 | String[] toolTips = new String[] { 42 | "Open file", "Save file", 43 | "Undo", "Redo", "Cut selection", "Copy selection", "Paste", 44 | "Increase indentation (Tab)", "Decrease indentation (Shift+Tab)", 45 | "Save and compile project", "", "Change Project" 46 | }; 47 | tb = UIComponents.toolbar(bts, toolTips); 48 | int h = ScreenParams.scaledSize(3); 49 | tb.setBorder(UIComponents.lightBkgdMatteBorder(h, 0, h, 0)); 50 | } 51 | 52 | /** 53 | * Returns this toolbar 54 | * 55 | * @return the JToolBar 56 | */ 57 | public JToolBar toolBar() { 58 | return tb; 59 | } 60 | 61 | /** 62 | * Sets listeners for file actions 63 | * 64 | * @param td the reference to {@link TabbedDocuments} 65 | */ 66 | public void setFileActions(TabbedDocuments td) { 67 | openBt.addActionListener(e -> td.open()); 68 | saveBt.addActionListener(e -> td.save()); 69 | } 70 | 71 | /** 72 | * Sets listeners for actions to edit text 73 | * 74 | * @param edit the reference to {@link Edit} 75 | */ 76 | public void setEditActions(Edit edit) { 77 | undoBt.addActionListener(e -> edit.undo()); 78 | redoBt.addActionListener(e -> edit.redo()); 79 | cutBt.addActionListener(e -> edit.cut()); 80 | copyBt.addActionListener(e -> edit.setClipboard()); 81 | pasteBt.addActionListener(e -> edit.pasteText()); 82 | indentBt.addActionListener(e -> edit.indent()); 83 | outdentBt.addActionListener(e -> edit.outdent()); 84 | } 85 | 86 | /** 87 | * Sets listeners for project actions 88 | * 89 | * @param p the reference to {@link Projects} 90 | */ 91 | public void setProjectActions(Projects p) { 92 | changeProjBt.addActionListener(e -> p.change()); 93 | runBt.addActionListener(e -> p.run()); 94 | compileBt.addActionListener(e -> p.compile()); 95 | } 96 | 97 | /** 98 | * Enables or diables the buttons for cutting and copying actions. 99 | * 100 | * @param b true to enable, false to disable 101 | */ 102 | public void enableCutCopyBts(boolean b) { 103 | cutBt.setEnabled(b); 104 | copyBt.setEnabled(b); 105 | } 106 | 107 | /** 108 | * Enables or disables the button for saving actions 109 | * 110 | * @param b true to enable, false to disable 111 | */ 112 | public void enableSaveBt(boolean b) { 113 | saveBt.setEnabled(b); 114 | } 115 | 116 | /** 117 | * Enables or disables the buttons for und/redo actions. The 118 | * specified boolean each are true to enable, false to disable 119 | * 120 | * @param isUndo the boolean for undo actions 121 | * @param isRedo the boolean for redo actions 122 | */ 123 | public void enableUndoRedoBts(boolean isUndo, boolean isRedo) { 124 | undoBt.setEnabled(isUndo); 125 | redoBt.setEnabled(isRedo); 126 | } 127 | 128 | /** 129 | * Enables the button for actions to compile a project 130 | * 131 | * @param b true to enable, false to disable 132 | */ 133 | public void enableCompileBt(boolean b) { 134 | compileBt.setEnabled(b); 135 | } 136 | 137 | /** 138 | * Enables the button for actions to run a project 139 | * 140 | * @param b true to enable, false to disable 141 | * @param tooltip the tooltip text for the button 142 | */ 143 | public void enableRunBt(boolean b, String tooltip) { 144 | runBt.setEnabled(b); 145 | runBt.setToolTipText(tooltip); 146 | } 147 | 148 | /** 149 | * Enables or disables the button for actions to change project 150 | * 151 | * @param b true to enable, false to disable 152 | */ 153 | public void enableChangeProjBt(boolean b) { 154 | changeProjBt.setEnabled(b); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/eg/ui/FontSettingWin.java: -------------------------------------------------------------------------------- 1 | package eg.ui; 2 | 3 | import java.awt.FlowLayout; 4 | import java.awt.GraphicsEnvironment; 5 | 6 | import java.awt.event.ActionListener; 7 | import java.awt.event.WindowAdapter; 8 | import java.awt.event.WindowEvent; 9 | 10 | import javax.swing.JFrame; 11 | import javax.swing.JComboBox; 12 | import javax.swing.JLabel; 13 | import javax.swing.JPanel; 14 | import javax.swing.BoxLayout; 15 | import javax.swing.Box; 16 | import javax.swing.BorderFactory; 17 | import javax.swing.JButton; 18 | import javax.swing.WindowConstants; 19 | 20 | import eg.utils.ScreenParams; 21 | 22 | /** 23 | * The dialog for setting the font and font size 24 | */ 25 | public class FontSettingWin { 26 | 27 | private static final String[] FONTS = 28 | GraphicsEnvironment.getLocalGraphicsEnvironment() 29 | .getAvailableFontFamilyNames(); 30 | 31 | private final JFrame frame = new JFrame("Font"); 32 | private final JComboBox selectFont; 33 | private final JComboBox selectSize; 34 | private final JButton okBt = new JButton("OK"); 35 | private final JButton cancelBt = new JButton("Cancel"); 36 | private final Integer[] fontSizes; 37 | 38 | private String font; 39 | private int size; 40 | 41 | /** 42 | * Creates a FontSettingsWin 43 | * 44 | * @param fontSizes the array of selectable (unscaled) font sizes 45 | * @param font the font name that is initially set selected 46 | * @param size the (unscaled) font size that is initiallay 47 | * set selected 48 | */ 49 | public FontSettingWin(Integer[] fontSizes, String font, int size) { 50 | this.fontSizes = fontSizes; 51 | this.font = font; 52 | this.size = size; 53 | selectFont = new JComboBox<>(FONTS); 54 | selectSize = new JComboBox<>(fontSizes); 55 | initFrame(font, size); 56 | cancelBt.addActionListener(e -> undoSettings()); 57 | frame.addWindowListener(new WindowAdapter() { 58 | 59 | @Override 60 | public void windowClosing(WindowEvent we) { 61 | undoSettings(); 62 | } 63 | }); 64 | } 65 | 66 | /** 67 | * Sets this frame visible or invisible 68 | * 69 | * @param b the boolean value that is true to set visible, false 70 | * set invisible 71 | */ 72 | public void setVisible(boolean b) { 73 | frame.setVisible(b); 74 | } 75 | 76 | /** 77 | * Registers the listener on this ok button 78 | * 79 | * @param al the {@code ActionListener} 80 | */ 81 | public void okAct(ActionListener al) { 82 | okBt.addActionListener(al); 83 | } 84 | 85 | /** 86 | * Returns the font selection 87 | * 88 | * @return the font 89 | */ 90 | public String font() { 91 | font = FONTS[selectFont.getSelectedIndex()]; 92 | return font; 93 | } 94 | 95 | /** 96 | * Returns the font size selection 97 | * 98 | * @return the font size 99 | */ 100 | public int size() { 101 | size = fontSizes[selectSize.getSelectedIndex()]; 102 | return size; 103 | } 104 | 105 | // 106 | //--private--/ 107 | // 108 | 109 | private void undoSettings() { 110 | selectFont.setSelectedItem(font); 111 | selectSize.setSelectedItem(String.valueOf(size)); 112 | setVisible(false); 113 | } 114 | 115 | private void initFrame(String font, int size) { 116 | frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); 117 | frame.setResizable(false); 118 | frame.setLocation(550, 100); 119 | frame.setContentPane(combinedPnl(font, size)); 120 | frame.pack(); 121 | frame.setLocationRelativeTo(null); 122 | frame.setAlwaysOnTop(true); 123 | frame.setIconImage(IconFiles.EADGYTH_ICON_16.getImage()); 124 | } 125 | 126 | private JPanel combinedPnl(String font, int size) { 127 | JPanel twoComboBx = new JPanel(); 128 | twoComboBx.setLayout(new BoxLayout(twoComboBx, BoxLayout.LINE_AXIS)); 129 | twoComboBx.add(fontPnl(font)); 130 | twoComboBx.add(Box.createRigidArea(ScreenParams.scaledDimension(10, 0))); 131 | twoComboBx.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 132 | twoComboBx.add(sizePnl(size)); 133 | 134 | JPanel combined = new JPanel(); 135 | combined.setLayout(new BoxLayout(combined, BoxLayout.Y_AXIS)); 136 | combined.add(twoComboBx); 137 | combined.add(buttonPnl()); 138 | combined.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 139 | 140 | return combined; 141 | } 142 | 143 | private JPanel fontPnl(String font) { 144 | selectFont.setSelectedItem(font); 145 | return comboBoxPnl(selectFont, "Font: "); 146 | } 147 | 148 | private JPanel sizePnl(int size) { 149 | selectSize.setSelectedItem(size); 150 | return comboBoxPnl(selectSize, "Size: "); 151 | } 152 | 153 | private JPanel comboBoxPnl(JComboBox comboBox, String title) { 154 | comboBox.setFocusable(false); 155 | JLabel titleLb = new JLabel(title); 156 | titleLb.setFont(ScreenParams.scaledFontToBold(titleLb.getFont(), 9)); 157 | JPanel pnl = new JPanel(); 158 | pnl.setLayout(new BoxLayout(pnl, BoxLayout.LINE_AXIS)); 159 | pnl.add(titleLb); 160 | pnl.add(comboBox); 161 | return pnl; 162 | } 163 | 164 | private JPanel buttonPnl() { 165 | JPanel pnl = new JPanel(new FlowLayout()); 166 | pnl.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 167 | pnl.add(okBt); 168 | pnl.add(cancelBt); 169 | return pnl; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/eg/ui/tabpane/ExtTabbedPane.java: -------------------------------------------------------------------------------- 1 | package eg.ui.tabpane; 2 | 3 | import java.awt.Component; 4 | import java.awt.Font; 5 | 6 | import java.awt.event.ActionListener; 7 | import java.awt.event.MouseMotionListener; 8 | import java.awt.event.MouseMotionAdapter; 9 | import java.awt.event.MouseEvent; 10 | 11 | import javax.swing.Box; 12 | import javax.swing.BoxLayout; 13 | import javax.swing.JButton; 14 | import javax.swing.JPanel; 15 | import javax.swing.JLabel; 16 | import javax.swing.JTabbedPane; 17 | 18 | //--Eadgyth--/ 19 | import eg.BackgroundTheme; 20 | import eg.FunctionalAction; 21 | import eg.utils.ScreenParams; 22 | import eg.ui.IconFiles; 23 | 24 | /** 25 | * The tabbed pane for the editor. 26 | *

27 | * Uses {@link ExtTabbedPaneUI} for the tabbar appearance. The 28 | * UI requires that the tab placement property (top) and the 29 | * tab layout property (scroll layout) are not changed. 30 | */ 31 | @SuppressWarnings("serial") 32 | public final class ExtTabbedPane extends JTabbedPane { 33 | 34 | private final transient ExtTabbedPaneUI etpUI; 35 | private final transient BackgroundTheme theme; 36 | 37 | /** 38 | * The FunctionalAction that may remove a tab 39 | * on a button click at a given index */ 40 | private FunctionalAction closeAct; 41 | /** 42 | * The index of the tab where the mouse is moved over */ 43 | private int iTabMouseOver = -1; 44 | /** 45 | * The boolean that indicates if the tabbar is currently 46 | * shown */ 47 | private boolean isShowTabbar; 48 | 49 | /** 50 | * Creates an ExtTabbedPane 51 | * 52 | * @param theme the BackgroundTheme 53 | * @param tabHeight the height of the tabbar 54 | */ 55 | public ExtTabbedPane(BackgroundTheme theme, int tabHeight) { 56 | this.theme = theme; 57 | etpUI = new ExtTabbedPaneUI(theme, tabHeight); 58 | setUI(etpUI); 59 | setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); 60 | setFocusable(false); 61 | addMouseMotionListener(mml); 62 | } 63 | 64 | /** 65 | * Sets the TabClosing 66 | * 67 | * @param tabClose the TabClosing 68 | */ 69 | public void setTabClosing(TabClosing tabClose) { 70 | ActionListener close = e -> tabClose.close(iTabMouseOver); 71 | closeAct = new FunctionalAction("", IconFiles.CLOSE_ICON, close); 72 | } 73 | 74 | /** 75 | * Adds a new closable tab 76 | * 77 | * @param title the title for the tab 78 | * @param c the component to be displayed when the tab is selected 79 | */ 80 | public void addClosableTab(String title, Component c) { 81 | int index = getTabCount(); 82 | addTab(title, c); 83 | setTabComponentAt(index, new ETPTabComponent(title)); 84 | setSelectedIndex(index); 85 | } 86 | 87 | /** 88 | * Shows or hides the tabbar 89 | * 90 | * @param b true to show the tabbar, false to hide 91 | * @throws IllegalStateException if b is false 92 | * while more than one tab is open 93 | */ 94 | public void showTabbar(boolean b) { 95 | if (!b && getTabCount() > 1) { 96 | throw new IllegalStateException( 97 | "Hiding tabs is not allowed since more than " 98 | + " one tab is open"); 99 | } 100 | etpUI.setShowTabs(b); 101 | revalidate(); 102 | repaint(); 103 | isShowTabbar = b; 104 | } 105 | 106 | /** 107 | * Returns if this tabbar is currently set visible 108 | * 109 | * @return true if visible, false otherwise 110 | */ 111 | public boolean isShowTabbar() { 112 | return isShowTabbar; 113 | } 114 | 115 | /** 116 | * Sets the title for the tab at the specified index 117 | * 118 | * @param index the index 119 | * @param title the title 120 | */ 121 | @Override 122 | public void setTitleAt(int index, String title) { 123 | super.setTitleAt(index, title); 124 | ETPTabComponent c = (ETPTabComponent) getTabComponentAt(index); 125 | if (c != null) { 126 | c.setTitle(title); 127 | } 128 | } 129 | 130 | // 131 | //--private--/ 132 | // 133 | 134 | private class ETPTabComponent extends JPanel { 135 | 136 | private final JLabel lb = new JLabel(); 137 | 138 | private ETPTabComponent(String title) { 139 | setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); 140 | setOpaque(false); 141 | Font f = lb.getFont(); 142 | lb.setFont(ScreenParams.scaledFontToPlain(f, 8)); 143 | lb.setText(title); 144 | lb.setForeground(theme.normalText()); 145 | JButton bt = undecoratedButton(); 146 | bt.setAction(closeAct); 147 | add(lb); 148 | add(Box.createRigidArea(ScreenParams.scaledDimension(5, 0))); 149 | add(bt); 150 | } 151 | 152 | private void setTitle(String title) { 153 | lb.setText(title); 154 | } 155 | 156 | private JButton undecoratedButton() { 157 | JButton bt = new JButton(); 158 | bt.setBorder(null); 159 | bt.setFocusable(false); 160 | bt.setFocusPainted(false); 161 | bt.setContentAreaFilled(false); 162 | return bt; 163 | } 164 | } 165 | 166 | private final transient MouseMotionListener mml = new MouseMotionAdapter() { 167 | 168 | @Override 169 | public void mouseMoved(MouseEvent e) { 170 | JTabbedPane sourceTb = (JTabbedPane) e.getSource(); 171 | int x = sourceTb.indexAtLocation(e.getX(), e.getY()); 172 | if (x != -1 && x != iTabMouseOver) { 173 | iTabMouseOver = x; 174 | } 175 | } 176 | }; 177 | } 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Eadgyth Programming Editor

2 |

3 | A text and code editor with the possibility to easily set up coding projects, 4 | first of all for Java. Setting a project means that it can be run (or compiled) 5 | by built-in functions that are invoked by menu selections, button clicks or with 6 | the keyboard. Additional project categories are C#, Python, R, Perl and HTML as well 7 | as a category 'Custom commands' to define own commands to run own batch files/scripts, 8 | for example. 9 |

10 | The editor may be useful for writing applications for own use, learning or quickly 11 | trying out code in case that a more advanced code editor or an IDE is not necessary 12 | (examples for project settings can be found 13 | here). The program can 14 | be tried out by downloading the executable jar file in a 15 | release 16 | (requires a JDK, version 8 or higher). The additional idea is that other project 17 | categories can be implemented as needed (To do: add a guide for programming a 18 | project type). 19 |

20 |

Features for editing text are ...

21 |
    22 |
  • Find/replace.
  • 23 |
  • Clearing end-of-line (trailing) white spaces.
  • 24 |
  • Choosing between spaces and tabs for indentation.
  • 25 |
  • Auto-indentation which distinguishes "curly-bracket-indentation".
  • 26 |
  • Block-wise increase or decrease of the indentation.
  • 27 |
  • A 'notes' editor next to the main editor for notes, viewing text 28 | or facilitated exchange of text.
  • 29 |
  • A basic syntax highlighting (for Java, Perl, Python, R, HTML, XML, CSS, 30 | Javascript, PHP, C#).
  • 31 |
32 |

33 |

Features for running source code are ...

34 |
    35 |
  • Compile and run Java code that may be organized in packages and create an 36 | executable jar file. Use external libraries and, if run with JDK 9+, library 37 | modules. Also, optionally run a module in Java 9+.
  • 38 |
  • Compile and run C# code (v. 1.2.0) and use compiler options for the output 39 | target. The built-in compile command invokes csc compiler (Windows) or Mono 40 | mcs compiler (Linux/Mac). The PATH to these executables must be set 41 | (see Requirements).
  • 42 |
  • Run scripts in Python, R or Perl. 43 |
  • Specify additional options or arguments for the built-in commands.
  • 44 |
  • View HTML code in the default browser.
  • 45 |
  • A console for showing output/error during running (or compiling) a program and 46 | entering input in interactive command-line programs.
  • 47 |
  • Set up several projects which can be switched between and retrieve project settings 48 | after newly starting the editor.
  • 49 |
  • View a project in a file view from where also files can be opened and project 50 | subdirectories created. 51 |
52 |

REQUIREMENTS

53 |

54 | Compiling the program requires Java 8 or higher. It can be built by creating a Java 55 | project with existing sources in Netbeans or Eclipse using the src folder from the 56 | repository as sources directory. It can also be built by the program itself using the 57 | executable jar file in a 58 | release 🙂. 59 |

60 | To compile Java code by the built-in compile function it must be made sure that it is 61 | run using the JRE contained in a JDK (as of Java 11 only a JDK but no separate JRE is 62 | available anyway). 63 |

64 | Important: To run code (or possibly to compile code as for C#) by the built-in 65 | functions the path variables that point to the executables of a programming language 66 | must be set in the OS as permanent environment variables. 67 |
68 |

LIMITATIONS

69 |

70 | Apart from the fact that the syntax highlighting is rather simple the example of the 71 | Perl language shows that it cannot cover all kinds of syntax elememts (in this case: 72 | regex give an example). 73 |

74 | The console of the editor may appear "frozen" in cases that the output of a process 75 | is buffered because its standard output is redirected to the 'console' of this program. 76 | Among the given project categories this applies to Perl (noticable in an interactive 77 | console program) and it may apply to custom commands. This block-buffering may be 78 | disabled (or auto-flushing enabled) by a command-line switch or a command in a script 79 | itself if available for a language (for comparison and for the time using this editor!). 80 |
81 |

THE NAME

82 |

The name of the program is 'Eadgyth' although it's the owner (me) of the repo and 83 | not the repo name. I haven't thought about it in the beginning but it shall not be 84 | changed. Eadgyth (as an Old English version of the name Edith) does not refer to 85 | Queen Eadgyth of Wessex but to MS-DOS Editor which was invoked by typing 'edit'. 86 |
87 |

CREDITS & ACKNOWLEDGEMENTS

88 |
    89 |
  • William Gilreath for his advice, comments, enthusiasm
  • 90 |
  • The program uses icons from 91 | Tango Desktop Project.
  • 92 |
  • The dark-blue background uses the 93 | Dracula Color Palette and 94 | other the dark backgrounds have learned from it.
  • 95 |
96 |

LICENSE

97 |

98 | MIT, see LICENSE
99 |

100 |

SCREENSHOTS

101 |

102 | An example for a command-line program in Java (Eadgyth run on Windows 10): 103 |
104 |

105 |
106 | The 'Dracula' derived dark-blue background: 107 |

108 | -------------------------------------------------------------------------------- /src/eg/javatools/LibModules.java: -------------------------------------------------------------------------------- 1 | package eg.javatools; 2 | 3 | import java.io.File; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | 9 | /** 10 | * Stores configured libraries that can be added to the module path 11 | */ 12 | public class LibModules { 13 | 14 | private static final String F_SEP = File.separator; 15 | 16 | private final List mods = new ArrayList<>(); 17 | private final List modsAbs = new ArrayList<>(); 18 | private final StringBuilder notFound = new StringBuilder(); 19 | 20 | private String joinedParents = ""; 21 | private String joinedAbsParents = ""; 22 | private String joinedNames = ""; 23 | private String errMsg = ""; 24 | 25 | /** 26 | * Configures the library modules 27 | * 28 | * @param modules the list of paths of (putative) library modules 29 | * which may be relative to the project directory or absolute 30 | * @param projectDir the project directory 31 | */ 32 | public void configure(List modules, String projectDir) { 33 | notFound.setLength(0); 34 | mods.clear(); 35 | modsAbs.clear(); 36 | if (!modules.isEmpty()) { 37 | for (String s : modules) { 38 | File f = new File(s); 39 | if (f.exists() && f.isAbsolute()) { 40 | modsAbs.add(s); 41 | mods.add(s); 42 | } 43 | else { 44 | String absInProj = projectDir + F_SEP + s; 45 | f = new File(absInProj); 46 | if (f.exists()) { 47 | mods.add(s); 48 | modsAbs.add(absInProj); 49 | } 50 | else { 51 | notFound.append("\n").append(s); 52 | } 53 | } 54 | } 55 | } 56 | joinedParents = joinedParents(mods, projectDir); 57 | joinedAbsParents = joinedParents(modsAbs, projectDir); 58 | joinedNames = joinedNames(modsAbs); 59 | errMsg = notFound.length() == 0 ? "" : 60 | "The following modules cannot be found:" + notFound.toString(); 61 | } 62 | 63 | /** 64 | * Returns the message that indicates invalid entries 65 | * 66 | * @return the message; the empty string if no invalid entries 67 | * are present 68 | */ 69 | public String errorMessage() { 70 | return errMsg; 71 | } 72 | 73 | /** 74 | * Returns a string in which the parent directories of modules are 75 | * joined with the system's path separator and duplicates removed. 76 | * 77 | * @return the joined parent directories; the empty string if none 78 | * are given 79 | */ 80 | public String joinedParents() { 81 | return joinedParents; 82 | } 83 | 84 | /** 85 | * Returns a string in which the parent directories of modules 86 | * are joined with the system's path separator, duplicates removed 87 | * and relative paths converted to absolute paths 88 | * 89 | * @return the joined parent directories; the empty string none 90 | * are given 91 | */ 92 | public String joinedParentsAbs() { 93 | return joinedAbsParents; 94 | } 95 | 96 | /** 97 | * Returns a string in which the last names of modules are joined 98 | * with commas. 99 | *

In the case the module is a jar file the extension and, if 100 | * present, the version number are removed. Hyphens are replaced 101 | * with dots. 102 | *

The removal of a version number takes place on the assumption 103 | * that it's separated by a hyphen and contains only digits and 104 | * dots. 105 | * 106 | * @return the joined names; the empty string of none are given 107 | */ 108 | public String joinedNames() { 109 | return joinedNames; 110 | } 111 | 112 | // 113 | //--private--/ 114 | // 115 | 116 | private String joinedParents(List l, String projDir) { 117 | List parents = new ArrayList<>(); 118 | if (l.isEmpty()) { 119 | return ""; 120 | } 121 | else { 122 | HashSet checkDupl = new HashSet<>(); 123 | for (String s : l) { 124 | String parent = new File(s).getParent(); 125 | if (!parent.equals(projDir)) { 126 | if (!checkDupl.contains(parent)) { 127 | checkDupl.add(parent); 128 | } 129 | else { 130 | continue; 131 | } 132 | parents.add(parent); 133 | } 134 | } 135 | } 136 | return String.join(File.pathSeparator, parents); 137 | } 138 | 139 | private String joinedNames(List l) { 140 | List names = new ArrayList<>(); 141 | if (l.isEmpty()) { 142 | return ""; 143 | } 144 | else { 145 | for (String s : l) { 146 | File f = new File(s); 147 | String name = f.getName(); 148 | if (name.endsWith(".jar")) { 149 | names.add(moduleNameOfJar(name).replace("-", ".")); 150 | } 151 | else { 152 | names.add(name); 153 | } 154 | } 155 | } 156 | return String.join(",", names); 157 | } 158 | 159 | private String moduleNameOfJar(String name) { 160 | int extPos = name.lastIndexOf("."); 161 | int lastHyphen = name.lastIndexOf("-"); 162 | boolean hasVersion = false; 163 | if (lastHyphen != -1) { 164 | char[] c = name.substring(lastHyphen, extPos).toCharArray(); 165 | int i; 166 | if (c.length > 1 && Character.isDigit(c[1])) { 167 | for (i = 2; i < c.length && (c[i] == '.' || Character.isDigit(c[i])); i++); 168 | hasVersion = i == c.length; 169 | } 170 | } 171 | return hasVersion ? name.substring(0, lastHyphen) : name.substring(0, extPos); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/eg/syntax/CSSHighlighter.java: -------------------------------------------------------------------------------- 1 | package eg.syntax; 2 | 3 | import eg.document.styledtext.Attributes; 4 | 5 | /** 6 | * Syntax highlighting for CSS 7 | */ 8 | public class CSSHighlighter implements Highlighter { 9 | 10 | private static final String[] PROPS = { 11 | "align", "all", "animation", "appearance", 12 | "bottom", "box-shadow", 13 | "caption-side", "clear", "clip", "color", "content", "counter-increment", 14 | "counter-reset", "cursor", 15 | "direction", "display", 16 | "empty-cells", 17 | "filer", "float", 18 | "height", 19 | "left", "letter-spacing", "line-height", 20 | "max-height", "max-width", "min-height", "min-width", 21 | "opacity", "orphans", "overflow", 22 | "page-break-after", "page-break-before", "page-break-inside", "position", 23 | "quotes", 24 | "right", 25 | "size", 26 | "table-layout", "text-align", "text-decoration", "text-indent", 27 | "text-transform", 28 | "top", "transform", "transform-origin", 29 | "unicode-bidi", 30 | "vertical-align", "visibility", 31 | "white-space", "widows", "width", "word-spacing", 32 | "z-index" 33 | }; 34 | private static final String[] BACKGROUND_PROPS = { 35 | "-attachment", "-clip", "-color", 36 | "-image", "-origin", "-position", 37 | "-repeat", "-size" 38 | }; 39 | private static final String[] BORDER_PROPS = { 40 | "-bottom", "-bottom-color", "-bottom-left-radius", 41 | "-bottom-rigth-radius", "-bottom-style", "-bottom-width", 42 | "-collapse", "-color", "-image", "-image-outset", 43 | "-image-repeat", "-image-slice", "-image-source", 44 | "-image-width", "-left", "-left-color", "-left-style", 45 | "-left-width", "-radius", "-right", "-right-color", 46 | "-right-style", "-right-width", "-spacing", "-style", 47 | "-top", "-top-color", "-top-left-radius", 48 | "-top-right-radius", "-top-style", "-top-width", 49 | "-width" 50 | }; 51 | private static final String[] TOP_LEFT_RIGHT_BOTTOM = { 52 | "-bottom", "-left", "-right", "-top" 53 | }; 54 | private static final String[] FONT_PROPS = { 55 | "-family", "-size", "-size-adjust", "-stretch", "-style", 56 | "-synthesis", "-variant", "-weight" 57 | }; 58 | private static final String[] LIST_PROPS = { 59 | "-style", "-style-image", "-style-position", "-style-type" 60 | }; 61 | private static final String[] MARGIN_PROPS = TOP_LEFT_RIGHT_BOTTOM; 62 | private static final String[] OUTLINE_PROPS = { 63 | "-color", "-style", "-width" 64 | }; 65 | private static final String[] PADDING_PROPS = TOP_LEFT_RIGHT_BOTTOM; 66 | private static final String[] TRANSITION_PROPS = { 67 | "-delay", "-duration", "-property", "-timing-function" 68 | }; 69 | 70 | private static final char[] CLASS_START = {'.', '#'}; 71 | private static final char[] CLASS_END = {' ', '{', ')'}; 72 | private static final char[] NON_PROP_START = {'-', '.'}; 73 | private static final int IGNORE_COND = 0; 74 | private static final int OPEN_BRACE_AHEAD_COND = 1; 75 | private static final int NO_OPEN_BRACE_AHEAD_COND = 2; 76 | 77 | @Override 78 | public void highlight(SyntaxSearcher s, Attributes attr) { 79 | s.setBlockSection("}"); 80 | s.resetAttributes(); 81 | s.setCondition(NO_OPEN_BRACE_AHEAD_COND); 82 | s.keywords(SyntaxConstants.HTML_TAGS, CLASS_START, 83 | attr.bluePlain); 84 | 85 | s.signedVariables(CLASS_START, CLASS_END, null, attr.bluePlain); 86 | 87 | s.setCondition(OPEN_BRACE_AHEAD_COND); 88 | s.extensibleKeyword("background", BACKGROUND_PROPS, NON_PROP_START, 89 | attr.redPlain); 90 | 91 | s.extensibleKeyword("border", BORDER_PROPS, NON_PROP_START, 92 | attr.redPlain); 93 | 94 | s.extensibleKeyword("font", FONT_PROPS, NON_PROP_START, 95 | attr.redPlain); 96 | 97 | s.extensibleKeyword("list", LIST_PROPS, NON_PROP_START, 98 | attr.redPlain); 99 | 100 | s.extensibleKeyword("margin", MARGIN_PROPS, NON_PROP_START, 101 | attr.redPlain); 102 | 103 | s.extensibleKeyword("outline", OUTLINE_PROPS, NON_PROP_START, 104 | attr.redPlain); 105 | 106 | s.extensibleKeyword("padding", PADDING_PROPS, NON_PROP_START, 107 | attr.redPlain); 108 | 109 | s.extensibleKeyword("transition", TRANSITION_PROPS, NON_PROP_START, 110 | attr.redPlain); 111 | 112 | s.keywords(PROPS, NON_PROP_START, attr.redPlain); 113 | s.setCondition(IGNORE_COND); 114 | s.braces(); 115 | s.setCondition(OPEN_BRACE_AHEAD_COND); 116 | s.quote(true); 117 | s.setCondition(IGNORE_COND); 118 | s.blockComments(SyntaxConstants.SLASH_STAR, SyntaxConstants.STAR_SLASH, false); 119 | } 120 | 121 | @Override 122 | public boolean isValid(String text, int pos, int condition) { 123 | if (condition == IGNORE_COND) { 124 | return true; 125 | } 126 | int lastOpenBrace 127 | = SyntaxUtils.lastBlockStart(text, pos, "{", "}"); 128 | 129 | while (lastOpenBrace != -1 130 | && -1 != SyntaxUtils.inBlock(text, SyntaxConstants.SLASH_STAR, 131 | SyntaxConstants.STAR_SLASH, lastOpenBrace)) { 132 | 133 | lastOpenBrace 134 | = SyntaxUtils.lastBlockStart(text, lastOpenBrace - 1, "{", "}"); 135 | } 136 | 137 | return (condition == OPEN_BRACE_AHEAD_COND && lastOpenBrace != -1) 138 | || (condition == NO_OPEN_BRACE_AHEAD_COND && lastOpenBrace == -1); 139 | } 140 | 141 | @Override 142 | public int behindLineCmntMark(String text, int pos) { 143 | return -1; 144 | } 145 | 146 | @Override 147 | public int inBlockCmntMarks(String text, int pos) { 148 | return SyntaxUtils.inBlock(text, SyntaxConstants.SLASH_STAR, 149 | SyntaxConstants.STAR_SLASH, pos); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/eg/utils/Dialogs.java: -------------------------------------------------------------------------------- 1 | package eg.utils; 2 | 3 | import java.awt.BorderLayout; 4 | 5 | import javax.swing.Icon; 6 | import javax.swing.JDialog; 7 | import javax.swing.JOptionPane; 8 | import javax.swing.JTextField; 9 | import javax.swing.JPanel; 10 | import javax.swing.JLabel; 11 | 12 | import javax.swing.event.AncestorListener; 13 | import javax.swing.event.AncestorEvent; 14 | 15 | import javax.swing.border.Border; 16 | import javax.swing.border.EmptyBorder; 17 | 18 | //--Eadgyth--// 19 | import eg.ui.IconFiles; 20 | 21 | /** 22 | * Static methods to show dialogs using JOptionPane 23 | */ 24 | public class Dialogs { 25 | 26 | private static final Border EMPTY_BORDER = new EmptyBorder(5, 5, 5, 5); 27 | private static final Icon INFO_ICON = IconFiles.INFO_ICON; 28 | private static final Icon WARNING_ICON = IconFiles.WARNING_ICON; 29 | private static final Icon ERROR_ICON = IconFiles.ERROR_ICON; 30 | 31 | /** 32 | * Shows an information message 33 | * 34 | * @param message the information message 35 | * @param title the title for the dialog. Can be Null. 36 | */ 37 | public static void infoMessage(String message, String title) { 38 | JOptionPane.showMessageDialog (null, message, title, 39 | JOptionPane.PLAIN_MESSAGE, INFO_ICON); 40 | } 41 | 42 | /** 43 | * Shows a warning message 44 | * 45 | * @param message the warning message 46 | */ 47 | public static void warnMessage(String message) { 48 | JOptionPane.showMessageDialog(null, message, null, 49 | JOptionPane.PLAIN_MESSAGE, WARNING_ICON); 50 | } 51 | 52 | /** 53 | * Shows a warning message that is shown on top of all windows 54 | * 55 | * @param message the warning message 56 | */ 57 | public static void warnMessageOnTop(String message) { 58 | final JDialog dialog = new JDialog(); 59 | dialog.setAlwaysOnTop(true); 60 | JOptionPane.showMessageDialog(dialog, message, "", 61 | JOptionPane.PLAIN_MESSAGE, WARNING_ICON); 62 | } 63 | 64 | /** 65 | * Shows an error message 66 | * 67 | * @param message the error message 68 | * @param title the title for the dialog 69 | */ 70 | public static void errorMessage(String message, String title) { 71 | JOptionPane.showMessageDialog(null, message, title, 72 | JOptionPane.PLAIN_MESSAGE, ERROR_ICON); 73 | } 74 | 75 | /** 76 | * Shows a confirmation dialog with Yes, No and Cancel options 77 | * 78 | * @param message the message for the dialog 79 | * @return the Yes, No or Cancel option specified in 80 | * JOptionPane 81 | */ 82 | public static int confirmYesNoCancel(String message) { 83 | return JOptionPane.showConfirmDialog(null, message, null, 84 | JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 85 | } 86 | 87 | /** 88 | * Shows a confirmation dialog with Yes and No options 89 | * 90 | * @param message the message for the dialog 91 | * @return the Yes or No option specified in JOptionPane 92 | */ 93 | public static int confirmYesNo(String message) { 94 | return JOptionPane.showConfirmDialog(null, message, null, 95 | JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 96 | } 97 | 98 | /** 99 | * Shows an info kind of confirmation dialog with Yes and No options 100 | * 101 | * @param message the message for the dialog 102 | * @return the Yes or No option specified in JOptionPane 103 | */ 104 | public static int infoConfirmYesNo(String message) { 105 | return JOptionPane.showConfirmDialog(null, message, null, 106 | JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, 107 | INFO_ICON); 108 | } 109 | 110 | /** 111 | * Shows a warning confirmation dialog with Yes and No options 112 | * 113 | * @param message the message for the dialog 114 | * @return the Yes or No option specified in JOptionPane 115 | */ 116 | public static int warnConfirmYesNo(String message) { 117 | return JOptionPane.showConfirmDialog(null, message, null, 118 | JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, 119 | WARNING_ICON); 120 | } 121 | 122 | /** 123 | * Shows a dialog with the option to enter text 124 | * 125 | * @param message the message for the dialog 126 | * @param title the title for the dialog 127 | * @param initText the text that is initially shown in the text field 128 | * @return the string entered in the text field if ok is clicked, 129 | * null otherwise 130 | */ 131 | public static String textFieldInput(String message, String title, 132 | String initText) { 133 | 134 | JTextField tf = new JTextField(); 135 | tf.setFont(ScreenParams.scaledFontToPlain(tf.getFont(), 8)); 136 | tf.setText(initText); 137 | tf.addAncestorListener(new AncestorListener() { 138 | 139 | @Override 140 | public void ancestorRemoved(AncestorEvent e) { 141 | // not used 142 | } 143 | 144 | @Override 145 | public void ancestorMoved(AncestorEvent e) { 146 | // not used 147 | } 148 | 149 | @Override 150 | public void ancestorAdded(AncestorEvent e) { 151 | tf.requestFocusInWindow(); 152 | } 153 | }); 154 | JPanel pnl = new JPanel(new BorderLayout()); 155 | JLabel lb = new JLabel(message); 156 | lb.setFont(ScreenParams.scaledFontToPlain(tf.getFont(), 9)); 157 | lb.setBorder(EMPTY_BORDER); 158 | pnl.add(lb, BorderLayout.NORTH); 159 | pnl.add(tf, BorderLayout.CENTER); 160 | int res = JOptionPane.showConfirmDialog(null, pnl, title, 161 | JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 162 | 163 | if (JOptionPane.YES_OPTION == res) { 164 | return tf.getText(); 165 | } 166 | else { 167 | return null; 168 | } 169 | } 170 | 171 | private Dialogs() {} 172 | } 173 | -------------------------------------------------------------------------------- /src/eg/utils/ScreenParams.java: -------------------------------------------------------------------------------- 1 | package eg.utils; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.Font; 5 | import java.awt.Toolkit; 6 | 7 | import java.awt.GraphicsDevice; 8 | import java.awt.GraphicsEnvironment; 9 | import java.awt.HeadlessException; 10 | 11 | /** 12 | * The screen size and parameters that depend on the screen resolution. 13 | */ 14 | public class ScreenParams { 15 | 16 | /** 17 | * The screen size */ 18 | public static final Dimension SCREEN_SIZE 19 | = Toolkit.getDefaultToolkit().getScreenSize(); 20 | 21 | private static final int SCREEN_RES 22 | = Toolkit.getDefaultToolkit().getScreenResolution(); 23 | 24 | private static final GraphicsEnvironment GE 25 | = GraphicsEnvironment.getLocalGraphicsEnvironment(); 26 | 27 | private static final double SCREEN_RES_RATIO = SCREEN_RES / 72.0; 28 | 29 | private static final String SANS_SERIF = "SansSerif"; 30 | 31 | /** 32 | * Returns a new Dimension which may be scaled 33 | * depending on the criteria in {@link #scaledSize} 34 | * 35 | * @param unscaledWidth the width in pt 36 | * @param unscaledHeight the height in pt 37 | * @return the Dimension 38 | */ 39 | public static Dimension scaledDimension(int unscaledWidth, int unscaledHeight) { 40 | int width = scaledSize(unscaledWidth); 41 | int height = scaledSize(unscaledHeight); 42 | return new Dimension(width, height); 43 | } 44 | 45 | /** 46 | * Returns if currently a setting with more that one monitor 47 | * is present 48 | * 49 | * @return true for more that one monitor, false otherwise 50 | */ 51 | public static boolean isMultipleScreens() { 52 | try { 53 | GraphicsDevice[] devices = GE.getScreenDevices(); 54 | return devices.length > 1; 55 | } catch (HeadlessException e) { 56 | FileUtils.log(e); 57 | return false; 58 | } 59 | } 60 | 61 | /** 62 | * Scaled sans-serif, plain; unscaled size 8 pt */ 63 | public static final Font SANSSERIF_PLAIN_8 64 | = new Font(SANS_SERIF, Font.PLAIN, scaledSize(8)); 65 | 66 | /** 67 | * Scaled sans-serif, plain; unscaled size 9 pt */ 68 | public static final Font SANSSERIF_PLAIN_9 69 | = new Font(SANS_SERIF, Font.PLAIN, scaledSize(9)); 70 | 71 | /** 72 | * Scaled sans-serif, bold; unscaled size 9 pt */ 73 | public static final Font SANSSERIF_BOLD_9 74 | = new Font(SANS_SERIF, Font.BOLD, scaledSize(9)); 75 | 76 | /** 77 | * Scaled sans-serif, bold; unscaled size 11 pt */ 78 | public static final Font SANSSERIF_BOLD_11 79 | = new Font(SANS_SERIF, Font.BOLD, scaledSize(11)); 80 | 81 | /** 82 | * Returns the specified font with a scaled size and type plain 83 | * 84 | * @param f the font 85 | * @param unscaledSize the original unscaled size 86 | * @return the font 87 | */ 88 | public static Font scaledFontToPlain(Font f, int unscaledSize) { 89 | float s = (float) scaledSize(unscaledSize); 90 | return f.deriveFont(Font.PLAIN, s); 91 | } 92 | 93 | /** 94 | * Returns the specified font with a scaled size and type bold 95 | * 96 | * @param f the font 97 | * @param unscaledSize the original unscaled size 98 | * @return the font 99 | */ 100 | public static Font scaledFontToBold(Font f, int unscaledSize) { 101 | float s = (float) scaledSize(unscaledSize); 102 | return f.deriveFont(Font.BOLD, s); 103 | } 104 | 105 | /** 106 | * Returns the (font) size which is scaled to the screen 107 | * resolution. Although fonts are measured in point (1/72 108 | * of an inch) Java seems to assume a screen resolution of 109 | * 72 dpi for the font size such that pt equals px. 110 | *

111 | * Using this scaling for components other than fonts should 112 | * ensure predictable dimensions relative to font sizes. 113 | * 114 | * @param unscaledSize the unscaled size 115 | * @return the scaled size 116 | */ 117 | public static int scaledSize(int unscaledSize) { 118 | // 119 | // comment if-else statements and uncomment the last line if ui 120 | // scaling is set to 1 in main method in eg.Eadgyth 121 | // 122 | //if (SystemParams.IS_JAVA_9_OR_HIGHER) { 123 | // if (SystemParams.IS_WINDOWS) { 124 | // return Math.round(unscaledSize * 96 / 72); 125 | // } 126 | // else { 127 | // return unscaledSize; 128 | // } 129 | //} 130 | //else { 131 | // return (int) (Math.round(unscaledSize * SCREEN_RES_RATIO)); 132 | //} 133 | // 134 | // comment this line and uncomment if-else statements above if 135 | // ui scaling is not set to 1 in main method in eg.Eadgyth 136 | // 137 | return (int) (Math.round(unscaledSize * SCREEN_RES_RATIO)); 138 | } 139 | 140 | /** 141 | * Returns the size that is the inversion of the scaled size 142 | * 143 | * @param scaledSize the previously scaled size 144 | * @return the rounded inverted scaled size 145 | * @see scaledSize 146 | */ 147 | public static int invertedScaledSize(int scaledSize) { 148 | // 149 | // comment if-else statements and uncomment last line if ui scaling 150 | // is set to 1 in main method in eg.Eadgyth 151 | // 152 | //if (SystemParams.IS_JAVA_9_OR_HIGHER) { 153 | // if (SystemParams.IS_WINDOWS) { 154 | // return Math.round(scaledSize / (96 / 72)); 155 | // } 156 | // else { 157 | // return scaledSize; 158 | // } 159 | //} 160 | //else { 161 | // return (int) (Math.round(scaledSize / SCREEN_RES_RATIO)); 162 | //} 163 | // 164 | // comment this line and uncomment if-else statements above if 165 | // ui scaling is not set to 1 in main method in eg.Eadgyth 166 | // 167 | return (int) (Math.round(scaledSize / SCREEN_RES_RATIO)); 168 | } 169 | 170 | // 171 | //--private--/ 172 | // 173 | 174 | private ScreenParams() {} 175 | } 176 | --------------------------------------------------------------------------------