SciterUI: Add widget for menu bar

This commit is contained in:
N3xoX1 2025-03-25 09:15:38 +10:30
parent 80b3c4fadd
commit c0fc8b44b6
7 changed files with 229 additions and 9 deletions

2
external/sciterui vendored

@ -1 +1 @@
Subproject commit bb76cd6d4d213a647d18361b08b7cbbbe417bf58
Subproject commit ae16bf646df94d1bd15a9a5fd63335ed56deceb0

View File

@ -42,7 +42,6 @@ html > header > window-caption img
height: 1.5em;
}
html > header > window-buttons
{
display: block;
@ -99,4 +98,104 @@ html[window-state="maximized"] > header > window-buttons > window-button[role="w
html > header > window-buttons > window-button[role="window-minimize"]
{
foreground-image: url(icon:window-minimize);
}
}
ul#menu-bar
{
margin: 0;
border-bottom: 1px solid #434242;
border-left: 1px solid transparent;
background: #31363b;
color: #eff0f1;
font-family: 'Segoe UI', Arial, sans-serif;
font-size: 0.9em;
font-weight: 100;
}
ul#menu-bar
{
behavior:menu-bar;
flow: horizontal;
padding: 0;
margin: 0;
}
ul#menu-bar > li
{
padding: 0.5em 0.5em 0.1em 0.5em;
border: 1px solid transparent;
margin:0;
white-space:nowrap;
width:max-content;
display:block;
flow:horizontal;
}
ul#menu-bar > li:hover
{
border: 1px solid #76797c;
}
ul#menu-bar:focus > li:current,
ul#menu-bar > li:owns-popup {
background-color: #3daee9;
}
menu
{
behavior:menu;
flow: vertical;
display:none;
margin:0;
padding:0;
max-width:max-content;
background: #31363b;
color: #eff0f1;
}
@media (menu-animation-supported) {
menu {
popup-animation: popup-animation(type:blend,duration:100ms);
}
}
menu menu
{
max-width: max-content;
}
menu li
{
width:*;
display:block;
flow:horizontal;
vertical-align:middle;
foreground-repeat: no-repeat;
foreground-position: left 2px top 50%;
padding: 0.7em 1.8em 0.7em 1.3em;
margin: 0;
}
menu li:hover
{
background: #18465d;
}
menu li:disabled
{
color:graytext;
foreground-image: none;
}
menu li:has-child-of-type(menu)
{
foreground-image:url(stock:arrow-right);
foreground-repeat: no-repeat;
foreground-position: top 50% right 2px;
}
menu li:has-child-of-type(menu):rtl
{
foreground-image:url(stock:arrow-left);
foreground-repeat: no-repeat;
foreground-position: top 50% left 2px;
}

View File

@ -10,4 +10,5 @@
<window-button role="window-close"></window-button>
</window-buttons>
</header>
<mainmenu id="MainMenu" />
</html>

View File

@ -2,6 +2,7 @@
#include "user_interface/main_window.h"
#include "user_interface/notification.h"
#include "user_interface/sciter_main_window.h"
#include <widgets/menubar.h>
#include <common/std_string.h>
#include <memory>
#include <nxemu-core/app_init.h>
@ -9,6 +10,11 @@
#include <sciter_ui.h>
#include <windows.h>
void RegisterWidgets(ISciterUI & sciterUI)
{
WidgetMenuBar::Register(sciterUI);
}
int WINAPI WinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ LPSTR /*lpszArgs*/, _In_ int /*nWinMode*/)
{
bool Res = AppInit(&Notification::GetInstance());
@ -22,6 +28,7 @@ int WINAPI WinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInsta
}
if (Res)
{
RegisterWidgets(*sciterUI);
SciterMainWindow window(*sciterUI);
window.Show();
sciterUI->Run();

View File

@ -3,11 +3,11 @@
#include "settings/ui_settings.h"
#include <common/path.h>
#include <common/std_string.h>
#include <nxemu-core/machine/switch_system.h>
#include <nxemu-core/settings/core_settings.h>
#include <nxemu-core/settings/identifiers.h>
#include <nxemu-core/settings/settings.h>
#include <nxemu-core/switch_rom.h>
#include <nxemu-core/machine/switch_system.h>
#include <yuzu_common/settings_input.h>
MainWindow::MainWindow(const wchar_t * windowTitle) :
@ -138,7 +138,7 @@ LRESULT MainWindow::OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL
int keyIndex = VKCodeToSwitchKey((uint32_t)wParam);
if (keyIndex != 0)
{
OperatingSystem.KeyboardKeyPress(0, keyIndex, wParam);
OperatingSystem.KeyboardKeyPress(0, keyIndex, wParam);
}
}
return 0;

View File

@ -1,13 +1,56 @@
#include "sciter_main_window.h"
#include "settings/ui_settings.h"
#include <common/std_string.h>
#include <nxemu-core/switch_rom.h>
#include <nxemu-core/version.h>
#include <sciter_element.h>
#include <widgets/menubar.h>
SciterMainWindow::SciterMainWindow(ISciterUI& SciterUI) :
SciterMainWindow::SciterMainWindow(ISciterUI & SciterUI) :
m_sciterUI(SciterUI),
m_window(nullptr),
m_renderWindow(nullptr)
{
}
void SciterMainWindow::ResetMenu()
{
if (m_menuBar == nullptr)
{
return;
}
MenuBarItemList fileMenu;
fileMenu.push_back(MenuBarItem(ID_FILE_OPEN_GAME, "Open Game..."));
Stringlist & recentFiles = uiSettings.recentFiles;
MenuBarItemList RecentGameMenu;
if (recentFiles.size() > 0)
{
int32_t recentFileIndex = 0;
for (Stringlist::const_iterator itr = recentFiles.begin(); itr != recentFiles.end(); itr++)
{
stdstr_f MenuString("%d %s", recentFileIndex + 1, itr->c_str());
RecentGameMenu.push_back(MenuBarItem(ID_RECENT_FILE_START + recentFileIndex, MenuString.c_str()));
recentFileIndex += 1;
}
fileMenu.emplace_back(MenuBarItem::SUB_MENU, "Recent Games", &RecentGameMenu);
}
fileMenu.push_back(MenuBarItem(MenuBarItem::SPLITER));
fileMenu.push_back(MenuBarItem(ID_FILE_EXIT, "Exit"));
MenuBarItemList OptionsMenu;
OptionsMenu.push_back(MenuBarItem(ID_OPTIONS_SETTINGS, "Settings..."));
MenuBarItemList mainTitleMenu;
mainTitleMenu.push_back(MenuBarItem(MenuBarItem::SUB_MENU, "File", &fileMenu));
if (uiSettings.enableModuleConfiguration)
{
mainTitleMenu.push_back(MenuBarItem(MenuBarItem::SUB_MENU, "Options", &OptionsMenu));
}
m_menuBar->AddSink(this);
m_menuBar->SetMenuContent(mainTitleMenu);
}
bool SciterMainWindow::Show(void)
{
enum
@ -31,14 +74,59 @@ bool SciterMainWindow::Show(void)
{
caption.SetHTML((uint8_t *)windowTitle.data(), windowTitle.size());
}
SciterElement menuElement(rootElement.GetElementByID("MainMenu"));
void * interfacePtr = nullptr;
if (menuElement.IsValid() && m_sciterUI.GetElementInterface(menuElement, IID_IMENUBAR, &interfacePtr))
{
m_menuBar = std::shared_ptr<IMenuBar>(reinterpret_cast<IMenuBar *>(interfacePtr), [](IMenuBar *) {});
ResetMenu();
}
return true;
}
void SciterMainWindow::OnOpenGame(void)
{
Path fileToOpen;
const char * filter = "Switch Files (*.nro)\0*.nro\0All files (*.*)\0*.*\0";
if (fileToOpen.FileSelect((void *)m_window->GetHandle(), Path(Path::MODULE_DIRECTORY), filter, true))
{
LaunchSwitchRom(*this, fileToOpen);
}
}
void SciterMainWindow::OnFileExit(void)
{
m_sciterUI.Stop();
}
void SciterMainWindow::OnSettings(void)
{
}
void SciterMainWindow::OnRecetGame(uint32_t fileIndex)
{
}
void SciterMainWindow::OnWindowDestroy(HWINDOW /*hWnd*/)
{
m_sciterUI.Stop();
}
void SciterMainWindow::OnMenuItem(int32_t id, SCITER_ELEMENT item)
{
switch (id)
{
case ID_FILE_OPEN_GAME: OnOpenGame(); break;
case ID_FILE_EXIT: OnFileExit(); break;
case ID_OPTIONS_SETTINGS: OnSettings(); break;
default:
if (id >= ID_RECENT_FILE_START && id <= ID_RECENT_FILE_END)
{
OnRecetGame(id - ID_RECENT_FILE_START);
}
}
}
void * SciterMainWindow::RenderSurface(void) const
{
return m_renderWindow;

View File

@ -1,30 +1,55 @@
#pragma once
#include <memory>
#include <nxemu-core/modules/module_base.h>
#include <sciter_ui.h>
#include <widgets/menubar.h>
class SciterMainWindow :
public IWindowDestroySink,
public IMenuBarSink,
public IRenderWindow
{
enum MainMenuID
{
// File Menu
ID_FILE_OPEN_GAME = 1,
ID_FILE_EXIT,
// Options Menu
ID_OPTIONS_SETTINGS,
// Recent files
ID_RECENT_FILE_START,
ID_RECENT_FILE_END = ID_RECENT_FILE_START + 20,
};
public:
SciterMainWindow(ISciterUI & SciterUI);
void ResetMenu();
bool Show(void);
private:
SciterMainWindow(void) = delete;
SciterMainWindow(const SciterMainWindow&) = delete;
SciterMainWindow& operator=(const SciterMainWindow&) = delete;
SciterMainWindow(const SciterMainWindow &) = delete;
SciterMainWindow & operator=(const SciterMainWindow &) = delete;
void OnOpenGame(void);
void OnFileExit(void);
void OnSettings(void);
void OnRecetGame(uint32_t fileIndex);
// IWindowDestroySink
void OnWindowDestroy(HWINDOW hWnd);
// IMenuBarSink
void OnMenuItem(int32_t id, SCITER_ELEMENT item);
// IRenderWindow
void * RenderSurface(void) const;
ISciterUI & m_sciterUI;
ISciterWindow * m_window;
std::shared_ptr<IMenuBar> m_menuBar;
void * m_renderWindow;
};