Expand Up
@@ -22,18 +22,19 @@ public class Code.FormatBar : Gtk.Box {
public bool tab_width_set_by_editor_config { get; set; default = false; }
private FormatBox line_formatbox;
private Gtk.MenuButton line_menubutton;
private FormatBox lang_formatbox;
private FormatBox tab_formatbox;
private Granite.SwitchModelButton space_tab_modelbutton;
private Gtk.Entry goto_entry;
private Gtk.InfoBar editorconfig_infobar;
private Gtk.ListBox lang_selection_listbox;
private Gtk.MenuButton line_menubutton;
private Gtk.SourceLanguageManager manager;
private Gtk.SpinButton width_spinbutton;
private LangEntry normal_entry;
private SimpleAction language_action;
private ulong cursor_handler = 0;
private ulong language_handler = 0;
private unowned Scratch.Services.Document? doc = null;
private unowned Scratch.Services.Document? current_doc = null;
construct {
get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED);
Expand Down
Expand Up
@@ -97,7 +98,7 @@ public class Code.FormatBar : Gtk.Box {
placeholder_text = _("Filter languages")
};
lang_selection_listbox = new Gtk.ListBox () {
var lang_selection_listbox = new Gtk.ListBox () {
selection_mode = SINGLE
};
lang_selection_listbox.set_sort_func ((row1, row2) => {
Expand All
@@ -108,16 +109,13 @@ public class Code.FormatBar : Gtk.Box {
return (((LangEntry) row).lang_name.down ().contains (lang_selection_filter.text.down ().strip ()));
});
unowned SList<Gtk.RadioButton> group = null;
foreach (unowned string id in manager.get_language_ids ()) {
weak Gtk.SourceLanguage lang = manager.get_language (id);
var entry = new LangEntry (id, lang.name, group);
group = entry.get_radio_group ();
var entry = new LangEntry (id, lang.name);
lang_selection_listbox.add (entry);
}
normal_entry = new LangEntry (null, _("Plain Text"), group);
var normal_entry = new LangEntry ("", _("Plain Text"));
lang_selection_listbox.add (normal_entry);
var lang_scrolled = new Gtk.ScrolledWindow (null, null) {
Expand Down
Expand Up
@@ -187,16 +185,32 @@ public class Code.FormatBar : Gtk.Box {
add (lang_menubutton);
add (line_menubutton);
lang_selection_listbox.row_activated.connect ((row) => {
var lang_entry = ((LangEntry) row);
select_language (lang_entry);
language_action = new SimpleAction.stateful ("language", VariantType.STRING, new Variant.string (""));
language_action.change_state.connect ((parameter) => {
language_action.set_state (parameter);
var lang_id = parameter.get_string ();
if (current_doc.source_view.language.id != lang_id) { // Avoids loop
current_doc.source_view.language = lang_id != "" ? manager.get_language (lang_id) : null;
}
if (lang_id != "") {
unowned var lang = manager.get_language (lang_id);
lang_formatbox.text = lang.name;
} else {
lang_formatbox.text = _("Plain Text");
current_doc.source_view.language = null;
}
});
var action_group = new SimpleActionGroup ();
action_group.add_action (language_action);
insert_action_group ("format", action_group);
lang_selection_filter.changed.connect (() => {
lang_selection_listbox.invalidate_filter ();
});
format_tab_header_from_global_settings ();
width_spinbutton.value_changed.connect (() => {
if (!tab_width_set_by_editor_config) {
Scratch.settings.set_int (
Expand All
@@ -215,14 +229,16 @@ public class Code.FormatBar : Gtk.Box {
}
});
// We need to connect_after because otherwise, the text isn't parsed into the "value" property and we only get the previous value
// We need to connect_after because otherwise, the text isn't parsed into the "value" property
// and we only get the previous value
goto_entry.activate.connect_after (() => {
int line, column;
goto_entry.text = goto_entry.text.replace (":", ".");
goto_entry.text.scanf ("%i.%i", out line, out column);
doc.source_view.go_to_line (line, column - 1);
// Focuses parent to the source view, so that the cursor, which indicates line and column is actually visible.
doc.source_view.grab_focus ();
current_doc.source_view.go_to_line (line, column - 1);
// Focuses parent to the source view, so that the cursor, which indicates line and column
// is actually visible.
current_doc.source_view.grab_focus ();
});
Scratch.settings.changed["indent-width"].connect (format_tab_header_from_global_settings);
Expand All
@@ -236,32 +252,60 @@ public class Code.FormatBar : Gtk.Box {
line_menubutton.active = true;
}
private void select_language (LangEntry lang, bool update_source_view = true) {
lang_selection_listbox.select_row (lang);
lang_formatbox.text = lang.lang_name;
if (update_source_view) {
lang.active = true;
doc.source_view.language = lang.lang_id != null ? manager.get_language (lang.lang_id) : null;
public void set_document (Scratch.Services.Document doc) requires (doc != null) {
if (current_doc != null) {
SignalHandler.disconnect (current_doc, cursor_handler);
SignalHandler.disconnect (current_doc, language_handler);
}
current_doc = doc;
if (doc.loading) {
Timeout.add (200, () => {
if (doc.loading) {
return Source.CONTINUE;
} else {
update_widgets ();
return Source.REMOVE;
}
});
} else {
lang.selected = true ;
update_widgets () ;
}
}
private void format_tab_header_from_global_settings () {
if (!tab_style_set_by_editor_config) {
set_insert_spaces_instead_of_tabs (Scratch.settings.get_boolean ("spaces-instead-of-tabs"));
public void set_insert_spaces_instead_of_tabs (bool use_spaces) requires (current_doc != null) {
space_tab_modelbutton.active = use_spaces;
current_doc.source_view.insert_spaces_instead_of_tabs = use_spaces;
}
public void set_tab_width (int indent_width) requires (current_doc != null) {
width_spinbutton.@value = indent_width;
if (space_tab_modelbutton.active) {
tab_formatbox.text = ngettext ("%d Space", "%d Spaces", indent_width).printf (indent_width);
} else {
tab_formatbox.text = ngettext ("%d Tab", "%d Tabs", indent_width).printf (indent_width);
}
if (!tab_width_set_by_editor_config) {
set_tab_width (Scratch.settings.get_int ("indent-width"));
current_doc.source_view.indent_width = indent_width;
current_doc.source_view.tab_width = indent_width;
}
private void update_widgets () requires (current_doc != null) {
format_tab_header_from_global_settings ();
update_current_lang ();
format_tab_header_from_global_settings ();
format_line_header ();
if (cursor_handler == 0) {
cursor_handler = current_doc.source_view.buffer.notify["cursor-position"].connect (format_line_header);
}
editorconfig_infobar.revealed = tab_style_set_by_editor_config || tab_width_set_by_editor_config;
space_tab_modelbutton.sensitive = !tab_style_set_by_editor_config;
if (language_handler == 0) {
language_handler = current_doc.source_view.notify["language"].connect (update_current_lang);
}
}
private void format_line_header () {
var buffer = doc .source_view.buffer;
private void format_line_header () requires (current_doc != null) {
var buffer = current_doc .source_view.buffer;
var position = buffer.cursor_position;
Gtk.TextIter iter;
buffer.get_iter_at_offset (out iter, position);
Expand All
@@ -270,52 +314,24 @@ public class Code.FormatBar : Gtk.Box {
goto_entry.text = "%d.%d".printf (line, iter.get_line_offset () + 1);
}
public void set_document (Scratch.Services.Document doc) {
if (this.doc != null) {
this.doc.source_view.buffer.notify["cursor-position"].disconnect (format_line_header);
}
this.doc = doc;
update_current_lang ();
format_tab_header_from_global_settings ();
format_line_header ();
this.doc.source_view.buffer.notify["cursor-position"].connect (format_line_header);
private void update_current_lang () requires (current_doc != null) {
var language = current_doc.source_view.language;
var lang_id = language != null ? language.id : "";
// Should not directly modify action state
language_action.change_state (new Variant.string (lang_id));
}
public void set_insert_spaces_instead_of_tabs (bool use_spaces) {
space_tab_modelbutton.active = use_spaces;
if (doc != null) {
doc.source_view.insert_spaces_instead_of_tabs = use_spaces;
}
}
public void set_tab_width (int indent_width) {
width_spinbutton.@value = indent_width;
if (space_tab_modelbutton.active) {
tab_formatbox.text = ngettext ("%d Space", "%d Spaces", indent_width).printf (indent_width);
} else {
tab_formatbox.text = ngettext ("%d Tab", "%d Tabs", indent_width).printf (indent_width);
private void format_tab_header_from_global_settings () {
if (!tab_style_set_by_editor_config) {
set_insert_spaces_instead_of_tabs (Scratch.settings.get_boolean ("spaces-instead-of-tabs"));
}
if (doc != null) {
doc.source_view.indent_width = indent_width;
doc.source_view.tab_width = indent_width;
if (!tab_width_set_by_editor_config) {
set_tab_width (Scratch.settings.get_int ("indent-width"));
}
}
private void update_current_lang () {
var language = doc.source_view.language;
if (language != null) {
var lang_id = language.id;
lang_selection_listbox.get_children ().foreach ((child) => {
var lang_entry = ((LangEntry) child);
if (lang_entry.lang_id == lang_id) {
select_language (lang_entry, false);
}
});
} else {
select_language (normal_entry, false);
}
editorconfig_infobar.revealed = tab_style_set_by_editor_config || tab_width_set_by_editor_config;
space_tab_modelbutton.sensitive = !tab_style_set_by_editor_config;
}
private class FormatBox : Gtk.Box {
Expand Down
Expand Up
@@ -348,56 +364,24 @@ public class Code.FormatBar : Gtk.Box {
}
private class LangEntry : Gtk.ListBoxRow {
public string? lang_id { get; construct; }
public string lang_id { get; construct; }
public string lang_name { get; construct; }
public unowned SList<Gtk.RadioButton> group { get; construct; }
public bool active {
get {
return lang_radio.active;
}
set {
lang_radio.active = value;
}
}
public bool selected {
get {
return lang_radio.active;
}
set {
lang_radio.toggled.disconnect (radio_toggled);
lang_radio.active = value;
lang_radio.toggled.connect (radio_toggled);
}
}
private Gtk.RadioButton lang_radio;
public LangEntry (string? lang_id, string lang_name, SList<Gtk.RadioButton> group) {
Object (group: group, lang_id: lang_id, lang_name: lang_name);
public LangEntry (string lang_id, string lang_name) {
Object (lang_id: lang_id, lang_name: lang_name);
}
class construct {
set_css_name (Gtk.STYLE_CLASS_MENUITEM);
}
construct {
lang_radio = new Gtk.RadioButton.with_label (group, lang_name);
add (lang_radio);
lang_radio.toggled.connect (radio_toggled);
}
private void radio_toggled () {
if (lang_radio.active) {
activate ();
}
}
var lang_checkbutton = new Gtk.CheckButton.with_label (lang_name) {
action_name = "format.language",
action_target = new Variant.string (lang_id)
};
public unowned SList<Gtk.RadioButton> get_radio_group () {
return lang_radio.get_group ();
child = lang_checkbutton;
}
}
}