Packages

Elixir implementation of D-Bus StatusNotifierItem and com.canonical.dbusmenu

Current section

Files

Jump to
ex_sni lib menu menu_item.ex
Raw

lib/menu/menu_item.ex

defmodule ExSni.Menu.Item do
alias ExSni.Icon.Info, as: IconInfo
alias ExSni.Menu
defstruct id: 0,
type: "standard",
enabled: true,
visible: true,
label: "",
icon: nil,
toggle_type: nil,
toggle_state: nil,
children: [],
callbacks: []
@type id() :: non_neg_integer()
@type toggle_type() :: nil | :checkmark | :radio
@type toggle_state() :: nil | :on | :off
@type t() :: %__MODULE__{
id: id(),
type: String.t(),
enabled: boolean(),
visible: boolean(),
label: String.t(),
icon: String.t() | IconInfo.t(),
toggle_type: toggle_type(),
toggle_state: toggle_state(),
children: list(t()),
callbacks: list(Menu.callback())
}
@type layout() :: {:dbus_variant, {:struct, list()}, dbus_menu_item()}
@type dbus_variant() :: {:dbus_variant, any(), any()}
@type dbus_menu_properties() :: list({String.t(), dbus_variant()})
@type dbus_menu_item() :: {integer(), dbus_menu_properties(), list(dbus_menu_item())}
@dbus_menu_item_type {:struct, [:int32, {:dict, :string, :variant}, {:array, :variant}]}
@spec get_layout(t(), integer(), list(String.t())) :: layout()
def get_layout(%__MODULE__{id: id, children: children} = menu_item, depth, properties) do
prop_values =
properties
|> Enum.map(fn property ->
case ExSni.DbusProtocol.get_property(menu_item, property) do
{:ok, value} -> {property, value}
_ -> nil
end
end)
|> Enum.reject(&(&1 == nil))
children =
case depth do
0 -> []
-1 -> Enum.map(children, &get_layout(&1, -1, properties))
depth -> Enum.map(children, &get_layout(&1, depth - 1, properties))
end
{:dbus_variant, @dbus_menu_item_type,
{
id,
prop_values,
children
}}
end
@spec find_item(t(), id()) :: nil | t()
def find_item(%__MODULE__{children: []}, _id) do
nil
end
def find_item(%__MODULE__{children: [%__MODULE__{id: id} = item | _]}, id) do
item
end
def find_item(%__MODULE__{children: [item | items]}, id) do
case find_item(item, id) do
nil -> find_item(%{item | children: items}, id)
item -> item
end
end
defimpl ExSni.DbusProtocol do
def get_property(%{type: type}, "type") do
{:ok, {:dbus_variant, :string, type}}
end
def get_property(%{enabled: enabled}, "enabled") do
{:ok, {:dbus_variant, :boolean, enabled}}
end
def get_property(%{visible: visible}, "visible") do
{:ok, {:dbus_variant, :boolean, visible}}
end
def get_property(%{label: label}, "label") do
{:ok, {:dbus_variant, :string, label}}
end
def get_property(%{icon: icon_name}, "icon_name") when is_binary(icon_name) do
{:ok, {:dbus_variant, :string, icon_name}}
end
def get_property(%{icon: %IconInfo{name: name}}, "icon-name") do
{:ok, {:dbus_variant, :string, name}}
end
def get_property(%{icon: %IconInfo{data: data}}, "icon-data") when is_binary(data) do
{:ok, data}
end
def get_property(_, "icon-data") do
{:ok, {:dbus_variant, :string, ""}}
end
def get_property(%{toggle_type: :checkmark}, "toggle-type") do
{:ok, {:dbus_variant, :string, "checkmark"}}
end
def get_property(%{toggle_type: :radio}, "toggle-type") do
{:ok, {:dbus_variant, :string, "radio"}}
end
def get_property(_, "toggle-type") do
{:ok, {:dbus_variant, :string, ""}}
end
def get_property(%{toggle_state: :on}, "toggle-state") do
{:ok, {:dbus_variant, :int32, 1}}
end
def get_property(%{toggle_state: :off}, "toggle-state") do
{:ok, {:dbus_variant, :int32, 0}}
end
def get_property(_, "toggle-state") do
{:ok, {:dbus_variant, :int32, -1}}
end
def get_property(%{children: [_ | _]}, "children-display") do
{:ok, {:dbus_variant, :string, "submenu"}}
end
def get_property(%{children: []}, "children-display") do
{:ok, {:dbus_variant, :string, ""}}
end
def get_property(_, _) do
{:error, "org.freedesktop.DBus.Error.UnknownProperty", "Invalid property"}
end
def get_properties(item, []) do
get_properties(item, [
"type",
"enabled",
"visible",
"label",
"icon-name",
"icon-data",
"toggle-type",
"toggle-state",
"children-display"
])
end
def get_properties(item, properties) do
properties
|> Enum.reduce([], fn property, acc ->
case get_property(item, property) do
{:ok, value} -> [{property, value} | acc]
_ -> acc
end
end)
end
end
end