Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GridView: use FlowBoxes #330

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
89 changes: 5 additions & 84 deletions src/SlingshotView.vala
Original file line number Diff line number Diff line change
@@ -88,6 +88,7 @@ public class Slingshot.SlingshotView : Gtk.Grid {
top.add (search_entry);

grid_view = new Widgets.Grid ();
grid_view.app_launched.connect (() => close_indicator ());

category_view = new Widgets.CategoryView (this);

@@ -264,6 +265,10 @@ public class Slingshot.SlingshotView : Gtk.Grid {
case "Return":
case "KP_Enter":
case "Tab":
case "Up":
case "Down":
case "Left":
case "Right":
return Gdk.EVENT_PROPAGATE;

case "Alt_L":
@@ -295,50 +300,6 @@ public class Slingshot.SlingshotView : Gtk.Grid {
}

return Gdk.EVENT_PROPAGATE;
case "Left":
if (modality == Modality.NORMAL_VIEW) {
if (get_style_context ().direction == Gtk.TextDirection.LTR) {
move_left (event);
} else {
move_right (event);
}
} else {
return Gdk.EVENT_PROPAGATE;
}

break;
case "Right":
if (modality == Modality.NORMAL_VIEW) {
if (get_style_context ().direction == Gtk.TextDirection.LTR) {
move_right (event);
} else {
move_left (event);
}
} else {
return Gdk.EVENT_PROPAGATE;
}

break;
case "Up":
if (modality == Modality.NORMAL_VIEW) {
normal_move_focus (0, -1);
} else {
return Gdk.EVENT_PROPAGATE;
}
break;

case "Down":
if (modality == Modality.NORMAL_VIEW) {
if (search_entry.has_focus) {
grid_view.top_left_focus ();
} else {
normal_move_focus (0, +1);
}
} else {
return Gdk.EVENT_PROPAGATE;
}
break;

case "Page_Up":
if (modality == Modality.NORMAL_VIEW) {
grid_view.go_to_previous ();
@@ -435,28 +396,6 @@ public class Slingshot.SlingshotView : Gtk.Grid {
stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT;
}

/*
* Moves the current view to the left (undependent of the TextDirection).
*/
private void move_left (Gdk.EventKey event) {
if (event.state == Gdk.ModifierType.SHIFT_MASK) {// Shift + Left
grid_view.go_to_previous ();
} else {
normal_move_focus (-1, 0);
}
}

/*
* Moves the current view to the right (undependent of the TextDirection).
*/
private void move_right (Gdk.EventKey event) {
if (event.state == Gdk.ModifierType.SHIFT_MASK) { // Shift + Right
grid_view.go_to_next ();
} else {
normal_move_focus (+1, 0);
}
}

private void set_modality (Modality new_modality) {
modality = new_modality;

@@ -528,22 +467,4 @@ public class Slingshot.SlingshotView : Gtk.Grid {
return false;
});
}

private void normal_move_focus (int delta_column, int delta_row) {
if (grid_view.set_focus_relative (delta_column, delta_row)) {
return;
}

int pages = grid_view.get_n_pages ();
int current = grid_view.get_current_page ();
int columns = grid_view.get_page_columns ();

if (delta_column > 0 && current < pages && grid_view.set_focus ((pages - 1) * columns, 0)) {
return;
}

if (delta_column < 0 || delta_row < 0) {
search_entry.grab_focus ();
}
}
}
125 changes: 53 additions & 72 deletions src/Views/GridView.vala
Original file line number Diff line number Diff line change
@@ -27,16 +27,10 @@ public class Slingshot.Widgets.Grid : Gtk.Grid {
public int number;
}

private Gtk.Grid current_grid;
private Gtk.Widget? focused_widget;
private Gee.HashMap<int, Gtk.Grid> grids;
private AppFlowBox current_grid;
private Gee.HashMap<int, AppFlowBox> grids;
private Page page;

private int focused_column;
private int focused_row;
private uint current_row = 0;
private uint current_col = 0;

construct {
page.rows = 3;
page.columns = 5;
@@ -55,21 +49,24 @@ public class Slingshot.Widgets.Grid : Gtk.Grid {
add (stack);
add (page_switcher);

grids = new Gee.HashMap<int, Gtk.Grid> (null, null);
grids = new Gee.HashMap<int, AppFlowBox> (null, null);
create_new_grid ();
go_to_number (1);
}

public void populate (Backend.AppSystem app_system) {
foreach (Gtk.Grid grid in grids.values) {
grid.destroy ();
foreach (AppFlowBox flowbox in grids.values) {
flowbox.destroy ();
}

grids.clear ();
current_row = 0;
current_col = 0;

var current_row = 0;
var current_col = 0;
page.number = 1;

create_new_grid ();

stack.set_visible_child (current_grid);

foreach (Backend.App app in app_system.get_apps_by_name ()) {
@@ -87,8 +84,7 @@ public class Slingshot.Widgets.Grid : Gtk.Grid {
current_row = 0;
}

current_grid.get_child_at ((int)current_col, (int)current_row).destroy ();
current_grid.attach (app_button, (int)current_col, (int)current_row, 1, 1);
current_grid.add (app_button);
current_col++;
current_grid.show ();
}
@@ -97,51 +93,35 @@ public class Slingshot.Widgets.Grid : Gtk.Grid {
}

private void create_new_grid () {
// Grid properties
current_grid = new Gtk.Grid ();
current_grid.expand = true;
current_grid.row_homogeneous = true;
current_grid.column_homogeneous = true;
current_grid = new AppFlowBox ();
current_grid.margin_start = 12;
current_grid.margin_end = 12;

current_grid.row_spacing = 24;
current_grid.column_spacing = 0;
grids.set (page.number, current_grid);
stack.add_titled (current_grid, page.number.to_string (), page.number.to_string ());

// Fake grids in case there are not enough apps to fill the grid
for (var row = 0; row < page.rows; row++)
for (var column = 0; column < page.columns; column++)
current_grid.attach (new Gtk.Grid (), column, row, 1, 1);
}
current_grid.child_activated.connect ((child) => {
((Widgets.AppButton) child).launch_app ();
app_launched ();
});

private Gtk.Widget? get_child_at (int column, int row) {
var col = ((int)(column / page.columns)) + 1;
current_grid.go_to_next.connect (() => {
go_to_next ();
});

var grid = grids.get (col);
if (grid != null) {
return grid.get_child_at (column - (int)page.columns * (col - 1), row) as Widgets.AppButton;
} else {
return null;
}
}
current_grid.go_to_previous.connect (() => {
go_to_previous ();
});

public int get_page_columns () {
return (int) page.columns;
}
grids.set (page.number, current_grid);

public int get_n_pages () {
return (int) page.number;
stack.add_titled (current_grid, page.number.to_string (), page.number.to_string ());
}

public int get_current_page () {
private int get_current_page () {
return int.parse (stack.get_visible_child_name ());
}

public void go_to_next () {
int page_number = get_current_page () + 1;
if (page_number <= get_n_pages ())
if (page_number <= page.number)
stack.set_visible_child_name (page_number.to_string ());
}

@@ -152,41 +132,42 @@ public class Slingshot.Widgets.Grid : Gtk.Grid {
}

public void go_to_last () {
stack.set_visible_child_name (get_n_pages ().to_string ());
stack.set_visible_child_name (page.number.to_string ());
}

public void go_to_number (int number) {
stack.set_visible_child_name (number.to_string ());
}

public bool set_focus (int column, int row) {
var target_widget = get_child_at (column, row);

if (target_widget != null) {
go_to_number (((int) (column / page.columns)) + 1);

focused_column = column;
focused_row = row;
focused_widget = target_widget;
private class AppFlowBox : Gtk.FlowBox {
public signal void go_to_next ();
public signal void go_to_previous ();

focused_widget.grab_focus ();

return true;
construct {
homogeneous = true;
expand = true;
selection_mode = Gtk.SelectionMode.NONE;
column_spacing = 0;
row_spacing = 24;
max_children_per_line = 5;
min_children_per_line = 5;
}

return false;
}

private bool set_paginated_focus (int column, int row) {
int first_column = (get_current_page () - 1) * get_page_columns ();
return set_focus (first_column, 0);
}

public bool set_focus_relative (int delta_column, int delta_row) {
return set_focus (focused_column + delta_column, focused_row + delta_row);
}
public override bool move_cursor (Gtk.MovementStep step, int count) {
var selected = (Gtk.FlowBoxChild) get_focus_child ();
if (selected != null && step == Gtk.MovementStep.VISUAL_POSITIONS) {
var selected_index = selected.get_index () % max_children_per_line;
var target = (int) selected_index + count;
if (target < 0) {
go_to_previous ();
return Gdk.EVENT_STOP;
} else if (target >= max_children_per_line) {
go_to_next ();
return Gdk.EVENT_STOP;
}
}

public void top_left_focus () {
set_paginated_focus (0, 0);
return Gdk.EVENT_PROPAGATE;
}
}
}
7 changes: 2 additions & 5 deletions src/Widgets/AppButton.vala
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

public class Slingshot.Widgets.AppButton : Gtk.Button {
public class Slingshot.Widgets.AppButton : Gtk.FlowBoxChild {
public signal void app_launched ();

public Backend.App app { get; construct; }
@@ -53,8 +53,6 @@ public class Slingshot.Widgets.AppButton : Gtk.Button {

tooltip_text = app.description;

get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);

var app_label = new Gtk.Label (app.name);
app_label.halign = Gtk.Align.CENTER;
app_label.justify = Gtk.Justification.CENTER;
@@ -93,13 +91,12 @@ public class Slingshot.Widgets.AppButton : Gtk.Button {
grid.row_spacing = 6;
grid.expand = true;
grid.halign = Gtk.Align.CENTER;
grid.margin = 6;
grid.add (overlay);
grid.add (app_label);

add (grid);

this.clicked.connect (launch_app);

this.button_press_event.connect ((e) => {
if (e.button != Gdk.BUTTON_SECONDARY) {
return Gdk.EVENT_PROPAGATE;