Skip to content

Commit e640df3

Browse files
committed
Setup Image Gallery V2 - Added Markdown support to Notes.
1 parent 65af92c commit e640df3

37 files changed

Lines changed: 142 additions & 10 deletions

dependency-reduced-pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<artifactId>javafx-maven-plugin</artifactId>
2020
<version>0.0.8</version>
2121
<configuration>
22-
<mainClass>com.tarek.notetool.Launcher</mainClass>
22+
<mainClass>com.tarek.notetool.MainApp</mainClass>
2323
</configuration>
2424
</plugin>
2525
<plugin>

pom.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@
2828
<artifactId>javafx-fxml</artifactId>
2929
<version>${javafx.version}</version>
3030
</dependency>
31+
<!-- JavaFX Web (for WebView) -->
32+
<dependency>
33+
<groupId>org.openjfx</groupId>
34+
<artifactId>javafx-web</artifactId>
35+
<version>${javafx.version}</version>
36+
</dependency>
37+
<!-- Flexmark for Markdown rendering. Using 'flexmark-all' simplifies dependency management. -->
38+
<dependency>
39+
<groupId>com.vladsch.flexmark</groupId>
40+
<artifactId>flexmark-all</artifactId>
41+
<version>0.64.8</version>
42+
</dependency>
3143
<!-- AtlantaFX for modern themes -->
3244
<dependency>
3345
<groupId>io.github.mkpaz</groupId>
@@ -69,7 +81,7 @@
6981
<artifactId>javafx-maven-plugin</artifactId>
7082
<version>0.0.8</version>
7183
<configuration>
72-
<mainClass>com.tarek.notetool.Launcher</mainClass>
84+
<mainClass>com.tarek.notetool.MainApp</mainClass>
7385
</configuration>
7486
</plugin>
7587
<plugin>

src/main/java/com/tarek/notetool/MainApp.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void start(Stage stage) throws Exception {
109109
stage.setTitle("Note Tool");
110110
// Add the application icon. The .ico format is used for the launch4j executable and works here too.
111111
stage.getIcons().add(new Image(getClass().getResourceAsStream("/com/tarek/notetool/assets/icon.ico")));
112-
Scene scene = new Scene(root, 1200, 800);
112+
Scene scene = new Scene(root, 1350, 850);
113113

114114
// Set up global shortcuts now that the scene is available
115115
controller.setupShortcuts(scene);

src/main/java/com/tarek/notetool/MainViewController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ private void setupImageGallery() {
270270
imageGalleryPane.getChildren().add(galleryContent);
271271

272272
// Initially hide the gallery off-screen to the right
273-
imageGalleryPane.setTranslateX(300); // Assuming gallery width is 300
273+
imageGalleryPane.setTranslateX(350); // Assuming gallery width is 350
274274
imageGalleryPane.setVisible(false);
275275

276276
} catch (IOException e) {

src/main/java/com/tarek/notetool/NoteDetailViewController.java

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import javafx.scene.control.CheckBox;
88
import javafx.scene.control.ComboBox;
99
import javafx.scene.control.ButtonType;
10+
import javafx.scene.control.Tab;
11+
import javafx.scene.control.TabPane;
1012
import javafx.scene.control.ProgressBar;
1113
import javafx.scene.control.TextArea;
1214
import javafx.scene.control.Button;
@@ -44,13 +46,17 @@
4446
import javafx.geometry.Side;
4547
import javafx.scene.layout.VBox;
4648
import javafx.scene.image.Image;
49+
import javafx.scene.web.WebView;
4750
import javafx.stage.FileChooser;
4851
import javafx.util.Pair;
4952
import javafx.util.Duration;
5053
import org.kordamp.ikonli.javafx.FontIcon;
5154
import org.kordamp.ikonli.materialdesign2.MaterialDesignL;
5255
import org.kordamp.ikonli.materialdesign2.MaterialDesignC;
5356
import org.kordamp.ikonli.materialdesign2.MaterialDesignP;
57+
import com.vladsch.flexmark.html.HtmlRenderer;
58+
import com.vladsch.flexmark.parser.Parser;
59+
import com.vladsch.flexmark.util.data.MutableDataSet;
5460

5561
import java.awt.Desktop;
5662
import java.io.File;
@@ -81,12 +87,18 @@ public record EditorResult(Note savedNote, Set<String> newTags) {
8187
@FXML
8288
private TextField titleField;
8389
@FXML
84-
private ComboBox<Note.Priority> priorityComboBox;
90+
private TabPane contentTabPane;
8591
@FXML
86-
private DatePicker dueDatePicker;
92+
private Tab previewTab;
8793
@FXML
8894
private TextArea contentArea;
8995
@FXML
96+
private WebView contentPreview;
97+
@FXML
98+
private ComboBox<Note.Priority> priorityComboBox;
99+
@FXML
100+
private DatePicker dueDatePicker;
101+
@FXML
90102
private ProgressBar goalsProgressBar;
91103
@FXML
92104
private VBox goalsContainer; // Placeholder for the TreeView
@@ -150,7 +162,14 @@ public record EditorResult(Note savedNote, Set<String> newTags) {
150162

151163
private ContextMenu noteSuggestionsPopup;
152164
private UUID noteToOpen = null;
165+
private final Parser markdownParser;
166+
private final HtmlRenderer markdownRenderer;
153167

168+
public NoteDetailViewController() {
169+
MutableDataSet options = new MutableDataSet();
170+
this.markdownParser = Parser.builder(options).build();
171+
this.markdownRenderer = HtmlRenderer.builder(options).build();
172+
}
154173

155174
@FXML
156175
private void initialize() {
@@ -248,6 +267,15 @@ protected void updateItem(Note.Comment item, boolean empty) {
248267
if (referenceImagesFlowPane != null) {
249268
setupReferencePaneDragAndDrop();
250269
}
270+
271+
// --- NEW: Markdown Preview Setup ---
272+
if (previewTab != null) {
273+
previewTab.setOnSelectionChanged(event -> {
274+
if (previewTab.isSelected()) {
275+
renderMarkdown();
276+
}
277+
});
278+
}
251279
}
252280

253281
public void setDialogStage(Stage dialogStage) {
@@ -539,6 +567,70 @@ private Node createTagLabel(String tag) {
539567
return tagView;
540568
}
541569

570+
private void renderMarkdown() {
571+
if (contentArea == null || contentPreview == null) {
572+
return;
573+
}
574+
String markdownText = contentArea.getText();
575+
com.vladsch.flexmark.util.ast.Node document = markdownParser.parse(markdownText);
576+
String rawHtml = markdownRenderer.render(document);
577+
578+
// This HTML uses CSS variables defined by the AtlantaFX theme, so it will adapt to light/dark mode.
579+
String fullHtml = """
580+
<html>
581+
<head>
582+
<style>
583+
body {
584+
font-family: -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
585+
background-color: var(-color-bg-default, #22272e);
586+
color: var(-color-fg-default, #adbac7);
587+
line-height: 1.6;
588+
}
589+
a { color: var(-color-accent-fg, #9370DB); text-decoration: none; }
590+
a:hover { text-decoration: underline; }
591+
h1, h2, h3, h4, h5, h6 {
592+
color: var(-color-header-fg, #adbac7);
593+
border-bottom: 1px solid var(-color-border-muted, #444c56);
594+
padding-bottom: 0.3em;
595+
margin-top: 24px;
596+
margin-bottom: 16px;
597+
}
598+
code {
599+
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
600+
background-color: var(-color-neutral-muted, rgba(173, 186, 199, 0.1));
601+
padding: 0.2em 0.4em;
602+
margin: 0;
603+
font-size: 85%%;
604+
border-radius: 6px;
605+
}
606+
pre {
607+
background-color: var(-color-canvas-subtle, #2d333b);
608+
padding: 16px;
609+
overflow: auto;
610+
border-radius: 6px;
611+
}
612+
pre > code { padding: 0; margin: 0; font-size: 100%%; background-color: transparent; border: 0; }
613+
blockquote {
614+
border-left: 0.25em solid var(-color-border-default, #444c56);
615+
padding: 0 1em;
616+
color: var(-color-fg-muted, #768390);
617+
}
618+
table { border-collapse: collapse; width: 100%%; }
619+
th, td { border: 1px solid var(-color-border-muted, #444c56); padding: 8px 13px; }
620+
th { font-weight: bold; background-color: var(-color-canvas-subtle, #2d333b); }
621+
img { max-width: 100%%; height: auto; border-radius: 6px; }
622+
ul, ol { padding-left: 2em; }
623+
</style>
624+
</head>
625+
<body>
626+
%s
627+
</body>
628+
</html>
629+
""".formatted(rawHtml);
630+
631+
contentPreview.getEngine().loadContent(fullHtml);
632+
}
633+
542634
// --- Reference Image Methods ---
543635

544636
private void setupReferencePaneDragAndDrop() {

src/main/resources/com/tarek/notetool/main-view.fxml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@
5656
</VBox>
5757
</center>
5858
</BorderPane>
59-
<VBox fx:id="imageGalleryPane" alignment="TOP_CENTER" maxWidth="300" style="-fx-background-color: -color-bg-overlay;" StackPane.alignment="CENTER_RIGHT" />
59+
<VBox fx:id="imageGalleryPane" alignment="TOP_CENTER" maxWidth="350" style="-fx-background-color: -color-bg-overlay;" StackPane.alignment="CENTER_RIGHT" />
6060
</children>
6161
</StackPane>

src/main/resources/com/tarek/notetool/note-detail-view.fxml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<?import javafx.scene.control.ComboBox?>
88
<?import javafx.scene.control.DatePicker?>
99
<?import javafx.scene.control.Label?>
10+
<?import javafx.scene.web.WebView?>
1011
<?import javafx.scene.control.ScrollPane?>
1112
<?import javafx.scene.control.ListView?>
1213
<?import javafx.scene.control.ProgressBar?>
@@ -58,7 +59,20 @@
5859

5960
<VBox spacing="5" VBox.vgrow="ALWAYS">
6061
<Label text="Content" style="-fx-font-size: 13px; -fx-font-weight: bold;"/>
61-
<TextArea fx:id="contentArea" wrapText="true" prefRowCount="6" VBox.vgrow="ALWAYS"/>
62+
<TabPane fx:id="contentTabPane" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS">
63+
<tabs>
64+
<Tab text="Write">
65+
<content>
66+
<TextArea fx:id="contentArea" prefRowCount="6" wrapText="true" />
67+
</content>
68+
</Tab>
69+
<Tab fx:id="previewTab" text="Preview">
70+
<content>
71+
<WebView fx:id="contentPreview" />
72+
</content>
73+
</Tab>
74+
</tabs>
75+
</TabPane>
6276
</VBox>
6377
</VBox>
6478
</ScrollPane>
156 Bytes
Binary file not shown.
-39 Bytes
Binary file not shown.
16 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)