[gnome-games/wip/exalm/mobile: 13/15] platforms-view: Make adaptive
- From: Alexander Mikhaylenko <alexm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/exalm/mobile: 13/15] platforms-view: Make adaptive
- Date: Wed, 29 May 2019 16:55:28 +0000 (UTC)
commit 85c6e7cfc323e446fb2a414d7789a490a3f8fa72
Author: Alexander Mikhaylenko <exalm7659 gmail com>
Date: Thu May 23 15:11:59 2019 +0500
platforms-view: Make adaptive
Add a leaflet to PlatformsView. When folded, open subview when clicking
on a platform.
Add a second headerbar to CollectionHeaderBar, show it when viewing a
platform when the window is narrow. This headerbar contains a back button
and another search button.
Implement Alt+Left (or Alt+Right, depending on text direction) to go back
to platforms list when folded.
data/ui/collection-header-bar.ui | 63 +++++++++++++++++++++-
data/ui/platforms-view.ui | 38 ++++++++------
src/ui/collection-box.vala | 6 ++-
src/ui/collection-header-bar.vala | 44 ++++++++++++++--
src/ui/collection-view.vala | 9 ++++
src/ui/platforms-view.vala | 107 +++++++++++++++++++++++++++++++++-----
6 files changed, 233 insertions(+), 34 deletions(-)
---
diff --git a/data/ui/collection-header-bar.ui b/data/ui/collection-header-bar.ui
index 73eaf4df..ba855e98 100644
--- a/data/ui/collection-header-bar.ui
+++ b/data/ui/collection-header-bar.ui
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
- <template class="GamesCollectionHeaderBar" parent="GtkBin">
+ <template class="GamesCollectionHeaderBar" parent="GtkStack">
<property name="visible">True</property>
+ <property name="transition-type">slide-left-right</property>
<child>
<object class="GtkHeaderBar">
<property name="visible">True</property>
@@ -103,6 +104,66 @@
</packing>
</child>
</object>
+ <packing>
+ <property name="name">main</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHeaderBar" id="subview_header_bar">
+ <property name="visible">True</property>
+ <property name="show_close_button">True</property>
+ <child>
+ <object class="GtkButton">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <signal name="clicked" handler="on_subview_back_clicked"/>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="accessible-name" translatable="yes">Back</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">go-previous-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkToggleButton" id="search_subview">
+ <property name="visible">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <style>
+ <class name="image-button"/>
+ </style>
+ <child internal-child="accessible">
+ <object class="AtkObject">
+ <property name="accessible-name" translatable="yes">Search</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon-name">edit-find-symbolic</property>
+ <property name="icon-size">1</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack-type">end</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="name">subview</property>
+ </packing>
</child>
</template>
<object class="GtkPopover" id="menu_popover">
diff --git a/data/ui/platforms-view.ui b/data/ui/platforms-view.ui
index b0f548cc..68dceeaf 100644
--- a/data/ui/platforms-view.ui
+++ b/data/ui/platforms-view.ui
@@ -1,31 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
- <template class="GamesPlatformsView" parent="GtkBox">
+ <template class="GamesPlatformsView" parent="GtkBin">
<property name="visible">True</property>
<property name="expand">True</property>
<signal name="map" after="yes" handler="on_map"/>
<signal name="unmap" after="no" handler="on_unmap"/>
<child>
- <object class="GtkScrolledWindow">
+ <object class="HdyLeaflet" id="leaflet">
<property name="visible">True</property>
- <property name="vexpand">True</property>
- <property name="width-request">250</property>
+ <property name="mode-transition-type">slide</property>
+ <property name="child-transition-type">slide</property>
+ <signal name="notify::folded" handler="on_leaflet_folded_changed"/>
<child>
- <object class="GtkListBox" id="list_box">
+ <object class="GtkScrolledWindow" id="scrolled_window">
<property name="visible">True</property>
- <signal name="row-activated" handler="on_list_box_row_activated"/>
- <style>
- <class name="sidebar"/>
- </style>
+ <property name="vexpand">True</property>
+ <property name="width-request">250</property>
+ <child>
+ <object class="GtkListBox" id="list_box">
+ <property name="visible">True</property>
+ <signal name="row-activated" handler="on_list_box_row_activated"/>
+ <style>
+ <class name="sidebar"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GamesCollectionIconView" id="collection_view">
+ <property name="visible">True</property>
+ <property name="expand">True</property>
</object>
</child>
- </object>
- </child>
- <child>
- <object class="GamesCollectionIconView" id="collection_view">
- <property name="visible">True</property>
- <property name="expand">True</property>
</object>
</child>
</template>
diff --git a/src/ui/collection-box.vala b/src/ui/collection-box.vala
index 565e2775..2627775d 100644
--- a/src/ui/collection-box.vala
+++ b/src/ui/collection-box.vala
@@ -46,7 +46,11 @@ private class Games.CollectionBox : Gtk.Box {
get { return _adaptive_state; }
construct {
_adaptive_state = value;
+
+ platform_view.adaptive_state = adaptive_state;
+
adaptive_state.notify["is-showing-bottom-bar"].connect (update_bottom_bar);
+ adaptive_state.notify["is-subview-open"].connect (update_bottom_bar);
}
}
@@ -179,6 +183,6 @@ private class Games.CollectionBox : Gtk.Box {
}
private void update_bottom_bar () {
- view_switcher_bar.reveal = adaptive_state.is_showing_bottom_bar;
+ view_switcher_bar.reveal = adaptive_state.is_showing_bottom_bar &&
!adaptive_state.is_subview_open;
}
}
diff --git a/src/ui/collection-header-bar.vala b/src/ui/collection-header-bar.vala
index 1bdb8b22..9042bb79 100644
--- a/src/ui/collection-header-bar.vala
+++ b/src/ui/collection-header-bar.vala
@@ -1,7 +1,7 @@
// This file is part of GNOME Games. License: GPL-3.0+.
[GtkTemplate (ui = "/org/gnome/Games/ui/collection-header-bar.ui")]
-private class Games.CollectionHeaderBar : Gtk.Bin {
+private class Games.CollectionHeaderBar : Gtk.Stack {
public bool search_mode { get; set; }
private Gtk.Stack _viewstack;
public Gtk.Stack viewstack {
@@ -31,6 +31,19 @@ private class Games.CollectionHeaderBar : Gtk.Bin {
}
}
+ private AdaptiveState _adaptive_state;
+ public AdaptiveState adaptive_state {
+ get { return _adaptive_state; }
+ construct {
+ _adaptive_state = value;
+ adaptive_state.notify["is-folded"].connect (update_folded);
+ adaptive_state.notify["is-subview-open"].connect (update_subview);
+ adaptive_state.notify["subview-title"].connect (update_subview_title);
+ }
+ }
+
+ [GtkChild]
+ private Gtk.HeaderBar subview_header_bar;
[GtkChild]
private Hdy.Squeezer title_squeezer;
[GtkChild]
@@ -39,15 +52,19 @@ private class Games.CollectionHeaderBar : Gtk.Bin {
private Hdy.ViewSwitcher view_switcher;
[GtkChild]
private Gtk.ToggleButton search;
- private Binding search_binding;
+ [GtkChild]
+ private Gtk.ToggleButton search_subview;
- public AdaptiveState adaptive_state { get; construct; }
+ private Binding search_binding;
+ private Binding search_subview_binding;
private ulong viewstack_child_changed_id;
construct {
search_binding = bind_property ("search-mode", search, "active",
BindingFlags.BIDIRECTIONAL);
+ search_subview_binding = bind_property ("search-mode", search_subview,
+ "active", BindingFlags.BIDIRECTIONAL);
}
public CollectionHeaderBar (AdaptiveState adaptive_state) {
@@ -77,4 +94,25 @@ private class Games.CollectionHeaderBar : Gtk.Bin {
title_label.label = title;
}
+
+ private void update_subview () {
+ bool show_subview = adaptive_state.is_subview_open && adaptive_state.is_folded;
+ visible_child_name = show_subview ? "subview" : "main";
+ }
+
+ private void update_folded () {
+ bool show_subview = adaptive_state.is_subview_open && adaptive_state.is_folded;
+
+ // FIXME: have a transition here. Crossfade doens't work well at the moment
+ set_visible_child_full (show_subview ? "subview" : "main", Gtk.StackTransitionType.NONE);
+ }
+
+ private void update_subview_title () {
+ subview_header_bar.title = adaptive_state.subview_title;
+ }
+
+ [GtkCallback]
+ private void on_subview_back_clicked () {
+ adaptive_state.is_subview_open = false;
+ }
}
diff --git a/src/ui/collection-view.vala b/src/ui/collection-view.vala
index 8455e5b9..be34a2cc 100644
--- a/src/ui/collection-view.vala
+++ b/src/ui/collection-view.vala
@@ -109,6 +109,15 @@ private class Games.CollectionView : Object, UiView {
public bool on_key_pressed (Gdk.EventKey event) {
var default_modifiers = Gtk.accelerator_get_default_mod_mask ();
+ if (((event.state & default_modifiers) == Gdk.ModifierType.MOD1_MASK) &&
+ (((window.get_direction () == Gtk.TextDirection.LTR) && event.keyval == Gdk.Key.Left) ||
+ ((window.get_direction () == Gtk.TextDirection.RTL) && event.keyval == Gdk.Key.Right)) &&
+ adaptive_state.is_subview_open) {
+ adaptive_state.is_subview_open = false;
+
+ return true;
+ }
+
if ((event.keyval == Gdk.Key.f || event.keyval == Gdk.Key.F) &&
(event.state & default_modifiers) == Gdk.ModifierType.CONTROL_MASK) {
if (!search_mode)
diff --git a/src/ui/platforms-view.vala b/src/ui/platforms-view.vala
index 37f4c471..144af338 100644
--- a/src/ui/platforms-view.vala
+++ b/src/ui/platforms-view.vala
@@ -1,12 +1,27 @@
// This file is part of GNOME Games. License: GPL-3.0+.
[GtkTemplate (ui = "/org/gnome/Games/ui/platforms-view.ui")]
-private class Games.PlatformsView : Gtk.Box {
+private class Games.PlatformsView : Gtk.Bin {
public signal void game_activated (Game game);
+ [GtkChild]
+ private Hdy.Leaflet leaflet;
+ [GtkChild]
+ private Gtk.ScrolledWindow scrolled_window;
+ [GtkChild]
+ private Gtk.ListBox list_box;
+ [GtkChild]
+ private CollectionIconView collection_view;
+ [GtkChild]
+ private GamepadBrowse gamepad_browse;
+
private ulong model_items_changed_id;
+ private ulong adaptive_state_folded_id;
+ private ulong adaptive_state_subview_id;
+
private GenericSet<Platform> platforms;
private Platform selected_platform;
+ private bool has_used_gamepad;
private string[] filtering_terms;
public string filtering_text {
@@ -52,14 +67,28 @@ private class Games.PlatformsView : Gtk.Box {
}
}
- [GtkChild]
- private CollectionIconView collection_view;
+ private AdaptiveState _adaptive_state;
+ public AdaptiveState adaptive_state {
+ get { return _adaptive_state; }
+ set {
+ if (adaptive_state_subview_id != 0) {
+ adaptive_state.disconnect (adaptive_state_subview_id);
+ adaptive_state_subview_id = 0;
+ }
- [GtkChild]
- private Gtk.ListBox list_box;
+ if (adaptive_state_folded_id != 0) {
+ adaptive_state.disconnect (adaptive_state_folded_id);
+ adaptive_state_folded_id = 0;
+ }
- [GtkChild]
- private GamepadBrowse gamepad_browse;
+ _adaptive_state = value;
+
+ if (adaptive_state != null) {
+ adaptive_state_subview_id = adaptive_state.notify["is-subview-open"].connect
(update_subview);
+ adaptive_state_folded_id = adaptive_state.notify["is-folded"].connect
(update_selection_mode);
+ }
+ }
+ }
construct {
platforms = new GenericSet<Platform> (Platform.hash, Platform.equal);
@@ -71,6 +100,10 @@ private class Games.PlatformsView : Gtk.Box {
});
collection_view.set_game_filter (filter_game);
+
+ on_leaflet_folded_changed ();
+
+ has_used_gamepad = false;
}
private int sort_rows (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
@@ -146,7 +179,9 @@ private class Games.PlatformsView : Gtk.Box {
if (first_row == null)
return false;
- list_box.select_row (first_row);
+ has_used_gamepad = true;
+ update_selection_mode ();
+
// This is needed to start moving the cursor with the gamepad only.
first_row.focus (direction);
@@ -156,15 +191,16 @@ private class Games.PlatformsView : Gtk.Box {
switch (direction) {
case Gtk.DirectionType.UP:
list_box.move_cursor (Gtk.MovementStep.DISPLAY_LINES, -1);
- list_box.activate_cursor_row ();
+ select_platform_for_row (list_box.get_selected_row ());
return true;
case Gtk.DirectionType.DOWN:
list_box.move_cursor (Gtk.MovementStep.DISPLAY_LINES, 1);
- list_box.activate_cursor_row ();
+ select_platform_for_row (list_box.get_selected_row ());
return true;
case Gtk.DirectionType.RIGHT:
+ adaptive_state.is_subview_open = true;
collection_view.select_default_game (Gtk.DirectionType.RIGHT);
return true;
@@ -175,7 +211,8 @@ private class Games.PlatformsView : Gtk.Box {
[GtkCallback]
private bool on_gamepad_accept () {
- list_box.activate_cursor_row ();
+ adaptive_state.is_subview_open = true;
+ collection_view.select_default_game (Gtk.DirectionType.RIGHT);
return true;
}
@@ -183,14 +220,22 @@ private class Games.PlatformsView : Gtk.Box {
[GtkCallback]
private bool on_gamepad_cancel () {
collection_view.unselect_game ();
+ adaptive_state.is_subview_open = false;
return true;
}
[GtkCallback]
private void on_list_box_row_activated (Gtk.ListBoxRow row_item) {
+ select_platform_for_row (row_item);
+
+ adaptive_state.is_subview_open = true;
+ }
+
+ private void select_platform_for_row (Gtk.ListBoxRow row_item) {
var row = row_item as PlatformListItem;
selected_platform = row.platform;
+ adaptive_state.subview_title = selected_platform.get_name ();
collection_view.invalidate_flow_box_filter ();
collection_view.reset_scroll_position ();
@@ -214,14 +259,28 @@ private class Games.PlatformsView : Gtk.Box {
}
}
- public void select_default_row () {
+ public void select_first_visible_row () {
foreach (var child in list_box.get_children ()) {
var row = child as Gtk.ListBoxRow;
if (row.visible) {
list_box.select_row (row);
row.focus (Gtk.DirectionType.LEFT);
- on_list_box_row_activated (row);
+ select_platform_for_row (row);
+ break;
+ }
+ }
+ }
+
+ private void select_current_row () {
+ if (adaptive_state.is_folded && !has_used_gamepad)
+ return;
+
+ foreach (var child in list_box.get_children ()) {
+ var platform_item = child as PlatformListItem;
+
+ if (Platform.equal (platform_item.platform, selected_platform)) {
+ list_box.select_row (platform_item);
break;
}
}
@@ -257,6 +316,26 @@ private class Games.PlatformsView : Gtk.Box {
row.visible = is_row_visible;
}
- select_default_row ();
+ select_first_visible_row ();
+ }
+
+ private void update_selection_mode () {
+ if (!adaptive_state.is_folded || has_used_gamepad)
+ list_box.selection_mode = Gtk.SelectionMode.SINGLE;
+ else
+ list_box.selection_mode = Gtk.SelectionMode.NONE;
+ select_current_row ();
+ }
+
+ [GtkCallback]
+ private void on_leaflet_folded_changed () {
+ adaptive_state.is_folded = leaflet.folded;
+ }
+
+ private void update_subview () {
+ if (adaptive_state.is_subview_open)
+ leaflet.visible_child = collection_view;
+ else
+ leaflet.visible_child = scrolled_window;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]