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

Use drop downs instead of combo boxes #400

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
101 changes: 100 additions & 1 deletion src/Objects/VirtualMonitor.vala
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,31 @@
*/

public class Display.VirtualMonitor : GLib.Object {
public class Transform : Object, Utils.StringRepresentable {
public string string_representation { get; construct; }
public DisplayTransform transform { get; construct; }

public Transform (DisplayTransform transform) {
Object (transform: transform, string_representation: transform.to_string ());
}
}

public class RefreshRate : Object, Utils.StringRepresentable {
public string string_representation { get; construct; }
public MonitorMode mode { get; construct; }

public RefreshRate (MonitorMode mode) {
Object (mode: mode, string_representation: _("%g Hz").printf (Math.round (mode.frequency)));
}
}

public int x { get; set; }
public int y { get; set; }
public int current_x { get; set; }
public int current_y { get; set; }
public double scale { get; set; }
public DisplayTransform transform { get; set; }
public Gtk.SingleSelection available_transforms { get; construct; }
public Gtk.SingleSelection available_refresh_rates { get; construct; }
public bool primary { get; set; }
public Gee.LinkedList<Display.Monitor> monitors { get; construct; }

Expand Down Expand Up @@ -55,6 +74,15 @@ public class Display.VirtualMonitor : GLib.Object {

public bool is_active { get; set; default = true; }

public DisplayTransform transform {
get {
return (DisplayTransform) available_transforms.selected;
}
set {
available_transforms.selected = value;
}
}

/*
* Get the first monitor of the list, handy in non-mirror context.
*/
Expand All @@ -68,8 +96,30 @@ public class Display.VirtualMonitor : GLib.Object {
}
}

private ListStore available_transforms_store;
private ListStore available_refresh_rates_store;

construct {
monitors = new Gee.LinkedList<Display.Monitor> ();

available_transforms_store = new ListStore (typeof (Transform));
available_transforms = new Gtk.SingleSelection (available_transforms_store) {
autoselect = true
};

for (int i = 0; i <= DisplayTransform.FLIPPED_ROTATION_270; i++) {
available_transforms_store.append (new Transform ((DisplayTransform) i));
}

available_refresh_rates_store = new ListStore (typeof (RefreshRate));
available_refresh_rates = new Gtk.SingleSelection (available_refresh_rates_store) {
autoselect = true
};

available_refresh_rates.selection_changed.connect (() =>
set_current_mode (((RefreshRate) available_refresh_rates.get_item (available_refresh_rates.selected)).mode));

Idle.add_once (update_available_refresh_rates);
}

public unowned string get_display_name () {
Expand Down Expand Up @@ -125,6 +175,12 @@ public class Display.VirtualMonitor : GLib.Object {
}

public void set_current_mode (Display.MonitorMode current_mode) {
var old_current_mode = monitors[0].current_mode;

if (old_current_mode == current_mode) {
return;
}

if (is_mirror) {
monitors.foreach ((_monitor) => {
bool mode_found = false;
Expand All @@ -149,6 +205,49 @@ public class Display.VirtualMonitor : GLib.Object {
mode.is_current = mode == current_mode;
}
}

update_available_refresh_rates ();
}

private void update_available_refresh_rates () {
int active_width, active_height;
get_current_mode_size (out active_width, out active_height);

double[] frequencies = {};
RefreshRate[] refresh_rates = {};
uint to_select = 0;
foreach (var mode in get_available_modes ()) {
if (mode.width != active_width || mode.height != active_height) {
continue;
}

if (mode.frequency in frequencies) {
continue;
}

bool freq_already_added = false;
foreach (var freq in frequencies) {
if ((mode.frequency - freq).abs () < 1) {
freq_already_added = true;
break;
}
}

if (freq_already_added) {
continue;
}

frequencies += mode.frequency;

refresh_rates += new RefreshRate (mode);

if (mode.is_current) {
to_select = refresh_rates.length - 1;
}
}

available_refresh_rates_store.splice (0, available_refresh_rates_store.get_n_items (), refresh_rates);
available_refresh_rates.selected = to_select;
}

public static string generate_id_from_monitors (MutterReadMonitorInfo[] infos) {
Expand Down
24 changes: 24 additions & 0 deletions src/Utils.vala
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,28 @@ namespace Display.Utils {

return min_scale;
}

public interface StringRepresentable : Object {
public abstract string string_representation { get; construct; }
}

/**
* Sets up a ListItemFactory that represents its items by a single start aligned label.
* The items have to implement {@link StringRepresentable}.
* Useful for {@link Gtk.DropDown}s.
*/
public static Gtk.ListItemFactory create_string_list_item_factory () {
var string_list_item_factory = new Gtk.SignalListItemFactory ();
string_list_item_factory.setup.connect ((obj) => {
var list_item = (Gtk.ListItem) obj;
list_item.child = new Gtk.Label (null) { xalign = 0 };
});
string_list_item_factory.bind.connect ((obj) => {
var list_item = (Gtk.ListItem) obj;
var item = (StringRepresentable) list_item.item;
var scale_label = (Gtk.Label) list_item.child;
scale_label.label = item.string_representation;
});
return string_list_item_factory;
}
}
Loading