diff --git a/src/main/java/org/editor/CanvasFrame.java b/src/main/java/org/editor/CanvasFrame.java index 9a9d077..c14440f 100644 --- a/src/main/java/org/editor/CanvasFrame.java +++ b/src/main/java/org/editor/CanvasFrame.java @@ -59,6 +59,11 @@ public class CanvasFrame extends JPanel implements MouseListener, MouseMotionLis private static CanvasFrame _the = null; private DockKey key = new DockKey("canvas"); + /** + * Initializes the CanvasFrame with grid rendering, mouse interaction, and a periodic repaint timer. + * + * Sets up the layout, background color, mouse listeners, grid image, preferred size, and starts a timer to repaint the canvas and update frame timing. + */ private CanvasFrame() { super(new BorderLayout()); this.setBackground(new Color(18, 18, 18)); @@ -306,6 +311,14 @@ private void drawGrid() { public void mouseClicked(MouseEvent e) { } + /** + * Draws a red crosshair at the current mouse position on the canvas. + * + * If grid snapping is enabled, the crosshair aligns to the nearest grid intersection. + * The crosshair consists of intersecting vertical and horizontal lines and a small circle at the intersection point. + * + * @param g2 the graphics context used for drawing + */ private void drawCrosshair(Graphics2D g2) { if (mouseX >= 0 && mouseY >= 0) { diff --git a/src/main/java/org/editor/CodeEditor.java b/src/main/java/org/editor/CodeEditor.java index e554135..ca92b9a 100644 --- a/src/main/java/org/editor/CodeEditor.java +++ b/src/main/java/org/editor/CodeEditor.java @@ -47,10 +47,23 @@ public class CodeEditor extends JPanel implements Dockable { private DockKey key; // = new DockKey("textEditor"); public int tabIndex =0; + /** + * Constructs a new CodeEditor with no associated file, initializing a temporary editor instance. + */ public CodeEditor() { this(null); } + /** + * Constructs a code editor panel with syntax highlighting, code completion, and docking support. + * + *
If a file path is provided, initializes the editor with that file; otherwise, creates a temporary file for editing. + * Sets up syntax highlighting for the "piccode" language, enables code folding, line numbers, bookmarks, and installs code completion. + * Configures docking integration with appropriate title, tooltip, and icon. + * Adds focus and caret listeners to update the selected editor and cursor position display. + * + * @param path the file path to open in the editor, or {@code null} to create a temporary file + */ public CodeEditor(Path path) { super(new BorderLayout()); textArea = new TextEditorPane(); @@ -131,6 +144,13 @@ public void focusLost(FocusEvent e) { this.add(sp, BorderLayout.CENTER); } + /** + * Saves the current file, writing the editor's content to disk. + * + * If the file is marked as temporary or an error occurs during saving, prompts the user to choose a save location. Updates the editor window's status and persists the file after saving. + * + * @return {@code true} if the file was saved successfully; {@code false} otherwise + */ public boolean saveFile() { if (isTmp) { return saveFileAs(); @@ -155,6 +175,13 @@ public void setIsTmp(boolean isTmp) { this.isTmp = isTmp; } + /** + * Opens a file chooser dialog to save the current editor content to a user-selected file. + * + * Applies file filters for markdown and piccode files. If the user approves, saves the content to the chosen file, reloads it into the editor, updates the file path, persists the file, updates UI elements, and marks the file as non-temporary. Returns {@code true} if the save is successful, or {@code false} if the operation is canceled or an error occurs. + * + * @return {@code true} if the file was saved successfully; {@code false} otherwise + */ public boolean saveFileAs() { var fileChooser = new JFileChooser("."); fileChooser.setFileFilter(FileFilter.mdFilter); @@ -237,6 +264,11 @@ private CompletionProvider createCompletionProvider() { } + /** + * Adds predefined code templates for common drawing operations to the global code template manager. + * + * These templates provide shorthand insertions for frequently used drawing functions in the editor. + */ public static void createTemplateManager() { CodeTemplateManager ctm = RSyntaxTextArea.getCodeTemplateManager(); String[][] templates = { @@ -254,6 +286,12 @@ public static void createTemplateManager() { } } + /** + * Loads the specified file into the editor, applies appropriate syntax highlighting based on file extension, and persists the file. + * + * @param fp the file to load into the editor + * @return true if the file was loaded successfully; false if an I/O error occurred + */ public boolean load(File fp) { setIsTmp(false); var loc = FileLocation.create(fp); @@ -276,11 +314,21 @@ public boolean load(File fp) { } } + /** + * Returns the docking key associated with this editor for integration with the docking framework. + * + * @return the DockKey for this editor + */ @Override public DockKey getDockKey() { return key; } + /** + * Returns the editor component for docking integration. + * + * @return this editor panel as a Swing component + */ @Override public Component getComponent() { return this; diff --git a/src/main/java/org/editor/DockablePanel.java b/src/main/java/org/editor/DockablePanel.java index e753f1d..05a35d0 100644 --- a/src/main/java/org/editor/DockablePanel.java +++ b/src/main/java/org/editor/DockablePanel.java @@ -14,26 +14,56 @@ public class DockablePanel extends JPanel implements Dockable { private DockKey key; + /** + * Constructs a DockablePanel with the specified layout and a unique DockKey ID. + * + * @param layout the layout manager to use for this panel + */ public DockablePanel(LayoutManager layout) { super(layout); key = new DockKey("dock-" + System.nanoTime()); } + /** + * Constructs a DockablePanel with the specified layout manager and a DockKey identified by the given ID. + * + * @param layout the layout manager to use for this panel + * @param id the unique identifier for the DockKey associated with this panel + */ public DockablePanel(LayoutManager layout, String id) { super(layout); key = new DockKey(id); } + /** + * Constructs a DockablePanel with the specified layout, identifier, name, tooltip, and icon. + * + * @param layout the layout manager to use for this panel + * @param id the unique identifier for the dock key + * @param name the display name for the dock key + * @param tip the tooltip text for the dock key + * @param icon the icon identifier used to retrieve the panel's icon + */ public DockablePanel(LayoutManager layout, String id, String name, String tip, String icon) { super(layout); key = new DockKey(id, name, tip, Icons.getIcon(icon)); } + /** + * Returns the {@link DockKey} associated with this dockable panel. + * + * @return the DockKey identifying and describing this panel for docking operations + */ @Override public DockKey getDockKey() { return key; } + /** + * Returns this panel as the dockable component. + * + * @return this panel instance + */ @Override public Component getComponent() { return this; diff --git a/src/main/java/org/editor/EditorWindow.java b/src/main/java/org/editor/EditorWindow.java index 1afc5c9..b15d033 100644 --- a/src/main/java/org/editor/EditorWindow.java +++ b/src/main/java/org/editor/EditorWindow.java @@ -77,6 +77,11 @@ public final class EditorWindow extends JFrame implements SearchListener { private DockingDesktop desk = new DockingDesktop(); private static CodeEditor selected = null; + /** + * Returns the singleton instance of the EditorWindow, creating it if necessary. + * + * @return the single EditorWindow instance + */ public static EditorWindow the() { if (win == null) { win = new EditorWindow(); @@ -86,6 +91,13 @@ public static EditorWindow the() { public static JRootPane root = null; + /** + * Constructs the main application window for the code editor, initializing the docking framework, UI components, toolbars, status bars, and dockable panels. + * + *
+ * Sets up the main window layout with a docking desktop for managing code editors and panels, configures toolbars for file and project actions, and initializes status indicators. Integrates dashboard, rendering, quick access, and access panels as dockable components. Installs look-and-feel, customizes docking UI, and sets up listeners to handle editor closing events with prompts for unsaved changes. + *
+ */ public EditorWindow() { super("Piccode - DashBoard"); var _ =new CodeEditor(); @@ -226,6 +238,9 @@ public EditorWindow() { this.setVisible(true); } + /** + * Initializes the find and replace dialogs for text search operations, ensuring they share a common search context. + */ private void initSearchDialogs() { findDialog = new FindDialog(this, this); replaceDialog = new ReplaceDialog(this, this); @@ -234,6 +249,11 @@ private void initSearchDialogs() { replaceDialog.setSearchContext(context); } + /** + * Adds a new empty code editor as a dockable tab in the main window. + * + * Creates a new {@code CodeEditor} instance, assigns it a unique index, updates the UI to reflect the new editor, and docks it within the docking desktop. The first editor is docked relative to the dashboard; subsequent editors are added as tabs alongside the first editor. + */ public static void addTab(ActionEvent e) { int index = tabEditors.size(); CodeEditor editor = new CodeEditor(); @@ -254,6 +274,11 @@ public static void addTab(ActionEvent e) { } } + /** + * Opens a file in a new code editor dockable and adds it to the docking desktop. + * + * @param path the path to the file to open in the new editor + */ public static void addTab(Path path, Void e) { var index = tabEditors.size(); var editor = new CodeEditor(path); @@ -272,10 +297,23 @@ public static void addTab(Path path, Void e) { } } + /** + * Sets the currently selected code editor in the main window. + * + * @param ed the CodeEditor instance to set as selected + */ public static void setSelectedEditor(CodeEditor ed) { selected = ed; } + /** + * Returns the currently selected code editor. + * + * If no editor is explicitly selected, returns the editor whose text area has focus. + * If none are focused, returns the first available editor as a fallback. + * + * @return the selected or focused {@link CodeEditor}, or the first editor if none are selected or focused + */ public static CodeEditor getSelectedEditor() { if (selected != null) { return selected; @@ -289,6 +327,13 @@ public static CodeEditor getSelectedEditor() { return tabEditors.values().toArray(CodeEditor[]::new)[0]; // fallback if nothing has focus } + /** + * Adds a special "+" tab to the provided tabbed pane, allowing users to create new editor tabs. + * + * The "+" tab displays a button that, when clicked, triggers the addition of a new editor tab. + * + * @param tabs the JTabbedPane to which the "+" tab will be added + */ private static void addPlusTab(JTabbedPane tabs) { var dashb = new JPanel(new BorderLayout()); dashb.add(new DashboardPanel(), BorderLayout.CENTER); @@ -304,6 +349,15 @@ private static void addPlusTab(JTabbedPane tabs) { tabs.setTabComponentAt(tabs.getTabCount() - 1, plusBtn); } + /** + * Creates a custom tab header component with a title label and a close button for use in a tabbed pane. + * + * The close button triggers removal of the associated tab, prompting to save if the editor is modified. + * + * @param tabs the tabbed pane to which the header belongs + * @param title the title to display on the tab header + * @return a component representing the tab header with a close button + */ private static Component makeTabHeader(JTabbedPane tabs, String title) { JPanel tabHeader = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); tabHeader.setOpaque(false); @@ -333,6 +387,11 @@ private static Component makeTabHeader(JTabbedPane tabs, String title) { return tabHeader; } + /** + * Removes the currently selected code editor tab, prompting to save changes if the editor is modified. + * + * If only one editor is open or no editor is selected, the method does nothing. + */ public static void removeTab() { if (tabEditors.size() <= 1) { return; @@ -351,6 +410,9 @@ public static void removeTab() { removeIfDirty(index, selected); } + /** + * Removes all open code editor tabs, prompting to save any with unsaved changes before closing. + */ public static void removeAllTabs() { var editors = new HashMap<>(tabEditors); // Copy to avoid ConcurrentModificationException for (var entry : editors.entrySet()) { @@ -358,10 +420,22 @@ public static void removeAllTabs() { } } + /** + * Returns the number of open code editor instances currently managed by the window. + * + * @return the count of open code editors + */ public static int tabsCount() { return tabEditors.size(); } + /** + * Removes the specified code editor from the docking layout, prompting to save changes if the editor is modified. + * + * @param index the index of the editor in the internal map + * @param ed the code editor to remove + * @return true if the editor was removed (and saved if modified), false if the removal was canceled + */ private static boolean removeIfDirty(Integer index, CodeEditor ed) { if (ed.textArea.isDirty()) { int result = JOptionPane.showConfirmDialog(win, "File " + ed.filePathTruncated() + " is modified. Save?"); @@ -376,6 +450,12 @@ private static boolean removeIfDirty(Integer index, CodeEditor ed) { return true; } + /** + * Determines whether the specified dockable component is currently docked in the docking desktop. + * + * @param d the dockable component to check + * @return true if the dockable is present in the docking desktop; false otherwise + */ private static boolean isDocked(Dockable d) { for (var state: win.desk.getDockables()) { var dockable = state.getDockable(); @@ -386,6 +466,12 @@ private static boolean isDocked(Dockable d) { return false; } + /** + * Returns the index associated with the specified code editor in the tab editors map. + * + * @param ed the code editor to look up + * @return the index of the editor if found, or null if not present + */ private static Integer getEditorIndex(CodeEditor ed) { for (var entry : tabEditors.entrySet()) { if (entry.getValue() == ed) { @@ -395,6 +481,11 @@ private static Integer getEditorIndex(CodeEditor ed) { return null; } + /** + * Reindexes the tabEditors map to ensure editor indexes are sequential starting from zero. + * + * This method rebuilds the tabEditors map after editor removals to maintain contiguous integer keys. + */ private static void migrateIndexes() { HashMap+ * This implementation does nothing. + */ public void mousePressed(MouseEvent e) { } + /**** + * Invoked when a mouse button is released on the list component. + *
+ * This implementation does nothing.
+ */
public void mouseReleased(MouseEvent e) {
}
}
diff --git a/src/main/java/org/editor/events/MenuEvents.java b/src/main/java/org/editor/events/MenuEvents.java
index 31774f5..fc4cb43 100644
--- a/src/main/java/org/editor/events/MenuEvents.java
+++ b/src/main/java/org/editor/events/MenuEvents.java
@@ -56,6 +56,11 @@ static void replaceEvent(ActionEvent e) {
replaceDialog.setVisible(true);
}
+ /**
+ * Displays the find dialog and hides the replace dialog if it is currently visible.
+ *
+ * @param e the action event triggering the find operation
+ */
static void findEvent(ActionEvent e) {
var replaceDialog = EditorWindow.replaceDialog;
var findDialog = EditorWindow.findDialog;
@@ -65,18 +70,32 @@ static void findEvent(ActionEvent e) {
findDialog.setVisible(true);
}
+ /**
+ * Displays the About dialog for the editor application.
+ */
public static void aboutDialog(ActionEvent e) {
var _ = new AboutDialog(EditorWindow.win);
}
+ /**
+ * Closes the currently active editor tab.
+ */
public static void closeTab(ActionEvent e) {
EditorWindow.removeTab();
}
+ /**
+ * Closes all open editor tabs in the application.
+ */
public static void closeAllTabs(ActionEvent e) {
EditorWindow.removeAllTabs();
}
+ /**
+ * Opens a file chooser dialog for the user to select a file and adds a new editor tab for the chosen file.
+ *
+ * The dialog starts in the current directory and applies filters for markdown and picture files. If the user selects a file and approves, a new tab is created in the editor for that file.
+ */
static void openFile(ActionEvent e) {
// TODO: Use the System object to get the current pwd
var fileChooser = new JFileChooser(".");
@@ -93,6 +112,11 @@ static void openFile(ActionEvent e) {
EditorWindow.addTab(path, null);
}
+ /**
+ * Saves the currently selected file if more than one tab is open.
+ *
+ * Does nothing if only one tab is present.
+ */
static void saveFile(ActionEvent e) {
if (EditorWindow.tabsCount() == 1) {
return;
@@ -101,6 +125,9 @@ static void saveFile(ActionEvent e) {
ed.saveFile();
}
+ /**
+ * Saves the currently selected file under a new name using a "Save As" dialog, if more than one tab is open.
+ */
static void saveFileAs(ActionEvent e) {
if (EditorWindow.tabsCount() == 1) {
return;
@@ -109,10 +136,20 @@ static void saveFileAs(ActionEvent e) {
ed.saveFileAs();
}
+ /**
+ * Saves all open files in the editor.
+ *
+ * Calls the save operation for every open tab, ensuring all changes are written to disk.
+ */
static void saveAllFiles(ActionEvent e) {
EditorWindow.saveAll();
}
+ /**
+ * Closes the currently active editor tab.
+ *
+ * This method is an alias for {@link #closeTab(ActionEvent)}.
+ */
static void closeFile(ActionEvent e) {
closeTab(e);
}
diff --git a/src/main/java/org/editor/fs/FilePersistance.java b/src/main/java/org/editor/fs/FilePersistance.java
index cdd1056..0500fd3 100644
--- a/src/main/java/org/editor/fs/FilePersistance.java
+++ b/src/main/java/org/editor/fs/FilePersistance.java
@@ -19,33 +19,73 @@ public class FilePersistance {
private static final String RECENT_FILES = "./etc/rf/xxx.yy";
private static final String RECENT_PROJECTS = "./etc/rf/xxx.yy";
+ /**
+ * Retrieves a list of recently accessed files.
+ *
+ * @return a list of up to 15 recent file paths as strings; returns an empty list if none are found or on error
+ */
public static List
+ * This method sets up the layout, panels, lists, buttons, labels, and other controls
+ * that comprise the dashboard interface, including the "Recent Files" and "Recent Projects" sections,
+ * community and update controls, and informational links.
+ *
+ * This method is auto-generated by the GUI form editor and should not be modified manually.
+ *