123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- using Gtk;
- using Adw;
- using GtkCommonMark;
- namespace Publicate.Editors {
- public class MarkdownEditor : Box, EditorWidget, Savable {
- 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;
- public Adw.TabPage tab_page { get {
- return page;
- } }
- public string asset_name { get{
- return asset.name;
- } }
- private bool unsaved = false;
- public bool has_unsaved_changes { get{
- return unsaved;
- } }
- private Ppub.Asset asset;
- public MarkdownEditor(ViewerWindow win, TabView tab_view) {
- window = win;
- orientation = Orientation.VERTICAL;
- 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);
- 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(leaflet);
- page = tab_view.add_page (this, null);
- }
- public void set_zoom_percentage (int percent) {
- var scale = (float)percent / 100f;
- markdown_view.tag_manager.font_scale = scale;
- }
-
- public async void load_asset (Ppub.Publication publication, Ppub.Asset asset) {
- this.publication = publication;
- markdown_view.buffer.set_text("", 0);
- page.title = asset.name;
- this.asset = asset;
- 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);
- set_tab_name(false);
- }
- public override async void save_asset(Ppub.Builder builder) {
- var article_data = get_text().to_utf8();
- var article_stream = new MemoryInputStream.from_data((uint8[])article_data);
- var compression_info = new Ppub.CompressionInfo(article_stream);
- article_stream.seek(0, SeekType.SET);
- builder.add_asset(asset.name, asset.mimetype, article_stream, Invercargill.empty<string>(), compression_info);
- set_tab_name(false);
- }
- protected async void widget_embedded(GtkCommonMark.MarkdownViewEmbeddedWidgetHost widget, string file, string title) {
- var image = new Gtk.Picture();
- image.content_fit = Gtk.ContentFit.FILL;
- widget.append (image);
- var pixbuf = yield new Gdk.Pixbuf.from_stream_async (publication.read_asset (file), null);
- image.set_pixbuf (pixbuf);
- widget.available_width_changed.connect(wid => {
- image.width_request = wid;
- var ratio = image.get_paintable().get_intrinsic_aspect_ratio ();
- image.height_request = (int)(wid / ratio);
- });
- }
- private void configure_tags() {
- var link = new LinkButton("");
- 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);
- set_tab_name(true);
- }
- 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;
- }
- private void set_tab_name(bool unsaved) {
- this.unsaved = unsaved;
- if(unsaved) {
- tab_page.title = @"⏺ $(asset.name)";
- }
- else {
- tab_page.title = asset.name;
- }
- }
-
- }
- }
|