Update to v070r10 release.

byuu says:

- added workaround to phoenix/Windows to prevent horizontal scrollbar
  always being visible on single-column ListBoxes
- phoenix gains Window::geometry()
- added code to save and restore window positions, as in bsnes/Qt.
  Positions are saved to bsnes-phoenix-geometry.cfg this time
- resizing the main window will keep its position onscreen now

There's one issue with GTK+, if you close a window and then call
gtk_window_get_position(), it returns the previously set position rather
than where you actually placed the window. My easy fix of calling
gtk_window_get_position right before actually closing the window didn't
work, so for now you'll have to live with it.
This commit is contained in:
Tim Allen 2010-10-07 20:15:29 +11:00
parent 8a53e9ed22
commit e2db2c24fc
35 changed files with 340 additions and 223 deletions

View File

@ -145,7 +145,7 @@ namespace nall {
break;
}
p_fd = ::open(filename, open_flags);
p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if(p_fd < 0) return false;
struct stat p_stat;

View File

@ -1,190 +1,221 @@
#ifndef NALL_UPS_HPP
#define NALL_UPS_HPP
#include <stdio.h>
#include <nall/algorithm.hpp>
#include <nall/crc32.hpp>
#include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/stdint.hpp>
namespace nall {
class ups {
public:
enum result {
ok,
patch_unreadable,
patch_unwritable,
patch_invalid,
input_invalid,
output_invalid,
patch_crc32_invalid,
input_crc32_invalid,
output_crc32_invalid,
};
ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) {
if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable;
struct ups {
enum class result_t : unsigned {
unknown,
success,
patch_unwritable,
patch_invalid,
source_invalid,
target_invalid,
target_too_small,
patch_checksum_invalid,
source_checksum_invalid,
target_checksum_invalid,
};
crc32 = ~0;
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
uint32_t y_crc32 = crc32_calculate(y_data, y_size);
function<void (unsigned offset, unsigned length)> progress;
//header
write('U');
write('P');
write('S');
write('1');
encptr(x_size);
encptr(y_size);
result_t create(
const uint8_t *source_data_, unsigned source_length_,
const uint8_t *target_data_, unsigned target_length_,
const char *patch_filename
) {
source_data = (uint8_t*)source_data_, target_data = (uint8_t*)target_data_;
source_length = source_length_, target_length = target_length_;
source_offset = target_offset = 0;
source_checksum = target_checksum = patch_checksum = ~0;
//body
unsigned max_size = max(x_size, y_size);
unsigned relative = 0;
for(unsigned i = 0; i < max_size;) {
uint8_t x = i < x_size ? x_data[i] : 0x00;
uint8_t y = i < y_size ? y_data[i] : 0x00;
if(patch_file.open(patch_filename, file::mode_write) == false) return result_t::patch_unwritable;
if(x == y) {
i++;
continue;
}
patch_write('U');
patch_write('P');
patch_write('S');
patch_write('1');
encode(source_length);
encode(target_length);
encptr(i++ - relative);
write(x ^ y);
unsigned output_length = source_length > target_length ? source_length : target_length;
unsigned relative = 0;
for(unsigned offset = 0; offset < output_length;) {
uint8_t x = source_read();
uint8_t y = target_read();
while(true) {
if(i >= max_size) {
write(0x00);
break;
}
x = i < x_size ? x_data[i] : 0x00;
y = i < y_size ? y_data[i] : 0x00;
i++;
write(x ^ y);
if(x == y) break;
}
relative = i;
if(x == y) {
offset++;
continue;
}
//footer
for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3));
for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3));
uint32_t p_crc32 = ~crc32;
for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3));
encode(offset++ - relative);
patch_write(x ^ y);
fp.close();
return ok;
}
ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) {
if(p_size < 18) return patch_invalid;
p_buffer = p_data;
crc32 = ~0;
//header
if(read() != 'U') return patch_invalid;
if(read() != 'P') return patch_invalid;
if(read() != 'S') return patch_invalid;
if(read() != '1') return patch_invalid;
unsigned px_size = decptr();
unsigned py_size = decptr();
//mirror
if(x_size != px_size && x_size != py_size) return input_invalid;
y_size = (x_size == px_size) ? py_size : px_size;
y_data = new uint8_t[y_size]();
for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i];
for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00;
//body
unsigned relative = 0;
while(p_buffer < p_data + p_size - 12) {
relative += decptr();
while(true) {
uint8_t x = read();
if(x && relative < y_size) {
uint8_t y = relative < x_size ? x_data[relative] : 0x00;
y_data[relative] = x ^ y;
}
relative++;
if(!x) break;
}
}
//footer
unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0;
for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3);
for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3);
uint32_t p_crc32 = ~crc32;
for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3);
uint32_t x_crc32 = crc32_calculate(x_data, x_size);
uint32_t y_crc32 = crc32_calculate(y_data, y_size);
if(px_size != py_size) {
if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid;
if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid;
if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid;
if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid;
} else {
if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid;
if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid;
if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid;
if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid;
}
if(p_crc32 != pp_crc32) return patch_crc32_invalid;
return ok;
}
private:
file fp;
uint32_t crc32;
const uint8_t *p_buffer;
uint8_t read() {
uint8_t n = *p_buffer++;
crc32 = crc32_adjust(crc32, n);
return n;
}
void write(uint8_t n) {
fp.write(n);
crc32 = crc32_adjust(crc32, n);
}
void encptr(uint64_t offset) {
while(true) {
uint64_t x = offset & 0x7f;
offset >>= 7;
if(offset == 0) {
write(0x80 | x);
if(offset >= output_length) {
patch_write(0x00);
break;
}
write(x);
offset--;
x = source_read();
y = target_read();
offset++;
patch_write(x ^ y);
if(x == y) break;
}
relative = offset;
}
source_checksum = ~source_checksum;
target_checksum = ~target_checksum;
for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8));
for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8));
uint32_t patch_result_checksum = ~patch_checksum;
for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8));
patch_file.close();
return result_t::success;
}
result_t apply(
const uint8_t *patch_data_, unsigned patch_length_,
const uint8_t *source_data_, unsigned source_length_,
uint8_t *target_data_, unsigned &target_length_
) {
patch_data = (uint8_t*)patch_data_, source_data = (uint8_t*)source_data_, target_data = target_data_;
patch_length = patch_length_, source_length = source_length_, target_length = target_length_;
patch_offset = source_offset = target_offset = 0;
patch_checksum = source_checksum = target_checksum = ~0;
if(patch_length < 18) return result_t::patch_invalid;
if(patch_read() != 'U') return result_t::patch_invalid;
if(patch_read() != 'P') return result_t::patch_invalid;
if(patch_read() != 'S') return result_t::patch_invalid;
if(patch_read() != '1') return result_t::patch_invalid;
unsigned source_read_length = decode();
unsigned target_read_length = decode();
if(source_length != source_read_length && source_length != target_read_length) return result_t::source_invalid;
target_length_ = (source_length == source_read_length ? target_read_length : source_read_length);
if(target_length < target_length_) return result_t::target_too_small;
target_length = target_length_;
while(patch_offset < patch_length - 12) {
unsigned length = decode();
while(length--) target_write(source_read());
while(true) {
uint8_t patch_xor = patch_read();
target_write(patch_xor ^ source_read());
if(patch_xor == 0) break;
}
}
uint64_t decptr() {
uint64_t offset = 0, shift = 1;
while(true) {
uint8_t x = read();
offset += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
offset += shift;
}
return offset;
uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0;
for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8);
for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8);
uint32_t patch_result_checksum = ~patch_checksum;
source_checksum = ~source_checksum;
target_checksum = ~target_checksum;
for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8);
if(patch_result_checksum != patch_read_checksum) return result_t::patch_invalid;
if(source_checksum == source_read_checksum && source_length == source_read_length) {
if(target_checksum == target_read_checksum && target_length == target_read_length) return result_t::success;
return result_t::target_invalid;
} else if(source_checksum == target_read_checksum && source_length == target_read_length) {
if(target_checksum == source_read_checksum && target_length == source_read_length) return result_t::success;
return result_t::target_invalid;
} else {
return result_t::source_invalid;
}
};
}
private:
uint8_t *patch_data, *source_data, *target_data;
unsigned patch_length, source_length, target_length;
unsigned patch_offset, source_offset, target_offset;
unsigned patch_checksum, source_checksum, target_checksum;
file patch_file;
uint8_t patch_read() {
if(patch_offset < patch_length) {
uint8_t n = patch_data[patch_offset++];
patch_checksum = crc32_adjust(patch_checksum, n);
return n;
}
return 0x00;
}
uint8_t source_read() {
if(source_offset < source_length) {
uint8_t n = source_data[source_offset++];
source_checksum = crc32_adjust(source_checksum, n);
return n;
}
return 0x00;
}
uint8_t target_read() {
uint8_t result = 0x00;
if(target_offset < target_length) {
result = target_data[target_offset];
target_checksum = crc32_adjust(target_checksum, result);
}
if(((target_offset++ & 255) == 0) && progress) {
progress(target_offset, source_length > target_length ? source_length : target_length);
}
return result;
}
void patch_write(uint8_t n) {
patch_file.write(n);
patch_checksum = crc32_adjust(patch_checksum, n);
}
void target_write(uint8_t n) {
if(target_offset < target_length) {
target_data[target_offset] = n;
target_checksum = crc32_adjust(target_checksum, n);
}
if(((target_offset++ & 255) == 0) && progress) {
progress(target_offset, source_length > target_length ? source_length : target_length);
}
}
void encode(uint64_t offset) {
while(true) {
uint64_t x = offset & 0x7f;
offset >>= 7;
if(offset == 0) {
patch_write(0x80 | x);
break;
}
patch_write(x);
offset--;
}
}
uint64_t decode() {
uint64_t offset = 0, shift = 1;
while(true) {
uint8_t x = patch_read();
offset += (x & 0x7f) * shift;
if(x & 0x80) break;
shift <<= 7;
offset += shift;
}
return offset;
}
};
}
#endif

View File

@ -12,6 +12,13 @@ struct Object {
Data *object;
};
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object {
enum class Style : unsigned {
None = 0,
@ -91,6 +98,7 @@ struct Window : Widget {
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
bool focused();
void setFocused();
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setDefaultFont(Font &font);
void setFont(Font &font);
@ -188,7 +196,7 @@ struct ListBox : Widget {
struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
void setProgress(unsigned progress);
void setPosition(unsigned position);
};
struct RadioBox : Widget {

View File

@ -6,7 +6,7 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width,
gtk_widget_show(object->widget);
}
void ProgressBar::setProgress(unsigned progress) {
progress = progress <= 100 ? progress : 0;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(object->widget), (double)progress / 100.0);
void ProgressBar::setPosition(unsigned position) {
position = position <= 100 ? position : 0;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(object->widget), (double)position / 100.0);
}

View File

@ -47,6 +47,13 @@ void Window::setFocused() {
gtk_window_present(GTK_WINDOW(object->widget));
}
Geometry Window::geometry() {
gint x, y, width, height;
gtk_window_get_position(GTK_WINDOW(object->widget), &x, &y);
gtk_widget_get_size_request(object->formContainer, &width, &height);
return Geometry(x, y, width, height);
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
gtk_window_move(GTK_WINDOW(object->widget), x, y);
gtk_widget_set_size_request(object->formContainer, width, height);

View File

@ -6,8 +6,8 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width,
progressBar->show();
}
void ProgressBar::setProgress(unsigned progress) {
progressBar->setValue(progress);
void ProgressBar::setPosition(unsigned position) {
progressBar->setValue(position);
}
ProgressBar::ProgressBar() {

View File

@ -12,6 +12,13 @@ struct Object {
Data *object;
};
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object {
enum class Style : unsigned {
None = 0,
@ -123,6 +130,7 @@ struct Widget : Object {
struct Window : Widget {
nall::function<bool ()> onClose;
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setDefaultFont(Font &font);
void setFont(Font &font);
@ -240,7 +248,7 @@ struct ListBox : Widget {
struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
void setProgress(unsigned progress);
void setPosition(unsigned position);
ProgressBar();
//private:
struct Data;

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'qt.moc.hpp'
**
** Created: Mon Oct 4 00:53:54 2010
** Created: Wed Oct 6 18:50:06 2010
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.2)
**
** WARNING! All changes made in this file will be lost!

View File

@ -23,6 +23,10 @@ void Window::create(unsigned x, unsigned y, unsigned width, unsigned height, con
window->layout->addWidget(window->statusBar);
}
Geometry Window::geometry() {
return Geometry(window->x(), window->y(), window->container->width(), window->container->height());
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
window->container->setFixedSize(width, height);
window->move(x, y);

View File

@ -65,6 +65,9 @@ void ListBox::addItem(const char *text) {
utf16_t wtext(list[i]);
ListView_SetItemText(widget->window, row, i, wtext);
}
//workaround: when there is only one column, the horizontal scrollbar will always appear without this
if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER);
}
void ListBox::setItem(unsigned row, const char *text) {
@ -74,6 +77,9 @@ void ListBox::setItem(unsigned row, const char *text) {
utf16_t wtext(list[i]);
ListView_SetItemText(widget->window, row, i, wtext);
}
//workaround: when there is only one column, the horizontal scrollbar will always appear without this
if(listBox->columns == 1) ListView_SetColumnWidth(widget->window, 0, LVSCW_AUTOSIZE_USEHEADER);
}
optional<unsigned> ListBox::selection() {

View File

@ -9,10 +9,10 @@ void ProgressBar::create(Window &parent, unsigned x, unsigned y, unsigned width,
SendMessage(widget->window, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
}
unsigned ProgressBar::progress() {
unsigned ProgressBar::position() {
return SendMessage(widget->window, PBM_GETPOS, 0, 0);
}
void ProgressBar::setProgress(unsigned progress) {
SendMessage(widget->window, PBM_SETPOS, (WPARAM)progress, 0);
void ProgressBar::setPosition(unsigned position) {
SendMessage(widget->window, PBM_SETPOS, (WPARAM)position, 0);
}

View File

@ -26,6 +26,18 @@ void Window::setFont(Font &font) {
SendMessage(window->status, WM_SETFONT, (WPARAM)font.font->font, 0);
}
Geometry Window::geometry() {
RECT position, size;
GetWindowRect(widget->window, &position);
GetClientRect(widget->window, &size);
if(GetWindowLongPtr(window->status, GWL_STYLE) & WS_VISIBLE) {
RECT status;
GetClientRect(window->status, &status);
size.bottom -= status.bottom - status.top;
}
return Geometry(position.left, position.top, size.right, size.bottom);
}
void Window::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
bool isVisible = visible();
if(isVisible) setVisible(false);

View File

@ -11,6 +11,13 @@ private:
virtual void unused();
};
struct Geometry {
unsigned x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(unsigned x, unsigned y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object {
enum class Style : unsigned {
None = 0,
@ -96,6 +103,7 @@ struct Window : Widget {
void create(unsigned x, unsigned y, unsigned width, unsigned height, const char *text = "");
void setDefaultFont(Font &font);
void setFont(Font &font);
Geometry geometry();
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const char *text);
@ -198,8 +206,8 @@ struct ListBox : Widget {
struct ProgressBar : Widget {
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height);
unsigned progress();
void setProgress(unsigned progress);
unsigned position();
void setPosition(unsigned position);
};
struct RadioBox : Widget {

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "070.09";
static const char Version[] = "070.10";
static const unsigned SerializerVersion = 13;
}
}

View File

@ -14,6 +14,11 @@ using namespace ruby;
#include <phoenix/phoenix.hpp>
using namespace phoenix;
struct TopLevelWindow : Window {
string name;
string position;
};
#include "interface.hpp"
#include "config.hpp"
#include "general/general.hpp"
@ -24,13 +29,20 @@ using namespace phoenix;
#include "cartridge/cartridge.hpp"
struct Application {
array<Window*> windows;
Font proportionalFont;
Font proportionalFontBold;
Font monospaceFont;
bool quit;
void main(int argc, char **argv);
void addWindow(TopLevelWindow *window, const string &name, const string &position);
private:
array<TopLevelWindow*> windows;
configuration geometryConfig;
void loadGeometry();
void saveGeometry();
};
extern Application application;

View File

@ -1,9 +1,8 @@
FileBrowser fileBrowser;
void FileBrowser::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256);
setDefaultFont(application.proportionalFont);
application.addWindow(this, "FileBrowser", "160,160");
unsigned x = 5, y = 5, height = Style::TextBoxHeight;
@ -13,7 +12,7 @@ void FileBrowser::create() {
contentsBox.create(*this, x, y, 630, 350); y += 350 + 5;
setGeometry(160, 160, 640, y);
setGeometry(0, 0, 640, y);
pathBox.onActivate = []() { fileBrowser.setFolder(fileBrowser.pathBox.text()); };
browseButton.onTick = { &FileBrowser::folderBrowse, this };

View File

@ -1,4 +1,4 @@
struct FileBrowser : Window {
struct FileBrowser : TopLevelWindow {
TextBox pathBox;
Button browseButton;
Button upButton;

View File

@ -1,9 +1,8 @@
MainWindow mainWindow;
void MainWindow::create() {
application.windows.append(this);
Window::create(128, 128, 595, 448, string(SNES::Info::Name, " v", SNES::Info::Version));
setDefaultFont(application.proportionalFont);
Window::create(0, 0, 595, 448, string(SNES::Info::Name, " v", SNES::Info::Version));
application.addWindow(this, "MainWindow", "128,128");
setFont(application.proportionalFontBold);
setBackgroundColor(0, 0, 0);

View File

@ -1,4 +1,4 @@
struct MainWindow : Window {
struct MainWindow : TopLevelWindow {
Menu system;
MenuItem systemLoadCartridge;
Menu systemLoadCartridgeSpecial;

View File

@ -2,9 +2,8 @@ SingleSlotLoader singleSlotLoader;
DoubleSlotLoader doubleSlotLoader;
void SingleSlotLoader::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256);
setDefaultFont(application.proportionalFont);
application.addWindow(this, "SingleSlotLoader", "160,160");
unsigned x = 5, y = 5, height = Style::TextBoxHeight, width = 365 + height;
@ -18,7 +17,7 @@ void SingleSlotLoader::create() {
okButton.create(*this, x + width - 90, y, 80, Style::ButtonHeight, "Ok"); y += Style::ButtonHeight + 5;
setGeometry(160, 160, width, y);
setGeometry(0, 0, width, y);
baseBrowse.onTick = []() {
fileBrowser.fileOpen(FileBrowser::Mode::Cartridge, [](string filename) {
@ -88,9 +87,8 @@ void SingleSlotLoader::load() {
//
void DoubleSlotLoader::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256);
setDefaultFont(application.proportionalFont);
application.addWindow(this, "DoubleSlotLoader", "160,160");
unsigned x = 5, y = 5, height = Style::TextBoxHeight, width = 365 + height;
@ -108,7 +106,7 @@ void DoubleSlotLoader::create() {
okButton.create(*this, x + width - 90, y, 80, Style::ButtonHeight, "Ok"); y += Style::ButtonHeight + 5;
setGeometry(160, 160, width, y);
setGeometry(0, 0, width, y);
baseBrowse.onTick = []() {
fileBrowser.fileOpen(FileBrowser::Mode::Cartridge, [](string filename) {

View File

@ -1,4 +1,4 @@
struct SingleSlotLoader : Window {
struct SingleSlotLoader : TopLevelWindow {
Label baseLabel;
TextBox basePath;
Button baseBrowse;
@ -16,7 +16,7 @@ struct SingleSlotLoader : Window {
void load();
};
struct DoubleSlotLoader : Window {
struct DoubleSlotLoader : TopLevelWindow {
Label baseLabel;
TextBox basePath;
Button baseBrowse;

View File

@ -40,6 +40,7 @@ void Application::main(int argc, char **argv) {
if(config.input.driver == "") config.input.driver = input.default_driver();
palette.update();
mainWindow.create();
fileBrowser.create();
singleSlotLoader.create();
@ -50,6 +51,9 @@ void Application::main(int argc, char **argv) {
advancedSettings.create();
cheatEditor.create();
stateManager.create();
loadGeometry();
saveGeometry();
utility.setScale(config.video.scale);
mainWindow.setVisible();
OS::run();
@ -111,6 +115,7 @@ void Application::main(int argc, char **argv) {
}
cartridge.unload();
saveGeometry();
foreach(window, windows) window->setVisible(false);
OS::run();
SNES::system.term();
@ -121,7 +126,33 @@ void Application::main(int argc, char **argv) {
input.term();
}
void Application::addWindow(TopLevelWindow *window, const string &name, const string &position) {
windows.append(window);
window->setDefaultFont(proportionalFont);
window->name = name;
window->position = position;
geometryConfig.attach(window->position, window->name);
}
int main(int argc, char **argv) {
application.main(argc, argv);
return 0;
}
void Application::loadGeometry() {
geometryConfig.load(string(config.path.user, "bsnes-phoenix-geometry.cfg"));
foreach(window, windows) {
lstring position;
position.split(",", window->position);
Geometry geom = window->geometry();
window->setGeometry(strunsigned(position[0]), strunsigned(position[1]), geom.width, geom.height);
}
}
void Application::saveGeometry() {
foreach(window, windows) {
Geometry geom = window->geometry();
window->position = string(geom.x, ",", geom.y);
}
geometryConfig.save(string(config.path.user, "bsnes-phoenix-geometry.cfg"));
}

View File

@ -1,9 +1,8 @@
AdvancedSettings advancedSettings;
void AdvancedSettings::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "Advanced Settings");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "AdvancedSettings", "160,160");
unsigned x = 5, y = 5;
@ -27,7 +26,7 @@ void AdvancedSettings::create() {
if(config.settings.focusPolicy == 1) focusPolicyIgnore.setChecked();
if(config.settings.focusPolicy == 2) focusPolicyAllow.setChecked();
setGeometry(160, 160, 605, y);
setGeometry(0, 0, 605, y);
lstring list;

View File

@ -1,4 +1,4 @@
struct AdvancedSettings : Window {
struct AdvancedSettings : TopLevelWindow {
Label driverSelectionLabel;
Label videoDriverLabel;
ComboBox videoDriverBox;

View File

@ -1,9 +1,8 @@
AudioSettings audioSettings;
void AudioSettings::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "Audio Settings");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "AudioSettings", "160,160");
unsigned x = 5, y = 5;
@ -29,5 +28,5 @@ void AudioSettings::create() {
audioSettings.frequencyValue.setText(string(config.audio.inputFrequency, "hz"));
};
setGeometry(160, 160, 440, y);
setGeometry(0, 0, 440, y);
}

View File

@ -1,4 +1,4 @@
struct AudioSettings : Window {
struct AudioSettings : TopLevelWindow {
Label volumeLabel;
Label volumeValue;
HorizontalSlider volumeSlider;

View File

@ -2,9 +2,8 @@ InputSettings inputSettings;
static InputMapper::AbstractInput *activeInput = 0;
void InputSettings::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "Input Settings");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "InputSettings", "160,160");
setFont(application.proportionalFontBold);
setStatusVisible();
@ -38,7 +37,7 @@ void InputSettings::create() {
clearButton.create(*this, 515 - 85, y, 80, height, "Clear");
y += height + 5;
setGeometry(160, 160, 515, y);
setGeometry(0, 0, 515, y);
refreshDevices();
portBox.onChange = { &InputSettings::refreshDevices, this };

View File

@ -1,4 +1,4 @@
struct InputSettings : Window {
struct InputSettings : TopLevelWindow {
Label portLabel;
ComboBox portBox;
Label deviceLabel;

View File

@ -1,9 +1,8 @@
VideoSettings videoSettings;
void VideoSettings::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "Video Settings");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "VideoSettings", "160,160");
unsigned x = 5, y = 5, height = Style::TextBoxHeight;
@ -33,7 +32,7 @@ void VideoSettings::create() {
shaderClear.create(*this, x + 430 - height - height - 5, y, height, height, "");
shaderSelect.create(*this, x + 430 - height, y, height, height, "..."); y += height + 5;
setGeometry(160, 160, 440, y);
setGeometry(0, 0, 440, y);
brightnessSlider.setPosition(config.video.brightness);
contrastSlider.setPosition(config.video.contrast);

View File

@ -1,4 +1,4 @@
struct VideoSettings : Window {
struct VideoSettings : TopLevelWindow {
Label colorAdjustmentLabel;
Label brightnessLabel;
Label brightnessValue;

View File

@ -79,9 +79,8 @@ void CheatEditor::save(string filename) {
}
void CheatEditor::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "Cheat Editor");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "CheatEditor", "160,160");
unsigned x = 5, y = 5, height = Style::ButtonHeight;
@ -99,7 +98,7 @@ void CheatEditor::create() {
clearAllButton.create(*this, x + 505 - 85 - 85, y, 80, height, "Clear All");
clearButton.create(*this, x + 505 - 85, y, 80, height, "Clear"); y += height + 5;
setGeometry(160, 160, 510, y);
setGeometry(0, 0, 510, y);
synchronize();
cheatList.onChange = { &CheatEditor::synchronize, this };
@ -115,9 +114,8 @@ void CheatEditor::create() {
};
//databaseWindow
application.windows.append(&databaseWindow);
databaseWindow.create(0, 0, 256, 256);
databaseWindow.setDefaultFont(application.proportionalFont);
application.addWindow(&databaseWindow, "CheatDatabase", "192,192");
x = 5, y = 5;
@ -128,7 +126,7 @@ void CheatEditor::create() {
databaseUnselectAll.create(databaseWindow, x + 105, y, 100, height, "Unselect All");
databaseOk.create(databaseWindow, 605 - 80, y, 80, height, "Ok"); y += height + 5;
databaseWindow.setGeometry(192, 192, 610, y);
databaseWindow.setGeometry(0, 0, 610, y);
databaseSelectAll.onTick = []() {
for(unsigned i = 0; i < cheatEditor.databaseCode.size(); i++) {

View File

@ -1,4 +1,4 @@
struct CheatEditor : Window {
struct CheatEditor : TopLevelWindow {
ListBox cheatList;
Label codeLabel;
TextBox codeEdit;
@ -8,7 +8,7 @@ struct CheatEditor : Window {
Button clearAllButton;
Button clearButton;
Window databaseWindow;
TopLevelWindow databaseWindow;
ListBox databaseList;
lstring databaseCode;
Button databaseSelectAll;

View File

@ -1,9 +1,8 @@
StateManager stateManager;
void StateManager::create() {
application.windows.append(this);
Window::create(0, 0, 256, 256, "State Manager");
setDefaultFont(application.proportionalFont);
application.addWindow(this, "StateManager", "160,160");
unsigned x = 5, y = 5;
@ -17,7 +16,7 @@ void StateManager::create() {
saveButton.create(*this, x + 505 - 85 - 85, y, 80, Style::ButtonHeight, "Save");
eraseButton.create(*this, x + 505 - 85, y, 80, Style::ButtonHeight, "Erase"); y += Style::ButtonHeight + 5;
setGeometry(160, 160, 510, y);
setGeometry(0, 0, 510, y);
synchronize();
stateList.onActivate = { &StateManager::slotLoad, this };

View File

@ -1,4 +1,4 @@
struct StateManager : Window {
struct StateManager : TopLevelWindow {
ListBox stateList;
Label descLabel;
TextBox descEdit;

View File

@ -66,7 +66,8 @@ void Utility::setScale(unsigned scale) {
if(config.video.aspectRatioCorrection) width *= 32.0 / 23.0;
}
mainWindow.viewport.setGeometry(0, 0, width, height);
mainWindow.setGeometry(128, 128, width, height);
Geometry geom = mainWindow.geometry();
mainWindow.setGeometry(geom.x, geom.y, width, height);
}
void Utility::setShader() {