Setup UI menu code
This commit is contained in:
parent
4411a4499d
commit
459024059a
|
@ -19,7 +19,8 @@ namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
MainWindow::MainWindow(Emulator* emulator)
|
MainWindow::MainWindow(Emulator* emulator)
|
||||||
: PlatformWindow(L"xenia"), emulator_(emulator) {}
|
: PlatformWindow(L"xenia"), emulator_(emulator),
|
||||||
|
main_menu_(MenuItem::Type::kNormal) {}
|
||||||
|
|
||||||
MainWindow::~MainWindow() = default;
|
MainWindow::~MainWindow() = default;
|
||||||
|
|
||||||
|
@ -64,6 +65,19 @@ bool MainWindow::Initialize() {
|
||||||
}
|
}
|
||||||
e.set_handled(handled);
|
e.set_handled(handled);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Main menu
|
||||||
|
// FIXME: This code is really messy.
|
||||||
|
auto file = std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&File");
|
||||||
|
file->AddChild(std::make_unique<PlatformMenu>(
|
||||||
|
MenuItem::Type::kString, Commands::IDC_FILE_OPEN, L"&Open"));
|
||||||
|
|
||||||
|
main_menu_.AddChild(std::move(file));
|
||||||
|
|
||||||
|
auto debug = std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&Debug");
|
||||||
|
|
||||||
|
SetMenu(&main_menu_);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +89,10 @@ void MainWindow::OnClose() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::OnCommand(int id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
X_STATUS MainWindow::LaunchPath(std::wstring path) {
|
X_STATUS MainWindow::LaunchPath(std::wstring path) {
|
||||||
X_STATUS result;
|
X_STATUS result;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
// TODO(benvanik): only on windows.
|
// TODO(benvanik): only on windows.
|
||||||
#include "xenia/ui/win32/win32_loop.h"
|
#include "xenia/ui/win32/win32_loop.h"
|
||||||
#include "xenia/ui/win32/win32_window.h"
|
#include "xenia/ui/win32/win32_window.h"
|
||||||
|
#include "xenia/ui/win32/win32_menu_item.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
class Emulator;
|
class Emulator;
|
||||||
|
@ -26,6 +27,7 @@ namespace ui {
|
||||||
|
|
||||||
using PlatformLoop = xe::ui::win32::Win32Loop;
|
using PlatformLoop = xe::ui::win32::Win32Loop;
|
||||||
using PlatformWindow = xe::ui::win32::Win32Window;
|
using PlatformWindow = xe::ui::win32::Win32Window;
|
||||||
|
using PlatformMenu = xe::ui::win32::Win32MenuItem;
|
||||||
|
|
||||||
class MainWindow : public PlatformWindow {
|
class MainWindow : public PlatformWindow {
|
||||||
public:
|
public:
|
||||||
|
@ -43,9 +45,15 @@ class MainWindow : public PlatformWindow {
|
||||||
bool Initialize();
|
bool Initialize();
|
||||||
|
|
||||||
void OnClose() override;
|
void OnClose() override;
|
||||||
|
void OnCommand(int id) override;
|
||||||
|
|
||||||
|
enum Commands {
|
||||||
|
IDC_FILE_OPEN,
|
||||||
|
};
|
||||||
|
|
||||||
Emulator* emulator_;
|
Emulator* emulator_;
|
||||||
PlatformLoop loop_;
|
PlatformLoop loop_;
|
||||||
|
PlatformMenu main_menu_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -14,6 +14,9 @@ namespace ui {
|
||||||
|
|
||||||
MenuItem::MenuItem(Type type) : type_(type), parent_item_(nullptr) {}
|
MenuItem::MenuItem(Type type) : type_(type), parent_item_(nullptr) {}
|
||||||
|
|
||||||
|
MenuItem::MenuItem(Type type, const std::wstring &text) :
|
||||||
|
type_(type), parent_item_(nullptr), text_(text) {}
|
||||||
|
|
||||||
MenuItem::~MenuItem() = default;
|
MenuItem::~MenuItem() = default;
|
||||||
|
|
||||||
void MenuItem::AddChild(MenuItem* child_item) {
|
void MenuItem::AddChild(MenuItem* child_item) {
|
||||||
|
|
|
@ -19,20 +19,22 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
class Window;
|
|
||||||
|
|
||||||
class MenuItem {
|
class MenuItem {
|
||||||
public:
|
public:
|
||||||
typedef std::unique_ptr<MenuItem, void (*)(MenuItem*)> MenuItemPtr;
|
typedef std::unique_ptr<MenuItem, void (*)(MenuItem*)> MenuItemPtr;
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
kNormal,
|
kPopup, // Popup menu (submenu)
|
||||||
kSeparator,
|
kSeparator,
|
||||||
|
kNormal, // Root menu
|
||||||
|
kString, // Menu is just a string
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~MenuItem();
|
virtual ~MenuItem();
|
||||||
|
|
||||||
MenuItem* parent_item() const { return parent_item_; }
|
MenuItem* parent_item() const { return parent_item_; }
|
||||||
|
Type type() { return type_; }
|
||||||
|
const std::wstring &text() { return text_; }
|
||||||
|
|
||||||
void AddChild(MenuItem* child_item);
|
void AddChild(MenuItem* child_item);
|
||||||
void AddChild(std::unique_ptr<MenuItem> child_item);
|
void AddChild(std::unique_ptr<MenuItem> child_item);
|
||||||
|
@ -43,16 +45,17 @@ class MenuItem {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MenuItem(Type type);
|
MenuItem(Type type);
|
||||||
|
MenuItem(Type type, const std::wstring &text);
|
||||||
|
|
||||||
virtual void OnChildAdded(MenuItem* child_item) {}
|
virtual void OnChildAdded(MenuItem* child_item) {}
|
||||||
virtual void OnChildRemoved(MenuItem* child_item) {}
|
virtual void OnChildRemoved(MenuItem* child_item) {}
|
||||||
|
|
||||||
virtual void OnSelected(UIEvent& e);
|
virtual void OnSelected(UIEvent& e);
|
||||||
|
|
||||||
private:
|
|
||||||
Type type_;
|
Type type_;
|
||||||
MenuItem* parent_item_;
|
MenuItem* parent_item_;
|
||||||
std::vector<MenuItemPtr> children_;
|
std::vector<MenuItemPtr> children_;
|
||||||
|
std::wstring text_; // Text associated with this item (typically the title)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -9,12 +9,29 @@
|
||||||
|
|
||||||
#include "xenia/ui/win32/win32_menu_item.h"
|
#include "xenia/ui/win32/win32_menu_item.h"
|
||||||
|
|
||||||
|
#include "xenia/base/assert.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
namespace win32 {
|
namespace win32 {
|
||||||
|
|
||||||
|
Win32MenuItem::Win32MenuItem(Type type, int id, const std::wstring& text)
|
||||||
|
: id_(id), MenuItem(type, text) {
|
||||||
|
switch (type) {
|
||||||
|
case MenuItem::Type::kNormal:
|
||||||
|
handle_ = CreateMenu();
|
||||||
|
break;
|
||||||
|
case MenuItem::Type::kPopup:
|
||||||
|
handle_ = CreatePopupMenu();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Win32MenuItem::Win32MenuItem(Type type)
|
Win32MenuItem::Win32MenuItem(Type type)
|
||||||
: MenuItem(type), handle_(CreateMenu()) {}
|
: Win32MenuItem(type, 0, L"") {}
|
||||||
|
|
||||||
|
Win32MenuItem::Win32MenuItem(Type type, const std::wstring& text)
|
||||||
|
: Win32MenuItem(type, 0, text) {}
|
||||||
|
|
||||||
Win32MenuItem::~Win32MenuItem() {
|
Win32MenuItem::~Win32MenuItem() {
|
||||||
if (handle_) {
|
if (handle_) {
|
||||||
|
@ -24,7 +41,20 @@ Win32MenuItem::~Win32MenuItem() {
|
||||||
|
|
||||||
void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) {
|
void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) {
|
||||||
auto child_item = static_cast<Win32MenuItem*>(generic_child_item);
|
auto child_item = static_cast<Win32MenuItem*>(generic_child_item);
|
||||||
//
|
|
||||||
|
switch (child_item->type()) {
|
||||||
|
case MenuItem::Type::kPopup:
|
||||||
|
AppendMenuW(handle_, MF_POPUP, (UINT)child_item->handle(),
|
||||||
|
child_item->text().c_str());
|
||||||
|
break;
|
||||||
|
case MenuItem::Type::kSeparator:
|
||||||
|
AppendMenuW(handle_, MF_SEPARATOR, child_item->id(), 0);
|
||||||
|
break;
|
||||||
|
case MenuItem::Type::kString:
|
||||||
|
AppendMenuW(handle_, MF_STRING, child_item->id(),
|
||||||
|
child_item->text().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32MenuItem::OnChildRemoved(MenuItem* generic_child_item) {
|
void Win32MenuItem::OnChildRemoved(MenuItem* generic_child_item) {
|
||||||
|
|
|
@ -21,16 +21,23 @@ namespace win32 {
|
||||||
|
|
||||||
class Win32MenuItem : public MenuItem {
|
class Win32MenuItem : public MenuItem {
|
||||||
public:
|
public:
|
||||||
|
Win32MenuItem(Type type);
|
||||||
|
Win32MenuItem(Type type, const std::wstring &text);
|
||||||
|
Win32MenuItem(Type type, int id, const std::wstring &text);
|
||||||
~Win32MenuItem() override;
|
~Win32MenuItem() override;
|
||||||
|
|
||||||
|
HMENU handle() { return handle_; }
|
||||||
|
int id() { return id_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OnChildAdded(MenuItem* child_item) override;
|
void OnChildAdded(MenuItem* child_item) override;
|
||||||
void OnChildRemoved(MenuItem* child_item) override;
|
void OnChildRemoved(MenuItem* child_item) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Win32MenuItem(Type type);
|
|
||||||
|
|
||||||
HMENU handle_;
|
HMENU handle_;
|
||||||
|
uint32_t position_; // Position within parent, if any
|
||||||
|
int id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace win32
|
} // namespace win32
|
||||||
|
|
|
@ -20,7 +20,9 @@ namespace ui {
|
||||||
namespace win32 {
|
namespace win32 {
|
||||||
|
|
||||||
Win32Window::Win32Window(const std::wstring& title)
|
Win32Window::Win32Window(const std::wstring& title)
|
||||||
: Window(title), main_menu_(nullptr), closing_(false) {}
|
: Window(title), closing_(false) {
|
||||||
|
menu_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Win32Window::~Win32Window() {}
|
Win32Window::~Win32Window() {}
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ bool Win32Window::Create() {
|
||||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
|
|
||||||
// Create window.
|
// Create window.
|
||||||
hwnd_ = CreateWindowEx(window_ex_style, L"XeniaWindowClass", L"Xenia",
|
hwnd_ = CreateWindowEx(window_ex_style, L"XeniaWindowClass", title_.c_str(),
|
||||||
window_style, rc.left, rc.top, rc.right - rc.left,
|
window_style, rc.left, rc.top, rc.right - rc.left,
|
||||||
rc.bottom - rc.top, nullptr, nullptr, hInstance, this);
|
rc.bottom - rc.top, nullptr, nullptr, hInstance, this);
|
||||||
if (!hwnd_) {
|
if (!hwnd_) {
|
||||||
|
@ -65,10 +67,6 @@ bool Win32Window::Create() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
main_menu_ = CreateMenu();
|
|
||||||
AppendMenu(main_menu_, MF_STRING, 0, L"TODO");
|
|
||||||
SetMenu(hwnd_, main_menu_);
|
|
||||||
|
|
||||||
// Disable flicks.
|
// Disable flicks.
|
||||||
ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty");
|
ATOM atom = GlobalAddAtom(L"MicrosoftTabletPenServiceProperty");
|
||||||
const DWORD_PTR dwHwndTabletProperty =
|
const DWORD_PTR dwHwndTabletProperty =
|
||||||
|
@ -137,7 +135,7 @@ bool Win32Window::set_title(const std::wstring& title) {
|
||||||
|
|
||||||
void Win32Window::Resize(int32_t width, int32_t height) {
|
void Win32Window::Resize(int32_t width, int32_t height) {
|
||||||
RECT rc = {0, 0, width, height};
|
RECT rc = {0, 0, width, height};
|
||||||
bool has_menu = main_menu_ ? true : false;
|
bool has_menu = menu_ ? true : false;
|
||||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, has_menu);
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, has_menu);
|
||||||
if (true) {
|
if (true) {
|
||||||
rc.right += 100 - rc.left;
|
rc.right += 100 - rc.left;
|
||||||
|
@ -151,7 +149,7 @@ void Win32Window::Resize(int32_t width, int32_t height) {
|
||||||
void Win32Window::Resize(int32_t left, int32_t top, int32_t right,
|
void Win32Window::Resize(int32_t left, int32_t top, int32_t right,
|
||||||
int32_t bottom) {
|
int32_t bottom) {
|
||||||
RECT rc = {left, top, right, bottom};
|
RECT rc = {left, top, right, bottom};
|
||||||
bool has_menu = main_menu_ ? true : false;
|
bool has_menu = menu_ ? true : false;
|
||||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, has_menu);
|
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, has_menu);
|
||||||
Window::Resize(rc.left, rc.top, rc.right, rc.bottom);
|
Window::Resize(rc.left, rc.top, rc.right, rc.bottom);
|
||||||
}
|
}
|
||||||
|
@ -168,6 +166,13 @@ void Win32Window::OnClose() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Win32Window::OnSetMenu(MenuItem* menu) {
|
||||||
|
Win32MenuItem* win_menu = reinterpret_cast<Win32MenuItem*>(menu);
|
||||||
|
if (win_menu) {
|
||||||
|
::SetMenu(hwnd_, win_menu->handle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
LPARAM lParam) {
|
LPARAM lParam) {
|
||||||
switch (message) {
|
switch (message) {
|
||||||
|
@ -197,9 +202,9 @@ LRESULT Win32Window::WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
TABLET_DISABLE_TOUCHSWITCH | TABLET_DISABLE_SMOOTHSCROLLING |
|
TABLET_DISABLE_TOUCHSWITCH | TABLET_DISABLE_SMOOTHSCROLLING |
|
||||||
TABLET_DISABLE_TOUCHUIFORCEON | TABLET_ENABLE_MULTITOUCHDATA;
|
TABLET_DISABLE_TOUCHUIFORCEON | TABLET_ENABLE_MULTITOUCHDATA;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND: {
|
||||||
switch (LOWORD(wParam)) {
|
OnCommand(LOWORD(wParam));
|
||||||
// TODO(benvanik): dispatch to menu.
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xenia/ui/win32/win32_control.h"
|
#include "xenia/ui/win32/win32_control.h"
|
||||||
|
#include "xenia/ui/win32/win32_menu_item.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -38,13 +39,14 @@ class Win32Window : public Window<Win32Control> {
|
||||||
bool Create() override;
|
bool Create() override;
|
||||||
void OnClose() override;
|
void OnClose() override;
|
||||||
|
|
||||||
|
void OnSetMenu(MenuItem*) override;
|
||||||
|
|
||||||
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||||
LPARAM lParam) override;
|
LPARAM lParam) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void EnableMMCSS();
|
void EnableMMCSS();
|
||||||
|
|
||||||
HMENU main_menu_;
|
|
||||||
bool closing_;
|
bool closing_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "xenia/base/delegate.h"
|
#include "xenia/base/delegate.h"
|
||||||
#include "xenia/ui/control.h"
|
#include "xenia/ui/control.h"
|
||||||
#include "xenia/ui/ui_event.h"
|
#include "xenia/ui/ui_event.h"
|
||||||
|
#include "xenia/ui/menu_item.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
@ -45,6 +46,12 @@ class Window : public T {
|
||||||
on_closed(e);
|
on_closed(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void SetMenu(MenuItem* menu) {
|
||||||
|
menu_ = menu;
|
||||||
|
|
||||||
|
OnSetMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Delegate<UIEvent> on_shown;
|
Delegate<UIEvent> on_shown;
|
||||||
Delegate<UIEvent> on_hidden;
|
Delegate<UIEvent> on_hidden;
|
||||||
|
@ -74,7 +81,11 @@ class Window : public T {
|
||||||
|
|
||||||
virtual void OnClose() {}
|
virtual void OnClose() {}
|
||||||
|
|
||||||
private:
|
virtual void OnSetMenu(MenuItem* menu) {}
|
||||||
|
|
||||||
|
virtual void OnCommand(int id) {}
|
||||||
|
|
||||||
|
MenuItem* menu_;
|
||||||
std::wstring title_;
|
std::wstring title_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue