Commit a9b47cd3 authored by Andrei Lisita's avatar Andrei Lisita 🎮

ui: Use the SavestatesList widget

parent 2816850f
Pipeline #103222 passed with stages
in 13 minutes and 52 seconds
......@@ -25,8 +25,19 @@
</packing>
</child>
<child>
<object class="GtkEventBox" id="display_bin">
<object class="GtkBox" id="display_box">
<property name="visible">True</property>
<child>
<object class="GtkEventBox" id="display_bin">
<property name="visible">True</property>
<property name="hexpand">True</property>
</object>
</child>
<child>
<object class="GamesSavestatesList" id="savestates_list">
<property name="visible">True</property>
</object>
</child>
</object>
<packing>
<property name="name">display</property>
......
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
<template class="GamesDisplayHeaderBar" parent="GtkBin">
<template class="GamesDisplayHeaderBar" parent="GtkStack">
<property name="visible">True</property>
<signal name="notify::is-fullscreen" handler="on_fullscreen_changed"/>
<signal name="notify::can-fullscreen" handler="on_fullscreen_changed"/>
<child>
<object class="GtkHeaderBar" id="header_bar">
<object class="GtkHeaderBar" id="ingame_header_bar">
<property name="visible">True</property>
<property name="title" translatable="yes">Games</property>
<property name="show_close_button">True</property>
......@@ -35,24 +35,28 @@
</object>
</child>
<child>
<object class="GtkButton" id="fullscreen">
<object class="GtkButton" id="restore">
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="use-underline">True</property>
<signal name="clicked" handler="on_fullscreen_clicked"/>
<property name="margin-left">5</property>
<signal name="clicked" handler="on_restore_clicked"/>
<style>
<class name="image-button"/>
</style>
<style>
<class name="flat"/>
</style>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-fullscreen">
<property name="accessible-name" translatable="yes">Fullscreen</property>
<object class="AtkObject" id="a11y-restore">
<property name="accessible-name" translatable="yes">Restore</property>
</object>
</child>
<child>
<object class="GtkImage" id="fullscreen_image">
<object class="GtkImage" id="restore_image">
<property name="visible">True</property>
<property name="icon-name">view-fullscreen-symbolic</property>
<property name="icon-name">view-restore-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
......@@ -62,24 +66,46 @@
</packing>
</child>
<child>
<object class="GtkButton" id="restore">
<object class="GtkMenuButton" id="secondary_menu_button">
<property name="popover">secondary_menu</property>
<property name="use-underline">True</property>
<property name="visible">True</property>
<property name="valign">center</property>
<property name="can-focus">False</property>
<style>
<class name="image-button"/>
</style>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="icon-name">view-more-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
<child>
<object class="GtkButton" id="fullscreen">
<property name="visible">False</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<property name="use-underline">True</property>
<signal name="clicked" handler="on_restore_clicked"/>
<signal name="clicked" handler="on_fullscreen_clicked"/>
<style>
<class name="image-button"/>
</style>
<child internal-child="accessible">
<object class="AtkObject" id="a11y-restore">
<property name="accessible-name" translatable="yes">Restore</property>
<object class="AtkObject" id="a11y-fullscreen">
<property name="accessible-name" translatable="yes">Fullscreen</property>
</object>
</child>
<child>
<object class="GtkImage" id="restore_image">
<object class="GtkImage" id="fullscreen_image">
<property name="visible">True</property>
<property name="icon-name">view-restore-symbolic</property>
<property name="icon-name">view-fullscreen-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
......@@ -104,5 +130,72 @@
</child>
</object>
</child>
<child>
<object class="GtkHeaderBar" id="savestates_header_bar">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="load">
<property name="visible">True</property>
<property name="valign">center</property>
<property name="use-underline">True</property>
<property name="label" translatable="yes">_Load</property>
<signal name="clicked" handler="on_savestates_load_clicked"/>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
<child>
<object class="GtkButton" id="delete">
<property name="visible">True</property>
<property name="valign">center</property>
<property name="use-underline">True</property>
<property name="label" translatable="yes">_Delete</property>
<signal name="clicked" handler="on_savestates_delete_clicked"/>
</object>
<packing>
<property name="pack-type">end</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cancel">
<property name="visible">True</property>
<property name="valign">center</property>
<property name="use-underline">True</property>
<property name="label" translatable="yes">_Cancel</property>
<signal name="clicked" handler="on_savestates_cancel_clicked"/>
</object>
<packing>
<property name="pack-type">start</property>
</packing>
</child>
</object>
</child>
</template>
<object class="GtkPopoverMenu" id="secondary_menu">
<child>
<object class="GtkBox" id="secondary_menu_box">
<property name="visible">True</property>
<property name="margin">6</property>
<child>
<object class="GtkModelButton" id="savestates_menu_button">
<property name="visible">True</property>
<property name="text" translatable="yes">_Savestates</property>
<signal name="clicked" handler="on_secondary_menu_savestates_clicked"/>
</object>
</child>
</object>
</child>
</object>
<object class="GtkSizeGroup">
<property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
<widgets>
<widget name="load"/>
<widget name="delete"/>
<widget name="cancel"/>
</widgets>
</object>
</interface>
......@@ -10,11 +10,21 @@ private class Games.DisplayBox : Gtk.Bin {
get { return fullscreen_header_bar; }
}
public SavestatesListState savestates_list_state {
get { return savestates_list.state; }
set {
value.notify["is-revealed"].connect (on_savestates_list_state_changed);
savestates_list.state = value;
fullscreen_header_bar.savestates_list_state = value;
}
}
private Runner _runner;
public Runner runner {
get { return _runner; }
set {
stack.visible_child = display_bin;
stack.visible_child = display_box;
_runner = value;
remove_display ();
......@@ -25,6 +35,8 @@ private class Games.DisplayBox : Gtk.Bin {
var display = runner.get_display ();
set_display (display);
savestates_list.runner = value;
}
}
......@@ -35,11 +47,15 @@ private class Games.DisplayBox : Gtk.Bin {
[GtkChild]
private ErrorDisplay error_display;
[GtkChild]
private Gtk.Box display_box;
[GtkChild]
private Gtk.EventBox display_bin;
[GtkChild]
private DisplayHeaderBar fullscreen_header_bar;
private Binding fullscreen_binding;
[GtkChild]
private SavestatesList savestates_list;
private Binding fullscreen_binding;
private long timeout_id;
construct {
......@@ -49,6 +65,10 @@ private class Games.DisplayBox : Gtk.Bin {
timeout_id = -1;
}
public DisplayBox (SavestatesListState savestates_list_state) {
Object (savestates_list_state: savestates_list_state);
}
public void display_running_game_failed (Game game, string error_message) {
stack.visible_child = error_display;
error_display.running_game_failed (game, error_message);
......@@ -94,4 +114,8 @@ private class Games.DisplayBox : Gtk.Bin {
return runner.gamepad_button_press_event (button);
}
public void on_savestates_list_state_changed () {
fullscreen_box.autohide = !savestates_list.state.is_revealed;
}
}
// This file is part of GNOME Games. License: GPL-3.0+.
[GtkTemplate (ui = "/org/gnome/Games/ui/display-header-bar.ui")]
private class Games.DisplayHeaderBar : Gtk.Bin {
private class Games.DisplayHeaderBar : Gtk.Stack {
public signal void back ();
[GtkChild]
private MediaMenuButton media_button;
private SavestatesListState _savestates_list_state;
public SavestatesListState savestates_list_state {
get { return _savestates_list_state; }
set {
_savestates_list_state = value;
if (value != null)
value.notify["is-revealed"].connect (on_savestates_list_state_changed);
}
}
public string game_title {
set { header_bar.title = value; }
set {
ingame_header_bar.title = value;
savestates_header_bar.title = value;
}
}
public bool show_title_buttons {
set { header_bar.show_close_button = value; }
set { ingame_header_bar.show_close_button = value; }
}
public bool can_fullscreen { get; set; }
......@@ -31,8 +45,12 @@ private class Games.DisplayHeaderBar : Gtk.Bin {
_runner = value;
input_mode_switcher.runner = value;
if (runner != null)
if (runner != null) {
extra_widget = runner.get_extra_widget ();
secondary_menu_button.sensitive = runner.supports_savestates;
secondary_menu_button.visible = runner.can_support_savestates;
}
else
extra_widget = null;
}
......@@ -46,28 +64,40 @@ private class Games.DisplayHeaderBar : Gtk.Bin {
return;
if (extra_widget != null)
header_bar.remove (extra_widget);
ingame_header_bar.remove (extra_widget);
_extra_widget = value;
if (extra_widget != null)
header_bar.pack_end (extra_widget);
ingame_header_bar.pack_end (extra_widget);
}
}
[GtkChild]
private Gtk.HeaderBar header_bar;
private Gtk.HeaderBar ingame_header_bar;
[GtkChild]
private Gtk.Button fullscreen;
[GtkChild]
private Gtk.Button restore;
[GtkChild]
private Gtk.MenuButton secondary_menu_button;
[GtkChild]
private Gtk.HeaderBar savestates_header_bar;
private Settings settings;
public DisplayHeaderBar (SavestatesListState savestates_list_state) {
Object (savestates_list_state: savestates_list_state);
}
construct {
settings = new Settings ("org.gnome.Games");
}
public void hide_secondary_menu_button () {
secondary_menu_button.visible = false;
}
[GtkCallback]
private void on_fullscreen_changed () {
fullscreen.visible = can_fullscreen && !is_fullscreen;
......@@ -90,4 +120,31 @@ private class Games.DisplayHeaderBar : Gtk.Bin {
is_fullscreen = false;
settings.set_boolean ("fullscreen", false);
}
[GtkCallback]
private void on_secondary_menu_savestates_clicked () {
savestates_list_state.is_revealed = true;
}
[GtkCallback]
private void on_savestates_load_clicked () {
savestates_list_state.load_clicked ();
}
[GtkCallback]
private void on_savestates_delete_clicked () {
savestates_list_state.delete_clicked ();
}
[GtkCallback]
private void on_savestates_cancel_clicked () {
savestates_list_state.is_revealed = false;
}
private void on_savestates_list_state_changed () {
if (savestates_list_state.is_revealed)
set_visible_child (savestates_header_bar);
else
set_visible_child (ingame_header_bar);
}
}
......@@ -52,6 +52,8 @@ private class Games.DisplayView : Object, UiView {
private ResumeFailedDialog resume_failed_dialog;
private QuitDialog quit_dialog;
private SavestatesListState savestates_list_state;
private long focus_out_timeout_id;
public DisplayView (Gtk.Window window) {
......@@ -59,14 +61,16 @@ private class Games.DisplayView : Object, UiView {
}
construct {
box = new DisplayBox ();
header_bar = new DisplayHeaderBar ();
savestates_list_state = new SavestatesListState ();
box = new DisplayBox (savestates_list_state);
header_bar = new DisplayHeaderBar (savestates_list_state);
box.back.connect (on_display_back);
header_bar.back.connect (on_display_back);
settings = new Settings ("org.gnome.Games");
// Bind the is_fullscreen property between the header_bar and the box
box_fullscreen_binding = bind_property ("is-fullscreen", box, "is-fullscreen",
BindingFlags.BIDIRECTIONAL);
header_bar_fullscreen_binding = bind_property ("is-fullscreen", header_bar,
......@@ -94,14 +98,15 @@ private class Games.DisplayView : Object, UiView {
if ((event.keyval == Gdk.Key.f || event.keyval == Gdk.Key.F) &&
(event.state & default_modifiers) == Gdk.ModifierType.CONTROL_MASK &&
header_bar.can_fullscreen) {
header_bar.can_fullscreen && !savestates_list_state.is_revealed) {
is_fullscreen = !is_fullscreen;
settings.set_boolean ("fullscreen", is_fullscreen);
return true;
}
if (event.keyval == Gdk.Key.F11 && header_bar.can_fullscreen) {
if (event.keyval == Gdk.Key.F11 && header_bar.can_fullscreen &&
!savestates_list_state.is_revealed) {
is_fullscreen = !is_fullscreen;
settings.set_boolean ("fullscreen", is_fullscreen);
......@@ -148,7 +153,7 @@ private class Games.DisplayView : Object, UiView {
switch (button) {
case EventCode.BTN_MODE:
back ();
on_display_back ();
return true;
default:
......@@ -165,6 +170,9 @@ private class Games.DisplayView : Object, UiView {
}
private void on_display_back () {
if (savestates_list_state.is_revealed)
return;
back ();
}
......@@ -349,6 +357,15 @@ private class Games.DisplayView : Object, UiView {
box.runner.pause ();
if (!box.runner.can_support_savestates) {
// Game does not and will not support savestates (e.g. Steam games)
// => Progress cannot be saved so game can be quit safely
box.runner.stop ();
return true;
}
box.runner.capture_current_state_pixbuf ();
if (box.runner.try_create_savestate (true) != null) {
// Progress saved => can quit game safely
box.runner.stop ();
......@@ -394,6 +411,8 @@ private class Games.DisplayView : Object, UiView {
}
private void reset_display_page () {
header_bar.hide_secondary_menu_button ();
header_bar.can_fullscreen = false;
box.header_bar.can_fullscreen = false;
header_bar.runner = null;
......@@ -411,8 +430,10 @@ private class Games.DisplayView : Object, UiView {
if (!can_update_pause ())
return;
if (window.is_active)
box.runner.resume ();
if (window.is_active) {
if (!savestates_list_state.is_revealed)
box.runner.resume ();
}
else if (with_delay)
focus_out_timeout_id = Timeout.add (FOCUS_OUT_DELAY_MILLISECONDS, on_focus_out_delay_elapsed);
else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment