Skip to content

Commit

Permalink
Overlay windows support (flyout windows)
Browse files Browse the repository at this point in the history
  • Loading branch information
frang75 committed Feb 14, 2024
1 parent 46a3e4a commit ee5c8c8
Show file tree
Hide file tree
Showing 32 changed files with 714 additions and 257 deletions.
8 changes: 8 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@

* `listbox_OnDown()`. [Commit](https://github.com/frang75/nappgui_src/commit/711ea786b8d5dabede70180b57e2414fc8b3533c).

* Overlay windows (flyout) [Issue](https://github.com/frang75/nappgui_src/issues/50). [Doc](https://nappgui.com/en/gui/window.html#h4).

* `window_overlay()`.

* `window_control_frame()` and `window_client_to_screen()` [Issue](https://github.com/frang75/nappgui_src/issues/103).

* `gui_OnIdle()`.

### Fixed

* macOS Sonoma OSView clipping. [Commit](https://github.com/frang75/nappgui_src/commit/ac038f90e555f8751e4dab1889e0448b47c900ae). [Doc](https://developer.apple.com/documentation/macos-release-notes/appkit-release-notes-for-macos-14#NSView).
Expand Down
266 changes: 266 additions & 0 deletions demo/guihello/flyout.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/* Flyout window */

#include "flyout.h"
#include <gui/guiall.h>

typedef struct _flyout_t FlyOut;

struct _flyout_t
{
Window *parent;
Window *flywin;
Menu *menu;
TextView *text;
GuiControl *edit;
uint32_t align;
};

/*---------------------------------------------------------------------------*/

static void i_destroy_flyout(FlyOut **flyout)
{
cassert_no_null(flyout);
cassert_no_null(*flyout);
window_destroy(&(*flyout)->flywin);
if ((*flyout)->menu != NULL)
menu_destroy(&(*flyout)->menu);
heap_delete(flyout, FlyOut);
}

/*---------------------------------------------------------------------------*/

static Window *i_create_flywin(void)
{
uint32_t nrows = 4;
Layout *layout = layout_create(2, nrows);
Panel *panel = panel_create();
Window *window = window_create(ekWINDOW_RETURN | ekWINDOW_ESC);
uint32_t i;

for (i = 0; i < nrows; ++i)
{
char_t text[64];
Label *label = label_create();
Slider *slider = slider_create();
bstd_sprintf(text, sizeof(text), "Flyout control %d", i);
label_text(label, text);
layout_label(layout, label, 0, i);
layout_slider(layout, slider, 1, i);

if (i < nrows - 1)
layout_vmargin(layout, i, 5);
}

layout_hmargin(layout, 0, 5);
layout_margin(layout, 10);
layout_skcolor(layout, kCOLOR_RED);
panel_layout(panel, layout);
window_panel(window, panel);
return window;
}

/*---------------------------------------------------------------------------*/

static void i_OnIdleLaunch(FlyOut *flyout, Event *e)
{
/* Edit control bounds in window coordinates */
R2Df frame = window_control_frame(flyout->parent, flyout->edit);
/* Top-Left edit control in screen coordinates */
V2Df pos = window_client_to_screen(flyout->parent, frame.pos);
/* Flyout window size */
S2Df size = window_get_size(flyout->flywin);

switch (flyout->align) {
case 0:
pos.y += frame.size.height;
break;
case 1:
pos.y -= size.height;
break;
case 2:
pos.x -= size.width - frame.size.width;
pos.y += frame.size.height;
break;
case 3:
pos.x -= size.width - frame.size.width;
pos.y -= size.height;
break;
}

/* Position in screen coordinates */
window_origin(flyout->flywin, pos);
window_overlay(flyout->flywin, flyout->parent);
unref(e);
}

/*---------------------------------------------------------------------------*/

static void i_OnClick(FlyOut *flyout, Event *e)
{
gui_OnIdle(listener(flyout, i_OnIdleLaunch, FlyOut));
unref(e);
}

/*---------------------------------------------------------------------------*/

static Layout *i_controls_layout(FlyOut *flyout)
{
Layout *layout = layout_create(5, 1);
Button *button1 = button_push();
Button *button2 = button_push();
Slider *slider = slider_create();
Edit *edit = edit_create();
button_text(button1, "Push Button");
button_text(button2, "...");
button_OnClick(button2, listener(flyout, i_OnClick, FlyOut));
layout_button(layout, button1, 0, 0);
layout_button(layout, button2, 4, 0);
layout_slider(layout, slider, 1, 0);
layout_edit(layout, edit, 3, 0);
layout_hmargin(layout, 0, 5);
layout_hmargin(layout, 1, 5);
layout_hexpand(layout, 2);
flyout->edit = guicontrol(edit);
return layout;
}

/*---------------------------------------------------------------------------*/

static void i_OnAlign(FlyOut *flyout, Event *e)
{
const EvButton *p = event_params(e, EvButton);
cassert_no_null(flyout);
flyout->align = p->index;
}

/*---------------------------------------------------------------------------*/

static Layout *i_align_layout(FlyOut *flyout)
{
Layout *layout = layout_create(4, 1);
Button *button1 = button_radio();
Button *button2 = button_radio();
Button *button3 = button_radio();
Button *button4 = button_radio();
button_text(button1, "Left-top");
button_text(button2, "Left-bottom");
button_text(button3, "Right-top");
button_text(button4, "Right-bottom");
button_OnClick(button1, listener(flyout, i_OnAlign, FlyOut));
layout_button(layout, button1, 0, 0);
layout_button(layout, button2, 1, 0);
layout_button(layout, button3, 2, 0);
layout_button(layout, button4, 3, 0);
layout_hmargin(layout, 0, 5);
layout_hmargin(layout, 1, 5);
layout_hmargin(layout, 2, 5);
button_state(button1, ekGUI_ON);
return layout;
}

/*---------------------------------------------------------------------------*/

static void i_OnMenu(FlyOut *flyout, Event *e)
{
const EvMenu *p = event_params(e, EvMenu);
textview_writef(flyout->text, p->text);
textview_writef(flyout->text, "\n");
}

/*---------------------------------------------------------------------------*/

static void i_OnDown(FlyOut *flyout, Event *e)
{
const EvMouse *p = event_params(e, EvMouse);
if (p->button == ekGUI_MOUSE_RIGHT && p->tag != UINT32_MAX)
{
uint32_t i = 0;

if (flyout->menu != NULL)
menu_destroy(&flyout->menu);

flyout->menu = menu_create();

for (i = 0; i < 4; ++i)
{
char_t text[64];
MenuItem *item = menuitem_create();
bstd_sprintf(text, sizeof(text), "Item %d Option %d", p->tag + 1, i + 1);
menuitem_text(item, text);
menuitem_OnClick(item, listener(flyout, i_OnMenu, FlyOut));
menu_item(flyout->menu, item);
}

{
V2Df pos = gui_mouse_pos();
menu_launch(flyout->menu, pos);
}
}
}

/*---------------------------------------------------------------------------*/

static Layout *i_listbox_layout(FlyOut *flyout)
{
Layout *layout = layout_create(2, 1);
ListBox *list = listbox_create();
TextView *text = textview_create();
listbox_add_elem(list, "Item 1", NULL);
listbox_add_elem(list, "Item 2", NULL);
listbox_add_elem(list, "Item 3", NULL);
listbox_add_elem(list, "Item 4", NULL);
listbox_OnDown(list, listener(flyout, i_OnDown, FlyOut));
layout_listbox(layout, list, 0, 0);
layout_textview(layout, text, 1, 0);
layout_hmargin(layout, 0, 20);
flyout->text = text;
return layout;
}

/*---------------------------------------------------------------------------*/

static Layout *i_layout(FlyOut *flyout)
{
Layout *layout1 = layout_create(1, 5);
Layout *layout2 = i_align_layout(flyout);
Layout *layout3 = i_controls_layout(flyout);
Layout *layout4 = i_listbox_layout(flyout);
Label *label1 = label_multiline();
Label *label2 = label_create();
label_text(label1, "A flyout window will be show when you press ... button\nPress [ESC] or [RETURN] to close the flyout window");
label_text(label2, "A popup menu will be show when right click in ListBox");
layout_label(layout1, label1, 0, 0);
layout_layout(layout1, layout2, 0, 1);
layout_layout(layout1, layout3, 0, 2);
layout_label(layout1, label2, 0, 3);
layout_layout(layout1, layout4, 0, 4);
layout_vmargin(layout1, 0, 10);
layout_vmargin(layout1, 1, 5);
layout_vmargin(layout1, 2, 5);
layout_vmargin(layout1, 3, 5);
return layout1;
}

/*---------------------------------------------------------------------------*/

static FlyOut *i_flyout(Window *window)
{
FlyOut *flyout = heap_new(FlyOut);
flyout->parent = window;
flyout->flywin = i_create_flywin();
flyout->menu = NULL;
flyout->align = 0;
return flyout;
}

/*---------------------------------------------------------------------------*/

Panel *flyout_window(Window *window)
{
FlyOut *flyout = i_flyout(window);
Layout *layout = i_layout(flyout);
Panel *panel = panel_create();
panel_data(panel, &flyout, i_destroy_flyout, FlyOut);
panel_layout(panel, layout);
return panel;
}
5 changes: 5 additions & 0 deletions demo/guihello/flyout.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* Flyout window */

#include <gui/gui.hxx>

Panel *flyout_window(Window *window);
21 changes: 13 additions & 8 deletions demo/guihello/guihello.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "listboxes.h"
#include "textviews.h"
#include "table.h"
#include "flyout.h"
#include "guibind.h"
#include "ipinput.h"
#include "layoutbind.h"
Expand Down Expand Up @@ -82,30 +83,33 @@ static void i_set_panel(App *app, const uint32_t index)
panel = modal_windows(app->window);
break;
case 14:
panel = hotkeys(app->window);
panel = flyout_window(app->window);
break;
case 15:
panel = guibind();
panel = hotkeys(app->window);
break;
case 16:
panel = layoutbind();
panel = guibind();
break;
case 17:
panel = basic_layout();
panel = layoutbind();
break;
case 18:
panel = sublayouts();
panel = basic_layout();
break;
case 19:
panel = subpanels();
panel = sublayouts();
break;
case 20:
panel = multilayouts();
panel = subpanels();
break;
case 21:
panel = scrollpanel();
panel = multilayouts();
break;
case 22:
panel = scrollpanel();
break;
case 23:
panel = ip_input(app->window);
break;
}
Expand Down Expand Up @@ -151,6 +155,7 @@ static Panel *i_panel(App *app)
listbox_add_elem(list, "TableView", NULL);
listbox_add_elem(list, "SplitViews", NULL);
listbox_add_elem(list, "Modal Windows", NULL);
listbox_add_elem(list, "Flyout Windows", NULL);
listbox_add_elem(list, "Hotkeys", NULL);
listbox_add_elem(list, "Data Binding", NULL);
listbox_add_elem(list, "Struct Binding", NULL);
Expand Down
2 changes: 1 addition & 1 deletion prj/build.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4874
4901
3 changes: 1 addition & 2 deletions src/draw2d/guictx.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ typedef enum _gui_event_t
ekGUI_EVENT_TBL_SEL,
ekGUI_EVENT_TBL_HEADCLICK,
ekGUI_EVENT_TBL_ROWCLICK,

ekGUI_EVENT_IDLE
} gui_event_t;

Expand Down Expand Up @@ -968,7 +967,7 @@ struct _evmenu_t
{
uint32_t index;
gui_state_t state;
const char_t *str;
const char_t *text;
};

struct _evscroll_t
Expand Down

0 comments on commit ee5c8c8

Please sign in to comment.