HelenOS sources

root/uspace/lib/ui/src/menudd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ui_menu_dd_create
  2. ui_menu_dd_destroy
  3. ui_menu_dd_first
  4. ui_menu_dd_next
  5. ui_menu_dd_last
  6. ui_menu_dd_prev
  7. ui_menu_dd_caption
  8. ui_menu_dd_get_accel
  9. ui_menu_dd_open
  10. ui_menu_dd_close
  11. ui_menu_dd_is_open
  12. ui_menu_dd_left
  13. ui_menu_dd_right
  14. ui_menu_dd_close_req
  15. ui_menu_dd_press_accel

/*
 * Copyright (c) 2023 Jiri Svoboda
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/** @addtogroup libui
 * @{
 */
/**
 * @file Menu drop-down
 *
 * One of the drop-down menus of a menu bar. This class takes the generic
 * ui_menu and ties it to the menu bar.
 */

#include <adt/list.h>
#include <errno.h>
#include <stdlib.h>
#include <str.h>
#include <ui/accel.h>
#include <ui/menu.h>
#include <ui/menudd.h>
#include <ui/menubar.h>
#include <ui/resource.h>
#include "../private/menubar.h"
#include "../private/menudd.h"

static void ui_menu_dd_left(ui_menu_t *, void *, sysarg_t);
static void ui_menu_dd_right(ui_menu_t *, void *, sysarg_t);
static void ui_menu_dd_close_req(ui_menu_t *, void *);
static void ui_menu_dd_press_accel(ui_menu_t *, void *, char32_t, sysarg_t);

static ui_menu_cb_t ui_menu_dd_menu_cb = {
        .left = ui_menu_dd_left,
        .right = ui_menu_dd_right,
        .close_req = ui_menu_dd_close_req,
        .press_accel = ui_menu_dd_press_accel
};

/** Create new menu drop-down.
 *
 * @param mbar Menu bar
 * @param caption Caption
 * @param rmdd Place to store pointer to new menu drop-down or @c NULL
 * @param rmenu Place to store pointer to new menu or @c NULL
 * @return EOK on success, ENOMEM if out of memory
 */
errno_t ui_menu_dd_create(ui_menu_bar_t *mbar, const char *caption,
    ui_menu_dd_t **rmdd, ui_menu_t **rmenu)
{
        errno_t rc;
        ui_menu_dd_t *mdd;

        mdd = calloc(1, sizeof(ui_menu_dd_t));
        if (mdd == NULL)
                return ENOMEM;

        mdd->caption = str_dup(caption);
        if (mdd->caption == NULL) {
                free(mdd);
                return ENOMEM;
        }

        /* Create menu */
        rc = ui_menu_create(mbar->window, &mdd->menu);
        if (rc != EOK) {
                free(mdd->caption);
                free(mdd);
                return rc;
        }

        mdd->mbar = mbar;
        list_append(&mdd->lmenudds, &mbar->menudds);

        ui_menu_set_cb(mdd->menu, &ui_menu_dd_menu_cb, (void *)mdd);

        if (rmdd != NULL)
                *rmdd = mdd;
        if (rmenu != NULL)
                *rmenu = mdd->menu;
        return EOK;
}

/** Destroy menu drop-down.
 *
 * @param menu Menu or @c NULL
 */
void ui_menu_dd_destroy(ui_menu_dd_t *mdd)
{
        if (mdd == NULL)
                return;

        /* Destroy menu */
        ui_menu_destroy(mdd->menu);

        list_remove(&mdd->lmenudds);
        free(mdd->caption);
        free(mdd);
}

/** Get first menu drop-down in menu bar.
 *
 * @param mbar Menu bar
 * @return First menu or @c NULL if there is none
 */
ui_menu_dd_t *ui_menu_dd_first(ui_menu_bar_t *mbar)
{
        link_t *link;

        link = list_first(&mbar->menudds);
        if (link == NULL)
                return NULL;

        return list_get_instance(link, ui_menu_dd_t, lmenudds);
}

/** Get next menu drop-down in menu bar.
 *
 * @param cur Current menu drop-down
 * @return Next menu drop-down or @c NULL if @a cur is the last one
 */
ui_menu_dd_t *ui_menu_dd_next(ui_menu_dd_t *cur)
{
        link_t *link;

        link = list_next(&cur->lmenudds, &cur->mbar->menudds);
        if (link == NULL)
                return NULL;

        return list_get_instance(link, ui_menu_dd_t, lmenudds);
}

/** Get last menu drop-down in menu bar.
 *
 * @param mbar Menu bar
 * @return Last menu drop-down or @c NULL if there is none
 */
ui_menu_dd_t *ui_menu_dd_last(ui_menu_bar_t *mbar)
{
        link_t *link;

        link = list_last(&mbar->menudds);
        if (link == NULL)
                return NULL;

        return list_get_instance(link, ui_menu_dd_t, lmenudds);
}

/** Get previous menu drop-down in menu bar.
 *
 * @param cur Current menu drop-down
 * @return Previous menu drop-down or @c NULL if @a cur is the fist one
 */
ui_menu_dd_t *ui_menu_dd_prev(ui_menu_dd_t *cur)
{
        link_t *link;

        link = list_prev(&cur->lmenudds, &cur->mbar->menudds);
        if (link == NULL)
                return NULL;

        return list_get_instance(link, ui_menu_dd_t, lmenudds);
}

/** Get menu drop-down caption.
 *
 * @param mdd Menu drop-down
 * @return Caption (owned by @a menu)
 */
const char *ui_menu_dd_caption(ui_menu_dd_t *mdd)
{
        return mdd->caption;
}

/** Get menu drop-down accelerator character.
 *
 * @param mdd Menu drop-down
 * @return Accelerator character (lowercase) or the null character if
 *         the menu has no accelerator.
 */
char32_t ui_menu_dd_get_accel(ui_menu_dd_t *mdd)
{
        return ui_accel_get(mdd->caption);
}

/** Open menu drop-down.
 *
 * @param mdd Menu drop-down
 * @param prect Parent rectangle around which the drop-down should be placed
 * @param idev_id Input device associated with the drop-down's seat
 */
errno_t ui_menu_dd_open(ui_menu_dd_t *mdd, gfx_rect_t *prect, sysarg_t idev_id)
{
        return ui_menu_open(mdd->menu, prect, idev_id);
}

/** Close menu drop-down.
 *
 * @param mdd Menu drop-down
 */
void ui_menu_dd_close(ui_menu_dd_t *mdd)
{
        ui_menu_close(mdd->menu);
}

/** Determine if menu drop-down is open.
 *
 * @param mdd Menu drop-down
 * @return @c true iff menu drop-down is open
 */
bool ui_menu_dd_is_open(ui_menu_dd_t *mdd)
{
        return ui_menu_is_open(mdd->menu);
}

/** Handle menu left event.
 *
 * @param menu Menu
 * @param arg Argument (ui_menu_dd_t *)
 * @param idev_id Input device ID
 */
static void ui_menu_dd_left(ui_menu_t *menu, void *arg, sysarg_t idev_id)
{
        ui_menu_dd_t *mdd = (ui_menu_dd_t *)arg;

        (void)menu;

        ui_menu_bar_left(mdd->mbar, idev_id);
}

/** Handle menu right event.
 *
 * @param menu Menu
 * @param arg Argument (ui_menu_dd_t *)
 * @param idev_id Input device ID
 */
static void ui_menu_dd_right(ui_menu_t *menu, void *arg, sysarg_t idev_id)
{
        ui_menu_dd_t *mdd = (ui_menu_dd_t *)arg;

        (void)menu;

        ui_menu_bar_right(mdd->mbar, idev_id);
}

/** Handle menu close request.
 *
 * @param menu Menu
 * @param arg Argument (ui_menu_dd_t *)
 */
static void ui_menu_dd_close_req(ui_menu_t *menu, void *arg)
{
        ui_menu_dd_t *mdd = (ui_menu_dd_t *)arg;

        (void)menu;
        ui_menu_bar_deactivate(mdd->mbar);
}

/** Handle menu accelerator key press event.
 *
 * @param menu Menu
 * @param arg Argument (ui_menu_dd_t *)
 * @param c Character
 * @param kbd_id Keyboard ID
 */
static void ui_menu_dd_press_accel(ui_menu_t *menu, void *arg, char32_t c,
    sysarg_t kbd_id)
{
        ui_menu_dd_t *mdd = (ui_menu_dd_t *)arg;

        (void)menu;
        ui_menu_bar_press_accel(mdd->mbar, c, kbd_id);
}

/** @}
 */

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub