|
@@ -6,10 +6,16 @@ namespace Publicate.Editors {
|
|
|
|
|
|
public class MarkdownEditor : Box, EditorWidget {
|
|
|
|
|
|
- protected ScrolledWindow scrolled_window;
|
|
|
- protected ClampScrollable clamp;
|
|
|
- protected GtkCommonMark.MarkdownView markdown_view;
|
|
|
+ private Box leaflet; // For now, a box
|
|
|
+
|
|
|
+ private GtkCommonMark.MarkdownView markdown_view;
|
|
|
private Ppub.Publication publication;
|
|
|
+ private GtkSource.View text_view;
|
|
|
+ private GtkSource.Buffer source_buffer;
|
|
|
+ private GtkSource.LanguageManager language_manager;
|
|
|
+
|
|
|
+ private ScrolledWindow source_scroller;
|
|
|
+ private ScrolledWindow markdown_scroller;
|
|
|
|
|
|
private ViewerWindow window;
|
|
|
private TabPage page;
|
|
@@ -18,44 +24,70 @@ namespace Publicate.Editors {
|
|
|
window = win;
|
|
|
|
|
|
orientation = Orientation.VERTICAL;
|
|
|
- scrolled_window = new ScrolledWindow ();
|
|
|
- clamp = new ClampScrollable ();
|
|
|
- clamp.maximum_size = 800;
|
|
|
- scrolled_window.child = clamp;
|
|
|
- scrolled_window.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);
|
|
|
- scrolled_window.vexpand = true;
|
|
|
+ source_scroller = new ScrolledWindow ();
|
|
|
+ markdown_scroller = new ScrolledWindow ();
|
|
|
+ leaflet = new Box(Orientation.HORIZONTAL, 0);
|
|
|
+
|
|
|
+ text_view = new GtkSource.View ();
|
|
|
+ language_manager = new GtkSource.LanguageManager ();
|
|
|
+ text_view.monospace = true;
|
|
|
+ text_view.show_line_numbers = true;
|
|
|
+ text_view.auto_indent = true;
|
|
|
+ source_buffer = (GtkSource.Buffer) text_view.buffer;
|
|
|
+ source_buffer.language = language_manager.guess_language ("file.md", "text/markdown");
|
|
|
+ text_view.hexpand = true;
|
|
|
+ text_view.set_wrap_mode (WrapMode.WORD_CHAR);
|
|
|
+ text_view.top_margin = 18;
|
|
|
+ text_view.bottom_margin = 18;
|
|
|
+ text_view.left_margin = 18;
|
|
|
+ text_view.right_margin = 18;
|
|
|
+ text_view.buffer.changed.connect (update_preview);
|
|
|
+
|
|
|
+
|
|
|
+ source_scroller.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);
|
|
|
+ source_scroller.vexpand = true;
|
|
|
+ markdown_scroller.set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC);
|
|
|
+ markdown_scroller.vexpand = true;
|
|
|
+
|
|
|
+ source_scroller.vadjustment.value_changed.connect(sync_scroll);
|
|
|
|
|
|
markdown_view = new GtkCommonMark.MarkdownView ();
|
|
|
+ markdown_view.hexpand = true;
|
|
|
markdown_view.set_wrap_mode (WrapMode.WORD_CHAR);
|
|
|
markdown_view.widget_embedded.connect(widget_embedded);
|
|
|
- clamp.child = markdown_view;
|
|
|
+
|
|
|
+ source_scroller.child = text_view;
|
|
|
+ markdown_scroller.child = markdown_view;
|
|
|
+
|
|
|
+ leaflet.append(source_scroller);
|
|
|
+ leaflet.append(new Separator(Orientation.VERTICAL));
|
|
|
+ leaflet.append (markdown_scroller);
|
|
|
|
|
|
Gtk.Settings.get_default().notify["gtk-application-prefer-dark-theme"].connect(() => configure_tags());
|
|
|
configure_tags();
|
|
|
|
|
|
- append(scrolled_window);
|
|
|
+ append(leaflet);
|
|
|
|
|
|
page = tab_view.add_page (this, null);
|
|
|
}
|
|
|
|
|
|
- public double get_scroll_position () {
|
|
|
- return scrolled_window.vadjustment.get_value ();
|
|
|
- }
|
|
|
-
|
|
|
public void set_zoom_percentage (int percent) {
|
|
|
var scale = (float)percent / 100f;
|
|
|
markdown_view.tag_manager.font_scale = scale;
|
|
|
}
|
|
|
-
|
|
|
- public void set_scroll_position (double position) {
|
|
|
- scrolled_window.vadjustment.set_value (position);
|
|
|
- }
|
|
|
|
|
|
public virtual async void load_asset (Ppub.Publication publication, Ppub.Asset asset) {
|
|
|
this.publication = publication;
|
|
|
markdown_view.buffer.set_text("", 0);
|
|
|
page.title = asset.name;
|
|
|
- yield markdown_view.load_from_stream_async (publication.read_asset (asset.name));
|
|
|
+
|
|
|
+ text_view.buffer.set_text("", 0);
|
|
|
+ MemoryOutputStream os = new MemoryOutputStream (null, GLib.realloc, GLib.free);
|
|
|
+ yield os.splice_async (publication.read_asset (asset.name), OutputStreamSpliceFlags.CLOSE_SOURCE | OutputStreamSpliceFlags.CLOSE_TARGET);
|
|
|
+ var text = os.steal_data ();
|
|
|
+ text.length = (int) os.get_data_size ();
|
|
|
+
|
|
|
+ text_view.buffer.set_text ((string)text, text.length);
|
|
|
}
|
|
|
|
|
|
protected async void widget_embedded(GtkCommonMark.MarkdownViewEmbeddedWidgetHost widget, string file, string title) {
|
|
@@ -79,7 +111,34 @@ namespace Publicate.Editors {
|
|
|
markdown_view.tag_manager.update_link_colour(link.get_color());
|
|
|
}
|
|
|
|
|
|
+ private void update_preview() {
|
|
|
+ var text = get_text();
|
|
|
+ markdown_view.buffer.set_text("", 0);
|
|
|
+ markdown_view.load_from_string((string)text);
|
|
|
+ }
|
|
|
+
|
|
|
+ public string get_text() {
|
|
|
+ TextIter start_iter;
|
|
|
+ TextIter end_iter;
|
|
|
+ text_view.buffer.get_start_iter (out start_iter);
|
|
|
+ text_view.buffer.get_end_iter (out end_iter);
|
|
|
+
|
|
|
+ var text = text_view.buffer.get_text (start_iter, end_iter, true);
|
|
|
+ return text;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void sync_scroll() {
|
|
|
+ set_scroll_from_frac(markdown_scroller, get_scroll_frac(source_scroller));
|
|
|
+ }
|
|
|
+
|
|
|
+ private static double get_scroll_frac(ScrolledWindow scroller) {
|
|
|
+ return (scroller.vadjustment.value/(scroller.vadjustment.upper - scroller.vadjustment.page_size));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void set_scroll_from_frac(ScrolledWindow scroller, double frac) {
|
|
|
+ scroller.vadjustment.value = (scroller.vadjustment.upper - scroller.vadjustment.page_size)*frac;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|
|
|
-
|
|
|
}
|