mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-07 06:16:47 +02:00
Update to v093r04 release.
byuu says: This version replaces the old folder-browser with a proper game library.
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "higan";
|
static const char Name[] = "higan";
|
||||||
static const char Version[] = "093.03";
|
static const char Version[] = "093.04";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
static const char Website[] = "http://byuu.org/";
|
static const char Website[] = "http://byuu.org/";
|
||||||
|
@@ -15,7 +15,6 @@ using namespace nall;
|
|||||||
|
|
||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
#include "utility.cpp"
|
|
||||||
#include "layout/fixed-layout.cpp"
|
#include "layout/fixed-layout.cpp"
|
||||||
#include "layout/horizontal-layout.cpp"
|
#include "layout/horizontal-layout.cpp"
|
||||||
#include "layout/vertical-layout.cpp"
|
#include "layout/vertical-layout.cpp"
|
||||||
|
@@ -243,7 +243,6 @@ struct pWidget : public pSizable {
|
|||||||
GtkWidget* gtkParent = nullptr;
|
GtkWidget* gtkParent = nullptr;
|
||||||
|
|
||||||
virtual GtkWidget* container(Widget& widget);
|
virtual GtkWidget* container(Widget& widget);
|
||||||
virtual Position containerOffset();
|
|
||||||
virtual bool focused();
|
virtual bool focused();
|
||||||
virtual Size minimumSize();
|
virtual Size minimumSize();
|
||||||
virtual void setEnabled(bool enabled);
|
virtual void setEnabled(bool enabled);
|
||||||
@@ -545,7 +544,6 @@ struct pTabFrame : public pWidget {
|
|||||||
|
|
||||||
void append(string text, const image& image);
|
void append(string text, const image& image);
|
||||||
GtkWidget* container(Widget& widget);
|
GtkWidget* container(Widget& widget);
|
||||||
Position containerOffset();
|
|
||||||
Position displacement();
|
Position displacement();
|
||||||
void remove(unsigned selection);
|
void remove(unsigned selection);
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
@@ -73,10 +73,6 @@ static Widget* GetParentWidget(Sizable* sizable) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool HasParentWidget(Sizable* sizable) {
|
|
||||||
return GetParentWidget(sizable) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Keyboard::Keycode Keysym(unsigned keysym) {
|
static Keyboard::Keycode Keysym(unsigned keysym) {
|
||||||
switch(keysym) {
|
switch(keysym) {
|
||||||
case GDK_Escape: return Keyboard::Keycode::Escape;
|
case GDK_Escape: return Keyboard::Keycode::Escape;
|
||||||
|
@@ -38,10 +38,6 @@ GtkWidget* pTabFrame::container(Widget& widget) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position pTabFrame::containerOffset() {
|
|
||||||
return {widget.state.geometry.x + 3, widget.state.geometry.y + 28};
|
|
||||||
}
|
|
||||||
|
|
||||||
Position pTabFrame::displacement() {
|
Position pTabFrame::displacement() {
|
||||||
return {6, 31};
|
return {6, 31};
|
||||||
}
|
}
|
||||||
@@ -63,8 +59,7 @@ void pTabFrame::setGeometry(Geometry geometry) {
|
|||||||
geometry.x += 1, geometry.width -= 5;
|
geometry.x += 1, geometry.width -= 5;
|
||||||
geometry.y += 26, geometry.height -= 31;
|
geometry.y += 26, geometry.height -= 31;
|
||||||
for(auto& layout : tabFrame.state.layout) {
|
for(auto& layout : tabFrame.state.layout) {
|
||||||
if(layout == nullptr) continue;
|
if(layout) layout->setGeometry(geometry);
|
||||||
layout->setGeometry(geometry);
|
|
||||||
}
|
}
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,6 @@ GtkWidget* pWidget::container(Widget& widget) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Position pWidget::containerOffset() {
|
|
||||||
return {0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pWidget::focused() {
|
bool pWidget::focused() {
|
||||||
return GTK_WIDGET_HAS_FOCUS(gtkWidget);
|
return GTK_WIDGET_HAS_FOCUS(gtkWidget);
|
||||||
}
|
}
|
||||||
|
@@ -153,7 +153,7 @@ void pWindow::append(Widget& widget) {
|
|||||||
widget.setFont(window.state.widgetFont);
|
widget.setFont(window.state.widgetFont);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HasParentWidget(&widget)) {
|
if(GetParentWidget(&widget)) {
|
||||||
widget.p.gtkParent = GetParentWidget(&widget)->p.container(widget);
|
widget.p.gtkParent = GetParentWidget(&widget)->p.container(widget);
|
||||||
} else {
|
} else {
|
||||||
widget.p.gtkParent = formContainer;
|
widget.p.gtkParent = formContainer;
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Fri Nov 22 09:50:07 2013
|
** Created: Sun Nov 24 07:06:37 2013
|
||||||
** by: The Qt Meta Object Compiler version 63 (Qt 4.8.2)
|
** by: The Qt Meta Object Compiler version 63 (Qt 4.8.2)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
@@ -127,8 +127,6 @@ public:
|
|||||||
QStatusBar* qtStatus;
|
QStatusBar* qtStatus;
|
||||||
QWidget* qtContainer;
|
QWidget* qtContainer;
|
||||||
|
|
||||||
static Window& none();
|
|
||||||
|
|
||||||
void append(Layout& layout);
|
void append(Layout& layout);
|
||||||
void append(Menu& menu);
|
void append(Menu& menu);
|
||||||
void append(Widget& widget);
|
void append(Widget& widget);
|
||||||
@@ -255,6 +253,8 @@ public slots:
|
|||||||
struct pSizable : public pObject {
|
struct pSizable : public pObject {
|
||||||
Sizable& sizable;
|
Sizable& sizable;
|
||||||
|
|
||||||
|
virtual Position displacement() { return {0, 0}; }
|
||||||
|
|
||||||
pSizable(Sizable& sizable) : pObject(sizable), sizable(sizable) {}
|
pSizable(Sizable& sizable) : pObject(sizable), sizable(sizable) {}
|
||||||
|
|
||||||
void constructor() {}
|
void constructor() {}
|
||||||
@@ -274,6 +274,7 @@ struct pWidget : public pSizable {
|
|||||||
Widget& widget;
|
Widget& widget;
|
||||||
QWidget* qtWidget;
|
QWidget* qtWidget;
|
||||||
|
|
||||||
|
virtual QWidget* container(Widget& widget);
|
||||||
bool focused();
|
bool focused();
|
||||||
virtual Size minimumSize();
|
virtual Size minimumSize();
|
||||||
virtual void setEnabled(bool enabled);
|
virtual void setEnabled(bool enabled);
|
||||||
@@ -664,6 +665,8 @@ public:
|
|||||||
QTabWidget* qtTabFrame;
|
QTabWidget* qtTabFrame;
|
||||||
|
|
||||||
void append(string text, const image& image);
|
void append(string text, const image& image);
|
||||||
|
QWidget* container(Widget& widget);
|
||||||
|
Position displacement();
|
||||||
void remove(unsigned selection);
|
void remove(unsigned selection);
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setGeometry(Geometry geometry);
|
void setGeometry(Geometry geometry);
|
||||||
|
@@ -23,6 +23,33 @@ static lstring DropPaths(QDropEvent* event) {
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Position GetDisplacement(Sizable* sizable) {
|
||||||
|
Position position;
|
||||||
|
while(sizable->state.parent) {
|
||||||
|
Position displacement = sizable->state.parent->p.displacement();
|
||||||
|
position.x += displacement.x;
|
||||||
|
position.y += displacement.y;
|
||||||
|
sizable = sizable->state.parent;
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Layout* GetParentWidgetLayout(Sizable* sizable) {
|
||||||
|
while(sizable) {
|
||||||
|
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Layout*)sizable;
|
||||||
|
sizable = sizable->state.parent;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget* GetParentWidget(Sizable* sizable) {
|
||||||
|
while(sizable) {
|
||||||
|
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Widget*)sizable->state.parent;
|
||||||
|
sizable = sizable->state.parent;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static Keyboard::Keycode Keysym(int keysym) {
|
static Keyboard::Keycode Keysym(int keysym) {
|
||||||
switch(keysym) {
|
switch(keysym) {
|
||||||
case XK_Escape: return Keyboard::Keycode::Escape;
|
case XK_Escape: return Keyboard::Keycode::Escape;
|
||||||
|
@@ -10,7 +10,7 @@ void pFrame::setGeometry(Geometry geometry) {
|
|||||||
if(frame.state.layout == nullptr) return;
|
if(frame.state.layout == nullptr) return;
|
||||||
Size size = pFont::size(widget.state.font, frame.state.text);
|
Size size = pFont::size(widget.state.font, frame.state.text);
|
||||||
if(frame.state.text.empty()) size.height = 8;
|
if(frame.state.text.empty()) size.height = 8;
|
||||||
geometry.x += 1, geometry.width -= 3;
|
geometry.x += 1, geometry.width -= 2;
|
||||||
geometry.y += size.height, geometry.height -= size.height + 1;
|
geometry.y += size.height, geometry.height -= size.height + 1;
|
||||||
frame.state.layout->setGeometry(geometry);
|
frame.state.layout->setGeometry(geometry);
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,14 @@ void pFrame::setVisible(bool visible) {
|
|||||||
|
|
||||||
void pFrame::constructor() {
|
void pFrame::constructor() {
|
||||||
qtWidget = qtFrame = new QGroupBox;
|
qtWidget = qtFrame = new QGroupBox;
|
||||||
|
if(QApplication::style()->objectName() == "gtk+") {
|
||||||
|
//QGtkStyle (gtk+) theme disrespects font weight and omits the border, even if native GTK+ theme does not
|
||||||
|
//bold Label controls already exist; so this style sheet forces QGtkStyle to look like a Frame instead
|
||||||
|
qtFrame->setStyleSheet(
|
||||||
|
"QGroupBox { border: 1px solid #aaa; border-radius: 5px; margin-top: 0.5em; }\n"
|
||||||
|
"QGroupBox::title { left: 5px; subcontrol-origin: margin; }\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pWidget::synchronizeState();
|
pWidget::synchronizeState();
|
||||||
setText(frame.state.text);
|
setText(frame.state.text);
|
||||||
|
@@ -2,11 +2,24 @@ namespace phoenix {
|
|||||||
|
|
||||||
void pTabFrame::append(string text, const image& image) {
|
void pTabFrame::append(string text, const image& image) {
|
||||||
unsigned selection = tabFrame.state.text.size() - 1;
|
unsigned selection = tabFrame.state.text.size() - 1;
|
||||||
QWidget* widget = new QWidget; //addTab() requires a child widget, so give it an empty one
|
qtTabFrame->addTab(new QWidget, QString::fromUtf8(text));
|
||||||
qtTabFrame->addTab(widget, QString::fromUtf8(text));
|
|
||||||
if(!image.empty()) setImage(selection, image);
|
if(!image.empty()) setImage(selection, image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget* pTabFrame::container(Widget& widget) {
|
||||||
|
Layout* widgetLayout = GetParentWidgetLayout(&widget);
|
||||||
|
unsigned selection = 0;
|
||||||
|
for(auto& layout : tabFrame.state.layout) {
|
||||||
|
if(layout == widgetLayout) return qtTabFrame->widget(selection);
|
||||||
|
selection++;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Position pTabFrame::displacement() {
|
||||||
|
return {5, 33};
|
||||||
|
}
|
||||||
|
|
||||||
void pTabFrame::remove(unsigned selection) {
|
void pTabFrame::remove(unsigned selection) {
|
||||||
qtTabFrame->removeTab(selection);
|
qtTabFrame->removeTab(selection);
|
||||||
}
|
}
|
||||||
@@ -20,11 +33,10 @@ void pTabFrame::setEnabled(bool enabled) {
|
|||||||
|
|
||||||
void pTabFrame::setGeometry(Geometry geometry) {
|
void pTabFrame::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry(geometry);
|
pWidget::setGeometry(geometry);
|
||||||
geometry.x += 1, geometry.width -= 2;
|
geometry.x += 0, geometry.width -= 5;
|
||||||
geometry.y += 29, geometry.height -= 30;
|
geometry.y += 29, geometry.height -= 33;
|
||||||
for(auto& layout : tabFrame.state.layout) {
|
for(auto& layout : tabFrame.state.layout) {
|
||||||
if(layout == nullptr) continue;
|
if(layout) layout->setGeometry(geometry);
|
||||||
layout->setGeometry(geometry);
|
|
||||||
}
|
}
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,9 @@
|
|||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
|
|
||||||
|
QWidget* pWidget::container(Widget& widget) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bool pWidget::focused() {
|
bool pWidget::focused() {
|
||||||
return qtWidget->hasFocus();
|
return qtWidget->hasFocus();
|
||||||
}
|
}
|
||||||
@@ -24,6 +28,10 @@ void pWidget::setFont(string font) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setGeometry(Geometry geometry) {
|
void pWidget::setGeometry(Geometry geometry) {
|
||||||
|
Position displacement = GetDisplacement(&widget);
|
||||||
|
geometry.x -= displacement.x;
|
||||||
|
geometry.y -= displacement.y;
|
||||||
|
|
||||||
qtWidget->setGeometry(geometry.x, geometry.y, geometry.width, geometry.height);
|
qtWidget->setGeometry(geometry.x, geometry.y, geometry.width, geometry.height);
|
||||||
if(widget.onSize) widget.onSize();
|
if(widget.onSize) widget.onSize();
|
||||||
}
|
}
|
||||||
|
@@ -1,11 +1,5 @@
|
|||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
|
|
||||||
Window& pWindow::none() {
|
|
||||||
static Window* window = nullptr;
|
|
||||||
if(window == nullptr) window = new Window;
|
|
||||||
return *window;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pWindow::append(Layout& layout) {
|
void pWindow::append(Layout& layout) {
|
||||||
Geometry geometry = window.state.geometry;
|
Geometry geometry = window.state.geometry;
|
||||||
geometry.x = geometry.y = 0;
|
geometry.x = geometry.y = 0;
|
||||||
@@ -14,7 +8,7 @@ void pWindow::append(Layout& layout) {
|
|||||||
|
|
||||||
void pWindow::append(Menu& menu) {
|
void pWindow::append(Menu& menu) {
|
||||||
if(window.state.menuFont != "") menu.p.setFont(window.state.menuFont);
|
if(window.state.menuFont != "") menu.p.setFont(window.state.menuFont);
|
||||||
else menu.p.setFont("Sans, 8");
|
else menu.p.setFont(Font::sans(8));
|
||||||
qtMenu->addMenu(menu.p.qtMenu);
|
qtMenu->addMenu(menu.p.qtMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,8 +16,12 @@ void pWindow::append(Widget& widget) {
|
|||||||
if(widget.font().empty() && !window.state.widgetFont.empty()) {
|
if(widget.font().empty() && !window.state.widgetFont.empty()) {
|
||||||
widget.setFont(window.state.widgetFont);
|
widget.setFont(window.state.widgetFont);
|
||||||
}
|
}
|
||||||
if(widget.font().empty()) widget.p.setFont("Sans, 8");
|
if(widget.font().empty()) widget.p.setFont(Font::sans(8));
|
||||||
widget.p.qtWidget->setParent(qtContainer);
|
if(GetParentWidget(&widget)) {
|
||||||
|
widget.p.qtWidget->setParent(GetParentWidget(&widget)->p.container(widget));
|
||||||
|
} else {
|
||||||
|
widget.p.qtWidget->setParent(qtContainer);
|
||||||
|
}
|
||||||
widget.setVisible(widget.visible());
|
widget.setVisible(widget.visible());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,10 +67,11 @@ void pWindow::remove(Widget& widget) {
|
|||||||
|
|
||||||
void pWindow::setBackgroundColor(Color color) {
|
void pWindow::setBackgroundColor(Color color) {
|
||||||
QPalette palette;
|
QPalette palette;
|
||||||
palette.setColor(QPalette::Window, QColor(color.red, color.green, color.blue, color.alpha));
|
palette.setColor(QPalette::Background, QColor(color.red, color.green, color.blue /*, color.alpha */));
|
||||||
qtContainer->setPalette(palette);
|
qtContainer->setPalette(palette);
|
||||||
qtContainer->setAutoFillBackground(true);
|
qtContainer->setAutoFillBackground(true);
|
||||||
qtWindow->setAttribute(Qt::WA_TranslucentBackground, color.alpha != 255);
|
//translucency results are very unpleasant without a compositor; so disable for now
|
||||||
|
//qtWindow->setAttribute(Qt::WA_TranslucentBackground, color.alpha != 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setDroppable(bool droppable) {
|
void pWindow::setDroppable(bool droppable) {
|
||||||
|
@@ -213,22 +213,6 @@ static LRESULT CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wpara
|
|||||||
case WM_ERASEBKGND: if(window.p.onEraseBackground()) return true; break;
|
case WM_ERASEBKGND: if(window.p.onEraseBackground()) return true; break;
|
||||||
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: window.p.onModalBegin(); return FALSE;
|
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: window.p.onModalBegin(); return FALSE;
|
||||||
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: window.p.onModalEnd(); return FALSE;
|
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: window.p.onModalEnd(); return FALSE;
|
||||||
|
|
||||||
case WM_CTLCOLORBTN:
|
|
||||||
case WM_CTLCOLORSTATIC: {
|
|
||||||
Object* object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
|
||||||
if(object == nullptr) break;
|
|
||||||
if(dynamic_cast<HexEdit*>(object) || dynamic_cast<LineEdit*>(object) || dynamic_cast<TextEdit*>(object)) {
|
|
||||||
//text edit controls, when disabled, use CTLCOLORSTATIC instead of CTLCOLOREDIT
|
|
||||||
//override this behavior: we do not want read-only edit controls to use the parent window background color
|
|
||||||
return DefWindowProc(hwnd, WM_CTLCOLOREDIT, wparam, lparam);
|
|
||||||
} else if(window.p.brush) {
|
|
||||||
HDC hdc = (HDC)wparam;
|
|
||||||
SetBkColor((HDC)wparam, window.p.brushColor);
|
|
||||||
return (INT_PTR)window.p.brush;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);
|
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);
|
||||||
|
@@ -14,3 +14,5 @@
|
|||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <nall/windows/registry.hpp>
|
#include <nall/windows/registry.hpp>
|
||||||
#include <nall/windows/utf8.hpp>
|
#include <nall/windows/utf8.hpp>
|
||||||
|
|
||||||
|
#define TBS_TRANSPARENTBKGND 0x1000
|
||||||
|
@@ -375,8 +375,8 @@ struct pFrame : public pWidget {
|
|||||||
|
|
||||||
struct pHexEdit : public pWidget {
|
struct pHexEdit : public pWidget {
|
||||||
HexEdit& hexEdit;
|
HexEdit& hexEdit;
|
||||||
HWND scrollBar;
|
WindowProc windowProc = nullptr;
|
||||||
LRESULT CALLBACK (*windowProc)(HWND, UINT, LPARAM, WPARAM);
|
HWND scrollBar = nullptr;
|
||||||
|
|
||||||
void setColumns(unsigned columns);
|
void setColumns(unsigned columns);
|
||||||
void setLength(unsigned length);
|
void setLength(unsigned length);
|
||||||
|
@@ -74,6 +74,19 @@ static unsigned GetWindowZOrder(HWND hwnd) {
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ImageList_Append(HIMAGELIST imageList, const nall::image& source, unsigned scale) {
|
||||||
|
auto image = source;
|
||||||
|
if(image.empty()) {
|
||||||
|
image.allocate(scale, scale);
|
||||||
|
image.fill(GetSysColor(COLOR_WINDOW));
|
||||||
|
}
|
||||||
|
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||||
|
image.scale(scale, scale);
|
||||||
|
HBITMAP bitmap = CreateBitmap(image);
|
||||||
|
ImageList_Add(imageList, bitmap, NULL);
|
||||||
|
DeleteObject(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
static Keyboard::Keycode Keysym(unsigned keysym, unsigned keyflags) {
|
static Keyboard::Keycode Keysym(unsigned keysym, unsigned keyflags) {
|
||||||
#define pressed(keysym) (GetAsyncKeyState(keysym) & 0x8000)
|
#define pressed(keysym) (GetAsyncKeyState(keysym) & 0x8000)
|
||||||
#define enabled(keysym) (GetKeyState(keysym))
|
#define enabled(keysym) (GetKeyState(keysym))
|
||||||
@@ -231,12 +244,34 @@ static LRESULT CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT
|
|||||||
if(process == false) return DefWindowProc(hwnd, msg, wparam, lparam);
|
if(process == false) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
|
||||||
switch(msg) {
|
switch(msg) {
|
||||||
|
case WM_CTLCOLORBTN:
|
||||||
|
case WM_CTLCOLORSTATIC: {
|
||||||
|
Object* object = (Object*)GetWindowLongPtr((HWND)lparam, GWLP_USERDATA);
|
||||||
|
if(object == nullptr) break;
|
||||||
|
if(dynamic_cast<HexEdit*>(object) || dynamic_cast<LineEdit*>(object) || dynamic_cast<TextEdit*>(object)) {
|
||||||
|
//text edit controls, when disabled, use CTLCOLORSTATIC instead of CTLCOLOREDIT
|
||||||
|
//override this behavior: we do not want read-only edit controls to use the parent window background color
|
||||||
|
return windowProc(hwnd, WM_CTLCOLOREDIT, wparam, lparam);
|
||||||
|
} else if(!GetParentWidget((Sizable*)object) && window.p.brush) {
|
||||||
|
SetBkColor((HDC)wparam, window.p.brushColor);
|
||||||
|
return (INT_PTR)window.p.brush;
|
||||||
|
}/* else {
|
||||||
|
//this will repaint the background properly, but the foreground isn't always rendered after ...
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect((HWND)lparam, &rc);
|
||||||
|
DrawThemeParentBackground((HWND)lparam, (HDC)wparam, &rc);
|
||||||
|
SetBkMode((HDC)wparam, TRANSPARENT);
|
||||||
|
return (INT_PTR)GetStockBrush(HOLLOW_BRUSH);
|
||||||
|
}*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case WM_DRAWITEM: {
|
case WM_DRAWITEM: {
|
||||||
unsigned id = LOWORD(wparam);
|
unsigned id = LOWORD(wparam);
|
||||||
HWND control = GetDlgItem(hwnd, id);
|
HWND control = GetDlgItem(hwnd, id);
|
||||||
Object* object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
|
Object* object = (Object*)GetWindowLongPtr(control, GWLP_USERDATA);
|
||||||
if(object == nullptr) break;
|
if(object == nullptr) break;
|
||||||
if(dynamic_cast<TabFrame*>(object)) { ((TabFrame*)object)->p.onDrawItem(lparam); break; }
|
if(dynamic_cast<TabFrame*>(object)) { ((TabFrame*)object)->p.onDrawItem(lparam); return TRUE; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,16 +280,16 @@ static LRESULT CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT
|
|||||||
HWND control = GetDlgItem(hwnd, id);
|
HWND control = GetDlgItem(hwnd, id);
|
||||||
Object* object = control ? (Object*)GetWindowLongPtr(control, GWLP_USERDATA) : (Object*)(&pObject::find(id)->object);
|
Object* object = control ? (Object*)GetWindowLongPtr(control, GWLP_USERDATA) : (Object*)(&pObject::find(id)->object);
|
||||||
if(object == nullptr) break;
|
if(object == nullptr) break;
|
||||||
if(dynamic_cast<Item*>(object)) { ((Item*)object)->p.onActivate(); break; }
|
if(dynamic_cast<Item*>(object)) { ((Item*)object)->p.onActivate(); return FALSE; }
|
||||||
if(dynamic_cast<CheckItem*>(object)) { ((CheckItem*)object)->p.onToggle(); break; }
|
if(dynamic_cast<CheckItem*>(object)) { ((CheckItem*)object)->p.onToggle(); return FALSE; }
|
||||||
if(dynamic_cast<Button*>(object)) { ((Button*)object)->p.onActivate(); break; }
|
if(dynamic_cast<Button*>(object)) { ((Button*)object)->p.onActivate(); return FALSE; }
|
||||||
if(dynamic_cast<CheckButton*>(object)) { ((CheckButton*)object)->p.onToggle(); break; }
|
if(dynamic_cast<CheckButton*>(object)) { ((CheckButton*)object)->p.onToggle(); return FALSE; }
|
||||||
if(dynamic_cast<CheckLabel*>(object)) { ((CheckLabel*)object)->p.onToggle(); break; }
|
if(dynamic_cast<CheckLabel*>(object)) { ((CheckLabel*)object)->p.onToggle(); return FALSE; }
|
||||||
if(dynamic_cast<ComboButton*>(object) && HIWORD(wparam) == CBN_SELCHANGE) { ((ComboButton*)object)->p.onChange(); break; }
|
if(dynamic_cast<ComboButton*>(object) && HIWORD(wparam) == CBN_SELCHANGE) { ((ComboButton*)object)->p.onChange(); return FALSE; }
|
||||||
if(dynamic_cast<LineEdit*>(object) && HIWORD(wparam) == EN_CHANGE) { ((LineEdit*)object)->p.onChange(); break; }
|
if(dynamic_cast<LineEdit*>(object) && HIWORD(wparam) == EN_CHANGE) { ((LineEdit*)object)->p.onChange(); return FALSE; }
|
||||||
if(dynamic_cast<RadioButton*>(object)) { ((RadioButton*)object)->p.onActivate(); break; }
|
if(dynamic_cast<RadioButton*>(object)) { ((RadioButton*)object)->p.onActivate(); return FALSE; }
|
||||||
if(dynamic_cast<RadioLabel*>(object)) { ((RadioLabel*)object)->p.onActivate(); break; }
|
if(dynamic_cast<RadioLabel*>(object)) { ((RadioLabel*)object)->p.onActivate(); return FALSE; }
|
||||||
if(dynamic_cast<TextEdit*>(object) && HIWORD(wparam) == EN_CHANGE) { ((TextEdit*)object)->p.onChange(); break; }
|
if(dynamic_cast<TextEdit*>(object) && HIWORD(wparam) == EN_CHANGE) { ((TextEdit*)object)->p.onChange(); return FALSE; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,8 +318,8 @@ static LRESULT CALLBACK Shared_windowProc(WindowProc windowProc, HWND hwnd, UINT
|
|||||||
if(object == nullptr) break;
|
if(object == nullptr) break;
|
||||||
if(dynamic_cast<HorizontalScroller*>(object)) { ((HorizontalScroller*)object)->p.onChange(wparam); return TRUE; }
|
if(dynamic_cast<HorizontalScroller*>(object)) { ((HorizontalScroller*)object)->p.onChange(wparam); return TRUE; }
|
||||||
if(dynamic_cast<VerticalScroller*>(object)) { ((VerticalScroller*)object)->p.onChange(wparam); return TRUE; }
|
if(dynamic_cast<VerticalScroller*>(object)) { ((VerticalScroller*)object)->p.onChange(wparam); return TRUE; }
|
||||||
if(dynamic_cast<HorizontalSlider*>(object)) { ((HorizontalSlider*)object)->p.onChange(); break; }
|
if(dynamic_cast<HorizontalSlider*>(object)) { ((HorizontalSlider*)object)->p.onChange(); return TRUE; }
|
||||||
if(dynamic_cast<VerticalSlider*>(object)) { ((VerticalSlider*)object)->p.onChange(); break; }
|
if(dynamic_cast<VerticalSlider*>(object)) { ((VerticalSlider*)object)->p.onChange(); return TRUE; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ void pComboButton::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pComboButton::setGeometry(Geometry geometry) {
|
void pComboButton::setGeometry(Geometry geometry) {
|
||||||
SetWindowPos(hwnd, NULL, geometry.x, geometry.y, geometry.width, 1, SWP_NOZORDER);
|
pWidget::setGeometry(geometry);
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetWindowRect(hwnd, &rc);
|
GetWindowRect(hwnd, &rc);
|
||||||
unsigned adjustedHeight = geometry.height - ((rc.bottom - rc.top) - SendMessage(hwnd, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
|
unsigned adjustedHeight = geometry.height - ((rc.bottom - rc.top) - SendMessage(hwnd, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
|
||||||
|
@@ -4,7 +4,6 @@ static LRESULT CALLBACK HexEdit_windowProc(HWND hwnd, UINT msg, WPARAM wparam, L
|
|||||||
HexEdit& hexEdit = *(HexEdit*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
HexEdit& hexEdit = *(HexEdit*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
|
|
||||||
switch(msg) {
|
switch(msg) {
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
if(hexEdit.p.keyPress(wparam)) return 0;
|
if(hexEdit.p.keyPress(wparam)) return 0;
|
||||||
break;
|
break;
|
||||||
@@ -45,7 +44,6 @@ static LRESULT CALLBACK HexEdit_windowProc(HWND hwnd, UINT msg, WPARAM wparam, L
|
|||||||
hexEdit.p.scrollTo(info.nPos);
|
hexEdit.p.scrollTo(info.nPos);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return hexEdit.p.windowProc(hwnd, msg, wparam, lparam);
|
return hexEdit.p.windowProc(hwnd, msg, wparam, lparam);
|
||||||
@@ -123,7 +121,7 @@ void pHexEdit::constructor() {
|
|||||||
);
|
);
|
||||||
SetWindowLongPtr(scrollBar, GWLP_USERDATA, (LONG_PTR)&hexEdit);
|
SetWindowLongPtr(scrollBar, GWLP_USERDATA, (LONG_PTR)&hexEdit);
|
||||||
|
|
||||||
windowProc = (LRESULT CALLBACK (*)(HWND, UINT, LPARAM, WPARAM))GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
windowProc = (WindowProc)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
||||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HexEdit_windowProc);
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)HexEdit_windowProc);
|
||||||
|
|
||||||
setDefaultFont();
|
setDefaultFont();
|
||||||
|
@@ -17,10 +17,11 @@ void pHorizontalSlider::setPosition(unsigned position) {
|
|||||||
|
|
||||||
void pHorizontalSlider::constructor() {
|
void pHorizontalSlider::constructor() {
|
||||||
hwnd = CreateWindow(
|
hwnd = CreateWindow(
|
||||||
TRACKBAR_CLASS, L"", WS_CHILD | WS_TABSTOP | TBS_NOTICKS | TBS_BOTH | TBS_HORZ,
|
TRACKBAR_CLASS, L"", WS_CHILD | WS_TABSTOP | TBS_TRANSPARENTBKGND | TBS_NOTICKS | TBS_BOTH | TBS_HORZ,
|
||||||
0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0
|
0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0
|
||||||
);
|
);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalSlider);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&horizontalSlider);
|
||||||
|
|
||||||
unsigned position = horizontalSlider.state.position;
|
unsigned position = horizontalSlider.state.position;
|
||||||
setLength(horizontalSlider.state.length);
|
setLength(horizontalSlider.state.length);
|
||||||
horizontalSlider.setPosition(position);
|
horizontalSlider.setPosition(position);
|
||||||
|
@@ -36,19 +36,13 @@ static LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPA
|
|||||||
Window* window = (Window*)label->Sizable::state.window;
|
Window* window = (Window*)label->Sizable::state.window;
|
||||||
if(window == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
|
if(window == nullptr) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
|
||||||
if(msg == WM_GETDLGCODE) {
|
switch(msg) {
|
||||||
return DLGC_STATIC | DLGC_WANTCHARS;
|
case WM_GETDLGCODE: return DLGC_STATIC | DLGC_WANTCHARS;
|
||||||
}
|
case WM_ERASEBKGND: return TRUE;
|
||||||
|
case WM_PAINT: {
|
||||||
if(msg == WM_ERASEBKGND) {
|
|
||||||
//background is erased during WM_PAINT to prevent flickering
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(msg == WM_PAINT) {
|
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
RECT rc;
|
|
||||||
BeginPaint(hwnd, &ps);
|
BeginPaint(hwnd, &ps);
|
||||||
|
RECT rc;
|
||||||
GetClientRect(hwnd, &rc);
|
GetClientRect(hwnd, &rc);
|
||||||
DrawThemeParentBackground(hwnd, ps.hdc, &rc);
|
DrawThemeParentBackground(hwnd, ps.hdc, &rc);
|
||||||
SetBkMode(ps.hdc, TRANSPARENT);
|
SetBkMode(ps.hdc, TRANSPARENT);
|
||||||
@@ -64,6 +58,8 @@ static LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPA
|
|||||||
rc.bottom = rc.top + height;
|
rc.bottom = rc.top + height;
|
||||||
DrawText(ps.hdc, text, -1, &rc, DT_LEFT | DT_END_ELLIPSIS);
|
DrawText(ps.hdc, text, -1, &rc, DT_LEFT | DT_END_ELLIPSIS);
|
||||||
EndPaint(hwnd, &ps);
|
EndPaint(hwnd, &ps);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
@@ -23,19 +23,6 @@ void ListView_SetImage(HWND hwnd, HIMAGELIST imageList, unsigned row, unsigned c
|
|||||||
ListView_SetItem(hwnd, &item);
|
ListView_SetItem(hwnd, &item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageList_Append(HIMAGELIST imageList, const nall::image& source) {
|
|
||||||
auto image = source;
|
|
||||||
if(image.empty()) {
|
|
||||||
image.allocate(15, 15);
|
|
||||||
image.fill(GetSysColor(COLOR_WINDOW));
|
|
||||||
}
|
|
||||||
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
|
||||||
image.scale(15, 15, Interpolation::Linear);
|
|
||||||
HBITMAP bitmap = CreateBitmap(image);
|
|
||||||
ImageList_Add(imageList, bitmap, NULL);
|
|
||||||
DeleteObject(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pListView::append(const lstring& list) {
|
void pListView::append(const lstring& list) {
|
||||||
wchar_t empty[] = L"";
|
wchar_t empty[] = L"";
|
||||||
unsigned row = ListView_GetItemCount(hwnd);
|
unsigned row = ListView_GetItemCount(hwnd);
|
||||||
@@ -122,7 +109,7 @@ void pListView::setImage(unsigned selection, unsigned position, const image& ima
|
|||||||
//append and assign new image
|
//append and assign new image
|
||||||
imageMap(selection)(position) = images.size();
|
imageMap(selection)(position) = images.size();
|
||||||
images.append(image);
|
images.append(image);
|
||||||
ImageList_Append(imageList, image);
|
ImageList_Append(imageList, image, 15);
|
||||||
ListView_SetImage(hwnd, imageList, selection, position, imageMap(selection)(position));
|
ListView_SetImage(hwnd, imageList, selection, position, imageMap(selection)(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +198,7 @@ void pListView::buildImageList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//build image list
|
//build image list
|
||||||
for(auto& imageItem : images) ImageList_Append(imageList, imageItem);
|
for(auto& imageItem : images) ImageList_Append(imageList, imageItem, 15);
|
||||||
if(images.size() <= 1) return;
|
if(images.size() <= 1) return;
|
||||||
|
|
||||||
//set images for all cells
|
//set images for all cells
|
||||||
|
@@ -94,7 +94,7 @@ void pTabFrame::buildImageList() {
|
|||||||
unsigned size = pFont::size(hfont, " ").height;
|
unsigned size = pFont::size(hfont, " ").height;
|
||||||
imageList = ImageList_Create(size, size, ILC_COLOR32, 1, 0);
|
imageList = ImageList_Create(size, size, ILC_COLOR32, 1, 0);
|
||||||
for(auto& image : tabFrame.state.image) {
|
for(auto& image : tabFrame.state.image) {
|
||||||
ImageList_Append(imageList, image);
|
ImageList_Append(imageList, image, size);
|
||||||
}
|
}
|
||||||
TabCtrl_SetImageList(hwnd, imageList);
|
TabCtrl_SetImageList(hwnd, imageList);
|
||||||
for(unsigned n = 0; n < tabFrame.state.image.size(); n++) {
|
for(unsigned n = 0; n < tabFrame.state.image.size(); n++) {
|
||||||
|
@@ -17,10 +17,11 @@ void pVerticalSlider::setPosition(unsigned position) {
|
|||||||
|
|
||||||
void pVerticalSlider::constructor() {
|
void pVerticalSlider::constructor() {
|
||||||
hwnd = CreateWindow(
|
hwnd = CreateWindow(
|
||||||
TRACKBAR_CLASS, L"", WS_CHILD | WS_TABSTOP | TBS_NOTICKS | TBS_BOTH | TBS_VERT,
|
TRACKBAR_CLASS, L"", WS_CHILD | WS_TABSTOP | TBS_TRANSPARENTBKGND | TBS_NOTICKS | TBS_BOTH | TBS_VERT,
|
||||||
0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0
|
0, 0, 0, 0, parentHwnd, (HMENU)id, GetModuleHandle(0), 0
|
||||||
);
|
);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalSlider);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&verticalSlider);
|
||||||
|
|
||||||
unsigned position = verticalSlider.state.position;
|
unsigned position = verticalSlider.state.position;
|
||||||
setLength(verticalSlider.state.length);
|
setLength(verticalSlider.state.length);
|
||||||
verticalSlider.setPosition(position);
|
verticalSlider.setPosition(position);
|
||||||
|
@@ -41,6 +41,10 @@ ConfigurationSettings::ConfigurationSettings() {
|
|||||||
server.append(server.password = "", "Password");
|
server.append(server.password = "", "Password");
|
||||||
append(server, "Server");
|
append(server, "Server");
|
||||||
|
|
||||||
|
library.append(library.selection = 0, "Selection");
|
||||||
|
library.append(library.showOnStartup = true, "ShowOnStartup");
|
||||||
|
append(library, "Library");
|
||||||
|
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,6 +45,11 @@ struct ConfigurationSettings : Configuration::Document {
|
|||||||
string password;
|
string password;
|
||||||
} server;
|
} server;
|
||||||
|
|
||||||
|
struct Library : Configuration::Node {
|
||||||
|
unsigned selection;
|
||||||
|
bool showOnStartup;
|
||||||
|
} library;
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void save();
|
void save();
|
||||||
ConfigurationSettings();
|
ConfigurationSettings();
|
||||||
|
@@ -66,7 +66,7 @@ Program::Program(int argc, char** argv) {
|
|||||||
utility = new Utility;
|
utility = new Utility;
|
||||||
inputManager = new InputManager;
|
inputManager = new InputManager;
|
||||||
windowManager = new WindowManager;
|
windowManager = new WindowManager;
|
||||||
browser = new Browser;
|
libraryManager = new LibraryManager;
|
||||||
presentation = new Presentation;
|
presentation = new Presentation;
|
||||||
dipSwitches = new DipSwitches;
|
dipSwitches = new DipSwitches;
|
||||||
videoSettings = new VideoSettings;
|
videoSettings = new VideoSettings;
|
||||||
@@ -85,6 +85,8 @@ Program::Program(int argc, char** argv) {
|
|||||||
presentation->setVisible();
|
presentation->setVisible();
|
||||||
utility->resize();
|
utility->resize();
|
||||||
|
|
||||||
|
if(config->library.showOnStartup) libraryManager->setVisible();
|
||||||
|
|
||||||
video.set(Video::Handle, presentation->viewport.handle());
|
video.set(Video::Handle, presentation->viewport.handle());
|
||||||
if(!video.cap(Video::Depth) || !video.set(Video::Depth, depth = 30u)) {
|
if(!video.cap(Video::Depth) || !video.set(Video::Depth, depth = 30u)) {
|
||||||
video.set(Video::Depth, depth = 24u);
|
video.set(Video::Depth, depth = 24u);
|
||||||
@@ -114,7 +116,6 @@ Program::Program(int argc, char** argv) {
|
|||||||
|
|
||||||
utility->unload();
|
utility->unload();
|
||||||
config->save();
|
config->save();
|
||||||
browser->saveConfiguration();
|
|
||||||
inputManager->saveConfiguration();
|
inputManager->saveConfiguration();
|
||||||
windowManager->saveGeometry();
|
windowManager->saveGeometry();
|
||||||
|
|
||||||
|
@@ -1,178 +0,0 @@
|
|||||||
Browser* browser = nullptr;
|
|
||||||
|
|
||||||
Browser::Browser() {
|
|
||||||
bootstrap();
|
|
||||||
setGeometry({128, 128, 640, 400});
|
|
||||||
windowManager->append(this, "Browser");
|
|
||||||
|
|
||||||
layout.setMargin(5);
|
|
||||||
homeButton.setImage({resource::home, sizeof resource::home});
|
|
||||||
upButton.setImage({resource::up, sizeof resource::up});
|
|
||||||
openButton.setText("Open");
|
|
||||||
|
|
||||||
append(layout);
|
|
||||||
layout.append(pathLayout, {~0, 0}, 5);
|
|
||||||
pathLayout.append(pathEdit, {~0, 0}, 5);
|
|
||||||
pathLayout.append(homeButton, {28, 28}, 5);
|
|
||||||
pathLayout.append(upButton, {28, 28});
|
|
||||||
layout.append(fileList, {~0, ~0}, 5);
|
|
||||||
layout.append(controlLayout, {~0, 0});
|
|
||||||
controlLayout.append(filterLabel, {~0, 0}, 5);
|
|
||||||
controlLayout.append(openButton, {80, 0});
|
|
||||||
|
|
||||||
pathEdit.onActivate = [&] {
|
|
||||||
string path = pathEdit.text();
|
|
||||||
path.transform("\\", "/");
|
|
||||||
if(path.endswith("/") == false) path.append("/");
|
|
||||||
setPath(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
homeButton.onActivate = [&] {
|
|
||||||
string libraryPath = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/");
|
|
||||||
if(libraryPath.empty()) libraryPath = {userpath(), "Emulation/"};
|
|
||||||
if(libraryPath.endswith("/") == false) libraryPath.append("/");
|
|
||||||
setPath(libraryPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
upButton.onActivate = [&] {
|
|
||||||
setPath(parentdir(path));
|
|
||||||
};
|
|
||||||
|
|
||||||
fileList.onChange = {&Browser::synchronize, this};
|
|
||||||
fileList.onActivate = openButton.onActivate = {&Browser::fileListActivate, this};
|
|
||||||
|
|
||||||
onClose = [&] {
|
|
||||||
setModal(false);
|
|
||||||
setVisible(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
synchronize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Browser::synchronize() {
|
|
||||||
openButton.setEnabled(fileList.selected());
|
|
||||||
if(fileList.selected()) {
|
|
||||||
for(auto& folder : folderList) {
|
|
||||||
if(folder.extension == extension) {
|
|
||||||
folder.selection = fileList.selection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Browser::saveConfiguration() {
|
|
||||||
config.save(program->path("paths.bml"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Browser::bootstrap() {
|
|
||||||
for(auto& emulator : program->emulator) {
|
|
||||||
for(auto& media : emulator->media) {
|
|
||||||
bool found = false;
|
|
||||||
for(auto& folder : folderList) {
|
|
||||||
if(folder.extension == media.type) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(found == true) continue;
|
|
||||||
|
|
||||||
Folder folder;
|
|
||||||
folder.extension = media.type;
|
|
||||||
folder.path = {userpath(), "Emulation/", media.name, "/"};
|
|
||||||
folder.selection = 0;
|
|
||||||
folderList.append(folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& folder : folderList) {
|
|
||||||
Configuration::Node node;
|
|
||||||
node.append(folder.path, "Path");
|
|
||||||
node.append(folder.selection, "Selection");
|
|
||||||
config.append(node, folder.extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
config.load(program->path("paths.bml"));
|
|
||||||
config.save(program->path("paths.bml"));
|
|
||||||
}
|
|
||||||
|
|
||||||
string Browser::select(string title, string extension) {
|
|
||||||
this->extension = extension;
|
|
||||||
|
|
||||||
string path;
|
|
||||||
unsigned selection = 0;
|
|
||||||
for(auto& folder : folderList) {
|
|
||||||
if(folder.extension == extension) {
|
|
||||||
path = folder.path;
|
|
||||||
selection = folder.selection;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(path.empty()) path = program->basepath;
|
|
||||||
setPath(path, selection);
|
|
||||||
|
|
||||||
filterLabel.setText({"Filter: *.", extension});
|
|
||||||
|
|
||||||
audio.clear();
|
|
||||||
setTitle(title);
|
|
||||||
setVisible(true);
|
|
||||||
fileList.setFocused();
|
|
||||||
outputFilename = "";
|
|
||||||
|
|
||||||
setModal();
|
|
||||||
return outputFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Browser::setPath(string path, unsigned selection) {
|
|
||||||
//save path for next browser selection
|
|
||||||
for(auto& folder : folderList) {
|
|
||||||
if(folder.extension == extension) folder.path = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->path = path;
|
|
||||||
pathEdit.setText(path);
|
|
||||||
|
|
||||||
fileList.reset();
|
|
||||||
filenameList.reset();
|
|
||||||
|
|
||||||
lstring contents = directory::ifolders(path);
|
|
||||||
|
|
||||||
for(auto& filename : contents) {
|
|
||||||
string suffix = {".", this->extension, "/"};
|
|
||||||
if(filename.endswith("/") && !filename.endswith(suffix)) {
|
|
||||||
string name = filename;
|
|
||||||
name.rtrim<1>("/");
|
|
||||||
fileList.append(name);
|
|
||||||
fileList.setImage(filenameList.size(), 0, {resource::folder, sizeof resource::folder});
|
|
||||||
filenameList.append(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& filename : contents) {
|
|
||||||
string suffix = {".", this->extension, "/"};
|
|
||||||
if(filename.endswith(suffix)) {
|
|
||||||
string name = filename;
|
|
||||||
name.rtrim<1>(suffix);
|
|
||||||
fileList.append(name);
|
|
||||||
if(1 || file::exists({path, filename, "unverified"}) == false) {
|
|
||||||
fileList.setImage(filenameList.size(), 0, {resource::game, sizeof resource::game});
|
|
||||||
} else {
|
|
||||||
//disabled for now due to performance penalty
|
|
||||||
fileList.setImage(filenameList.size(), 0, {resource::unverified, sizeof resource::unverified});
|
|
||||||
}
|
|
||||||
filenameList.append(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fileList.setSelection(selection);
|
|
||||||
fileList.setFocused();
|
|
||||||
synchronize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Browser::fileListActivate() {
|
|
||||||
unsigned selection = fileList.selection();
|
|
||||||
string filename = filenameList[selection];
|
|
||||||
if(string{filename}.rtrim<1>("/").endswith(this->extension) == false) return setPath({path, filename});
|
|
||||||
|
|
||||||
outputFilename = {path, filename};
|
|
||||||
onClose();
|
|
||||||
}
|
|
@@ -1,37 +0,0 @@
|
|||||||
struct Browser : Window {
|
|
||||||
VerticalLayout layout;
|
|
||||||
HorizontalLayout pathLayout;
|
|
||||||
LineEdit pathEdit;
|
|
||||||
Button homeButton;
|
|
||||||
Button upButton;
|
|
||||||
ListView fileList;
|
|
||||||
HorizontalLayout controlLayout;
|
|
||||||
Label filterLabel;
|
|
||||||
Button openButton;
|
|
||||||
|
|
||||||
string select(string title, string extension);
|
|
||||||
void saveConfiguration();
|
|
||||||
void synchronize();
|
|
||||||
void bootstrap();
|
|
||||||
Browser();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Configuration::Document config;
|
|
||||||
struct Folder {
|
|
||||||
string extension;
|
|
||||||
string path;
|
|
||||||
unsigned selection;
|
|
||||||
};
|
|
||||||
vector<Folder> folderList;
|
|
||||||
|
|
||||||
string outputFilename;
|
|
||||||
|
|
||||||
string extension;
|
|
||||||
string path;
|
|
||||||
lstring filenameList;
|
|
||||||
|
|
||||||
void setPath(string path, unsigned selection = 0);
|
|
||||||
void fileListActivate();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern Browser* browser;
|
|
@@ -17,6 +17,7 @@ DipSwitches::DipSwitches() {
|
|||||||
controlLayout.append(accept, {80, 0});
|
controlLayout.append(accept, {80, 0});
|
||||||
|
|
||||||
setGeometry({128, 128, 250, layout.minimumSize().height});
|
setGeometry({128, 128, 250, layout.minimumSize().height});
|
||||||
|
windowManager->append(this, "DipSwitches");
|
||||||
|
|
||||||
onClose = accept.onActivate = [&] {
|
onClose = accept.onActivate = [&] {
|
||||||
setModal(false);
|
setModal(false);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "../ethos.hpp"
|
#include "../ethos.hpp"
|
||||||
#include "browser.cpp"
|
#include "library.cpp"
|
||||||
#include "presentation.cpp"
|
#include "presentation.cpp"
|
||||||
#include "dip-switches.cpp"
|
#include "dip-switches.cpp"
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
#include "browser.hpp"
|
#include "library.hpp"
|
||||||
#include "presentation.hpp"
|
#include "presentation.hpp"
|
||||||
#include "dip-switches.hpp"
|
#include "dip-switches.hpp"
|
||||||
|
185
target-ethos/general/library.cpp
Normal file
185
target-ethos/general/library.cpp
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
LibraryManager* libraryManager = nullptr;
|
||||||
|
|
||||||
|
LibraryBrowser::LibraryBrowser() {
|
||||||
|
setMargin(5);
|
||||||
|
|
||||||
|
informationType.setText({
|
||||||
|
"Title:\n",
|
||||||
|
"Revision:\n",
|
||||||
|
"Region:\n",
|
||||||
|
"Serial:"
|
||||||
|
});
|
||||||
|
|
||||||
|
append(folders, {~0, ~0}, 5);
|
||||||
|
append(informationLayout, {~0, Font::size(program->normalFont, " ").height * 4});
|
||||||
|
informationLayout.append(informationType, {0, ~0}, 5);
|
||||||
|
informationLayout.append(information, {~0, ~0});
|
||||||
|
|
||||||
|
folders.onActivate = {&LibraryBrowser::onActivate, this};
|
||||||
|
folders.onChange = {&LibraryBrowser::setInformation, this};
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryBrowser::onActivate() {
|
||||||
|
if(folders.selected() == false) return;
|
||||||
|
unsigned selection = folders.selection();
|
||||||
|
string pathname = {this->pathname, folders.text(selection, 0), filterSuffix};
|
||||||
|
|
||||||
|
if(libraryManager->slotLoad == false) {
|
||||||
|
libraryManager->setStatusText(folders.text(selection, 0));
|
||||||
|
utility->loadMedia(pathname);
|
||||||
|
} else {
|
||||||
|
libraryManager->setStatusText({libraryManager->statusText(), " + ", folders.text(selection, 0)});
|
||||||
|
libraryManager->setModal(false);
|
||||||
|
libraryManager->loadPathname = pathname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryBrowser::refresh() {
|
||||||
|
folders.reset();
|
||||||
|
lstring pathnames = directory::ifolders(pathname, filterMask);
|
||||||
|
unsigned selection = 0;
|
||||||
|
for(auto& pathname : pathnames) {
|
||||||
|
folders.append(string{pathname}.rtrim<1>(filterSuffix));
|
||||||
|
folders.setImage(selection++, 0, {resource::game, sizeof resource::game});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryBrowser::setFilter(const string& filter) {
|
||||||
|
this->filter = filter;
|
||||||
|
filterMask = {"*.", filter};
|
||||||
|
filterSuffix = {".", filter, "/"};
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryBrowser::setInformation() {
|
||||||
|
if(folders.selected() == false) {
|
||||||
|
information.setText("");
|
||||||
|
} else {
|
||||||
|
string manifest = {pathname, folders.text(folders.selection(), 0), filterSuffix, "manifest.bml"};
|
||||||
|
auto document = Markup::Document(file::read(manifest));
|
||||||
|
information.setText({
|
||||||
|
document["information/title"].text(), "\n",
|
||||||
|
document["information/revision"].text(), "\n",
|
||||||
|
document["information/region"].text(), "\n",
|
||||||
|
document["information/serial"].text(), "\n"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryBrowser::setPath(const string& pathname) {
|
||||||
|
this->pathname = pathname;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
LibraryManager::LibraryManager() {
|
||||||
|
setTitle("Game Library");
|
||||||
|
setStatusVisible();
|
||||||
|
setGeometry({128, 128, 960, 640});
|
||||||
|
windowManager->append(this, "LibraryManager");
|
||||||
|
|
||||||
|
layout.setMargin(5);
|
||||||
|
libraryFrame.append("Import Games");
|
||||||
|
importLayout.setMargin(5);
|
||||||
|
importInformation.setText({
|
||||||
|
"higan manages games in a library. To play a game, you must first import the game.\n"
|
||||||
|
"After doing so, the game will appear inside your library, and can then be loaded and played."
|
||||||
|
});
|
||||||
|
importButton.setText("Import Game ...");
|
||||||
|
libraryFrame.setLayout(0, importLayout);
|
||||||
|
bootstrap();
|
||||||
|
libraryFrame.setSelection(config->library.selection);
|
||||||
|
|
||||||
|
append(layout);
|
||||||
|
layout.append(libraryFrame, {~0, ~0});
|
||||||
|
importLayout.append(importInformation, {0, 0}, 5);
|
||||||
|
importLayout.append(importButton, {0, 0});
|
||||||
|
|
||||||
|
onClose = [&] {
|
||||||
|
setModal(false);
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
libraryFrame.onChange = [&] {
|
||||||
|
config->library.selection = libraryFrame.selection();
|
||||||
|
};
|
||||||
|
|
||||||
|
importButton.onActivate = [&] {
|
||||||
|
if(program->ananke.open() == false) {
|
||||||
|
MessageWindow().setText("ananke must be installed to use this feature").warning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
function<string ()> browse = program->ananke.sym("ananke_browse");
|
||||||
|
if(!browse) return;
|
||||||
|
string pathname = browse();
|
||||||
|
if(pathname.empty()) return;
|
||||||
|
MessageWindow().setText({"Successfully imported ", notdir(pathname.rtrim<1>("/"))}).information();
|
||||||
|
string type = extension(pathname);
|
||||||
|
|
||||||
|
unsigned selection = 1;
|
||||||
|
for(auto& browser : browsers) {
|
||||||
|
if(browser->filter == type) {
|
||||||
|
browser->refresh();
|
||||||
|
libraryFrame.setSelection(selection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
selection++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryManager::bootstrap() {
|
||||||
|
unsigned selection = 1;
|
||||||
|
string basepath = utility->libraryPath();
|
||||||
|
vector<string> names;
|
||||||
|
|
||||||
|
for(auto& emulator : program->emulator) {
|
||||||
|
for(auto& media : emulator->media) {
|
||||||
|
if(media.bootable == false) continue;
|
||||||
|
if(names.find(media.name)) continue;
|
||||||
|
names.append(media.name);
|
||||||
|
LibraryBrowser* browser = new LibraryBrowser;
|
||||||
|
browser->setFilter(media.type);
|
||||||
|
browser->setPath({basepath, media.name, "/"});
|
||||||
|
libraryFrame.append(media.name);
|
||||||
|
libraryFrame.setLayout(selection++, *browser);
|
||||||
|
browsers.append(browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& emulator : program->emulator) {
|
||||||
|
for(auto& media : emulator->media) {
|
||||||
|
if(media.bootable == true) continue;
|
||||||
|
if(names.find(media.name)) continue;
|
||||||
|
names.append(media.name);
|
||||||
|
LibraryBrowser* browser = new LibraryBrowser;
|
||||||
|
browser->setFilter(media.type);
|
||||||
|
browser->setPath({basepath, media.name, "/"});
|
||||||
|
libraryFrame.append(media.name);
|
||||||
|
libraryFrame.setLayout(selection++, *browser);
|
||||||
|
browsers.append(browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string LibraryManager::load(const string& type) {
|
||||||
|
setFocused();
|
||||||
|
|
||||||
|
unsigned selection = 1;
|
||||||
|
for(auto& browser : browsers) {
|
||||||
|
if(browser->filter == type) {
|
||||||
|
libraryFrame.setSelection(selection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
selection++;
|
||||||
|
}
|
||||||
|
|
||||||
|
slotLoad = true;
|
||||||
|
loadPathname = "";
|
||||||
|
setModal(true);
|
||||||
|
slotLoad = false;
|
||||||
|
return loadPathname;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryManager::setVisible(bool visible) {
|
||||||
|
setStatusText("");
|
||||||
|
Window::setVisible(visible);
|
||||||
|
}
|
37
target-ethos/general/library.hpp
Normal file
37
target-ethos/general/library.hpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
struct LibraryBrowser : VerticalLayout {
|
||||||
|
ListView folders;
|
||||||
|
HorizontalLayout informationLayout;
|
||||||
|
Label informationType;
|
||||||
|
Label information;
|
||||||
|
|
||||||
|
LibraryBrowser();
|
||||||
|
void onActivate();
|
||||||
|
void refresh();
|
||||||
|
void setFilter(const string& filter);
|
||||||
|
void setInformation();
|
||||||
|
void setPath(const string& pathname);
|
||||||
|
|
||||||
|
string filter;
|
||||||
|
string filterMask;
|
||||||
|
string filterSuffix;
|
||||||
|
string pathname;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LibraryManager : Window {
|
||||||
|
VerticalLayout layout;
|
||||||
|
TabFrame libraryFrame;
|
||||||
|
VerticalLayout importLayout;
|
||||||
|
Label importInformation;
|
||||||
|
Button importButton;
|
||||||
|
vector<LibraryBrowser*> browsers;
|
||||||
|
|
||||||
|
LibraryManager();
|
||||||
|
void bootstrap();
|
||||||
|
string load(const string& type);
|
||||||
|
void setVisible(bool visible = true);
|
||||||
|
|
||||||
|
bool slotLoad = false;
|
||||||
|
string loadPathname;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern LibraryManager* libraryManager;
|
@@ -62,7 +62,7 @@ Presentation::Presentation() {
|
|||||||
viewport.setDroppable();
|
viewport.setDroppable();
|
||||||
|
|
||||||
loadMenu.setText("Library");
|
loadMenu.setText("Library");
|
||||||
loadImport.setText("Import Game ...");
|
loadGame.setText("Load Game ...");
|
||||||
settingsMenu.setText("Settings");
|
settingsMenu.setText("Settings");
|
||||||
videoMenu.setText("Video");
|
videoMenu.setText("Video");
|
||||||
centerVideo.setText("Center");
|
centerVideo.setText("Center");
|
||||||
@@ -90,11 +90,7 @@ Presentation::Presentation() {
|
|||||||
synchronizeTime.setText("Synchronize Time");
|
synchronizeTime.setText("Synchronize Time");
|
||||||
|
|
||||||
append(loadMenu);
|
append(loadMenu);
|
||||||
for(auto& item : loadListSystem) loadMenu.append(*item);
|
loadMenu.append(loadGame);
|
||||||
if(program->ananke.open()) {
|
|
||||||
loadMenu.append(loadSeparator);
|
|
||||||
loadMenu.append(loadImport);
|
|
||||||
}
|
|
||||||
for(auto& systemItem : emulatorList) append(systemItem->menu);
|
for(auto& systemItem : emulatorList) append(systemItem->menu);
|
||||||
append(settingsMenu);
|
append(settingsMenu);
|
||||||
settingsMenu.append(videoMenu);
|
settingsMenu.append(videoMenu);
|
||||||
@@ -154,15 +150,7 @@ Presentation::Presentation() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loadImport.onActivate = [&] {
|
loadGame.onActivate = [&] { libraryManager->setVisible(); };
|
||||||
if(program->ananke.open() == false) return;
|
|
||||||
function<string ()> browse = program->ananke.sym("ananke_browse");
|
|
||||||
if(!browse) return;
|
|
||||||
string pathname = browse();
|
|
||||||
if(pathname.empty()) return;
|
|
||||||
utility->loadMedia(pathname);
|
|
||||||
};
|
|
||||||
|
|
||||||
shaderNone.onActivate = [&] { config->video.shader = "None"; utility->updateShader(); };
|
shaderNone.onActivate = [&] { config->video.shader = "None"; utility->updateShader(); };
|
||||||
shaderBlur.onActivate = [&] { config->video.shader = "Blur"; utility->updateShader(); };
|
shaderBlur.onActivate = [&] { config->video.shader = "Blur"; utility->updateShader(); };
|
||||||
shaderEmulation.onActivate = [&] { config->video.shader = "Display Emulation"; utility->updateShader(); };
|
shaderEmulation.onActivate = [&] { config->video.shader = "Display Emulation"; utility->updateShader(); };
|
||||||
@@ -190,16 +178,6 @@ void Presentation::bootstrap() {
|
|||||||
auto iEmulator = new Emulator;
|
auto iEmulator = new Emulator;
|
||||||
iEmulator->interface = emulator;
|
iEmulator->interface = emulator;
|
||||||
|
|
||||||
for(auto& media : emulator->media) {
|
|
||||||
if(media.bootable == false) continue;
|
|
||||||
auto item = new Item;
|
|
||||||
item->onActivate = [=, &media] {
|
|
||||||
utility->loadMedia(iEmulator->interface, media);
|
|
||||||
};
|
|
||||||
item->setText({media.name, " ..."});
|
|
||||||
loadListSystem.append(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
iEmulator->menu.setText(emulator->information.name);
|
iEmulator->menu.setText(emulator->information.name);
|
||||||
iEmulator->power.setText("Power");
|
iEmulator->power.setText("Power");
|
||||||
iEmulator->reset.setText("Reset");
|
iEmulator->reset.setText("Reset");
|
||||||
|
@@ -22,9 +22,7 @@ struct Presentation : Window {
|
|||||||
Emulator* active = nullptr;
|
Emulator* active = nullptr;
|
||||||
|
|
||||||
Menu loadMenu;
|
Menu loadMenu;
|
||||||
vector<Item*> loadListSystem;
|
Item loadGame;
|
||||||
Separator loadSeparator;
|
|
||||||
Item loadImport;
|
|
||||||
Menu settingsMenu;
|
Menu settingsMenu;
|
||||||
Menu videoMenu;
|
Menu videoMenu;
|
||||||
RadioItem centerVideo;
|
RadioItem centerVideo;
|
||||||
|
@@ -2,19 +2,19 @@ AdvancedSettings* advancedSettings = nullptr;
|
|||||||
|
|
||||||
AdvancedSettings::AdvancedSettings() {
|
AdvancedSettings::AdvancedSettings() {
|
||||||
driverTitle.setFont(program->boldFont);
|
driverTitle.setFont(program->boldFont);
|
||||||
driverTitle.setText("Driver Selection");
|
driverTitle.setText("Driver Selection:");
|
||||||
videoLabel.setText("Video:");
|
videoLabel.setText("Video:");
|
||||||
audioLabel.setText("Audio:");
|
audioLabel.setText("Audio:");
|
||||||
inputLabel.setText("Input:");
|
inputLabel.setText("Input:");
|
||||||
libraryTitle.setFont(program->boldFont);
|
libraryTitle.setFont(program->boldFont);
|
||||||
libraryTitle.setText("Game Library Path");
|
libraryTitle.setText("Game Library:");
|
||||||
libraryLabel.setText("Path:");
|
libraryLabel.setText("Path:");
|
||||||
libraryPath.setEditable(false);
|
libraryPath.setEditable(false);
|
||||||
string path = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/");
|
libraryPath.setText(utility->libraryPath());
|
||||||
if(path.empty()) path = {userpath(), "Emulation/"};
|
|
||||||
if(path.endswith("/") == false) path.append("/");
|
|
||||||
libraryPath.setText(path);
|
|
||||||
libraryBrowse.setText("Browse ...");
|
libraryBrowse.setText("Browse ...");
|
||||||
|
libraryShowOnStartup.setChecked(config->library.showOnStartup);
|
||||||
|
libraryShowOnStartup.setText("Show game library on program start");
|
||||||
|
information.setText("Note: changing advanced settings requires program restart to take effect.");
|
||||||
infoLabel.setFont(program->boldFont);
|
infoLabel.setFont(program->boldFont);
|
||||||
infoLabel.setText({
|
infoLabel.setText({
|
||||||
Emulator::Name, " v", Emulator::Version, "\n",
|
Emulator::Name, " v", Emulator::Version, "\n",
|
||||||
@@ -53,10 +53,12 @@ AdvancedSettings::AdvancedSettings() {
|
|||||||
driverLayout.append(inputLabel, {0, 0}, 5);
|
driverLayout.append(inputLabel, {0, 0}, 5);
|
||||||
driverLayout.append(inputDriver, {~0, 0});
|
driverLayout.append(inputDriver, {~0, 0});
|
||||||
append(libraryTitle, {~0, 0});
|
append(libraryTitle, {~0, 0});
|
||||||
append(libraryLayout, {~0, 0}, 15);
|
append(libraryLayout, {~0, 0});
|
||||||
libraryLayout.append(libraryLabel, {0, 0}, 5);
|
libraryLayout.append(libraryLabel, {0, 0}, 5);
|
||||||
libraryLayout.append(libraryPath, {~0, 0}, 5);
|
libraryLayout.append(libraryPath, {~0, 0}, 5);
|
||||||
libraryLayout.append(libraryBrowse, {80, 0});
|
libraryLayout.append(libraryBrowse, {80, 0});
|
||||||
|
append(libraryShowOnStartup, {~0, 0}, 15);
|
||||||
|
append(information, {~0, 0}, 15);
|
||||||
if(Intrinsics::platform() != Intrinsics::Platform::MacOSX) {
|
if(Intrinsics::platform() != Intrinsics::Platform::MacOSX) {
|
||||||
append(spacer, {~0, ~0});
|
append(spacer, {~0, ~0});
|
||||||
append(infoLabel, {~0, 0});
|
append(infoLabel, {~0, 0});
|
||||||
@@ -72,4 +74,8 @@ AdvancedSettings::AdvancedSettings() {
|
|||||||
file::write({configpath(), "higan/library.bml"}, {"Path: ", path, "\n"});
|
file::write({configpath(), "higan/library.bml"}, {"Path: ", path, "\n"});
|
||||||
libraryPath.setText(path);
|
libraryPath.setText(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
libraryShowOnStartup.onToggle = [&] {
|
||||||
|
config->library.showOnStartup = libraryShowOnStartup.checked();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,9 @@ struct AdvancedSettings : SettingsLayout {
|
|||||||
Label libraryLabel;
|
Label libraryLabel;
|
||||||
LineEdit libraryPath;
|
LineEdit libraryPath;
|
||||||
Button libraryBrowse;
|
Button libraryBrowse;
|
||||||
|
CheckLabel libraryShowOnStartup;
|
||||||
|
|
||||||
|
Label information;
|
||||||
|
|
||||||
Widget spacer;
|
Widget spacer;
|
||||||
Label infoLabel;
|
Label infoLabel;
|
||||||
|
@@ -12,16 +12,6 @@ void Utility::loadMedia(string pathname) {
|
|||||||
pathname.transform("\\", "/");
|
pathname.transform("\\", "/");
|
||||||
if(pathname.endswith("/")) pathname.rtrim("/");
|
if(pathname.endswith("/")) pathname.rtrim("/");
|
||||||
|
|
||||||
//if a filename was provided: convert to game folder and then load
|
|
||||||
if(!directory::exists(pathname) && file::exists(pathname)) {
|
|
||||||
if(program->ananke.open() == false) return;
|
|
||||||
function<string (string)> open = program->ananke.sym("ananke_open");
|
|
||||||
if(!open) return;
|
|
||||||
string name = open(pathname);
|
|
||||||
if(name.empty()) return;
|
|
||||||
return loadMedia(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!directory::exists(pathname)) return;
|
if(!directory::exists(pathname)) return;
|
||||||
string type = extension(pathname);
|
string type = extension(pathname);
|
||||||
|
|
||||||
@@ -30,20 +20,15 @@ void Utility::loadMedia(string pathname) {
|
|||||||
for(auto& media : emulator->media) {
|
for(auto& media : emulator->media) {
|
||||||
if(media.bootable == false) continue;
|
if(media.bootable == false) continue;
|
||||||
if(type != media.type) continue;
|
if(type != media.type) continue;
|
||||||
return loadMedia(emulator, media, {pathname, "/"});
|
loadMedia(emulator, media, {pathname, "/"});
|
||||||
|
libraryManager->setVisible(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageWindow().setText("Unable to determine media type.").warning();
|
MessageWindow().setText("Unable to determine media type.").warning();
|
||||||
}
|
}
|
||||||
|
|
||||||
//load menu option selected
|
|
||||||
void Utility::loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media) {
|
|
||||||
string pathname = browser->select({"Load ", media.name}, media.type);
|
|
||||||
if(!directory::exists(pathname)) return;
|
|
||||||
return loadMedia(emulator, media, pathname);
|
|
||||||
}
|
|
||||||
|
|
||||||
//load base cartridge
|
//load base cartridge
|
||||||
void Utility::loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname) {
|
void Utility::loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname) {
|
||||||
unload();
|
unload();
|
||||||
@@ -62,7 +47,7 @@ void Utility::loadMedia(Emulator::Interface* emulator, Emulator::Interface::Medi
|
|||||||
|
|
||||||
//request from emulation core to load non-volatile media folder
|
//request from emulation core to load non-volatile media folder
|
||||||
void Utility::loadRequest(unsigned id, string name, string type) {
|
void Utility::loadRequest(unsigned id, string name, string type) {
|
||||||
string pathname = browser->select({"Load ", name}, type);
|
string pathname = libraryManager->load(type); //browser->select({"Load ", name}, type);
|
||||||
if(pathname.empty()) return;
|
if(pathname.empty()) return;
|
||||||
path(id) = pathname;
|
path(id) = pathname;
|
||||||
this->pathname.append(pathname);
|
this->pathname.append(pathname);
|
||||||
@@ -318,6 +303,13 @@ void Utility::showMessage(string message) {
|
|||||||
statusMessage = message;
|
statusMessage = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string Utility::libraryPath() {
|
||||||
|
string path = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/");
|
||||||
|
if(path.empty()) path = {userpath(), "Emulation/"};
|
||||||
|
if(path.endswith("/") == false) path.append("/");
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
Utility::Utility() {
|
Utility::Utility() {
|
||||||
tracerEnable = false;
|
tracerEnable = false;
|
||||||
statusTime = 0;
|
statusTime = 0;
|
||||||
|
@@ -2,7 +2,6 @@ struct Utility {
|
|||||||
void setInterface(Emulator::Interface* emulator);
|
void setInterface(Emulator::Interface* emulator);
|
||||||
|
|
||||||
void loadMedia(string pathname);
|
void loadMedia(string pathname);
|
||||||
void loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media);
|
|
||||||
void loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname);
|
void loadMedia(Emulator::Interface* emulator, Emulator::Interface::Media& media, string pathname);
|
||||||
|
|
||||||
void loadRequest(unsigned id, string name, string type);
|
void loadRequest(unsigned id, string name, string type);
|
||||||
@@ -30,6 +29,8 @@ struct Utility {
|
|||||||
void setStatusText(string text);
|
void setStatusText(string text);
|
||||||
void showMessage(string message);
|
void showMessage(string message);
|
||||||
|
|
||||||
|
string libraryPath();
|
||||||
|
|
||||||
Utility();
|
Utility();
|
||||||
|
|
||||||
lstring path;
|
lstring path;
|
||||||
|
Reference in New Issue
Block a user