Radical Menu System for AwesomeWM

repository·master·Indexed 42 days ago

https://github.com/elv13/radical

A comprehensive menu system extension for AwesomeWM providing a unified interface for context menus, docks, bars, and centered box menus. It includes a re-implementation of awful.taglist (Radical Taglist) with support for multi-screen and screen-independent tags, as well as customizable tasklists, styled tooltips, and flexible layout options for vertical, horizontal, and grid arrangements.

Tokens
5.2K
Snippets
14
Records
24
Agent score
53%

What's inside Radical

  1. Overview of Radical Taglist

    master

    Radical Taglist is a re-implementation of awful.taglist for AwesomeWM. It introduces a new abstraction layer between the taglist and the tags to support more flexible concepts like multi-screen tags and screen-independent tags.

    Unlike the original implementation, Radical Taglist simplifies the concept of "focused" tags by treating them as a list of selected tags, ignoring the traditional focus model.

  2. Extend Radical using the Object Model

    master

    Radical uses an object model similar to AwesomeWM, where objects emit signals for change notifications. A key feature is that properties are automatically generated. You can add new properties by defining a setter (set_propertyname) and a getter (get_propertyname). Once defined, Radical automatically generates a propertyname::changed signal. You can also manually emit custom signals using emit_signal.

    local menu = radical.context{}
    
    -- Create the setter
    menu.set_foo = function(m, value)
        print("Setting value to:", value)
        m._foo_real = value
    end
    
    -- Create the getter
    menu.get_foo = function(m)
        print("Getter called, returning", m._foo_real)
        return m._foo_real
    end
    
    -- The property is now created, this will call the setter:
    menu.foo = "my foo value"
    
    -- This will call the getter:
    print(menu.foo)
    
    -- The signals will be automatically generated
    menu:connect_signal("foo::changed", function(m, value)
        print("foo changed:", value)
    end)
    
    -- New signals don't need to be registered and can be called right away
    menu:connect_signal("my_new_signal::action_name", function(m, value1, value2, value3)
        print("Callback", m, value1, value2, value3)
    end)
    
    -- Manually emitting a signal
    menu:emit_signal("my_new_signal::action_name", value1, value2, value3)
  3. Create and use a context menu

    master

    Radical menus are built by adding items one by one using the :add_item method. This allows for programmatic interaction with individual items.

    To attach a menu to a widget, use the :set_menu method. This method supports lazy-loading via a function and allows specifying the trigger event and mouse button.

    Mouse Button Mapping:

    • 1: Left mouse button
    • 3: Right mouse button

    Key Bindings: You can add key bindings to menus using :add_key_binding(keys, key). This works best with "box" menus.

    local menu = radical.context{}
    menu:add_item {text="Screen 1", button1=function(_menu,item,mods) print("Hello World! ") end}
    menu:add_item {text="Screen 9", icon= beautiful.awesome_icon}
    menu:add_item {text="Sub Menu", sub_menu = function()
        local smenu = radical.context{}
        smenu:add_item{text="item 1"}
        smenu:add_item{text="item 2"}
        return smenu
    end}
    
    -- To add the menu to a widget:
    local mytextbox = wibox.widget.textbox()
    mytextbox:set_menu(menu, "button::pressed", 3) -- 3 = right mouse button
    
    -- To add a key binding
    menu:add_key_binding({"Mod4"}, ",")
  4. Install Radical for AwesomeWM

    master

    To install Radical, clone the repository into your AwesomeWM configuration directory (~/.config/awesome).

    Note on Versions:

    • For Awesome 4.0+: Use the master branch.
    • For Awesome 3.5: Use the awesome3.5 branch.
    • If using Awesome git master: Use the awesome3.6 branch.
    cd ~/.config/awesome
    git clone https://github.com/Elv13/radical.git
  5. Configure Radical Taglist options

    master

    Radical Taglist provides several configuration options to control behavior and appearance.

    Behavioral Options:

    • taglist_watch_name_changes: If enabled, the tag state will transition to changed when a client title changes.

    Styling Options:

    • taglist_style: Defines the style engine used for the taglist.
    • taglist_default_icon: The default icon used for tags.
    • taglist_disable_icon: Whether to disable icons.
    • taglist_icon_transformation: Function to transform icons.
    • taglist_fg_prefix: A prefix applied to the foreground color.
    • taglist_disable_index: Whether to disable the index.
    • taglist_default_margins: Default margins for the taglist.
    • taglist_default_item_margins: Default margins for individual items.
  6. Configure Radical via Beautiful (Theme)

    master

    Radical supports theme configuration using beautiful. You can set global styles for menus, including colors, borders, and corner radii.

    Key Beautiful keys:

    • menu_height: Menu height.
    • menu_width: Default/minimum menu width.
    • menu_border_width: Border width.
    • menu_border_color: Border color.
    • menu_fg_normal: Default text/foreground color.
    • menu_bg_focus: Selected item background color.
    • menu_bg_normal: Default background color.
    • menu_opacity: Menu translucency (0 to 1).
    • menu_corner_radius: Arrow-based menu corner radius (default: 10).
    • menu_checkbox_style: Style for checkboxes ("holo" or "default").
  7. Apply styles and layouts to a menu

    master

    When creating a menu, you can pass a configuration table to define its style, item style, and layout.

    local radical = require("radical")
    
    local m = radical.context {
        style      = radical.style.classic,
        item_style = radical.item.style.classic,
        layout     = radical.layout.vertical
    }
  8. Manage item states and colors

    master

    Radical supports multiple simultaneous states per item. States are identified by integer IDs (from $-\infty$ to $\infty$). The "current state" is determined by the state with the smallest ID.

    To implement custom states with specific colors, use radical.theme.register_color(id, radical_name, beautiful_name, true).

    You can toggle states using the item.state metatable.

    local my_state_name = 9999 -- <== The ID
    local menu = radical.context{}
    local item = menu:add_item{text="text"}
    
    -- Activate a state
    item.state[my_state_name] = true
    
    -- Deactivate a state
    item.state[my_state_name] = nil
  9. Use styled tooltips

    master

    Radical includes a styled tooltip widget. You can use it in menus or apply it to any widget using the :set_tooltip method.

    local mytextbox = wibox.widget.textbox()
    mytextbox:set_tooltip("foo bar")
  10. Handle menu and item signals

    master

    Radical menus emit signals for property changes and user interactions. Signals follow the pattern PROPERTY_NAME::changed or specific item events.

    Property Signals:

    • opacity::changed: Emitted when opacity changes.

    Item Signals:

    • item::moved, item::swapped, item::removed, item::appended.

    Widget/Layout Signals:

    • button::press / button::release: Mouse button interactions (includes mods array).
    • mouse::enter / mouse::leave: Mouse hover entry/exit.
    • long::hover / long::press: Long duration interactions (1.5 sec).

    Example: Catching an opacity change:

    mymenu:connect_signal("opacity::changed", function(value)
        -- Do something
    end)

    Example: Handling button presses with modifiers:

    local menubar = radical.bar{}
    menubar:connect_signal("button::press", function(data, item, button, mods)
        if mods.Control then
            print("Foo menu pressed!", item.text, button, data.rowcount)
        end
    end)
        local menubar = radical.bar{}
        menubar:connect_signal("button::press",function(data,item,button,mods)
            if mods.Control then
                print("Foo menu pressed!",item.text,button,data.rowcount)
            end
        end)
        
        -- Also work on items
        menubar:add_item{text="bar"}:connect_signal("button::release",function(d,i,b,m)
            print("bar click released!")
        end)
  11. Configure menu item visual properties

    master

    When creating a menu via radical.context(), you can define the visual appearance of items using several keys:

    • layout: The overall menu arrangement (e.g., radical.layout.horizontal).
    • item_layout: The layout of content within an individual item (e.g., radical.item.layout.centerred).
    • item_width / item_height: Dimensions for the items.
    • icon_size: The size of the icon within the item.
    • arrow_type: The style of navigation arrows (e.g., radical.base.arrow_type.CENTERED).
    • item_style: The visual style of the item container (e.g., radical.item.style.rounded).