1/*
2 * Copyright 2018 elementary, Inc. (https://elementary.io)
3 * SPDX-License-Identifier: GPL-2.0-or-later
4 */
5
6/**
7 * ModeSwitch is a selection control for choosing between two options that can be described with an icon.
8 *
9 * ''Example''<<BR>>
10 * {{{
11 *   var gtk_settings = Gtk.Settings.get_default ();
12 *
13 *   var mode_switch = new ModeSwitch.from_icon_name ("display-brightness-symbolic", "weather-clear-night-symbolic");
14 *   mode_switch.primary_icon_tooltip_text = _("Light background");
15 *   mode_switch.secondary_icon_tooltip_text = _("Dark background");
16 *   mode_switch.bind_property ("active", gtk_settings, "gtk_application_prefer_dark_theme");
17 * }}}
18 */
19public class Granite.ModeSwitch : Gtk.Grid {
20    /**
21     * Whether the {@link Gtk.Switch} widget is pointing to the secondary icon or not.
22     */
23    public bool active { get; set; }
24
25    /**
26     * The {@link GLib.Icon} to use for the primary icon for the switch.
27     */
28    public GLib.Icon primary_icon_gicon { get; construct set; }
29
30    /**
31     * The icon name to use for the primary icon for the switch.
32     */
33    public string primary_icon_name { get; construct set; }
34
35    /**
36     * The contents of the tooltip on the primary icon.
37     */
38    public string primary_icon_tooltip_text { get; set; }
39
40    /**
41     * The {@link GLib.Icon} to use for the secondary icon for the switch.
42     */
43    public GLib.Icon secondary_icon_gicon { get; construct set; }
44
45    /**
46     * The icon name to use for the secondary icon for the switch.
47     */
48    public string secondary_icon_name { get; construct set; }
49
50    /**
51     * The contents of the tooltip on the secondary icon.
52     */
53    public string secondary_icon_tooltip_text { get; set; }
54
55    /**
56     * Constructs a new {@link Granite.ModeSwitch} using {@link GLib.Icon}s.
57     *
58     * @param primary_icon_gicon The {@link GLib.Icon} to use for the primary icon for the switch.
59     * @param secondary_icon_gicon The {@link GLib.Icon} to use for the secondary icon for the switch.
60     */
61    public ModeSwitch (GLib.Icon primary_icon_gicon, GLib.Icon secondary_icon_gicon) {
62        Object (
63            primary_icon_gicon: primary_icon_gicon,
64            secondary_icon_gicon: secondary_icon_gicon
65        );
66    }
67
68    /**
69     * Constructs a new {@link Granite.ModeSwitch} from icon names.
70     *
71     * @param primary_icon_name The icon name to use for the primary icon for the switch.
72     * @param secondary_icon_name The icon name to use for the secondary icon for the switch.
73     */
74    public ModeSwitch.from_icon_name (string primary_icon_name, string secondary_icon_name) {
75        Object (
76            primary_icon_gicon: new ThemedIcon (primary_icon_name),
77            secondary_icon_gicon: new ThemedIcon (secondary_icon_name),
78            primary_icon_name: primary_icon_name,
79            secondary_icon_name: secondary_icon_name
80        );
81    }
82
83    construct {
84        var primary_image = new Gtk.Image ();
85        primary_image.pixel_size = 16;
86
87        var primary_icon_box = new Gtk.EventBox ();
88        primary_icon_box.add_events (Gdk.EventMask.BUTTON_RELEASE_MASK);
89        primary_icon_box.add (primary_image);
90
91        var mode_switch = new Gtk.Switch ();
92        mode_switch.valign = Gtk.Align.CENTER;
93        mode_switch.get_style_context ().add_class (Granite.STYLE_CLASS_MODE_SWITCH);
94
95        var secondary_icon = new Gtk.Image ();
96        secondary_icon.pixel_size = 16;
97
98        var secondary_icon_box = new Gtk.EventBox ();
99        secondary_icon_box.add_events (Gdk.EventMask.BUTTON_RELEASE_MASK);
100        secondary_icon_box.add (secondary_icon);
101
102        column_spacing = 6;
103        add (primary_icon_box);
104        add (mode_switch);
105        add (secondary_icon_box);
106
107        bind_property ("primary-icon-gicon", primary_image, "gicon", GLib.BindingFlags.SYNC_CREATE);
108        bind_property ("primary-icon-name", primary_image, "icon-name", GLib.BindingFlags.SYNC_CREATE);
109        bind_property ("primary-icon-tooltip-text", primary_image, "tooltip-text");
110        bind_property ("secondary-icon-gicon", secondary_icon, "gicon", GLib.BindingFlags.SYNC_CREATE);
111        bind_property ("secondary-icon-name", secondary_icon, "icon_name", GLib.BindingFlags.SYNC_CREATE);
112        bind_property ("secondary-icon-tooltip-text", secondary_icon, "tooltip-text");
113
114        this.notify["active"].connect (() => {
115            if (Gtk.StateFlags.DIR_RTL in get_state_flags ()) {
116                mode_switch.active = !active;
117            } else {
118                mode_switch.active = active;
119            }
120        });
121
122        mode_switch.notify["active"].connect (() => {
123            if (Gtk.StateFlags.DIR_RTL in get_state_flags ()) {
124                active = !mode_switch.active;
125            } else {
126                active = mode_switch.active;
127            }
128        });
129
130        primary_icon_box.button_release_event.connect (() => {
131            active = false;
132            return Gdk.EVENT_STOP;
133        });
134
135        secondary_icon_box.button_release_event.connect (() => {
136            active = true;
137            return Gdk.EVENT_STOP;
138        });
139    }
140}
141