DVUI

dropped

Parameters

#
self:*DropdownWidget
*DropdownWidget

Source

Implementation

#
pub fn dropped(self: *DropdownWidget) bool {
    if (self.drop != null) {
        // protect against calling this multiple times
        return true;
    }

    if (self.menuItem.activeRect()) |r| {
        var from = r;
        const s = dvui.parentGet().screenRectScale(Rect{}).s / dvui.windowNaturalScale();

        // move drop up-left to align first item
        const menuDefaults = dvui.FloatingMenuWidget.defaults;
        from.x -= menuDefaults.borderGet().x * s;
        from.x -= menuDefaults.paddingGet().x * s;
        from.y -= menuDefaults.borderGet().y * s;
        from.y -= menuDefaults.paddingGet().y * s;

        // move drop up so selected entry is aligned
        from.y -= self.drop_adjust * s;

        self.drop = @as(FloatingMenuWidget, undefined); // Needs to be a non-null value so `.?` bellow doesn't panic
        var drop = &self.drop.?;
        drop.init(@src(), .{ .from = from, .avoid = .none }, .{ .role = .none, .min_size_content = .cast(r.size()) });

        self.drop_first_frame = dvui.firstFrame(drop.data().id);

        // without this, if you trigger the dropdown with the keyboard and then
        // move the mouse, the entries are highlighted but not focused
        drop.menu.submenus_activated = true;

        // only want a mouse-up to choose something if the mouse has moved in the dropup
        var eat_mouse_up = dvui.dataGet(null, drop.data().id, "_eat_mouse_up", bool) orelse true;
        var drag_scroll = dvui.dataGet(null, drop.data().id, "_drag_scroll", bool) orelse false;

        const drop_rs = drop.data().rectScale();
        const scroll_rs = drop.scroll.data().contentRectScale();
        const evts = dvui.events();
        for (evts) |*e| {
            if (drag_scroll and e.evt == .mouse and !e.evt.mouse.button.touch() and (e.evt.mouse.action == .motion or e.evt.mouse.action == .position)) {
                if (e.evt.mouse.p.x >= scroll_rs.r.x and e.evt.mouse.p.x <= scroll_rs.r.x + scroll_rs.r.w and (e.evt.mouse.p.y <= scroll_rs.r.y or e.evt.mouse.p.y >= scroll_rs.r.y + scroll_rs.r.h)) {
                    if (e.evt.mouse.action == .motion) {
                        dvui.scrollDrag(.{
                            .mouse_pt = e.evt.mouse.p,
                            .screen_rect = drop.menu.data().rectScale().r,
                        });
                    } else if (e.evt.mouse.action == .position) {
                        dvui.currentWindow().inject_motion_event = true;
                    }
                }
            }

            if (!dvui.eventMatch(e, .{ .id = drop.data().id, .r = drop_rs.r }))
                continue;

            if (e.evt == .mouse) {
                if (e.evt.mouse.action == .release and e.evt.mouse.button.pointer()) {
                    if (eat_mouse_up) {
                        e.handle(@src(), drop.data());
                        eat_mouse_up = false;
                        dvui.dataSet(null, drop.data().id, "_eat_mouse_up", eat_mouse_up);
                    }
                } else if (e.evt.mouse.action == .motion or (e.evt.mouse.action == .press and e.evt.mouse.button.pointer())) {
                    if (eat_mouse_up) {
                        eat_mouse_up = false;
                        dvui.dataSet(null, drop.data().id, "_eat_mouse_up", eat_mouse_up);
                    }

                    if (!drag_scroll) {
                        drag_scroll = true;
                        dvui.dataSet(null, drop.data().id, "_drag_scroll", drag_scroll);
                    }
                }
            }
        }
    }

    if (self.drop != null) {
        return true;
    }

    return false;
}