Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 85 additions & 99 deletions src/SymbolPane/SymbolOutline.vala
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
/*-
* Copyright (c) 2013-2025 elementary LLC. (https://elementary.io)
* Copyright (C) 2013 Tom Beckmann <tomjonabc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
/*
* SPDX-License-Identifier: LGPL-3.0-or-later
* SPDX-FileCopyrightText: 2013-2025 elementary Inc. (https://elementary.io)
* 2013 Tom Beckmann <tomjonabc@gmail.com>
*/

public enum Scratch.Services.SymbolType {
Expand Down Expand Up @@ -64,21 +52,13 @@ public interface Scratch.Services.SymbolItem : Code.Widgets.SourceList.Expandabl
}

public class Scratch.Services.SymbolOutline : Gtk.Box {
protected static SymbolType[] filters; //Initialized by derived classes
const string ACTION_GROUP = "symbol";
const string ACTION_PREFIX = ACTION_GROUP + ".";
const string ACTION_SELECT = "action-select";
const string ACTION_TOGGLE = "toggle-";
const uint SPINNER_DELAY_MSEC = 300;
SimpleActionGroup symbol_action_group;

public Scratch.Services.Document doc { get; construct; }

protected Gee.HashMap<SymbolType, SimpleAction> checks;
protected Gtk.SearchEntry search_entry;
protected Code.Widgets.SourceList store;
protected Code.Widgets.SourceList.ExpandableItem root;
protected Gtk.CssProvider source_list_style_provider;
public Gtk.Widget get_widget () { return this; }
public bool tool_box_sensitive {
set {
Expand All @@ -87,36 +67,21 @@ public class Scratch.Services.SymbolOutline : Gtk.Box {
}
}

protected static SymbolType[] filters; //Initialized by derived classes
protected Gee.HashMap<SymbolType, SimpleAction> checks;
protected Gtk.SearchEntry search_entry;
protected Code.Widgets.SourceList store;
protected Code.Widgets.SourceList.ExpandableItem root;
protected Gtk.CssProvider source_list_style_provider;
protected bool took_too_long;
private uint show_spinner_timeout_id = 0;
protected void before_parse () {
tool_box_sensitive = true;
took_too_long = false;
show_spinner_timeout_id = Timeout.add (SPINNER_DELAY_MSEC, () => {
show_spinner_timeout_id = 0;
stack.visible_child = spinner;
spinner.start ();
return Source.REMOVE;
});
}

protected void after_parse () {
if (show_spinner_timeout_id > 0) {
Source.remove (show_spinner_timeout_id);
show_spinner_timeout_id = 0;
}

spinner.stop ();
stack.visible_child = filter_button;
tool_box_sensitive = !took_too_long;
}

public virtual void parse_symbols () {}
public virtual void add_tooltips (Code.Widgets.SourceList.ExpandableItem root) {}

private Gtk.MenuButton filter_button;
private uint refilter_timeout_id = 0;
private bool delay_refilter = false;
private Gtk.Spinner spinner;
private uint show_spinner_timeout_id = 0;
private Gtk.Stack stack;
private SimpleActionGroup symbol_action_group;

construct {
symbol_action_group = new SimpleActionGroup ();
Expand Down Expand Up @@ -192,61 +157,30 @@ public class Scratch.Services.SymbolOutline : Gtk.Box {
});
}

private void add_filter_menuitem (Menu menu, SymbolType filter) {
var filter_action = new SimpleAction.stateful (
ACTION_TOGGLE + ((uint)filter).to_string (),
null,
new Variant.boolean (true)
);

checks[filter] = filter_action;
filter_action.activate.connect (action_toggle_filter);
symbol_action_group.add_action (filter_action);

var filter_item = new MenuItem (
filter.to_string (),
ACTION_PREFIX + filter_action.get_name ()
);
public virtual void parse_symbols () {}
public virtual void add_tooltips (Code.Widgets.SourceList.ExpandableItem root) {}

menu.append_item (filter_item);
protected void before_parse () {
tool_box_sensitive = true;
took_too_long = false;
show_spinner_timeout_id = Timeout.add_once (SPINNER_DELAY_MSEC, () => {
show_spinner_timeout_id = 0;
stack.visible_child = spinner;
spinner.start ();
});
}

protected bool filter_func (Object item) {
if (!(item is SymbolItem)) {
return true;
}

var symbol_type = ((SymbolItem)item).symbol_type;
if (symbol_type == SymbolType.NAMESPACE) {
return true;
}

if (checks[symbol_type] == null) {
symbol_type = SymbolType.OTHER;
}

var filter_action = checks[symbol_type];

if (!filter_action.get_state ().get_boolean ()) {
return false;
}

// Do not exclude text search misses on Item with children as may
// hide hits on its children
if (item is Code.Widgets.SourceList.ExpandableItem) {
var expandable = (Code.Widgets.SourceList.ExpandableItem)item;
if (expandable.n_children > 0) {
return true;
}

return ((SymbolItem)item).name.contains (search_entry.text);
protected void after_parse () {
if (show_spinner_timeout_id > 0) {
Source.remove (show_spinner_timeout_id);
show_spinner_timeout_id = 0;
}

return true;
spinner.stop ();
stack.visible_child = filter_button;
tool_box_sensitive = !took_too_long;
}

uint refilter_timeout_id = 0;
bool delay_refilter = false;
protected void schedule_refilter () {
// Ensure a refilter happens at least 500mS later if not already
// delayed.
Expand Down Expand Up @@ -300,15 +234,67 @@ public class Scratch.Services.SymbolOutline : Gtk.Box {
}
}

protected bool filter_func (Object item) {
if (!(item is SymbolItem)) {
return true;
}

var symbol_type = ((SymbolItem)item).symbol_type;
if (symbol_type == SymbolType.NAMESPACE) {
return true;
}

if (checks[symbol_type] == null) {
symbol_type = SymbolType.OTHER;
}

var filter_action = checks[symbol_type];

if (!filter_action.get_state ().get_boolean ()) {
return false;
}

// Do not exclude text search misses on Item with children as may
// hide hits on its children
if (item is Code.Widgets.SourceList.ExpandableItem) {
var expandable = (Code.Widgets.SourceList.ExpandableItem)item;
if (expandable.n_children > 0) {
return true;
}

return ((SymbolItem)item).name.contains (search_entry.text);
}

return true;
}

private void add_filter_menuitem (Menu menu, SymbolType filter) {
var filter_action = new SimpleAction.stateful (
ACTION_TOGGLE + ((uint)filter).to_string (),
null,
new Variant.boolean (true)
);

checks[filter] = filter_action;
filter_action.activate.connect (action_toggle_filter);
symbol_action_group.add_action (filter_action);

var filter_item = new MenuItem (
filter.to_string (),
ACTION_PREFIX + filter_action.get_name ()
);

menu.append_item (filter_item);
}

private void action_select_filters (SimpleAction action, Variant? param) {
foreach (var filter_action in checks.values) {
filter_action.set_state (new Variant ("b", param.get_boolean ()));
}
schedule_refilter ();
// Keep menu open
Idle.add (() => {
Idle.add_once (() => {
filter_button.set_active (true);
return Source.REMOVE;
});
}

Expand Down