Update to v075r12 release.

byuu says:

phoenix has been completely rewritten from scratch, and bsnes/ui + bsnes/ui-gameboy have been updated to use the new API. Debugger works too. Currently, only phoenix/Qt is completed, and there are two known issues:

1: font sizes of menu items are wrong, I can fix this easily enough
2: there's some sort of multi-second lag when loading games, not sure
   what's happening there yet

The new phoenix isn't exactly complete yet, still making some key
changes, and then I'll start on phoenix/Windows and phoenix/GTK+.

The most noticeable difference is that you don't have to give all of the
header paths and PHOENIX_PLATFORM defines when compiling individual GUI
object files. It's only needed for phoenix.cpp itself. The overall
structure of the phoenix source folder is much saner as well for
sync.sh.

I'm really surprised things are working as well as they are for
a two-day power rewrite of an entire phoenix target. The other targets
won't be as bad insofar as the core stuff is completed this time. And
thank god for that, I was about ready to kill myself after writing
dozens of lines like this:

    HorizontalSlider::HorizontalSlider() : state(*new State),
    base_from_member<pHorizontalSlider&>(*new pHorizontalSlider(*this)),
    Widget(base_from_member<pHorizontalSlider&>::value),
    p(base_from_member<pHorizontalSlider&>::value) {}

But each platform does have some new, unique problems. phoenix/GTK+ was
acting screwy prior to the rewrite, and will most likely still have
issues. Even more important, one of the major points of this rewrite was
having the new phoenix/core cache widget settings/data, so that I can
destroy and recreate widgets rather than relying on SetParent. This
means that simple copying of the old phoenix/Windows won't work, and
this new method is significantly more involved.
This commit is contained in:
Tim Allen 2011-02-15 23:22:37 +11:00
parent a8ee35633c
commit 72a2967eeb
142 changed files with 2992 additions and 6653 deletions

View File

@ -2,7 +2,7 @@ include nall/Makefile
snes := snes
gameboy := gameboy
profile := compatibility
ui := ui
ui := ui-gameboy
# compiler
c := $(compiler) -std=gnu99

View File

@ -5,7 +5,7 @@
namespace GameBoy {
namespace Info {
static const char Name[] = "bgameboy";
static const char Version[] = "000.18";
static const char Version[] = "000.19";
static unsigned SerializerVersion = 1;
}
}

392
bsnes/phoenix/core/core.cpp Executable file
View File

@ -0,0 +1,392 @@
struct OS::State {
Font *defaultFont;
State() {
defaultFont = 0;
}
};
struct Font::State {
bool bold;
string family;
bool italic;
unsigned size;
bool underline;
State() {
bold = false;
italic = false;
size = 8;
underline = false;
}
};
struct Window::State {
bool backgroundColor;
unsigned backgroundColorRed, backgroundColorGreen, backgroundColorBlue;
bool fullScreen;
Geometry geometry;
Layout *layout;
Font *menuFont;
bool menuVisible;
bool resizable;
Font *statusFont;
string statusText;
bool statusVisible;
string title;
bool visible;
State() {
backgroundColor = false;
backgroundColorRed = 0;
backgroundColorGreen = 0;
backgroundColorBlue = 0;
fullScreen = false;
geometry = { 128, 128, 256, 256 };
layout = 0;
menuFont = 0;
menuVisible = false;
resizable = true;
statusVisible = false;
visible = false;
}
};
struct Action::State {
bool enabled;
bool visible;
State() {
enabled = true;
visible = true;
}
};
struct Menu::State {
string text;
};
struct MenuItem::State {
string text;
};
struct MenuCheckItem::State {
bool checked;
string text;
State() {
checked = false;
}
};
struct MenuRadioItem::State {
bool checked;
array<MenuRadioItem*> group;
string text;
State() {
checked = true;
}
};
struct Layout::State {
Window *parent;
State() {
parent = 0;
}
};
struct Widget::State {
bool enabled;
Font *font;
Geometry geometry;
bool visible;
State() {
enabled = true;
font = 0;
geometry = { 0, 0, 0, 0 };
visible = true;
}
};
struct Button::State {
string text;
};
struct CheckBox::State {
bool checked;
string text;
State() {
checked = false;
}
};
struct ComboBox::State {
unsigned selection;
linear_vector<string> text;
State() {
selection = 0;
}
};
struct HexEdit::State {
unsigned columns;
unsigned length;
unsigned offset;
unsigned rows;
State() {
columns = 16;
length = 0;
offset = 0;
rows = 16;
}
};
struct HorizontalSlider::State {
unsigned length;
unsigned position;
State() {
length = 101;
position = 0;
}
};
struct Label::State {
string text;
};
struct LineEdit::State {
bool editable;
string text;
State() {
editable = true;
}
};
struct ListBox::State {
bool checkable;
array<bool> checked;
lstring headerText;
bool headerVisible;
optional<unsigned> selection;
linear_vector<lstring> text;
State() : selection(false, 0) {
checkable = false;
headerVisible = false;
}
};
struct ProgressBar::State {
unsigned position;
State() {
position = 0;
}
};
struct RadioBox::State {
bool checked;
array<RadioBox*> group;
string text;
State() {
checked = true;
}
};
struct TextEdit::State {
unsigned cursorPosition;
bool editable;
string text;
bool wordWrap;
State() {
cursorPosition = 0;
editable = true;
wordWrap = false;
}
};
struct VerticalSlider::State {
unsigned length;
unsigned position;
State() {
length = 101;
position = 0;
}
};
#include "layout/fixed-layout.cpp"
#include "layout/horizontal-layout.cpp"
#include "layout/vertical-layout.cpp"
#if defined(PHOENIX_QT)
#include "../qt/qt.cpp"
#endif
Object::Object() { OS::initialize(); }
OS::State* OS::state = 0;
pOS* OS::p = 0;
unsigned OS::desktopWidth() { return p->desktopWidth(); }
unsigned OS::desktopHeight() { return p->desktopHeight(); }
string OS::fileLoad_(Window &parent, const string &path, lstring &filter) { if(filter.size() == 0) filter.append("All files (*)"); return p->fileLoad(parent, path, filter); }
string OS::fileSave_(Window &parent, const string &path, lstring &filter) { if(filter.size() == 0) filter.append("All files (*)"); return p->fileSave(parent, path, filter); }
string OS::folderSelect(Window &parent, const string &path) { return p->folderSelect(parent, path); }
void OS::main() { return p->main(); }
bool OS::pending() { return p->pending(); }
void OS::process() { return p->process(); }
void OS::quit() { return p->quit(); }
void OS::setDefaultFont(Font &font) { state->defaultFont = &font; return p->setDefaultFont(font); }
void OS::initialize() { if(state == 0) state = new State; if(p == 0) p = new pOS; }
void Font::setBold(bool bold) { state.bold = bold; return p.setBold(bold); }
void Font::setFamily(const string &family) { state.family = family; return p.setFamily(family); }
void Font::setItalic(bool italic) { state.italic = italic; return p.setItalic(italic); }
void Font::setSize(unsigned size) { state.size = size; return p.setSize(size); }
void Font::setUnderline(bool underline) { state.underline = underline; return p.setUnderline(underline); }
Font::Font() : state(*new State), p(*new pFont(*this)) {}
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::information(parent, text, buttons); }
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::question(parent, text, buttons); }
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::warning(parent, text, buttons); }
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) { return pMessageWindow::critical(parent, text, buttons); }
Window Window::None;
void Window::append(Menu &menu) { return p.append(menu); }
Geometry Window::frameGeometry() { return p.frameGeometry(); }
bool Window::focused() { return p.focused(); }
Geometry Window::geometry() { return p.geometry(); }
void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) { state.backgroundColor = true; state.backgroundColorRed = red; state.backgroundColorGreen = green; state.backgroundColorBlue = blue; return p.setBackgroundColor(red, green, blue); }
void Window::setFrameGeometry(const Geometry &geometry) { return p.setFrameGeometry(geometry); }
void Window::setFocused() { return p.setFocused(); }
void Window::setFullScreen(bool fullScreen) { state.fullScreen = fullScreen; return p.setFullScreen(fullScreen); }
void Window::setGeometry(const Geometry &geometry) { state.geometry = geometry; return p.setGeometry(geometry); }
void Window::setLayout(Layout &layout) { state.layout = &layout; return p.setLayout(layout); }
void Window::setMenuFont(Font &font) { state.menuFont = &font; return p.setMenuFont(font); }
void Window::setMenuVisible(bool visible) { state.menuVisible = visible; return p.setMenuVisible(visible); }
void Window::setResizable(bool resizable) { state.resizable = resizable; return p.setResizable(resizable); }
void Window::setStatusFont(Font &font) { state.statusFont = &font; return p.setStatusFont(font); }
void Window::setStatusText(const string &text) { state.statusText = text; return p.setStatusText(text); }
void Window::setStatusVisible(bool visible) { state.statusVisible = visible; return p.setStatusVisible(visible); }
void Window::setTitle(const string &text) { state.title = text; return p.setTitle(text); }
void Window::setVisible(bool visible) { state.visible = visible; return p.setVisible(visible); }
Window::Window() : state(*new State), p(*new pWindow(*this)) {}
void Action::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); }
void Action::setVisible(bool visible) { state.visible = visible; return p.setVisible(visible); }
Action::Action(pAction &p) : state(*new State), p(p) {}
void Menu::append(Action &action) { return p.append(action); }
void Menu::setText(const string &text) { state.text = text; return p.setText(text); }
Menu::Menu() : state(*new State), base_from_member<pMenu&>(*new pMenu(*this)), Action(base_from_member<pMenu&>::value), p(base_from_member<pMenu&>::value) {}
MenuSeparator::MenuSeparator() : base_from_member<pMenuSeparator&>(*new pMenuSeparator(*this)), Action(base_from_member<pMenuSeparator&>::value), p(base_from_member<pMenuSeparator&>::value) {}
void MenuItem::setText(const string &text) { state.text = text; return p.setText(text); }
MenuItem::MenuItem() : state(*new State), base_from_member<pMenuItem&>(*new pMenuItem(*this)), Action(base_from_member<pMenuItem&>::value), p(base_from_member<pMenuItem&>::value) {}
bool MenuCheckItem::checked() { return p.checked(); }
void MenuCheckItem::setChecked(bool checked) { state.checked = checked; return p.setChecked(checked); }
void MenuCheckItem::setText(const string &text) { state.text = text; return p.setText(text); }
MenuCheckItem::MenuCheckItem() : state(*new State), base_from_member<pMenuCheckItem&>(*new pMenuCheckItem(*this)), Action(base_from_member<pMenuCheckItem&>::value), p(base_from_member<pMenuCheckItem&>::value) {}
bool MenuRadioItem::checked() { return p.checked(); }
void MenuRadioItem::setChecked() { foreach(item, state.group) item->state.checked = false; state.checked = true; return p.setChecked(); }
void MenuRadioItem::setGroup(const array<MenuRadioItem*> &group) { state.group = group; return p.setGroup(group); }
void MenuRadioItem::setText(const string &text) { state.text = text; return p.setText(text); }
MenuRadioItem::MenuRadioItem() : state(*new State), base_from_member<pMenuRadioItem&>(*new pMenuRadioItem(*this)), Action(base_from_member<pMenuRadioItem&>::value), p(base_from_member<pMenuRadioItem&>::value) {}
void Layout::append(Widget &widget) { return p.append(widget); }
void Layout::setParent(Window &parent) { state.parent = &parent; }
Layout::Layout() : state(*new State), p(*new pLayout(*this)) {}
bool Widget::enabled() { return p.enabled(); }
void Widget::setEnabled(bool enabled) { state.enabled = enabled; return p.setEnabled(enabled); }
void Widget::setFocused() { return p.setFocused(); }
void Widget::setFont(Font &font) { state.font = &font; return p.setFont(font); }
void Widget::setGeometry(const Geometry &geometry) { state.geometry = geometry; return p.setGeometry(geometry); }
void Widget::setVisible(bool visible) { state.visible = visible; return p.setVisible(visible); }
Widget::Widget(pWidget &p) : state(*new State), p(p) {}
void Button::setText(const string &text) { state.text = text; return p.setText(text); }
Button::Button() : state(*new State), base_from_member<pButton&>(*new pButton(*this)), Widget(base_from_member<pButton&>::value), p(base_from_member<pButton&>::value) {}
bool CheckBox::checked() { return p.checked(); }
void CheckBox::setChecked(bool checked) { state.checked = checked; return p.setChecked(checked); }
void CheckBox::setText(const string &text) { state.text = text; return p.setText(text); }
CheckBox::CheckBox() : state(*new State), base_from_member<pCheckBox&>(*new pCheckBox(*this)), Widget(base_from_member<pCheckBox&>::value), p(base_from_member<pCheckBox&>::value) {}
void ComboBox::append(const string &text) { state.text.append(text); return p.append(text); }
void ComboBox::reset() { state.selection = 0; state.text.reset(); return p.reset(); }
unsigned ComboBox::selection() { return p.selection(); }
void ComboBox::setSelection(unsigned row) { state.selection = row; return p.setSelection(row); }
ComboBox::ComboBox() : state(*new State), base_from_member<pComboBox&>(*new pComboBox(*this)), Widget(base_from_member<pComboBox&>::value), p(base_from_member<pComboBox&>::value) {}
void HexEdit::setColumns(unsigned columns) { state.columns = columns; return p.setColumns(columns); }
void HexEdit::setLength(unsigned length) { state.length = length; return p.setLength(length); }
void HexEdit::setOffset(unsigned offset) { state.offset = offset; return p.setOffset(offset); }
void HexEdit::setRows(unsigned rows) { state.rows = rows; return p.setRows(rows); }
void HexEdit::update() { return p.update(); }
HexEdit::HexEdit() : state(*new State), base_from_member<pHexEdit&>(*new pHexEdit(*this)), Widget(base_from_member<pHexEdit&>::value), p(base_from_member<pHexEdit&>::value) {}
unsigned HorizontalSlider::position() { return p.position(); }
void HorizontalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); }
void HorizontalSlider::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
HorizontalSlider::HorizontalSlider() : state(*new State), base_from_member<pHorizontalSlider&>(*new pHorizontalSlider(*this)), Widget(base_from_member<pHorizontalSlider&>::value), p(base_from_member<pHorizontalSlider&>::value) {}
void Label::setText(const string &text) { state.text = text; return p.setText(text); }
Label::Label() : state(*new State), base_from_member<pLabel&>(*new pLabel(*this)), Widget(base_from_member<pLabel&>::value), p(base_from_member<pLabel&>::value) {}
void LineEdit::setEditable(bool editable) { state.editable = editable; return p.setEditable(editable); }
void LineEdit::setText(const string &text) { state.text = text; return p.setText(text); }
string LineEdit::text() { return p.text(); }
LineEdit::LineEdit() : state(*new State), base_from_member<pLineEdit&>(*new pLineEdit(*this)), Widget(base_from_member<pLineEdit&>::value), p(base_from_member<pLineEdit&>::value) {}
void ListBox::append_(lstring &text) { state.text.append(text); return p.append(text); }
void ListBox::autosizeColumns() { return p.autosizeColumns(); }
bool ListBox::checked(unsigned row) { return p.checked(row); }
void ListBox::modify_(unsigned row, lstring &text) { state.text[row] = text; return p.modify(row, text); }
void ListBox::modify(unsigned row, unsigned column, const string &text) { state.text[row][column] = text; return p.modify(row, column, text); }
void ListBox::reset() { state.checked.reset(); state.text.reset(); return p.reset(); }
optional<unsigned> ListBox::selection() { return p.selection(); }
void ListBox::setCheckable(bool checkable) { state.checkable = checkable; return p.setCheckable(checkable); }
void ListBox::setChecked(unsigned row, bool checked) { state.checked[row] = checked; return p.setChecked(row, checked); }
void ListBox::setHeaderText_(lstring &text) { state.headerText = text; return p.setHeaderText(text); }
void ListBox::setHeaderVisible(bool visible) { state.headerVisible = visible; return p.setHeaderVisible(visible); }
void ListBox::setSelection(unsigned row) { state.selection = { true, row }; return p.setSelection(row); }
ListBox::ListBox() : state(*new State), base_from_member<pListBox&>(*new pListBox(*this)), Widget(base_from_member<pListBox&>::value), p(base_from_member<pListBox&>::value) {}
void ProgressBar::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
ProgressBar::ProgressBar() : state(*new State), base_from_member<pProgressBar&>(*new pProgressBar(*this)), Widget(base_from_member<pProgressBar&>::value), p(base_from_member<pProgressBar&>::value) {}
bool RadioBox::checked() { return p.checked(); }
void RadioBox::setChecked() { foreach(item, state.group) item->state.checked = false; state.checked = true; return p.setChecked(); }
void RadioBox::setGroup(const array<RadioBox*> &group) { state.group = group; return p.setGroup(group); }
void RadioBox::setText(const string &text) { state.text = text; return p.setText(text); }
RadioBox::RadioBox() : state(*new State), base_from_member<pRadioBox&>(*new pRadioBox(*this)), Widget(base_from_member<pRadioBox&>::value), p(base_from_member<pRadioBox&>::value) {}
void TextEdit::setCursorPosition(unsigned position) { state.cursorPosition = position; return p.setCursorPosition(position); }
void TextEdit::setEditable(bool editable) { state.editable = editable; return p.setEditable(editable); }
void TextEdit::setText(const string &text) { state.text = text; return p.setText(text); }
void TextEdit::setWordWrap(bool wordWrap) { state.wordWrap = wordWrap; return p.setWordWrap(wordWrap); }
string TextEdit::text() { return p.text(); }
TextEdit::TextEdit() : state(*new State), base_from_member<pTextEdit&>(*new pTextEdit(*this)), Widget(base_from_member<pTextEdit&>::value), p(base_from_member<pTextEdit&>::value) {}
unsigned VerticalSlider::position() { return p.position(); }
void VerticalSlider::setLength(unsigned length) { state.length = length; return p.setLength(length); }
void VerticalSlider::setPosition(unsigned position) { state.position = position; return p.setPosition(position); }
VerticalSlider::VerticalSlider() : state(*new State), base_from_member<pVerticalSlider&>(*new pVerticalSlider(*this)), Widget(base_from_member<pVerticalSlider&>::value), p(base_from_member<pVerticalSlider&>::value) {}
uintptr_t Viewport::handle() { return p.handle(); }
Viewport::Viewport() : base_from_member<pViewport&>(*new pViewport(*this)), Widget(base_from_member<pViewport&>::value), p(base_from_member<pViewport&>::value) {}

451
bsnes/phoenix/core/core.hpp Executable file
View File

@ -0,0 +1,451 @@
struct Font;
struct Window;
struct Menu;
struct Layout;
struct Widget;
struct pOS;
struct pFont;
struct pWindow;
struct pAction;
struct pMenu;
struct pMenuSeparator;
struct pMenuItem;
struct pMenuCheckItem;
struct pMenuRadioItem;
struct pLayout;
struct pWidget;
struct pButton;
struct pCheckBox;
struct pComboBox;
struct pHexEdit;
struct pHorizontalSlider;
struct pLabel;
struct pLineEdit;
struct pListBox;
struct pProgressBar;
struct pRadioBox;
struct pTextEdit;
struct pVerticalSlider;
struct pViewport;
struct Geometry {
signed x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Object {
Object();
Object& operator=(const Object&) = delete;
Object(const Object&) = delete;
virtual void unused() {} //allows dynamic_cast<> on Object
};
struct OS : Object {
static unsigned desktopWidth();
static unsigned desktopHeight();
template<typename... Args> static nall::string fileLoad(Window &parent, const nall::string &path, const Args&... args) { nall::lstring filter; return fileLoad_(parent, path, filter, args...); }
template<typename... Args> static nall::string fileSave(Window &parent, const nall::string &path, const Args&... args) { nall::lstring filter; return fileSave_(parent, path, filter, args...); }
static nall::string folderSelect(Window &parent, const nall::string &path);
static void main();
static bool pending();
static void process();
static void quit();
static void setDefaultFont(Font &font);
OS();
struct State;
static State *state;
static pOS *p;
static void initialize();
private:
static nall::string fileLoad_(Window &parent, const nall::string &path, nall::lstring &filter);
template<typename... Args> static nall::string fileLoad_(Window &parent, const nall::string &path, nall::lstring &filter, const nall::string &item, const Args&... args) {
filter.append(item);
return fileLoad_(parent, path, filter, args...);
}
static nall::string fileSave_(Window &parent, const nall::string &path, nall::lstring &filter);
template<typename... Args> static nall::string fileSave_(Window &parent, const nall::string &path, nall::lstring &filter, const nall::string &item, const Args&... args) {
filter.append(item);
return fileSave_(parent, path, filter, args...);
}
};
struct Font : Object {
void setBold(bool bold = true);
void setFamily(const nall::string &family);
void setItalic(bool italic = true);
void setSize(unsigned size);
void setUnderline(bool underline = true);
Font();
struct State;
State &state;
pFont &p;
};
struct MessageWindow : Object {
enum class Buttons : unsigned {
Ok,
OkCancel,
YesNo,
};
enum class Response : unsigned {
Ok,
Cancel,
Yes,
No,
};
static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
};
struct Window : Object {
static Window None;
nall::function<void ()> onClose;
nall::function<void ()> onMove;
nall::function<void ()> onSize;
void append(Menu &menu);
Geometry frameGeometry();
bool focused();
Geometry geometry();
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setFrameGeometry(const Geometry &geometry);
void setFocused();
void setFullScreen(bool fullScreen = true);
void setGeometry(const Geometry &geometry);
void setLayout(Layout &layout);
void setMenuFont(Font &font);
void setMenuVisible(bool visible = true);
void setResizable(bool resizable = true);
void setStatusFont(Font &font);
void setStatusText(const nall::string &text);
void setStatusVisible(bool visible = true);
void setTitle(const nall::string &text);
void setVisible(bool visible = true);
Window();
struct State;
State &state;
pWindow &p;
};
struct Action : Object {
void setEnabled(bool enabled = true);
void setVisible(bool visible = true);
Action(pAction &p);
struct State;
State &state;
pAction &p;
};
struct Menu : private nall::base_from_member<pMenu&>, Action {
void append(Action &action);
void setText(const nall::string &text);
Menu();
struct State;
State &state;
pMenu &p;
};
struct MenuSeparator : private nall::base_from_member<pMenuSeparator&>, Action {
MenuSeparator();
pMenuSeparator &p;
};
struct MenuItem : private nall::base_from_member<pMenuItem&>, Action {
nall::function<void ()> onTick;
void setText(const nall::string &text);
MenuItem();
struct State;
State &state;
pMenuItem &p;
};
struct MenuCheckItem : private nall::base_from_member<pMenuCheckItem&>, Action {
nall::function<void ()> onTick;
bool checked();
void setChecked(bool checked = true);
void setText(const nall::string &text);
MenuCheckItem();
struct State;
State &state;
pMenuCheckItem &p;
};
struct MenuRadioItem : private nall::base_from_member<pMenuRadioItem&>, Action {
template<typename... Args> static void group(Args&... args) {
nall::array<MenuRadioItem*> list;
group_(list, args...);
foreach(item, list) item->setGroup(list);
if(list.size()) list[0]->setChecked();
}
nall::function<void ()> onTick;
bool checked();
void setChecked();
void setText(const nall::string &text);
MenuRadioItem();
struct State;
State &state;
pMenuRadioItem &p;
private:
void setGroup(const nall::array<MenuRadioItem*> &group);
static void group_(nall::array<MenuRadioItem*> &list) {}
template<typename... Args> static void group_(nall::array<MenuRadioItem*> &list, MenuRadioItem &item, Args&... args) {
list.append(&item);
group_(list, args...);
}
};
struct Layout : Object {
void append(Widget &widget);
virtual void setGeometry(Geometry &geometry) = 0;
virtual void setParent(Window &parent);
Layout();
struct State;
State &state;
pLayout &p;
};
struct Widget : Object {
bool enabled();
void setEnabled(bool enabled = true);
void setFocused();
void setFont(Font &font);
void setGeometry(const Geometry &geometry);
void setVisible(bool visible = true);
Widget(pWidget &p);
struct State;
State &state;
pWidget &p;
};
struct Button : private nall::base_from_member<pButton&>, Widget {
nall::function<void ()> onTick;
void setText(const nall::string &text);
Button();
struct State;
State &state;
pButton &p;
};
struct CheckBox : private nall::base_from_member<pCheckBox&>, Widget {
nall::function<void ()> onTick;
bool checked();
void setChecked(bool checked = true);
void setText(const nall::string &text);
CheckBox();
struct State;
State &state;
pCheckBox &p;
};
struct ComboBox : private nall::base_from_member<pComboBox&>, Widget {
nall::function<void ()> onChange;
void append(const nall::string &text);
void reset();
unsigned selection();
void setSelection(unsigned row);
ComboBox();
struct State;
State &state;
pComboBox &p;
};
struct HexEdit : private nall::base_from_member<pHexEdit&>, Widget {
nall::function<uint8_t (unsigned)> onRead;
nall::function<void (unsigned, uint8_t)> onWrite;
void setColumns(unsigned columns);
void setLength(unsigned length);
void setOffset(unsigned offset);
void setRows(unsigned rows);
void update();
HexEdit();
struct State;
State &state;
pHexEdit &p;
};
struct HorizontalSlider : private nall::base_from_member<pHorizontalSlider&>, Widget {
nall::function<void ()> onChange;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
HorizontalSlider();
struct State;
State &state;
pHorizontalSlider &p;
};
struct Label : private nall::base_from_member<pLabel&>, Widget {
void setText(const nall::string &text);
Label();
struct State;
State &state;
pLabel &p;
};
struct LineEdit : private nall::base_from_member<pLineEdit&>, Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
void setEditable(bool editable = true);
void setText(const nall::string &text);
nall::string text();
LineEdit();
struct State;
State &state;
pLineEdit &p;
};
struct ListBox : private nall::base_from_member<pListBox&>, Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
template<typename... Args> void append(const Args&... args) { nall::lstring list; append_(list, args...); }
void autosizeColumns();
bool checked(unsigned row);
template<typename... Args> void modify(unsigned row, const Args&... args) { nall::lstring list; modify_(row, list, args...); }
void modify(unsigned row, unsigned column, const nall::string &text);
void reset();
nall::optional<unsigned> selection();
void setCheckable(bool checkable = true);
void setChecked(unsigned row, bool checked = true);
template<typename... Args> void setHeaderText(const Args&... args) { nall::lstring list; setHeaderText_(list, args...); }
void setHeaderVisible(bool visible = true);
void setSelection(unsigned row);
ListBox();
struct State;
State &state;
pListBox &p;
private:
void modify_(unsigned row, nall::lstring &list);
template<typename... Args> void modify_(unsigned row, nall::lstring &list, const nall::string &text, const Args&... args) {
list.append(text);
modify_(row, list, args...);
}
void append_(nall::lstring &list);
template<typename... Args> void append_(nall::lstring &list, const nall::string &text, const Args&... args) {
list.append(text);
append_(list, args...);
}
void setHeaderText_(nall::lstring &list);
template<typename... Args> void setHeaderText_(nall::lstring &list, const nall::string &text, const Args&... args) {
list.append(text);
setHeaderText_(list, args...);
}
};
struct ProgressBar : private nall::base_from_member<pProgressBar&>, Widget {
void setPosition(unsigned position);
ProgressBar();
struct State;
State &state;
pProgressBar &p;
};
struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
template<typename... Args> static void group(Args&... args) {
nall::array<RadioBox*> list;
group_(list, args...);
foreach(item, list) item->setGroup(list);
if(list.size()) list[0]->setChecked();
}
nall::function<void ()> onTick;
bool checked();
void setChecked();
void setText(const nall::string &text);
RadioBox();
struct State;
State &state;
pRadioBox &p;
private:
void setGroup(const nall::array<RadioBox*> &group);
static void group_(nall::array<RadioBox*> &list) {}
template<typename... Args> static void group_(nall::array<RadioBox*> &list, RadioBox &item, Args&... args) {
list.append(&item);
group_(list, args...);
}
};
struct TextEdit : private nall::base_from_member<pTextEdit&>, Widget {
nall::function<void ()> onChange;
void setCursorPosition(unsigned position);
void setEditable(bool editable = true);
void setText(const nall::string &text);
void setWordWrap(bool wordWrap = true);
nall::string text();
TextEdit();
struct State;
State &state;
pTextEdit &p;
};
struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget {
nall::function<void ()> onChange;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
VerticalSlider();
struct State;
State &state;
pVerticalSlider &p;
};
struct Viewport : private nall::base_from_member<pViewport&>, Widget {
uintptr_t handle();
Viewport();
pViewport &p;
};
#include "layout/fixed-layout.hpp"
#include "layout/horizontal-layout.hpp"
#include "layout/vertical-layout.hpp"

View File

@ -2,12 +2,12 @@ void FixedLayout::setParent(Window &parent) {
Layout::setParent(parent);
foreach(child, children) {
Layout::append(*child.widget);
child.widget->setGeometry(child.x, child.y, child.width, child.height);
child.widget->setGeometry(child.geometry);
}
}
void FixedLayout::append(Widget &widget, unsigned x, unsigned y, unsigned width, unsigned height) {
children.append({ &widget, x, y, width, height });
void FixedLayout::append(Widget &widget, const Geometry &geometry) {
children.append({ &widget, geometry });
}
void FixedLayout::setGeometry(Geometry &geometry) {

View File

@ -1,15 +1,14 @@
struct FixedLayout : public Layout {
struct FixedLayout : Layout {
void setParent(Window &parent);
void setGeometry(Geometry &geometry);
void append(Widget &widget, unsigned x, unsigned y, unsigned width, unsigned height);
void append(Widget &widget, const Geometry &geometry);
FixedLayout();
//private:
Window *parent;
struct Children {
Widget *widget;
unsigned x, y;
unsigned width, height;
Geometry geometry;
};
nall::linear_vector<Children> children;
};

View File

@ -55,7 +55,7 @@ void HorizontalLayout::setGeometry(Geometry &geometry) {
}
if(child.widget) {
child.widget->setGeometry(geometry.x, geometry.y, child.width, child.height);
child.widget->setGeometry({ geometry.x, geometry.y, child.width, child.height });
geometry.x += child.width + child.spacing;
geometry.width -= child.width + child.spacing;
}

View File

@ -55,7 +55,7 @@ void VerticalLayout::setGeometry(Geometry &geometry) {
}
if(child.widget) {
child.widget->setGeometry(geometry.x, geometry.y, child.width, child.height);
child.widget->setGeometry({ geometry.x, geometry.y, child.width, child.height });
geometry.y += child.height + child.spacing;
geometry.height -= child.height + child.spacing;
}

View File

@ -1,29 +0,0 @@
static void Action_setFont(GtkWidget *widget, gpointer font) {
if(font) {
gtk_widget_modify_font(widget, (PangoFontDescription*)font);
if(GTK_IS_CONTAINER(widget)) {
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Action_setFont, (PangoFontDescription*)font);
}
}
}
bool Action::visible() {
return gtk_widget_get_visible(object->widget);
}
void Action::setVisible(bool visible) {
gtk_widget_set_visible(object->widget, visible);
}
bool Action::enabled() {
return gtk_widget_get_sensitive(object->widget);
}
void Action::setEnabled(bool enabled) {
gtk_widget_set_sensitive(object->widget, enabled);
}
Action::Action() {
action = new Action::Data;
action->font = 0;
}

View File

@ -1,22 +0,0 @@
static void MenuCheckItem_tick(MenuCheckItem *self) {
if(self->onTick && self->object->locked == false) self->onTick();
}
void MenuCheckItem::setText(const string &text) {
gtk_menu_item_set_label(GTK_MENU_ITEM(object->widget), text);
}
bool MenuCheckItem::checked() {
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(object->widget));
}
void MenuCheckItem::setChecked(bool state) {
object->locked = true;
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(object->widget), state);
object->locked = false;
}
MenuCheckItem::MenuCheckItem() {
object->widget = gtk_check_menu_item_new_with_label("");
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuCheckItem_tick), (gpointer)this);
}

View File

@ -1,12 +0,0 @@
static void MenuItem_tick(MenuItem *self) {
if(self->onTick) self->onTick();
}
void MenuItem::setText(const string &text) {
gtk_menu_item_set_label(GTK_MENU_ITEM(object->widget), text);
}
MenuItem::MenuItem() {
object->widget = gtk_menu_item_new_with_label("");
g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(MenuItem_tick), (gpointer)this);
}

View File

@ -1,31 +0,0 @@
static void MenuRadioItem_tick(MenuRadioItem *self) {
if(self->onTick && self->checked() && self->object->locked == false) self->onTick();
}
void MenuRadioItem::setParent(MenuRadioItem &parent) {
gtk_radio_menu_item_set_group(
GTK_RADIO_MENU_ITEM(object->widget),
gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(parent.object->widget))
);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(object->widget), false);
}
void MenuRadioItem::setText(const string &text) {
gtk_menu_item_set_label(GTK_MENU_ITEM(object->widget), text);
}
bool MenuRadioItem::checked() {
return gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(object->widget));
}
void MenuRadioItem::setChecked() {
object->locked = true;
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(object->widget), true);
object->locked = false;
}
MenuRadioItem::MenuRadioItem() {
object->widget = gtk_radio_menu_item_new_with_label(0, "");
setChecked();
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(MenuRadioItem_tick), (gpointer)this);
}

View File

@ -1,3 +0,0 @@
MenuSeparator::MenuSeparator() {
object->widget = gtk_separator_menu_item_new();
}

View File

@ -1,14 +0,0 @@
void Menu::append(Action &action) {
gtk_menu_shell_append(GTK_MENU_SHELL(object->menu), action.object->widget);
gtk_widget_show(action.object->widget);
}
void Menu::setText(const string &text) {
gtk_menu_item_set_label(GTK_MENU_ITEM(object->widget), text);
}
Menu::Menu() {
object->menu = gtk_menu_new();
object->widget = gtk_menu_item_new_with_label("");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(object->widget), object->menu);
}

View File

@ -1,18 +0,0 @@
bool Font::create(const string &name, unsigned size, Font::Style style) {
font->font = pango_font_description_new();
pango_font_description_set_family(font->font, name);
pango_font_description_set_size(font->font, size * PANGO_SCALE);
pango_font_description_set_style(font->font, (style & Style::Italic) == Style::Italic ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL);
pango_font_description_set_weight(font->font, (style & Style::Bold) == Style::Bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
return true;
}
Font::Font() {
font = new Font::Data;
font->font = 0;
}
Font::~Font() {
if(font->font) pango_font_description_free(font->font);
delete font;
}

View File

@ -1,206 +0,0 @@
#include <nall/config.hpp>
#include <nall/platform.hpp>
using namespace nall;
#include <unistd.h>
#include <pwd.h>
#include <sys/stat.h>
#define None X11None
#define Window X11Window
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <cairo.h>
#include <gdk/gdkkeysyms.h>
#undef None
#undef Window
using namespace nall;
namespace phoenix {
#include "settings.cpp"
#include "object.cpp"
#include "font.cpp"
#include "window.cpp"
#include "layout.cpp"
#include "message-window.cpp"
#include "action/action.cpp"
#include "action/menu.cpp"
#include "action/menu-separator.cpp"
#include "action/menu-item.cpp"
#include "action/menu-check-item.cpp"
#include "action/menu-radio-item.cpp"
#include "widget/widget.cpp"
#include "widget/button.cpp"
#include "widget/canvas.cpp"
#include "widget/check-box.cpp"
#include "widget/combo-box.cpp"
#include "widget/edit-box.cpp"
#include "widget/hex-editor.cpp"
#include "widget/horizontal-slider.cpp"
#include "widget/label.cpp"
#include "widget/list-box.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-box.cpp"
#include "widget/text-box.cpp"
#include "widget/vertical-slider.cpp"
#include "widget/viewport.cpp"
Window Window::None;
void OS::initialize() {
static bool initialized = false;
if(initialized == true) return;
initialized = true;
settings.load();
int argc = 1;
char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
gtk_init(&argc, &argvp);
gtk_rc_parse_string(
"style \"phoenix-gtk\"\n"
"{\n"
" GtkComboBox::appears-as-list = 1\n"
" GtkTreeView::vertical-separator = 0\n"
"}\n"
"class \"GtkComboBox\" style \"phoenix-gtk\"\n"
"class \"GtkTreeView\" style \"phoenix-gtk\"\n"
);
}
bool OS::pending() {
return gtk_events_pending();
}
void OS::run() {
while(pending()) gtk_main_iteration_do(false);
}
void OS::main() {
gtk_main();
}
void OS::quit() {
settings.save();
gtk_main_quit();
}
unsigned OS::desktopWidth() {
return gdk_screen_get_width(gdk_screen_get_default());
}
unsigned OS::desktopHeight() {
return gdk_screen_get_height(gdk_screen_get_default());
}
string OS::folderSelect(Window &parent, const string &path) {
string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new(
"Select Folder",
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
(const gchar*)0
);
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
name = temp;
g_free(temp);
}
gtk_widget_destroy(dialog);
if(name.endswith("/") == false) name.append("/");
return name;
}
string OS::fileOpen(Window &parent, const string &filter, const string &path) {
string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new(
"Open File",
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
(const gchar*)0
);
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
lstring list;
list.split("\n", filter);
foreach(item, list) {
lstring part;
part.split("\t", item);
GtkFileFilter *filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, string(part[0], " (", part[1], ")"));
lstring patterns;
patterns.split(",", part[1]);
foreach(pattern, patterns) gtk_file_filter_add_pattern(filter, pattern);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
}
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
name = temp;
g_free(temp);
}
gtk_widget_destroy(dialog);
return name;
}
string OS::fileSave(Window &parent, const string &filter, const string &path) {
string name;
GtkWidget *dialog = gtk_file_chooser_dialog_new(
"Save File",
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
(const gchar*)0
);
if(path) gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
lstring list;
list.split("\n", filter);
foreach(item, list) {
lstring part;
part.split("\t", item);
GtkFileFilter *filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, string(part[0], " (", part[1], ")"));
lstring patterns;
patterns.split(",", part[1]);
foreach(pattern, patterns) gtk_file_filter_add_pattern(filter, pattern);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
}
if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
char *temp = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
name = temp;
g_free(temp);
}
gtk_widget_destroy(dialog);
return name;
}
}

View File

@ -1,319 +0,0 @@
namespace phoenix {
struct Window;
struct Object {
Object();
Object& operator=(const Object&) = delete;
Object(const Object&) = delete;
//private:
virtual void unused();
struct Data;
Data *object;
};
struct Geometry {
signed x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object {
enum class Style : unsigned {
None = 0,
Bold = 1,
Italic = 2,
};
bool create(const nall::string &name, unsigned size, Font::Style style = Style::None);
Font();
~Font();
//private:
struct Data;
Data *font;
};
inline Font::Style operator|(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a | (unsigned)b); }
inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); }
struct Menu;
struct Layout;
struct Widget;
struct Window : Object {
static Window None;
nall::function<bool ()> onClose;
nall::function<void ()> onMove;
nall::function<void ()> onSize;
void append(Menu &menu);
void setLayout(Layout &layout);
void setResizable(bool resizable = true);
bool focused();
void setFocused();
Geometry frameGeometry();
Geometry geometry();
void setFrameGeometry(signed x, signed y, unsigned width, unsigned height);
void setGeometry(signed x, signed y, unsigned width, unsigned height);
void setDefaultFont(Font &font);
void setFont(Font &font);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const nall::string &text);
void setStatusText(const nall::string &text);
void setVisible(bool visible = true);
void setMenuVisible(bool visible = true);
void setStatusVisible(bool visible = true);
bool fullscreen();
void setFullscreen(bool fullscreen = true);
Window();
//private:
struct Data;
Data *window;
void updateFrameGeometry();
};
struct Action : Object {
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
Action();
//private:
struct Data;
Data *action;
};
struct Menu : Action {
void append(Action &action);
void setText(const nall::string &text);
Menu();
};
struct MenuSeparator : Action {
MenuSeparator();
};
struct MenuItem : Action {
nall::function<void ()> onTick;
void setText(const nall::string &text);
MenuItem();
};
struct MenuCheckItem : Action {
nall::function<void ()> onTick;
void setText(const nall::string &text);
bool checked();
void setChecked(bool checked = true);
MenuCheckItem();
};
struct MenuRadioItem : Action {
nall::function<void ()> onTick;
void setParent(MenuRadioItem &parent);
void setText(const nall::string &text);
bool checked();
void setChecked();
MenuRadioItem();
};
struct Layout : Object {
virtual void setParent(Window &parent);
virtual void setGeometry(Geometry &geometry) = 0;
virtual void append(Widget &widget);
Layout();
//private:
struct Data;
Data *layout;
};
struct Widget : Object {
virtual Geometry geometry();
virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
virtual void setFont(Font &font);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
virtual bool focused();
virtual void setFocused();
Widget();
//private:
struct Data;
Data *widget;
};
struct Button : Widget {
nall::function<void ()> onTick;
void setText(const nall::string &text);
Button();
};
struct Canvas : Widget {
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
uint32_t* buffer();
void redraw();
Canvas();
~Canvas();
//private:
struct Data;
Data *canvas;
};
struct CheckBox : Widget {
nall::function<void ()> onTick;
void setText(const nall::string &text);
bool checked();
void setChecked(bool checked = true);
CheckBox();
};
struct ComboBox : Widget {
nall::function<void ()> onChange;
void reset();
void addItem(const nall::string &text);
unsigned selection();
void setSelection(unsigned item);
ComboBox();
//private:
struct Data;
Data *comboBox;
};
struct EditBox : Widget {
nall::function<void ()> onChange;
void setFocused();
void setEditable(bool editable = true);
void setWordWrap(bool wordWrap = true);
nall::string text();
void setText(const nall::string &text);
void setCursorPosition(unsigned position);
EditBox();
};
struct HexEditor : Widget {
nall::function<uint8_t (unsigned)> onRead;
nall::function<void (unsigned, uint8_t)> onWrite;
void setSize(unsigned size);
void setOffset(unsigned offset);
void setColumns(unsigned columns);
void setRows(unsigned rows);
void update();
HexEditor();
//private:
struct Data;
Data *hexEditor;
bool keyPress(unsigned scancode);
void scroll(unsigned position);
void setScroll();
void updateScroll();
unsigned cursorPosition();
void setCursorPosition(unsigned position);
};
struct HorizontalSlider : Widget {
nall::function<void ()> onChange;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
HorizontalSlider();
};
struct Label : Widget {
void setText(const nall::string &text);
Label();
};
struct ListBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
void create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height, const nall::string &text = "");
void setFocused();
void setHeaderText(const nall::string &text);
void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void setFont(Font &font);
void reset();
void resizeColumnsToContent();
void addItem(const nall::string &text);
void setItem(unsigned row, const nall::string &text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection();
void setSelection(unsigned row);
ListBox();
//private:
struct Data;
Data *listBox;
private:
void create(const nall::string &text);
};
struct ProgressBar : Widget {
void setPosition(unsigned position);
ProgressBar();
};
struct RadioBox : Widget {
nall::function<void ()> onTick;
void setParent(RadioBox &parent);
void setText(const nall::string &text);
bool checked();
void setChecked();
RadioBox();
};
struct TextBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
void setEditable(bool editable = true);
nall::string text();
void setText(const nall::string &text);
TextBox();
};
struct VerticalSlider : Widget {
nall::function<void ()> onChange;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
VerticalSlider();
};
struct Viewport : Widget {
uintptr_t handle();
Viewport();
};
struct MessageWindow : Object {
enum class Buttons : unsigned {
Ok,
OkCancel,
YesNo,
};
enum class Response : unsigned {
Ok,
Cancel,
Yes,
No,
};
static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
};
struct OS : Object {
static bool pending();
static void run();
static void main();
static void quit();
static unsigned desktopWidth();
static unsigned desktopHeight();
static nall::string folderSelect(Window &parent, const nall::string &path = "");
static nall::string fileOpen(Window &parent, const nall::string &filter, const nall::string &path = "");
static nall::string fileSave(Window &parent, const nall::string &filter, const nall::string &path = "");
//private:
static void initialize();
};
}

View File

@ -1,19 +0,0 @@
void Layout::setParent(Window &parent) {
layout->parent = &parent;
}
void Layout::append(Widget &child) {
child.widget->parent = layout->parent;
gtk_fixed_put(GTK_FIXED(layout->parent->object->formContainer), child.object->widget, 0, 0);
if(child.widget->font) {
child.setFont(*child.widget->font);
} else if(layout->parent->window->defaultFont) {
child.setFont(*layout->parent->window->defaultFont);
}
gtk_widget_show(child.object->widget);
}
Layout::Layout() {
layout = new Layout::Data;
layout->parent = 0;
}

View File

@ -1,65 +0,0 @@
static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons buttons, gint response) {
if(response == GTK_RESPONSE_OK) return MessageWindow::Response::Ok;
if(response == GTK_RESPONSE_CANCEL) return MessageWindow::Response::Cancel;
if(response == GTK_RESPONSE_YES) return MessageWindow::Response::Yes;
if(response == GTK_RESPONSE_NO) return MessageWindow::Response::No;
if(buttons == MessageWindow::Buttons::OkCancel) return MessageWindow::Response::Cancel;
if(buttons == MessageWindow::Buttons::YesNo) return MessageWindow::Response::No;
return MessageWindow::Response::Ok;
}
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, buttonsType, "%s", (const char*)text
);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response);
}
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, buttonsType, "%s", (const char*)text
);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response);
}
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, buttonsType, "%s", (const char*)text
);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response);
}
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
GtkButtonsType buttonsType = GTK_BUTTONS_OK;
if(buttons == Buttons::OkCancel) buttonsType = GTK_BUTTONS_OK_CANCEL;
if(buttons == Buttons::YesNo) buttonsType = GTK_BUTTONS_YES_NO;
GtkWidget *dialog = gtk_message_dialog_new(
&parent != &Window::None ? GTK_WINDOW(parent.object->widget) : (GtkWindow*)0,
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, buttonsType, "%s", (const char*)text
);
gint response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return MessageWindow_response(buttons, response);
}

View File

@ -1,154 +0,0 @@
struct Object::Data {
bool locked;
GtkWidget *widget;
GtkWidget *subWidget;
GtkWidget *menuContainer;
GtkWidget *formContainer;
GtkWidget *statusContainer;
GtkWidget *menu;
GtkWidget *status;
Menu *parentMenu;
Window *parentWindow;
GtkTextBuffer *textBuffer;
unsigned position;
Data() {
locked = false;
widget = 0;
subWidget = 0;
menuContainer = 0;
formContainer = 0;
statusContainer = 0;
menu = 0;
status = 0;
parentMenu = 0;
parentWindow = 0;
textBuffer = 0;
position = 0;
}
};
struct Font::Data {
PangoFontDescription *font;
Data() {
font = 0;
}
};
struct Action::Data {
Font *font;
Data() {
font = 0;
}
};
struct Window::Data {
Layout *layout;
Font *defaultFont;
bool resizable;
bool fullscreen;
unsigned x, y;
unsigned width, height;
Data() {
layout = 0;
defaultFont = 0;
resizable = true;
fullscreen = false;
x = y = 0;
width = height = 0;
}
};
struct Widget::Data {
Window *parent;
Font *font;
unsigned x, y;
unsigned width, height;
Data() {
parent = 0;
font = 0;
x = y = 0;
width = height = 0;
}
};
struct Layout::Data {
Window *parent;
Data() {
parent = 0;
}
};
struct ComboBox::Data {
unsigned counter;
Data() {
counter = 0;
}
};
struct Canvas::Data {
uint32_t *bufferRGB;
uint32_t *bufferBGR;
unsigned pitch;
Data() {
bufferRGB = 0;
bufferBGR = 0;
pitch = 0;
}
};
struct HexEditor::Data {
GtkWidget *container;
GtkWidget *widget;
GtkWidget *scroll;
GtkTextMark *cursor;
unsigned size;
unsigned offset;
unsigned columns;
unsigned rows;
Data() {
container = 0;
widget = 0;
scroll = 0;
cursor = 0;
size = 0;
offset = 0;
columns = 0;
rows = 0;
}
};
struct ListBox::Data {
GtkListStore *store;
struct GtkColumn {
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
GtkWidget *label;
};
linear_vector<GtkColumn> column;
bool checkable;
signed selection;
Data() {
store = 0;
checkable = false;
selection = -1;
}
};
void Object::unused() {
}
Object::Object() {
OS::initialize();
object = new Object::Data;
object->locked = false;
}

View File

@ -1,29 +0,0 @@
struct Settings : public configuration {
unsigned frameGeometryX;
unsigned frameGeometryY;
unsigned frameGeometryWidth;
unsigned frameGeometryHeight;
void load() {
string path = { userpath(), ".config/phoenix/gtk.cfg" };
configuration::load(path);
}
void save() {
string path = { userpath(), ".config/" };
mkdir(path, 0755);
path.append("phoenix/");
mkdir(path, 0755);
path.append("gtk.cfg");
configuration::save(path);
}
Settings() {
attach(frameGeometryX = 0, "frameGeometryX");
attach(frameGeometryY = 0, "frameGeometryY");
attach(frameGeometryWidth = 0, "frameGeometryWidth");
attach(frameGeometryHeight = 0, "frameGeometryHeight");
}
};
static Settings settings;

View File

@ -1,12 +0,0 @@
static void Button_tick(Button *self) {
if(self->onTick) self->onTick();
}
void Button::setText(const string &text) {
gtk_button_set_label(GTK_BUTTON(object->widget), text);
}
Button::Button() {
object->widget = gtk_button_new();
g_signal_connect_swapped(G_OBJECT(object->widget), "clicked", G_CALLBACK(Button_tick), (gpointer)this);
}

View File

@ -1,61 +0,0 @@
static void Canvas_expose(Canvas *self) {
uint32_t *rgb = self->canvas->bufferRGB;
uint32_t *bgr = self->canvas->bufferBGR;
for(unsigned y = self->object->widget->allocation.height; y; y--) {
for(unsigned x = self->object->widget->allocation.width; x; x--) {
uint32_t pixel = *rgb++;
*bgr++ = ((pixel << 16) & 0xff0000) | (pixel & 0x00ff00) | ((pixel >> 16) & 0x0000ff);
}
}
gdk_draw_rgb_32_image(
self->object->widget->window,
self->object->widget->style->fg_gc[GTK_WIDGET_STATE(self->object->widget)],
0, 0, self->object->widget->allocation.width, self->object->widget->allocation.height,
GDK_RGB_DITHER_NONE, (guchar*)self->canvas->bufferBGR, self->canvas->pitch
);
}
void Canvas::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
if(canvas->bufferRGB) delete[] canvas->bufferRGB;
if(canvas->bufferBGR) delete[] canvas->bufferBGR;
canvas->bufferRGB = new uint32_t[width * height]();
canvas->bufferBGR = new uint32_t[width * height]();
canvas->pitch = width * sizeof(uint32_t);
Widget::setGeometry(x, y, width, height);
}
uint32_t* Canvas::buffer() {
return canvas->bufferRGB;
}
void Canvas::redraw() {
GdkRectangle rect;
rect.x = 0;
rect.y = 0;
rect.width = object->widget->allocation.width;
rect.height = object->widget->allocation.height;
gdk_window_invalidate_rect(object->widget->window, &rect, true);
}
Canvas::Canvas() {
canvas = new Canvas::Data;
canvas->bufferRGB = 0;
canvas->bufferBGR = 0;
canvas->pitch = 0;
object->widget = gtk_drawing_area_new();
GdkColor color;
color.pixel = color.red = color.green = color.blue = 0;
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
gtk_widget_set_double_buffered(object->widget, false);
gtk_widget_add_events(object->widget, GDK_EXPOSURE_MASK);
g_signal_connect_swapped(G_OBJECT(object->widget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
}
Canvas::~Canvas() {
if(canvas->bufferRGB) delete[] canvas->bufferRGB;
if(canvas->bufferBGR) delete[] canvas->bufferBGR;
}

View File

@ -1,22 +0,0 @@
static void CheckBox_tick(CheckBox *self) {
if(self->onTick && self->object->locked == false) self->onTick();
}
void CheckBox::setText(const string &text) {
gtk_button_set_label(GTK_BUTTON(object->widget), text);
}
bool CheckBox::checked() {
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->widget));
}
void CheckBox::setChecked(bool checked) {
object->locked = true;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(object->widget), checked);
object->locked = false;
}
CheckBox::CheckBox() {
object->widget = gtk_check_button_new_with_label("");
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)this);
}

View File

@ -1,34 +0,0 @@
void ComboBox_change(ComboBox *self) {
if(self->object->locked == false && self->onChange) self->onChange();
}
void ComboBox::reset() {
object->locked = true;
for(signed i = comboBox->counter - 1; i >= 0; i--) {
gtk_combo_box_remove_text(GTK_COMBO_BOX(object->widget), i);
}
object->locked = false;
comboBox->counter = 0;
}
void ComboBox::addItem(const string &text) {
gtk_combo_box_append_text(GTK_COMBO_BOX(object->widget), text);
if(comboBox->counter++ == 0) setSelection(0);
}
unsigned ComboBox::selection() {
return gtk_combo_box_get_active(GTK_COMBO_BOX(object->widget));
}
void ComboBox::setSelection(unsigned item) {
object->locked = true;
gtk_combo_box_set_active(GTK_COMBO_BOX(object->widget), item);
object->locked = false;
}
ComboBox::ComboBox() {
comboBox = new ComboBox::Data;
comboBox->counter = 0;
object->widget = gtk_combo_box_new_text();
g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(ComboBox_change), (gpointer)this);
}

View File

@ -1,52 +0,0 @@
static void EditBox_change(EditBox *self) {
if(self->object->locked == false && self->onChange) self->onChange();
}
void EditBox::setFocused() {
gtk_widget_grab_focus(object->subWidget);
}
void EditBox::setEditable(bool editable) {
gtk_text_view_set_editable(GTK_TEXT_VIEW(object->subWidget), editable);
}
void EditBox::setWordWrap(bool wordWrap) {
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(object->subWidget), wordWrap ? GTK_WRAP_WORD_CHAR : GTK_WRAP_NONE);
}
string EditBox::text() {
GtkTextIter start, end;
gtk_text_buffer_get_start_iter(object->textBuffer, &start);
gtk_text_buffer_get_end_iter(object->textBuffer, &end);
char *temp = gtk_text_buffer_get_text(object->textBuffer, &start, &end, true);
string text = temp;
g_free(temp);
return text;
}
void EditBox::setText(const string &text) {
object->locked = true;
gtk_text_buffer_set_text(object->textBuffer, text, -1);
object->locked = false;
}
void EditBox::setCursorPosition(unsigned position) {
GtkTextMark *mark = gtk_text_buffer_get_mark(object->textBuffer, "insert");
GtkTextIter iter;
gtk_text_buffer_get_end_iter(object->textBuffer, &iter);
gtk_text_iter_set_offset(&iter, min(position, gtk_text_iter_get_offset(&iter)));
gtk_text_buffer_place_cursor(object->textBuffer, &iter);
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(object->subWidget), mark);
}
EditBox::EditBox() {
object->widget = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
object->subWidget = gtk_text_view_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(object->subWidget), GTK_WRAP_WORD_CHAR);
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
object->textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(object->subWidget));
g_signal_connect_swapped(G_OBJECT(object->textBuffer), "changed", G_CALLBACK(EditBox_change), (gpointer)this);
gtk_widget_show(object->subWidget);
}

View File

@ -1,256 +0,0 @@
static bool HexEditor_keyPress(GtkWidget *widget, GdkEventKey *event, HexEditor *self) {
return self->keyPress(event->keyval);
}
static bool HexEditor_scroll(GtkRange *range, GtkScrollType scroll, gdouble value, HexEditor *self) {
self->scroll((unsigned)value);
return false;
}
void HexEditor::setSize(unsigned size) {
hexEditor->size = size;
setScroll();
}
void HexEditor::setOffset(unsigned offset) {
hexEditor->offset = offset;
setScroll();
updateScroll();
}
void HexEditor::setColumns(unsigned columns) {
hexEditor->columns = columns;
setScroll();
}
void HexEditor::setRows(unsigned rows) {
hexEditor->rows = rows;
setScroll();
}
void HexEditor::update() {
if(!onRead) {
gtk_text_buffer_set_text(object->textBuffer, "", -1);
return;
}
unsigned position = cursorPosition();
string output;
unsigned offset = hexEditor->offset;
for(unsigned row = 0; row < hexEditor->rows; row++) {
output.append(hex<8>(offset));
output.append(" ");
string hexdata;
string ansidata = " ";
for(unsigned column = 0; column < hexEditor->columns; column++) {
if(offset < hexEditor->size) {
uint8_t data = onRead(offset++);
hexdata.append(hex<2>(data));
hexdata.append(" ");
char buffer[2] = { data >= 0x20 && data <= 0x7e ? (char)data : '.', 0 };
ansidata.append(buffer);
} else {
hexdata.append(" ");
ansidata.append(" ");
}
}
output.append(hexdata);
output.append(ansidata);
if(offset >= hexEditor->size) break;
if(row != hexEditor->rows - 1) output.append("\n");
}
gtk_text_buffer_set_text(object->textBuffer, output, -1);
if(position == 0) position = 10; //start at first position where hex values can be entered
setCursorPosition(position);
}
HexEditor::HexEditor() {
hexEditor = new HexEditor::Data;
hexEditor->size = 0;
hexEditor->offset = 0;
hexEditor->columns = 16;
hexEditor->rows = 16;
object->widget = gtk_hbox_new(false, 0);
hexEditor->container = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(hexEditor->container), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(hexEditor->container), GTK_SHADOW_ETCHED_IN);
hexEditor->widget = gtk_text_view_new();
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(hexEditor->widget), GTK_WRAP_NONE);
gtk_container_add(GTK_CONTAINER(hexEditor->container), hexEditor->widget);
g_signal_connect(G_OBJECT(hexEditor->widget), "key-press-event", G_CALLBACK(HexEditor_keyPress), (gpointer)this);
hexEditor->scroll = gtk_vscrollbar_new((GtkAdjustment*)0);
gtk_range_set_range(GTK_RANGE(hexEditor->scroll), 0, 256);
gtk_range_set_increments(GTK_RANGE(hexEditor->scroll), 1, 16);
gtk_widget_set_sensitive(hexEditor->scroll, false);
g_signal_connect(G_OBJECT(hexEditor->scroll), "change-value", G_CALLBACK(HexEditor_scroll), (gpointer)this);
gtk_box_pack_start(GTK_BOX(object->widget), hexEditor->container, true, true, 0);
gtk_box_pack_start(GTK_BOX(object->widget), hexEditor->scroll, false, false, 1);
object->textBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(hexEditor->widget));
hexEditor->cursor = gtk_text_buffer_get_mark(object->textBuffer, "insert");
gtk_widget_show(hexEditor->scroll);
gtk_widget_show(hexEditor->widget);
gtk_widget_show(hexEditor->container);
}
//internal
bool HexEditor::keyPress(unsigned scancode) {
if(!onRead || !onWrite) return false;
unsigned position = cursorPosition();
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 1;
unsigned cursorY = position / lineWidth;
unsigned cursorX = position % lineWidth;
if(scancode == GDK_Home) {
setCursorPosition(cursorY * lineWidth + 10);
return true;
}
if(scancode == GDK_End) {
setCursorPosition(cursorY * lineWidth + 10 + (hexEditor->columns * 3 - 1));
return true;
}
if(scancode == GDK_Up) {
if(cursorY != 0) return false;
signed newOffset = hexEditor->offset - hexEditor->columns;
if(newOffset >= 0) {
setOffset(newOffset);
update();
}
return true;
}
if(scancode == GDK_Down) {
if(cursorY != hexEditor->rows - 1) return false;
signed newOffset = hexEditor->offset + hexEditor->columns;
if(newOffset + hexEditor->columns * hexEditor->rows - (hexEditor->columns - 1) <= hexEditor->size) {
setOffset(newOffset);
update();
}
return true;
}
if(scancode == GDK_Page_Up) {
signed newOffset = hexEditor->offset - hexEditor->columns * hexEditor->rows;
if(newOffset >= 0) {
setOffset(newOffset);
update();
} else {
setOffset(0);
update();
}
return true;
}
if(scancode == GDK_Page_Down) {
signed newOffset = hexEditor->offset + hexEditor->columns * hexEditor->rows;
for(unsigned n = 0; n < hexEditor->rows; n++) {
if(newOffset + hexEditor->columns * hexEditor->rows - (hexEditor->columns - 1) <= hexEditor->size) {
setOffset(newOffset);
update();
break;
}
newOffset -= hexEditor->columns;
}
return true;
}
//convert scancode to hex nibble
if(scancode >= '0' && scancode <= '9') scancode = scancode - '0';
else if(scancode >= 'A' && scancode <= 'F') scancode = scancode - 'A' + 10;
else if(scancode >= 'a' && scancode <= 'f') scancode = scancode - 'a' + 10;
else return false; //not a valid hex value
if(cursorX >= 10) {
//not on an offset
cursorX -= 10;
if((cursorX % 3) != 2) {
//not on a space
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
cursorX /= 3;
if(cursorX < hexEditor->columns) {
//not in ANSI region
unsigned offset = hexEditor->offset + (cursorY * hexEditor->columns + cursorX);
if(offset >= hexEditor->size) return false; //do not edit past end of file
uint8_t data = onRead(offset);
//write modified value
if(cursorNibble == 1) {
data = (data & 0xf0) | (scancode << 0);
} else {
data = (data & 0x0f) | (scancode << 4);
}
onWrite(offset, data);
//auto-advance cursor to next nibble/byte
position++;
if(cursorNibble && cursorX != hexEditor->columns - 1) position++;
setCursorPosition(position);
//refresh output to reflect modified data
update();
}
}
}
return true;
}
void HexEditor::scroll(unsigned position) {
unsigned rows = hexEditor->size / hexEditor->columns;
if(position >= rows) position = rows - 1;
setOffset(position * hexEditor->columns);
update();
}
void HexEditor::setScroll() {
unsigned rows = hexEditor->size / hexEditor->columns;
if(rows) rows--;
if(rows) {
gtk_range_set_range(GTK_RANGE(hexEditor->scroll), 0, rows);
gtk_widget_set_sensitive(hexEditor->scroll, true);
} else {
gtk_widget_set_sensitive(hexEditor->scroll, false);
}
}
void HexEditor::updateScroll() {
unsigned row = hexEditor->offset / hexEditor->columns;
gtk_range_set_value(GTK_RANGE(hexEditor->scroll), row);
}
unsigned HexEditor::cursorPosition() {
GtkTextIter iter;
gtk_text_buffer_get_iter_at_mark(object->textBuffer, &iter, hexEditor->cursor);
return gtk_text_iter_get_offset(&iter);
}
void HexEditor::setCursorPosition(unsigned position) {
GtkTextIter iter;
gtk_text_buffer_get_iter_at_mark(object->textBuffer, &iter, hexEditor->cursor);
//GTK+ will throw a hundred errors on the terminal
//if you set an iterator past the end of the text buffer
GtkTextIter endIter;
gtk_text_buffer_get_end_iter(object->textBuffer, &iter);
unsigned endPosition = gtk_text_iter_get_offset(&iter);
gtk_text_iter_set_offset(&iter, min(position, endPosition));
gtk_text_buffer_place_cursor(object->textBuffer, &iter);
}

View File

@ -1,25 +0,0 @@
static void HorizontalSlider_change(HorizontalSlider *self) {
if(self->object->position == self->position()) return;
self->object->position = self->position();
if(self->onChange) self->onChange();
}
unsigned HorizontalSlider::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(object->widget));
}
void HorizontalSlider::setLength(unsigned length) {
length += (length == 0);
gtk_range_set_range(GTK_RANGE(object->widget), 0, length - 1);
}
void HorizontalSlider::setPosition(unsigned position) {
gtk_range_set_value(GTK_RANGE(object->widget), position);
}
HorizontalSlider::HorizontalSlider() {
object->position = 0;
object->widget = gtk_hscale_new_with_range(0, 1, 1);
gtk_scale_set_draw_value(GTK_SCALE(object->widget), false);
g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(HorizontalSlider_change), (gpointer)this);
}

View File

@ -1,8 +0,0 @@
void Label::setText(const string &text) {
gtk_label_set_text(GTK_LABEL(object->widget), text);
}
Label::Label() {
object->widget = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(object->widget), 0.0, 0.5);
}

View File

@ -1,204 +0,0 @@
static void ListBox_activate(ListBox *self) {
signed selection = -1;
if(auto position = self->selection()) selection = position();
self->listBox->selection = selection;
if(self->onActivate) self->onActivate();
}
static void ListBox_change(ListBox *self) {
signed selection = -1;
if(auto position = self->selection()) selection = position();
if(selection == self->listBox->selection) return;
self->listBox->selection = selection;
if(self->onChange) self->onChange();
}
static void ListBox_tick(GtkCellRendererToggle *cell, gchar *path_string, ListBox *self) {
unsigned index = decimal(path_string);
self->setChecked(index, !self->checked(index));
if(self->onTick) self->onTick(index);
}
void ListBox::setFocused() {
gtk_widget_grab_focus(object->subWidget);
}
void ListBox::setHeaderText(const string &text) {
create(text);
}
void ListBox::setHeaderVisible(bool visible) {
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), visible);
}
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(object->subWidget) gtk_tree_view_column_set_visible(listBox->column[0].column, checkable);
}
void ListBox::setFont(Font &font) {
Widget::setFont(font);
unsigned columns = 1;
while(true) {
if(gtk_tree_view_get_column(GTK_TREE_VIEW(object->subWidget), columns) == 0) break;
columns++;
}
for(unsigned i = 0; i < columns; i++) {
gtk_widget_modify_font(listBox->column[i].label, font.font->font);
}
}
void ListBox::reset() {
listBox->selection = -1;
gtk_list_store_clear(GTK_LIST_STORE(listBox->store));
gtk_tree_view_set_model(GTK_TREE_VIEW(object->subWidget), GTK_TREE_MODEL(listBox->store));
//reset gtk_scrolled_window scrollbar position to 0,0 (top-left), as ListBox is now empty
gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(object->widget), 0);
gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(object->widget), 0);
}
void ListBox::resizeColumnsToContent() {
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(object->subWidget));
}
void ListBox::addItem(const string &text) {
lstring list;
list.split("\t", text);
GtkTreeIter iter;
gtk_list_store_append(listBox->store, &iter);
unsigned index = 1;
foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
}
void ListBox::setItem(unsigned row, const string &text) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreeIter iter;
for(unsigned i = 0; i <= row; i++) {
if(i == 0) gtk_tree_model_get_iter_first(model, &iter);
else gtk_tree_model_iter_next(model, &iter);
}
lstring list;
list.split("\t", text);
unsigned index = 1;
foreach(item, list) gtk_list_store_set(listBox->store, &iter, index++, (const char*)item, -1);
}
bool ListBox::checked(unsigned row) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
bool state;
gtk_tree_model_get_iter(model, &iter, path);
gtk_tree_model_get(model, &iter, 0, &state, -1);
gtk_tree_path_free(path);
return state;
}
void ListBox::setChecked(unsigned row, bool checked) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
GtkTreeIter iter;
gtk_tree_model_get_iter(model, &iter, path);
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1);
gtk_tree_path_free(path);
}
optional<unsigned> ListBox::selection() {
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(object->subWidget));
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
GtkTreeIter iter;
if(gtk_tree_model_get_iter_first(model, &iter) == false) return { false, 0 };
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return { true, 0 };
for(unsigned i = 1;; i++) {
if(gtk_tree_model_iter_next(model, &iter) == false) return { false, 0 };
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return { true, i };
}
return { false, 0 };
}
void ListBox::setSelection(unsigned row) {
signed current = -1;
if(auto position = selection()) current = position();
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(object->subWidget));
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(object->subWidget));
gtk_tree_selection_unselect_all(selection);
GtkTreeIter iter;
if(gtk_tree_model_get_iter_first(model, &iter) == false) return;
if(row == 0) {
gtk_tree_selection_select_iter(selection, &iter);
return;
}
for(unsigned i = 1;; i++) {
if(gtk_tree_model_iter_next(model, &iter) == false) return;
if(row == i) {
gtk_tree_selection_select_iter(selection, &iter);
return;
}
}
}
ListBox::ListBox() {
listBox = new ListBox::Data;
create("");
}
//internal
void ListBox::create(const string &text) {
if(object->subWidget) gtk_widget_destroy(object->subWidget);
if(object->widget) gtk_widget_destroy(object->widget);
object->widget = gtk_scrolled_window_new(0, 0);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(object->widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(object->widget), GTK_SHADOW_ETCHED_IN);
lstring list;
list.split("\t", string("\t", text));
GType *v = (GType*)malloc(list.size() * sizeof(GType));
for(unsigned i = 0; i < list.size(); i++) v[i] = (i == 0 ? G_TYPE_BOOLEAN : G_TYPE_STRING);
listBox->store = gtk_list_store_newv(list.size(), v);
free(v);
object->subWidget = gtk_tree_view_new_with_model(GTK_TREE_MODEL(listBox->store));
gtk_container_add(GTK_CONTAINER(object->widget), object->subWidget);
g_object_unref(G_OBJECT(listBox->store));
for(unsigned i = 0; i < list.size(); i++) {
if(i == 0) {
listBox->column[i].renderer = gtk_cell_renderer_toggle_new();
listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
"", listBox->column[i].renderer, "active", i, (void*)0
);
gtk_tree_view_column_set_resizable(listBox->column[i].column, false);
gtk_tree_view_column_set_visible(listBox->column[i].column, listBox->checkable);
g_signal_connect(listBox->column[i].renderer, "toggled", G_CALLBACK(ListBox_tick), (gpointer)this);
} else {
listBox->column[i].renderer = gtk_cell_renderer_text_new();
listBox->column[i].column = gtk_tree_view_column_new_with_attributes(
"", listBox->column[i].renderer, "text", i, (void*)0
);
gtk_tree_view_column_set_resizable(listBox->column[i].column, true);
}
listBox->column[i].label = gtk_label_new(list[i]);
gtk_tree_view_column_set_widget(GTK_TREE_VIEW_COLUMN(listBox->column[i].column), listBox->column[i].label);
gtk_tree_view_append_column(GTK_TREE_VIEW(object->subWidget), listBox->column[i].column);
gtk_widget_show(listBox->column[i].label);
}
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(object->subWidget), false);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(object->subWidget), list.size() >= 3); //>= 2 + one for the checkbox column
gtk_tree_view_set_search_column(GTK_TREE_VIEW(object->subWidget), 1);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "cursor-changed", G_CALLBACK(ListBox_change), (gpointer)this);
g_signal_connect_swapped(G_OBJECT(object->subWidget), "row-activated", G_CALLBACK(ListBox_activate), (gpointer)this);
gtk_widget_show(object->subWidget);
if(widget->font) {
setFont(*widget->font);
} else if(widget->parent && widget->parent->window->defaultFont) {
setFont(*widget->parent->window->defaultFont);
}
}

View File

@ -1,8 +0,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);
}
ProgressBar::ProgressBar() {
object->widget = gtk_progress_bar_new();
}

View File

@ -1,31 +0,0 @@
static void RadioBox_tick(RadioBox *self) {
if(self->onTick && self->checked() && self->object->locked == false) self->onTick();
}
void RadioBox::setParent(RadioBox &parent) {
gtk_radio_button_set_group(
GTK_RADIO_BUTTON(object->widget),
gtk_radio_button_get_group(GTK_RADIO_BUTTON(parent.object->widget))
);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(object->widget), false);
}
void RadioBox::setText(const string &text) {
gtk_button_set_label(GTK_BUTTON(object->widget), text);
}
bool RadioBox::checked() {
return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->widget));
}
void RadioBox::setChecked() {
object->locked = true;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(object->widget), true);
object->locked = false;
}
RadioBox::RadioBox() {
object->widget = gtk_radio_button_new_with_label(0, "");
// setChecked();
g_signal_connect_swapped(G_OBJECT(object->widget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)this);
}

View File

@ -1,27 +0,0 @@
static void TextBox_activate(TextBox *self) {
if(self->onActivate) self->onActivate();
}
static void TextBox_change(TextBox *self) {
if(self->object->locked == false && self->onChange) self->onChange();
}
void TextBox::setEditable(bool editable) {
gtk_entry_set_editable(GTK_ENTRY(object->widget), editable);
}
string TextBox::text() {
return gtk_entry_get_text(GTK_ENTRY(object->widget));
}
void TextBox::setText(const string &text) {
object->locked = true;
gtk_entry_set_text(GTK_ENTRY(object->widget), text);
object->locked = false;
}
TextBox::TextBox() {
object->widget = gtk_entry_new();
g_signal_connect_swapped(G_OBJECT(object->widget), "activate", G_CALLBACK(TextBox_activate), (gpointer)this);
g_signal_connect_swapped(G_OBJECT(object->widget), "changed", G_CALLBACK(TextBox_change), (gpointer)this);
}

View File

@ -1,25 +0,0 @@
static void VerticalSlider_change(VerticalSlider *self) {
if(self->object->position == self->position()) return;
self->object->position = self->position();
if(self->onChange) self->onChange();
}
unsigned VerticalSlider::position() {
return (unsigned)gtk_range_get_value(GTK_RANGE(object->widget));
}
void VerticalSlider::setLength(unsigned length) {
length += (length == 0);
gtk_range_set_range(GTK_RANGE(object->widget), 0, length - 1);
}
void VerticalSlider::setPosition(unsigned position) {
gtk_range_set_value(GTK_RANGE(object->widget), position);
}
VerticalSlider::VerticalSlider() {
object->position = 0;
object->widget = gtk_vscale_new_with_range(0, 1, 1);
gtk_scale_set_draw_value(GTK_SCALE(object->widget), false);
g_signal_connect_swapped(G_OBJECT(object->widget), "value-changed", G_CALLBACK(VerticalSlider_change), (gpointer)this);
}

View File

@ -1,15 +0,0 @@
uintptr_t Viewport::handle() {
return GDK_WINDOW_XID(object->widget->window);
}
Viewport::Viewport() {
object->widget = gtk_drawing_area_new();
//gtk_widget_set_double_buffered(object->widget, false);
GdkColor color;
color.pixel = 0;
color.red = 0;
color.green = 0;
color.blue = 0;
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
}

View File

@ -1,62 +0,0 @@
static void Widget_setFont(GtkWidget *widget, gpointer font) {
gtk_widget_modify_font(widget, (PangoFontDescription*)font);
if(GTK_IS_CONTAINER(widget)) {
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)Widget_setFont, font);
}
}
void Widget::setFont(Font &font) {
widget->font = &font;
Widget_setFont(object->widget, font.font->font);
}
bool Widget::visible() {
return gtk_widget_get_visible(object->widget);
}
void Widget::setVisible(bool visible) {
if(visible) gtk_widget_show(object->widget);
else gtk_widget_hide(object->widget);
}
bool Widget::enabled() {
return gtk_widget_get_sensitive(object->widget);
}
void Widget::setEnabled(bool enabled) {
gtk_widget_set_sensitive(object->widget, enabled);
}
bool Widget::focused() {
return gtk_widget_is_focus(object->widget);
}
void Widget::setFocused() {
if(visible() == false) setVisible(true);
gtk_widget_grab_focus(object->widget);
}
Geometry Widget::geometry() {
return { widget->x, widget->y, widget->width, widget->height };
}
void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
if(widget->parent == 0) return;
widget->x = x;
widget->y = y;
widget->width = width;
widget->height = height;
gtk_fixed_move(GTK_FIXED(widget->parent->object->formContainer), object->widget, x, y);
gtk_widget_set_size_request(object->widget, width, height);
}
Widget::Widget() {
widget = new Widget::Data;
widget->parent = 0;
widget->x = 0;
widget->y = 0;
widget->width = 0;
widget->height = 0;
}

View File

@ -1,206 +0,0 @@
static void Action_setFont(GtkWidget *widget, gpointer font);
static void Widget_setFont(GtkWidget *widget, gpointer font);
static gint Window_close(Window *window) {
if(window->onClose) {
if(window->onClose()) window->setVisible(false);
return true;
}
window->setVisible(false);
return true;
}
static void Window_configure(GtkWindow *widget, GdkEvent *event, Window *window) {
if(gtk_widget_get_realized(window->object->widget) == false) return;
window->updateFrameGeometry();
if(window->window->x != event->configure.x || window->window->y != event->configure.y) {
window->window->x = event->configure.x;
window->window->y = event->configure.y;
if(window->onMove) window->onMove();
}
if(window->window->width != event->configure.width || window->window->height != event->configure.height) {
window->window->width = event->configure.width;
window->window->height = event->configure.height;
Geometry geom = window->geometry();
geom.x = geom.y = 0;
if(window->window->layout) window->window->layout->setGeometry(geom);
if(window->onSize) window->onSize();
}
}
void Window::append(Menu &menu) {
menu.action->font = window->defaultFont;
if(window->defaultFont) Action_setFont(menu.object->widget, window->defaultFont->font->font);
gtk_menu_bar_append(object->menu, menu.object->widget);
gtk_widget_show(menu.object->widget);
}
void Window::setLayout(Layout &layout) {
window->layout = &layout;
layout.setParent(*this);
Geometry geom = geometry();
geom.x = geom.y = 0;
layout.setGeometry(geom);
}
void Window::setResizable(bool resizable) {
window->resizable = resizable;
gtk_window_set_resizable(GTK_WINDOW(object->widget), resizable);
}
bool Window::focused() {
return gtk_window_is_active(GTK_WINDOW(object->widget));
}
void Window::setFocused() {
gtk_window_present(GTK_WINDOW(object->widget));
}
Geometry Window::frameGeometry() {
return {
window->x - settings.frameGeometryX, window->y - settings.frameGeometryY,
window->width + settings.frameGeometryWidth, window->height + settings.frameGeometryHeight
};
}
Geometry Window::geometry() {
return { window->x, window->y, window->width, window->height };
}
void Window::setFrameGeometry(signed x, signed y, unsigned width, unsigned height) {
setGeometry(
x + settings.frameGeometryX, y + settings.frameGeometryY,
width - settings.frameGeometryWidth, height - settings.frameGeometryHeight
);
}
void Window::setGeometry(signed x, signed y, unsigned width, unsigned height) {
window->x = x;
window->y = y;
window->width = width;
window->height = height;
gtk_window_move(GTK_WINDOW(object->widget), x - settings.frameGeometryX, y - settings.frameGeometryY);
gtk_widget_set_size_request(object->formContainer, width, height);
}
void Window::setDefaultFont(Font &font) {
window->defaultFont = &font;
}
void Window::setFont(Font &font) {
Widget_setFont(object->status, font.font->font);
}
void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
GdkColor color;
color.pixel = (red << 16) | (green << 8) | (blue << 0);
color.red = (red << 8) | (red << 0);
color.green = (green << 8) | (green << 0);
color.blue = (blue << 8) | (blue << 0);
gtk_widget_modify_bg(object->widget, GTK_STATE_NORMAL, &color);
}
void Window::setTitle(const string &text) {
gtk_window_set_title(GTK_WINDOW(object->widget), text);
}
void Window::setStatusText(const string &text) {
gtk_statusbar_pop(GTK_STATUSBAR(object->status), 1);
gtk_statusbar_push(GTK_STATUSBAR(object->status), 1, text);
}
void Window::setVisible(bool visible) {
gtk_widget_set_visible(object->widget, visible);
}
void Window::setMenuVisible(bool visible) {
gtk_widget_set_visible(object->menu, visible);
}
void Window::setStatusVisible(bool visible) {
gtk_widget_set_visible(object->status, visible);
}
bool Window::fullscreen() {
return window->fullscreen;
}
void Window::setFullscreen(bool fullscreen) {
window->fullscreen = fullscreen;
if(fullscreen == true) {
gtk_window_fullscreen(GTK_WINDOW(object->widget));
gtk_window_set_decorated(GTK_WINDOW(object->widget), false);
gtk_widget_set_size_request(object->widget, gdk_screen_width(), gdk_screen_height());
gtk_window_set_resizable(GTK_WINDOW(object->widget), window->resizable);
} else {
gtk_window_set_resizable(GTK_WINDOW(object->widget), true);
gtk_widget_set_size_request(object->widget, -1, -1);
gtk_window_set_decorated(GTK_WINDOW(object->widget), true);
gtk_window_unfullscreen(GTK_WINDOW(object->widget));
}
}
Window::Window() {
window = new Window::Data;
window->layout = 0;
window->defaultFont = 0;
window->resizable = true;
window->fullscreen = false;
window->x = 128;
window->y = 128;
window->width = 256;
window->height = 256;
object->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_move(GTK_WINDOW(object->widget), window->x, window->y);
gtk_window_set_resizable(GTK_WINDOW(object->widget), window->resizable);
gtk_widget_set_app_paintable(object->widget, true);
object->menuContainer = gtk_vbox_new(false, 0);
gtk_container_add(GTK_CONTAINER(object->widget), object->menuContainer);
gtk_widget_show(object->menuContainer);
object->menu = gtk_menu_bar_new();
gtk_box_pack_start(GTK_BOX(object->menuContainer), object->menu, false, false, 0);
object->formContainer = gtk_fixed_new();
gtk_widget_set_size_request(object->formContainer, window->width, window->height);
gtk_box_pack_start(GTK_BOX(object->menuContainer), object->formContainer, true, true, 0);
gtk_widget_show(object->formContainer);
object->statusContainer = gtk_event_box_new();
object->status = gtk_statusbar_new();
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(object->status), false);
gtk_container_add(GTK_CONTAINER(object->statusContainer), object->status);
gtk_box_pack_start(GTK_BOX(object->menuContainer), object->statusContainer, false, false, 0);
gtk_widget_show(object->statusContainer);
g_signal_connect_swapped(G_OBJECT(object->widget), "delete_event", G_CALLBACK(Window_close), (gpointer)this);
g_signal_connect(G_OBJECT(object->widget), "configure_event", G_CALLBACK(Window_configure), (gpointer)this);
}
//internal
void Window::updateFrameGeometry() {
Display *display = XOpenDisplay(0);
XWindowAttributes attributes, parentAttributes;
XGetWindowAttributes(display, GDK_WINDOW_XID(object->widget->window), &attributes);
X11Window rootWindow, parentWindow, *childWindow = 0;
unsigned int childCount;
XQueryTree(display, GDK_WINDOW_XID(object->widget->window), &rootWindow, &parentWindow, &childWindow, &childCount);
XGetWindowAttributes(display, parentWindow, &parentAttributes);
if(childWindow) XFree(childWindow);
XCloseDisplay(display);
settings.frameGeometryX = attributes.x;
settings.frameGeometryY = attributes.y;
settings.frameGeometryWidth = parentAttributes.width - attributes.width;
settings.frameGeometryHeight = parentAttributes.height - attributes.height;
}

View File

@ -1,23 +1,11 @@
#if defined(PHOENIX_WINDOWS)
#define UNICODE
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0600
#define NOMINMAX
#endif
#include "phoenix.hpp"
using namespace nall;
#if defined(PHOENIX_WINDOWS)
#include "windows/windows.cpp"
#elif defined(PHOENIX_GTK)
#include "gtk/gtk.cpp"
#elif defined(PHOENIX_QT)
#include "qt/qt.cpp"
#if defined(PHOENIX_QT)
#include <QApplication>
#include <QtGui>
#endif
namespace phoenix {
#include "layout/fixed-layout.cpp"
#include "layout/horizontal-layout.cpp"
#include "layout/vertical-layout.cpp"
#include "core/core.cpp"
}

View File

@ -1,4 +1,5 @@
#include <nall/array.hpp>
#include <nall/config.hpp>
#include <nall/foreach.hpp>
#include <nall/function.hpp>
#include <nall/stdint.hpp>
@ -6,16 +7,6 @@
#include <nall/utility.hpp>
#include <nall/vector.hpp>
#if defined(PHOENIX_WINDOWS)
#include "windows/windows.hpp"
#elif defined(PHOENIX_GTK)
#include "gtk/gtk.hpp"
#elif defined(PHOENIX_QT)
#include "qt/qt.hpp"
#endif
namespace phoenix {
#include "layout/fixed-layout.hpp"
#include "layout/horizontal-layout.hpp"
#include "layout/vertical-layout.hpp"
#include "core/core.hpp"
}

View File

@ -0,0 +1,30 @@
void pAction::setEnabled(bool enabled) {
if(dynamic_cast<Menu*>(&action)) {
((Menu&)action).p.qtMenu->setEnabled(enabled);
} else if(dynamic_cast<MenuSeparator*>(&action)) {
((MenuSeparator&)action).p.qtAction->setEnabled(enabled);
} else if(dynamic_cast<MenuItem*>(&action)) {
((MenuItem&)action).p.qtAction->setEnabled(enabled);
} else if(dynamic_cast<MenuCheckItem*>(&action)) {
((MenuCheckItem&)action).p.qtAction->setEnabled(enabled);
} else if(dynamic_cast<MenuRadioItem*>(&action)) {
((MenuRadioItem&)action).p.qtAction->setEnabled(enabled);
}
}
void pAction::setVisible(bool visible) {
if(dynamic_cast<Menu*>(&action)) {
((Menu&)action).p.qtMenu->setVisible(visible);
} else if(dynamic_cast<MenuSeparator*>(&action)) {
((MenuSeparator&)action).p.qtAction->setVisible(visible);
} else if(dynamic_cast<MenuItem*>(&action)) {
((MenuItem&)action).p.qtAction->setVisible(visible);
} else if(dynamic_cast<MenuCheckItem*>(&action)) {
((MenuCheckItem&)action).p.qtAction->setVisible(visible);
} else if(dynamic_cast<MenuRadioItem*>(&action)) {
((MenuRadioItem&)action).p.qtAction->setVisible(visible);
}
}
pAction::pAction(Action &action) : action(action) {
}

View File

@ -1,33 +1,22 @@
void MenuCheckItem::setText(const string &text) {
menuCheckItem->setText(QString::fromUtf8(text));
bool pMenuCheckItem::checked() {
return qtAction->isChecked();
}
bool MenuCheckItem::visible() {
return menuCheckItem->isVisible();
void pMenuCheckItem::setChecked(bool checked) {
qtAction->setChecked(checked);
}
void MenuCheckItem::setVisible(bool visible) {
menuCheckItem->setVisible(visible);
void pMenuCheckItem::setText(const string &text) {
qtAction->setText(QString::fromUtf8(text));
}
bool MenuCheckItem::enabled() {
return menuCheckItem->isEnabled();
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &menuCheckItem) : menuCheckItem(menuCheckItem), pAction(menuCheckItem) {
qtAction = new QAction(0);
qtAction->setCheckable(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
}
void MenuCheckItem::setEnabled(bool enabled) {
menuCheckItem->setEnabled(enabled);
}
bool MenuCheckItem::checked() {
return menuCheckItem->isChecked();
}
void MenuCheckItem::setChecked(bool checked) {
menuCheckItem->setChecked(checked);
}
MenuCheckItem::MenuCheckItem() {
menuCheckItem = new MenuCheckItem::Data(*this);
menuCheckItem->setCheckable(true);
menuCheckItem->connect(menuCheckItem, SIGNAL(triggered()), SLOT(onTick()));
void pMenuCheckItem::onTick() {
menuCheckItem.state.checked = checked();
if(menuCheckItem.onTick) menuCheckItem.onTick();
}

View File

@ -1,24 +1,12 @@
void MenuItem::setText(const string &text) {
menuItem->setText(QString::fromUtf8(text));
void pMenuItem::setText(const string &text) {
qtAction->setText(QString::fromUtf8(text));
}
bool MenuItem::visible() {
return menuItem->isVisible();
pMenuItem::pMenuItem(MenuItem &menuItem) : menuItem(menuItem), pAction(menuItem) {
qtAction = new QAction(0);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
}
void MenuItem::setVisible(bool visible) {
menuItem->setVisible(visible);
}
bool MenuItem::enabled() {
return menuItem->isEnabled();
}
void MenuItem::setEnabled(bool enabled) {
menuItem->setEnabled(enabled);
}
MenuItem::MenuItem() {
menuItem = new MenuItem::Data(*this);
menuItem->connect(menuItem, SIGNAL(triggered()), SLOT(onTick()));
void pMenuItem::onTick() {
if(menuItem.onTick) menuItem.onTick();
}

View File

@ -1,41 +1,36 @@
void MenuRadioItem::setParent(MenuRadioItem &parent) {
delete menuRadioItem->actionGroup();
menuRadioItem->setActionGroup(parent.menuRadioItem->actionGroup());
bool pMenuRadioItem::checked() {
return qtAction->isChecked();
}
void MenuRadioItem::setText(const string &text) {
menuRadioItem->setText(QString::fromUtf8(text));
void pMenuRadioItem::setChecked() {
locked = true;
foreach(item, menuRadioItem.state.group) {
bool checkState = item->p.qtAction == qtAction;
item->state.checked = checkState;
item->p.qtAction->setChecked(checkState);
}
locked = false;
}
bool MenuRadioItem::visible() {
return menuRadioItem->isVisible();
void pMenuRadioItem::setGroup(const array<MenuRadioItem*> &group) {
}
void MenuRadioItem::setVisible(bool visible) {
menuRadioItem->setVisible(visible);
void pMenuRadioItem::setText(const string &text) {
qtAction->setText(QString::fromUtf8(text));
}
bool MenuRadioItem::enabled() {
return menuRadioItem->isEnabled();
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &menuRadioItem) : menuRadioItem(menuRadioItem), pAction(menuRadioItem) {
qtAction = new QAction(0);
qtGroup = new QActionGroup(0);
qtAction->setCheckable(true);
qtAction->setActionGroup(qtGroup);
qtAction->setChecked(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
}
void MenuRadioItem::setEnabled(bool enabled) {
menuRadioItem->setEnabled(enabled);
}
bool MenuRadioItem::checked() {
return menuRadioItem->isChecked();
}
void MenuRadioItem::setChecked() {
object->locked = true;
menuRadioItem->setChecked(true);
object->locked = false;
}
MenuRadioItem::MenuRadioItem() {
menuRadioItem = new MenuRadioItem::Data(*this);
menuRadioItem->setCheckable(true);
menuRadioItem->setActionGroup(new QActionGroup(0));
menuRadioItem->connect(menuRadioItem, SIGNAL(changed()), SLOT(onTick()));
void pMenuRadioItem::onTick() {
if(menuRadioItem.state.checked == false) {
setChecked();
if(locked == false && menuRadioItem.onTick) menuRadioItem.onTick();
}
}

View File

@ -1,19 +1,4 @@
bool MenuSeparator::visible() {
return menuSeparator->action->isVisible();
}
void MenuSeparator::setVisible(bool visible) {
menuSeparator->action->setVisible(visible);
}
bool MenuSeparator::enabled() {
return menuSeparator->action->isEnabled();
}
void MenuSeparator::setEnabled(bool enabled) {
menuSeparator->action->setEnabled(enabled);
}
MenuSeparator::MenuSeparator() {
menuSeparator = new MenuSeparator::Data(*this);
pMenuSeparator::pMenuSeparator(MenuSeparator &menuSeparator) : menuSeparator(menuSeparator), pAction(menuSeparator) {
qtAction = new QAction(0);
qtAction->setSeparator(true);
}

View File

@ -1,39 +1,21 @@
void Menu::setText(const string &text) {
menu->setTitle(QString::fromUtf8(text));
}
void Menu::append(Action &item) {
if(dynamic_cast<Menu*>(&item)) {
menu->addMenu(((Menu*)&item)->menu);
} else if(dynamic_cast<MenuSeparator*>(&item)) {
menu->addSeparator();
} else if(dynamic_cast<MenuItem*>(&item)) {
menu->addAction(((MenuItem*)&item)->menuItem);
} else if(dynamic_cast<MenuCheckItem*>(&item)) {
menu->addAction(((MenuCheckItem*)&item)->menuCheckItem);
} else if(dynamic_cast<MenuRadioItem*>(&item)) {
MenuRadioItem &radioItem = (MenuRadioItem&)item;
menu->addAction(radioItem.menuRadioItem);
if(radioItem.menuRadioItem->actionGroup()->checkedAction() == 0) radioItem.setChecked();
void pMenu::append(Action &action) {
if(dynamic_cast<Menu*>(&action)) {
qtMenu->addMenu(((Menu&)action).p.qtMenu);
} else if(dynamic_cast<MenuSeparator*>(&action)) {
qtMenu->addAction(((MenuSeparator&)action).p.qtAction);
} else if(dynamic_cast<MenuItem*>(&action)) {
qtMenu->addAction(((MenuItem&)action).p.qtAction);
} else if(dynamic_cast<MenuCheckItem*>(&action)) {
qtMenu->addAction(((MenuCheckItem&)action).p.qtAction);
} else if(dynamic_cast<MenuRadioItem*>(&action)) {
qtMenu->addAction(((MenuRadioItem&)action).p.qtAction);
}
}
bool Menu::visible() {
return menu->isVisible();
void pMenu::setText(const string &text) {
qtMenu->setTitle(QString::fromUtf8(text));
}
void Menu::setVisible(bool visible) {
menu->setVisible(visible);
}
bool Menu::enabled() {
return menu->isEnabled();
}
void Menu::setEnabled(bool enabled) {
menu->setEnabled(enabled);
}
Menu::Menu() {
menu = new Menu::Data(*this);
pMenu::pMenu(Menu &menu) : menu(menu), pAction(menu) {
qtMenu = new QMenu;
}

View File

@ -1,14 +1,17 @@
bool Font::create(const string &name, unsigned size, Font::Style style) {
font->setFamily(QString::fromUtf8(name));
font->setPointSize(size);
font->setBold((style & Style::Bold) == Style::Bold);
font->setItalic((style & Style::Italic) == Style::Italic);
void pFont::setBold(bool bold) { update(); }
void pFont::setFamily(const string &family) { update(); }
void pFont::setItalic(bool italic) { update(); }
void pFont::setSize(unsigned size) { update(); }
void pFont::setUnderline(bool underline) { update(); }
pFont::pFont(Font &font) : font(font) {
qtFont = new QFont;
}
Font::Font() {
font = new Font::Data(*this);
}
Font::~Font() {
delete font;
void pFont::update() {
qtFont->setFamily(QString::fromUtf8(font.state.family));
qtFont->setPointSize(font.state.size);
qtFont->setBold(font.state.bold);
qtFont->setItalic(font.state.italic);
qtFont->setUnderline(font.state.underline);
}

View File

@ -1,15 +1,8 @@
void Layout::setParent(Window &parent) {
layout->parent = &parent;
void pLayout::append(Widget &widget) {
if(!widget.state.font && OS::state->defaultFont) widget.p.qtWidget->setFont(*OS::state->defaultFont->p.qtFont);
widget.p.qtWidget->setParent(layout.state.parent->p.qtContainer);
widget.p.qtWidget->setVisible(true);
}
void Layout::append(Widget &child) {
child.widget->widget->setParent(layout->parent->window->container);
if(!child.widget->font && layout->parent->window->defaultFont) {
QWidget *control = child.widget->widget;
control->setFont(*layout->parent->window->defaultFont);
}
}
Layout::Layout() {
layout = new Layout::Data(*this);
pLayout::pLayout(Layout &layout) : layout(layout) {
}

View File

@ -11,35 +11,37 @@ static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons but
if(response == QMessageBox::Cancel) return MessageWindow::Response::Cancel;
if(response == QMessageBox::Yes) return MessageWindow::Response::Yes;
if(response == QMessageBox::No) return MessageWindow::Response::No;
//MessageWindow was closed via window manager, rather than by a button; assume a cancel/no response
if(buttons == MessageWindow::Buttons::OkCancel) return MessageWindow::Response::Cancel;
if(buttons == MessageWindow::Buttons::YesNo) return MessageWindow::Response::No;
return MessageWindow::Response::Ok;
}
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
MessageWindow::Response pMessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response(
buttons, QMessageBox::information(&parent != &Window::None ? parent.window : 0, " ",
buttons, QMessageBox::information(&parent != &Window::None ? parent.p.qtWindow : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
);
}
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
MessageWindow::Response pMessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response(
buttons, QMessageBox::question(&parent != &Window::None ? parent.window : 0, " ",
buttons, QMessageBox::question(&parent != &Window::None ? parent.p.qtWindow : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
);
}
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
MessageWindow::Response pMessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response(
buttons, QMessageBox::warning(&parent != &Window::None ? parent.window : 0, " ",
buttons, QMessageBox::warning(&parent != &Window::None ? parent.p.qtWindow : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
);
}
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
MessageWindow::Response pMessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
return MessageWindow_response(
buttons, QMessageBox::critical(&parent != &Window::None ? parent.window : 0, " ",
buttons, QMessageBox::critical(&parent != &Window::None ? parent.p.qtWindow : 0, " ",
QString::fromUtf8(text), MessageWindow_buttons(buttons))
);
}

View File

@ -1,7 +0,0 @@
void Object::unused() {
}
Object::Object() {
OS::initialize();
object = new Object::Data(*this);
}

View File

@ -1,21 +1,11 @@
#include <QApplication>
#include <QtGui>
#include <nall/config.hpp>
#include <nall/platform.hpp>
using namespace nall;
namespace phoenix {
#include "qt.moc.hpp"
#include "qt.moc"
#include "settings.cpp"
#include "object.cpp"
#include "font.cpp"
#include "message-window.cpp"
#include "window.cpp"
#include "layout.cpp"
#include "message-window.cpp"
#include "action/action.cpp"
#include "action/menu.cpp"
@ -26,119 +16,113 @@ namespace phoenix {
#include "widget/widget.cpp"
#include "widget/button.cpp"
#include "widget/canvas.cpp"
#include "widget/check-box.cpp"
#include "widget/combo-box.cpp"
#include "widget/edit-box.cpp"
#include "widget/hex-editor.cpp"
#include "widget/hex-edit.cpp"
#include "widget/horizontal-slider.cpp"
#include "widget/label.cpp"
#include "widget/line-edit.cpp"
#include "widget/list-box.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-box.cpp"
#include "widget/text-box.cpp"
#include "widget/text-edit.cpp"
#include "widget/vertical-slider.cpp"
#include "widget/viewport.cpp"
OS::Data *OS::os = 0;
Window Window::None;
unsigned pOS::desktopWidth() {
return QApplication::desktop()->screenGeometry().width();
}
void OS::initialize() {
static bool initialized = false;
if(initialized == true) return;
initialized = true;
unsigned pOS::desktopHeight() {
return QApplication::desktop()->screenGeometry().height();
}
string pOS::fileLoad(Window &parent, const string &path, const lstring &filter) {
string filterList;
foreach(item, filter) {
filterList.append(item);
filterList.append(";;");
}
filterList.rtrim<1>(";;");
//convert filter list from phoenix to Qt format, example:
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
signed parenthesis = 0;
foreach(n, filterList) {
if(n == '(') parenthesis++;
if(n == ')') parenthesis--;
if(n == ',' && parenthesis) n = ' ';
}
QString filename = QFileDialog::getOpenFileName(
&parent != &Window::None ? parent.p.qtWindow : 0, "Load File",
QString::fromUtf8(path), QString::fromUtf8(filterList)
);
return filename.toUtf8().constData();
}
string pOS::fileSave(Window &parent, const string &path, const lstring &filter) {
string filterList;
foreach(item, filter) {
filterList.append(item);
filterList.append(";;");
}
filterList.rtrim<1>(";;");
//convert filter list from phoenix to Qt format, example:
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
signed parenthesis = 0;
foreach(n, filterList) {
if(n == '(') parenthesis++;
if(n == ')') parenthesis--;
if(n == ',' && parenthesis) n = ' ';
}
QString filename = QFileDialog::getSaveFileName(
&parent != &Window::None ? parent.p.qtWindow : 0, "Save File",
QString::fromUtf8(path), QString::fromUtf8(filterList)
);
return filename.toUtf8().constData();
}
string pOS::folderSelect(Window &parent, const string &path) {
QString directory = QFileDialog::getExistingDirectory(
&parent != &Window::None ? parent.p.qtWindow : 0, "Select Directory",
QString::fromUtf8(path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
);
string name = directory.toUtf8().constData();
if(name != "" && name.endswith("/") == false) name.append("/");
return name;
}
void pOS::main() {
QApplication::exec();
}
bool pOS::pending() {
return QApplication::hasPendingEvents();
}
void pOS::process() {
while(pending()) QApplication::processEvents();
}
void pOS::quit() {
settings.save();
QApplication::quit();
}
void pOS::setDefaultFont(Font &font) {
}
pOS::pOS() {
settings.load();
os = new OS::Data;
static int argc = 1;
static char *argv[2];
argv[0] = new char[8];
argv[1] = 0;
strcpy(argv[0], "phoenix");
char **argvp = argv;
os->application = new QApplication(argc, argvp);
}
bool OS::pending() {
return QApplication::hasPendingEvents();
}
void OS::run() {
QApplication::processEvents();
}
void OS::main() {
QApplication::exec();
}
void OS::quit() {
settings.save();
QApplication::quit();
}
unsigned OS::desktopWidth() {
return QApplication::desktop()->screenGeometry().width();
}
unsigned OS::desktopHeight() {
return QApplication::desktop()->screenGeometry().height();
}
string OS::folderSelect(Window &parent, const string &path) {
QString directory = QFileDialog::getExistingDirectory(
&parent != &Window::None ? parent.window : 0, "Select Directory",
QString::fromUtf8(path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
);
string name = directory.toUtf8().constData();
if(name.endswith("/") == false) name.append("/");
return name;
}
string OS::fileOpen(Window &parent, const string &filter, const string &path) {
string filters;
lstring list;
list.split("\n", filter);
foreach(item, list) {
lstring part;
part.split("\t", item);
if(part.size() != 2) continue;
part[1].replace(",", " ");
filters.append(part[0]);
filters.append(" (");
filters.append(part[1]);
filters.append(");;");
}
filters.rtrim(";;");
QString filename = QFileDialog::getOpenFileName(
&parent != &Window::None ? parent.window : 0, "Open File",
QString::fromUtf8(path), QString::fromUtf8(filters)
);
return filename.toUtf8().constData();
}
string OS::fileSave(Window &parent, const string &filter, const string &path) {
string filters;
lstring list;
list.split("\n", filter);
foreach(item, list) {
lstring part;
part.split("\t", item);
if(part.size() != 2) continue;
part[1].replace(",", " ");
filters.append(part[0]);
filters.append(" (");
filters.append(part[1]);
filters.append(");;");
}
filters.rtrim(";;");
QString filename = QFileDialog::getSaveFileName(
&parent != &Window::None ? parent.window : 0, "Save File",
QString::fromUtf8(path), QString::fromUtf8(filters)
);
return filename.toUtf8().constData();
}
application = new QApplication(argc, argvp);
}

View File

@ -1,370 +0,0 @@
namespace phoenix {
struct Window;
struct Object {
Object();
Object& operator=(const Object&) = delete;
Object(const Object&) = delete;
//private:
virtual void unused();
struct Data;
Data *object;
};
struct Geometry {
signed x, y;
unsigned width, height;
inline Geometry() : x(0), y(0), width(0), height(0) {}
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
};
struct Font : Object {
enum class Style : unsigned {
None = 0,
Bold = 1,
Italic = 2,
};
bool create(const nall::string &name, unsigned size, Font::Style style = Style::None);
Font();
~Font();
//private:
struct Data;
Data *font;
};
inline Font::Style operator|(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a | (unsigned)b); }
inline Font::Style operator&(Font::Style a, Font::Style b) { return (Font::Style)((unsigned)a & (unsigned)b); }
struct Menu;
struct Layout;
struct Widget;
struct Window : Object {
static Window None;
nall::function<bool ()> onClose;
nall::function<void ()> onMove;
nall::function<void ()> onSize;
void append(Menu &menu);
void setLayout(Layout &layout);
void setResizable(bool resizable = true);
Geometry frameGeometry();
Geometry geometry();
void setFrameGeometry(signed x, signed y, unsigned width, unsigned height);
void setGeometry(signed x, signed y, unsigned width, unsigned height);
void setDefaultFont(Font &font);
void setFont(Font &font);
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setTitle(const nall::string &text);
void setStatusText(const nall::string &text);
void setVisible(bool visible = true);
void setMenuVisible(bool visible = true);
void setStatusVisible(bool visible = true);
bool focused();
bool fullscreen();
void setFullscreen(bool fullscreen = true);
Window();
//private:
struct Data;
Data *window;
private:
void updateFrameGeometry();
};
struct Action : Object {
virtual bool visible() = 0;
virtual void setVisible(bool visible = true) = 0;
virtual bool enabled() = 0;
virtual void setEnabled(bool enabled = true) = 0;
};
struct Menu : Action {
void append(Action &action);
void setText(const nall::string &text);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
Menu();
//private:
struct Data;
Data *menu;
};
struct MenuSeparator : Action {
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
MenuSeparator();
//private:
struct Data;
Data *menuSeparator;
};
struct MenuItem : Action {
nall::function<void ()> onTick;
void setText(const nall::string &text);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
MenuItem();
//private:
struct Data;
Data *menuItem;
};
struct MenuCheckItem : Action {
nall::function<void ()> onTick;
void setText(const nall::string &text);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
bool checked();
void setChecked(bool checked = true);
MenuCheckItem();
//private:
struct Data;
Data *menuCheckItem;
};
struct MenuRadioItem : Action {
nall::function<void ()> onTick;
void setParent(MenuRadioItem &parent);
void setText(const nall::string &text);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
bool checked();
void setChecked();
MenuRadioItem();
//private:
struct Data;
Data *menuRadioItem;
};
struct Layout : Object {
virtual void setParent(Window &parent);
virtual void setGeometry(Geometry &geometry) = 0;
virtual void append(Widget &widget);
Layout();
//private:
struct Data;
Data *layout;
};
struct Widget : Object {
virtual Geometry geometry();
virtual void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
void setFont(Font &font);
bool visible();
void setVisible(bool visible = true);
bool enabled();
void setEnabled(bool enabled = true);
bool focused();
void setFocused();
Widget();
//private:
struct Data;
Data *widget;
};
struct Button : Widget {
nall::function<void ()> onTick;
void setText(const nall::string &text);
Button();
//private:
struct Data;
Data *button;
};
struct Canvas : Widget {
void setGeometry(unsigned x, unsigned y, unsigned width, unsigned height);
uint32_t* buffer();
void redraw();
Canvas();
~Canvas();
//private:
struct Data;
Data *canvas;
};
struct CheckBox : Widget {
nall::function<void ()> onTick;
void setText(const nall::string &text);
bool checked();
void setChecked(bool checked = true);
CheckBox();
//private:
struct Data;
Data *checkBox;
};
struct ComboBox : Widget {
nall::function<void ()> onChange;
void reset();
void addItem(const nall::string &text);
unsigned selection();
void setSelection(unsigned row);
ComboBox();
//private:
struct Data;
Data *comboBox;
};
struct EditBox : Widget {
nall::function<void ()> onChange;
void setEditable(bool editable = true);
void setWordWrap(bool wordWrap = true);
nall::string text();
void setText(const nall::string &text);
void setCursorPosition(unsigned position);
EditBox();
//private:
struct Data;
Data *editBox;
};
struct HexEditor : Widget {
nall::function<uint8_t (unsigned)> onRead;
nall::function<void (unsigned, uint8_t)> onWrite;
void setSize(unsigned size);
void setOffset(unsigned offset);
void setColumns(unsigned columns);
void setRows(unsigned rows);
void update();
HexEditor();
//private:
struct Data;
Data *hexEditor;
};
struct HorizontalSlider : Widget {
nall::function<void ()> onChange;
void setLength(unsigned length);
unsigned position();
void setPosition(unsigned position);
HorizontalSlider();
//private:
struct Data;
Data *horizontalSlider;
};
struct Label : Widget {
void setText(const nall::string &text);
Label();
//private:
struct Data;
Data *label;
};
struct ListBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
nall::function<void (unsigned)> onTick;
void setHeaderText(const nall::string &text);
void setHeaderVisible(bool headerVisible = true);
void setCheckable(bool checkable = true);
void reset();
void resizeColumnsToContent();
void addItem(const nall::string &text);
void setItem(unsigned row, const nall::string &text);
bool checked(unsigned row);
void setChecked(unsigned row, bool checked = true);
nall::optional<unsigned> selection();
void setSelection(unsigned row);
ListBox();
//private:
struct Data;
Data *listBox;
};
struct ProgressBar : Widget {
void setPosition(unsigned position);
ProgressBar();
//private:
struct Data;
Data *progressBar;
};
struct RadioBox : Widget {
nall::function<void ()> onTick;
void setParent(RadioBox &parent);
void setText(const nall::string &text);
bool checked();
void setChecked();
RadioBox();
//private:
struct Data;
Data *radioBox;
};
struct TextBox : Widget {
nall::function<void ()> onActivate;
nall::function<void ()> onChange;
void setEditable(bool editable = true);
nall::string text();
void setText(const nall::string &text);
TextBox();
//private:
struct Data;
Data *textBox;
};
struct VerticalSlider : Widget {
nall::function<void ()> onChange;
void setLength(unsigned length);
unsigned position();
void setPosition(unsigned position);
VerticalSlider();
//private:
struct Data;
Data *verticalSlider;
};
struct Viewport : Widget {
uintptr_t handle();
Viewport();
//private:
struct Data;
Data *viewport;
};
struct MessageWindow : Object {
enum class Buttons : unsigned {
Ok,
OkCancel,
YesNo,
};
enum class Response : unsigned {
Ok,
Cancel,
Yes,
No,
};
static Response information(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response question(Window &parent, const nall::string &text, Buttons = Buttons::YesNo);
static Response warning(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
static Response critical(Window &parent, const nall::string &text, Buttons = Buttons::Ok);
};
struct OS : Object {
static bool pending();
static void run();
static void main();
static void quit();
static unsigned desktopWidth();
static unsigned desktopHeight();
static nall::string folderSelect(Window &parent, const nall::string &path = "");
static nall::string fileOpen(Window &parent, const nall::string &filter, const nall::string &path = "");
static nall::string fileSave(Window &parent, const nall::string &filter, const nall::string &path = "");
//private:
struct Data;
static Data *os;
static void initialize();
};
}

File diff suppressed because it is too large Load Diff

View File

@ -6,388 +6,420 @@ struct Settings : public configuration {
void load();
void save();
Settings();
};
struct Object::Data {
public:
Object &self;
struct pFont;
struct pWindow;
struct pMenu;
struct pLayout;
struct pWidget;
struct pObject {
bool locked;
Data(Object &self) : self(self) {
pObject() {
locked = false;
}
};
struct Font::Data : public QFont {
public:
Font &self;
Data(Font &self) : self(self) {
}
};
struct Menu::Data : public QMenu {
public:
Menu &self;
Window *parent;
Data(Menu &self) : self(self), parent(0) {
}
};
struct MenuSeparator::Data {
public:
MenuSeparator &self;
QAction *action;
Data(MenuSeparator &self) : self(self) {
}
};
struct MenuItem::Data : public QAction {
Q_OBJECT
public:
MenuItem &self;
Data(MenuItem &self) : self(self), QAction(0) {
}
public slots:
void onTick() {
if(self.onTick) self.onTick();
}
};
struct MenuCheckItem::Data : public QAction {
Q_OBJECT
public:
MenuCheckItem &self;
Data(MenuCheckItem &self) : self(self), QAction(0) {
}
public slots:
void onTick() {
if(self.onTick) self.onTick();
}
};
struct MenuRadioItem::Data : public QAction {
Q_OBJECT
public:
MenuRadioItem &self;
Data(MenuRadioItem &self) : self(self), QAction(0) {
}
public slots:
void onTick() {
if(self.object->locked == false && self.onTick && self.checked()) self.onTick();
}
};
struct Window::Data : public QWidget {
Q_OBJECT
public:
Window &self;
unsigned x, y, width, height;
bool resizable, fullscreen, menuVisible, statusVisible;
Layout *layout;
QFont *defaultFont;
QVBoxLayout *vlayout;
QMenuBar *menuBar;
QStatusBar *statusBar;
QWidget *container;
QSize sizeHint() const {
unsigned actualHeight = height;
if(menuVisible) actualHeight += menuBar->height();
if(statusVisible) actualHeight += statusBar->height();
return QSize(width, actualHeight);
}
void closeEvent(QCloseEvent *event) {
if(self.onClose) {
bool result = self.onClose();
if(result == false) event->ignore();
}
}
void moveEvent(QMoveEvent *event) {
if(self.object->locked == false && fullscreen == false && isVisible() == true) {
x += event->pos().x() - event->oldPos().x();
y += event->pos().y() - event->oldPos().y();
}
if(self.object->locked == false && self.onMove) {
self.onMove();
}
}
void resizeEvent(QResizeEvent *event) {
if(self.object->locked == false && fullscreen == false && isVisible() == true) {
width = container->geometry().width();
height = container->geometry().height();
}
if(layout) {
Geometry geom = self.geometry();
geom.x = geom.y = 0;
layout->setGeometry(geom);
}
if(self.object->locked == false && self.onSize) {
self.onSize();
}
}
Data(Window &self) : self(self) {
resizable = true;
fullscreen = false;
menuVisible = false;
statusVisible = false;
}
};
struct Layout::Data {
Layout &self;
Window *parent;
Data(Layout &self) : self(self) {
parent = 0;
}
};
struct Widget::Data {
Widget &self;
QWidget *widget;
Font *font;
Data(Widget &self) : self(self) {
widget = 0;
font = 0;
}
};
struct Button::Data : public QPushButton {
Q_OBJECT
public:
Button &self;
Data(Button &self) : self(self) {
}
public slots:
void onTick() {
if(self.onTick) self.onTick();
}
};
struct Canvas::Data : public QWidget {
Q_OBJECT
public:
Canvas &self;
QImage *image;
void paintEvent(QPaintEvent*);
Data(Canvas &self) : self(self) {
}
};
struct CheckBox::Data : public QCheckBox {
Q_OBJECT
public:
CheckBox &self;
Data(CheckBox &self) : self(self) {
}
public slots:
void onTick() {
if(self.onTick) self.onTick();
}
};
struct ComboBox::Data : public QComboBox {
Q_OBJECT
public:
ComboBox &self;
Data(ComboBox &self) : self(self) {
}
public slots:
void onChange() {
if(self.object->locked == false && self.onChange) self.onChange();
}
};
struct EditBox::Data : public QTextEdit {
Q_OBJECT
public:
EditBox &self;
Data(EditBox &self) : self(self) {
}
public slots:
void onChange() {
if(self.onChange) self.onChange();
}
};
struct HexEditor::Data : public QTextEdit {
Q_OBJECT
public:
HexEditor &self;
QHBoxLayout *layout;
QScrollBar *scrollBar;
unsigned size;
unsigned offset;
unsigned columns;
unsigned rows;
void keyPressEvent(QKeyEvent*);
Data(HexEditor &self) : self(self) {
}
public slots:
void scrollEvent();
};
struct HorizontalSlider::Data : public QSlider {
Q_OBJECT
public:
HorizontalSlider &self;
Data(HorizontalSlider &self) : self(self), QSlider(Qt::Horizontal) {
}
public slots:
void onChange() {
if(self.onChange) self.onChange();
}
};
struct Label::Data : public QLabel {
Q_OBJECT
public:
Label &self;
Data(Label &self) : self(self) {
}
};
struct ListBox::Data : public QTreeWidget {
Q_OBJECT
public:
ListBox &self;
bool checkable;
Data(ListBox &self) : self(self) {
checkable = false;
}
public slots:
void onActivate() {
if(self.object->locked == false && self.onActivate) self.onActivate();
}
void onChange() {
if(self.object->locked == false && self.onChange) self.onChange();
}
void onTick(QTreeWidgetItem *item) {
if(self.object->locked == false && self.onTick) self.onTick(item->data(0, Qt::UserRole).toUInt());
}
};
struct ProgressBar::Data : public QProgressBar {
public:
ProgressBar &self;
Data(ProgressBar &self) : self(self) {
}
};
struct RadioBox::Data : public QRadioButton {
Q_OBJECT
public:
RadioBox &self;
Window *parent;
QButtonGroup *buttonGroup;
Data(RadioBox &self) : self(self) {
}
public slots:
void onTick() {
if(self.onTick && self.checked()) self.onTick();
}
};
struct TextBox::Data : public QLineEdit {
Q_OBJECT
public:
TextBox &self;
Data(TextBox &self) : self(self) {
}
public slots:
void onActivate() {
if(self.onActivate) self.onActivate();
}
void onChange() {
if(self.onChange) self.onChange();
}
};
struct VerticalSlider::Data : public QSlider {
Q_OBJECT
public:
VerticalSlider &self;
Data(VerticalSlider &self) : self(self), QSlider(Qt::Vertical) {
}
public slots:
void onChange() {
if(self.onChange) self.onChange();
}
};
struct Viewport::Data : public QWidget {
public:
Viewport &self;
Data(Viewport &self) : self(self) {
}
};
struct OS::Data : public QObject {
Q_OBJECT
public:
struct pOS : public pObject {
QApplication *application;
public slots:
unsigned desktopWidth();
unsigned desktopHeight();
string fileLoad(Window &parent, const string &path, const lstring &filter);
string fileSave(Window &parent, const string &path, const lstring &filter);
string folderSelect(Window &parent, const string &path);
void main();
bool pending();
void process();
void quit();
void setDefaultFont(Font &font);
pOS();
};
struct pFont : public pObject {
Font &font;
QFont *qtFont;
void setBold(bool bold);
void setFamily(const string &family);
void setItalic(bool italic);
void setSize(unsigned size);
void setUnderline(bool underline);
pFont(Font &font);
void update();
};
struct pMessageWindow : public pObject {
static MessageWindow::Response information(Window &parent, const string &text, MessageWindow::Buttons buttons);
static MessageWindow::Response question(Window &parent, const string &text, MessageWindow::Buttons buttons);
static MessageWindow::Response warning(Window &parent, const string &text, MessageWindow::Buttons buttons);
static MessageWindow::Response critical(Window &parent, const string &text, MessageWindow::Buttons buttons);
};
struct pWindow : public QObject, public pObject {
Q_OBJECT
public:
Window &window;
struct QtWindow : public QWidget {
pWindow &self;
void closeEvent(QCloseEvent*);
void moveEvent(QMoveEvent*);
void resizeEvent(QResizeEvent*);
QSize sizeHint() const;
QtWindow(pWindow &self) : self(self) {}
} *qtWindow;
QVBoxLayout *qtLayout;
QMenuBar *qtMenu;
QStatusBar *qtStatus;
QWidget *qtContainer;
Layout *layout;
void append(Menu &menu);
Geometry frameGeometry();
bool focused();
Geometry geometry();
void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue);
void setFrameGeometry(const Geometry &geometry);
void setFocused();
void setFullScreen(bool fullScreen);
void setGeometry(const Geometry &geometry);
void setLayout(Layout &layout);
void setMenuFont(Font &font);
void setMenuVisible(bool visible);
void setResizable(bool resizable);
void setStatusFont(Font &font);
void setStatusText(const string &text);
void setStatusVisible(bool visible);
void setTitle(const string &text);
void setVisible(bool visible);
pWindow(Window &window);
void updateFrameGeometry();
};
struct pAction : public pObject {
Action &action;
void setEnabled(bool enabled);
void setVisible(bool visible);
pAction(Action &action);
};
struct pMenu : public pAction {
Menu &menu;
QMenu *qtMenu;
void append(Action &action);
void setText(const string &text);
pMenu(Menu &menu);
};
struct pMenuSeparator : public pAction {
MenuSeparator &menuSeparator;
QAction *qtAction;
pMenuSeparator(MenuSeparator &menuSeparator);
};
struct pMenuItem : public QObject, public pAction {
Q_OBJECT
public:
MenuItem &menuItem;
QAction *qtAction;
void setText(const string &text);
pMenuItem(MenuItem &menuItem);
public slots:
void onTick();
};
struct pMenuCheckItem : public QObject, public pAction {
Q_OBJECT
public:
MenuCheckItem &menuCheckItem;
QAction *qtAction;
bool checked();
void setChecked(bool checked);
void setText(const string &text);
pMenuCheckItem(MenuCheckItem &menuCheckItem);
public slots:
void onTick();
};
struct pMenuRadioItem : public QObject, public pAction {
Q_OBJECT
public:
MenuRadioItem &menuRadioItem;
QAction *qtAction;
QActionGroup *qtGroup;
bool checked();
void setChecked();
void setGroup(const array<MenuRadioItem*> &group);
void setText(const string &text);
pMenuRadioItem(MenuRadioItem &menuRadioitem);
public slots:
void onTick();
};
struct pLayout : public pObject {
Layout &layout;
pWindow *parent;
void append(Widget &widget);
pLayout(Layout &layout);
};
struct pWidget : public pObject {
Widget &widget;
QWidget *qtWidget;
bool enabled();
void setEnabled(bool enabled);
void setFocused();
void setFont(Font &font);
void setGeometry(const Geometry &geometry);
void setVisible(bool visible);
pWidget(Widget &widget);
};
struct pButton : public QObject, public pWidget {
Q_OBJECT
public:
Button &button;
QPushButton *qtButton;
void setText(const string &text);
pButton(Button &button);
public slots:
void onTick();
};
struct pCheckBox : public QObject, public pWidget {
Q_OBJECT
public:
CheckBox &checkBox;
QCheckBox *qtCheckBox;
bool checked();
void setChecked(bool checked);
void setText(const string &text);
pCheckBox(CheckBox &checkBox);
public slots:
void onTick();
};
struct pComboBox : public QObject, public pWidget {
Q_OBJECT
public:
ComboBox &comboBox;
QComboBox *qtComboBox;
void append(const string &text);
void reset();
unsigned selection();
void setSelection(unsigned row);
pComboBox(ComboBox &comboBox);
public slots:
void onChange();
};
struct pHexEdit : public QObject, public pWidget {
Q_OBJECT
public:
HexEdit &hexEdit;
struct QtHexEdit : public QTextEdit {
pHexEdit &self;
void keyPressEvent(QKeyEvent*);
void keyPressEventAcknowledge(QKeyEvent*);
QtHexEdit(pHexEdit &self) : self(self) {}
} *qtHexEdit;
QHBoxLayout *qtLayout;
QScrollBar *qtScroll;
void setColumns(unsigned columns);
void setLength(unsigned length);
void setOffset(unsigned offset);
void setRows(unsigned rows);
void update();
void keyPressEvent(QKeyEvent*);
pHexEdit(HexEdit &hexEdit);
public slots:
void onScroll();
};
struct pHorizontalSlider : public QObject, public pWidget {
Q_OBJECT
public:
HorizontalSlider &horizontalSlider;
QSlider *qtSlider;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
pHorizontalSlider(HorizontalSlider &horizontalSlider);
public slots:
void onChange();
};
struct pLabel : public pWidget {
Label &label;
QLabel *qtLabel;
void setText(const string &text);
pLabel(Label &label);
};
struct pLineEdit : public QObject, public pWidget {
Q_OBJECT
public:
LineEdit &lineEdit;
QLineEdit *qtLineEdit;
void setEditable(bool editable);
void setText(const string &text);
string text();
pLineEdit(LineEdit &lineEdit);
public slots:
void onActivate();
void onChange();
};
struct pListBox : public QObject, public pWidget {
Q_OBJECT
public:
ListBox &listBox;
QTreeWidget *qtListBox;
void append(const lstring &text);
void autosizeColumns();
bool checked(unsigned row);
void modify(unsigned row, const lstring &text);
void modify(unsigned row, unsigned column, const string &text);
void reset();
optional<unsigned> selection();
void setCheckable(bool checkable);
void setChecked(unsigned row, bool checked);
void setHeaderText(const lstring &text);
void setHeaderVisible(bool visible);
void setSelection(unsigned row);
pListBox(ListBox &listBox);
public slots:
void onActivate();
void onChange();
void onTick(QTreeWidgetItem *item);
};
struct pProgressBar : public pWidget {
ProgressBar &progressBar;
QProgressBar *qtProgressBar;
void setPosition(unsigned position);
pProgressBar(ProgressBar &progressBar);
};
struct pRadioBox : public QObject, public pWidget {
Q_OBJECT
public:
RadioBox &radioBox;
QRadioButton *qtRadioBox;
QButtonGroup *qtGroup;
bool checked();
void setChecked();
void setGroup(const array<RadioBox*> &group);
void setText(const string &text);
pRadioBox(RadioBox &radioBox);
public slots:
void onTick();
};
struct pTextEdit : public QObject, public pWidget {
Q_OBJECT
public:
TextEdit &textEdit;
QTextEdit *qtTextEdit;
void setCursorPosition(unsigned position);
void setEditable(bool editable);
void setText(const string &text);
void setWordWrap(bool wordWrap);
string text();
pTextEdit(TextEdit &textEdit);
public slots:
void onChange();
};
struct pVerticalSlider : public QObject, public pWidget {
Q_OBJECT
public:
VerticalSlider &verticalSlider;
QSlider *qtSlider;
unsigned position();
void setLength(unsigned length);
void setPosition(unsigned position);
pVerticalSlider(VerticalSlider &verticalSlider);
public slots:
void onChange();
};
struct pViewport : public pWidget {
Viewport &viewport;
uintptr_t handle();
pViewport(Viewport &viewport);
};

View File

@ -1,11 +1,6 @@
static Settings settings;
void Settings::load() {
attach(frameGeometryX = 0, "frameGeometryX");
attach(frameGeometryY = 0, "frameGeometryY");
attach(frameGeometryWidth = 0, "frameGeometryWidth");
attach(frameGeometryHeight = 0, "frameGeometryHeight");
string path = { userpath(), ".config/phoenix/qt.cfg" };
configuration::load(path);
}
@ -18,3 +13,10 @@ void Settings::save() {
path.append("qt.cfg");
configuration::save(path);
}
Settings::Settings() {
attach(frameGeometryX = 0, "frameGeometryX");
attach(frameGeometryY = 0, "frameGeometryY");
attach(frameGeometryWidth = 0, "frameGeometryWidth");
attach(frameGeometryHeight = 0, "frameGeometryHeight");
}

View File

@ -1,9 +1,12 @@
void Button::setText(const string &text) {
button->setText(QString::fromUtf8(text));
void pButton::setText(const string &text) {
qtButton->setText(QString::fromUtf8(text));
}
Button::Button() {
button = new Button::Data(*this);
widget->widget = button;
button->connect(button, SIGNAL(released()), SLOT(onTick()));
pButton::pButton(Button &button) : button(button), pWidget(button) {
qtWidget = qtButton = new QPushButton;
connect(qtButton, SIGNAL(released()), SLOT(onTick()));
}
void pButton::onTick() {
if(button.onTick) button.onTick();
}

View File

@ -1,33 +0,0 @@
void Canvas::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
delete canvas->image;
canvas->image = new QImage(width, height, QImage::Format_RGB32);
canvas->image->fill(0);
canvas->setGeometry(x, y, width, height);
canvas->update();
}
uint32_t* Canvas::buffer() {
return (uint32_t*)canvas->image->bits();
}
void Canvas::redraw() {
canvas->update();
}
Canvas::Canvas() {
canvas = new Canvas::Data(*this);
canvas->image = 0;
widget->widget = canvas;
canvas->image = new QImage(64, 64, QImage::Format_RGB32);
canvas->image->fill(0);
}
Canvas::~Canvas() {
if(canvas->image) delete canvas->image;
delete canvas;
}
void Canvas::Data::paintEvent(QPaintEvent *event) {
QPainter painter(this);
painter.drawImage(0, 0, *image);
}

View File

@ -1,17 +1,22 @@
void CheckBox::setText(const string &text) {
checkBox->setText(QString::fromUtf8(text));
bool pCheckBox::checked() {
return qtCheckBox->isChecked();
}
bool CheckBox::checked() {
return checkBox->isChecked();
void pCheckBox::setChecked(bool checked) {
locked = true;
qtCheckBox->setChecked(checked);
locked = false;
}
void CheckBox::setChecked(bool checked) {
checkBox->setChecked(checked);
void pCheckBox::setText(const string &text) {
qtCheckBox->setText(QString::fromUtf8(text));
}
CheckBox::CheckBox() {
checkBox = new CheckBox::Data(*this);
widget->widget = checkBox;
checkBox->connect(checkBox, SIGNAL(stateChanged(int)), SLOT(onTick()));
pCheckBox::pCheckBox(CheckBox &checkBox) : checkBox(checkBox), pWidget(checkBox) {
qtWidget = qtCheckBox = new QCheckBox;
connect(qtCheckBox, SIGNAL(stateChanged(int)), SLOT(onTick()));
}
void pCheckBox::onTick() {
if(locked == false && checkBox.onTick) checkBox.onTick();
}

View File

@ -1,24 +1,28 @@
void ComboBox::reset() {
while(comboBox->count()) comboBox->removeItem(0);
void pComboBox::append(const string &text) {
qtComboBox->addItem(QString::fromUtf8(text));
}
void ComboBox::addItem(const string &text) {
comboBox->addItem(QString::fromUtf8(text));
void pComboBox::reset() {
while(qtComboBox->count()) qtComboBox->removeItem(0);
}
unsigned ComboBox::selection() {
signed index = comboBox->currentIndex();
return (index >= 0 ? index : 0);
unsigned pComboBox::selection() {
signed index = qtComboBox->currentIndex();
return index >= 0 ? index : 0;
}
void ComboBox::setSelection(unsigned row) {
object->locked = true;
comboBox->setCurrentIndex(row);
object->locked = false;
void pComboBox::setSelection(unsigned row) {
locked = true;
qtComboBox->setCurrentIndex(row);
locked = false;
}
ComboBox::ComboBox() {
comboBox = new ComboBox::Data(*this);
widget->widget = comboBox;
comboBox->connect(comboBox, SIGNAL(currentIndexChanged(int)), SLOT(onChange()));
pComboBox::pComboBox(ComboBox &comboBox) : comboBox(comboBox), pWidget(comboBox) {
qtWidget = qtComboBox = new QComboBox;
connect(qtComboBox, SIGNAL(currentIndexChanged(int)), SLOT(onChange()));
}
void pComboBox::onChange() {
comboBox.state.selection = selection();
if(locked == false && comboBox.onChange) comboBox.onChange();
}

View File

@ -1,28 +0,0 @@
void EditBox::setEditable(bool editable) {
editBox->setReadOnly(editable == false);
}
void EditBox::setWordWrap(bool wordWrap) {
editBox->setWordWrapMode(wordWrap ? QTextOption::WordWrap : QTextOption::NoWrap);
}
string EditBox::text() {
return editBox->toPlainText().toUtf8().constData();
}
void EditBox::setText(const string &text) {
editBox->setPlainText(QString::fromUtf8(text));
}
void EditBox::setCursorPosition(unsigned position) {
QTextCursor cursor = editBox->textCursor();
unsigned lastchar = strlen(editBox->toPlainText().toUtf8().constData());
cursor.setPosition(min(position, lastchar));
editBox->setTextCursor(cursor);
}
EditBox::EditBox() {
editBox = new EditBox::Data(*this);
widget->widget = editBox;
editBox->connect(editBox, SIGNAL(textChanged()), SLOT(onChange()));
}

View File

@ -0,0 +1,170 @@
void pHexEdit::setColumns(unsigned columns) {
update();
}
void pHexEdit::setLength(unsigned length) {
//add one if last row is not equal to column length (eg only part of the row is present)
bool indivisible = hexEdit.state.columns == 0 || (hexEdit.state.length % hexEdit.state.columns) != 0;
qtScroll->setRange(0, hexEdit.state.length / hexEdit.state.columns + indivisible - hexEdit.state.rows);
update();
}
void pHexEdit::setOffset(unsigned offset) {
locked = true;
qtScroll->setSliderPosition(hexEdit.state.offset / hexEdit.state.columns);
locked = false;
update();
}
void pHexEdit::setRows(unsigned rows) {
qtScroll->setPageStep(hexEdit.state.rows);
update();
}
void pHexEdit::update() {
if(!hexEdit.onRead) {
qtHexEdit->setPlainText("");
return;
}
unsigned cursorPosition = qtHexEdit->textCursor().position();
string output;
unsigned offset = hexEdit.state.offset;
for(unsigned row = 0; row < hexEdit.state.rows; row++) {
output.append(hex<8>(offset));
output.append(" ");
string hexdata;
string ansidata = " ";
for(unsigned column = 0; column < hexEdit.state.columns; column++) {
if(offset < hexEdit.state.length) {
uint8_t data = hexEdit.onRead(offset++);
hexdata.append(hex<2>(data));
hexdata.append(" ");
char buffer[2] = { data >= 0x20 && data <= 0x7e ? (char)data : '.', 0 };
ansidata.append(buffer);
} else {
hexdata.append(" ");
ansidata.append(" ");
}
}
output.append(hexdata);
output.append(ansidata);
if(offset >= hexEdit.state.length) break;
if(row != hexEdit.state.rows - 1) output.append("\n");
}
qtHexEdit->setPlainText(QString::fromUtf8(output));
QTextCursor cursor = qtHexEdit->textCursor();
cursor.setPosition(cursorPosition);
qtHexEdit->setTextCursor(cursor);
}
pHexEdit::pHexEdit(HexEdit &hexEdit) : hexEdit(hexEdit), pWidget(hexEdit) {
qtWidget = qtHexEdit = new QtHexEdit(*this);
qtHexEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
qtHexEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
qtLayout = new QHBoxLayout;
qtLayout->setAlignment(Qt::AlignRight);
qtLayout->setMargin(0);
qtLayout->setSpacing(0);
qtHexEdit->setLayout(qtLayout);
qtScroll = new QScrollBar(Qt::Vertical);
qtScroll->setSingleStep(1);
qtLayout->addWidget(qtScroll);
connect(qtScroll, SIGNAL(actionTriggered(int)), SLOT(onScroll()));
}
void pHexEdit::onScroll() {
if(locked) return;
unsigned offset = qtScroll->sliderPosition();
hexEdit.state.offset = offset * hexEdit.state.columns;
update();
}
void pHexEdit::keyPressEvent(QKeyEvent *event) {
if(!hexEdit.onRead) return;
QTextCursor cursor = qtHexEdit->textCursor();
unsigned lineWidth = 10 + (hexEdit.state.columns * 3) + 1 + hexEdit.state.columns + 1;
unsigned cursorY = cursor.position() / lineWidth;
unsigned cursorX = cursor.position() % lineWidth;
unsigned nibble;
switch(event->key()) {
case Qt::Key_0: nibble = 0; break;
case Qt::Key_1: nibble = 1; break;
case Qt::Key_2: nibble = 2; break;
case Qt::Key_3: nibble = 3; break;
case Qt::Key_4: nibble = 4; break;
case Qt::Key_5: nibble = 5; break;
case Qt::Key_6: nibble = 6; break;
case Qt::Key_7: nibble = 7; break;
case Qt::Key_8: nibble = 8; break;
case Qt::Key_9: nibble = 9; break;
case Qt::Key_A: nibble = 10; break;
case Qt::Key_B: nibble = 11; break;
case Qt::Key_C: nibble = 12; break;
case Qt::Key_D: nibble = 13; break;
case Qt::Key_E: nibble = 14; break;
case Qt::Key_F: nibble = 15; break;
default: {
//allow navigation keys to move cursor, but block text input
qtHexEdit->setTextInteractionFlags(Qt::TextInteractionFlags(
Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse
));
qtHexEdit->keyPressEventAcknowledge(event);
qtHexEdit->setTextInteractionFlags(Qt::TextEditorInteraction);
return;
}
}
if(cursorX >= 10) {
//not on an offset
cursorX -= 10;
if((cursorX % 3) != 2) {
//not on a space
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
cursorX /= 3;
if(cursorX < hexEdit.state.columns) {
//not in ANSI region
unsigned offset = hexEdit.state.offset + (cursorY * hexEdit.state.columns + cursorX);
if(offset >= hexEdit.state.length) return; //do not edit past end of file
uint8_t data = hexEdit.onRead(offset);
//write modified value
if(cursorNibble == 1) {
data = (data & 0xf0) | (nibble << 0);
} else {
data = (data & 0x0f) | (nibble << 4);
}
if(hexEdit.onWrite) hexEdit.onWrite(offset, data);
//auto-advance cursor to next nibble/byte
unsigned step = 1;
if(cursorNibble && cursorX != hexEdit.state.columns - 1) step = 2;
cursor.setPosition(cursor.position() + step);
qtHexEdit->setTextCursor(cursor);
//refresh output to reflect modified data
update();
}
}
}
}
void pHexEdit::QtHexEdit::keyPressEvent(QKeyEvent *event) {
self.keyPressEvent(event);
}
void pHexEdit::QtHexEdit::keyPressEventAcknowledge(QKeyEvent *event) {
QTextEdit::keyPressEvent(event);
}

View File

@ -1,168 +0,0 @@
void HexEditor::setSize(unsigned size) {
hexEditor->size = size;
bool indivisible = (hexEditor->size % hexEditor->columns) != 0; //add one for incomplete row
hexEditor->scrollBar->setRange(0, hexEditor->size / hexEditor->columns + indivisible - hexEditor->rows);
}
void HexEditor::setOffset(unsigned offset) {
object->locked = true;
hexEditor->offset = offset;
hexEditor->scrollBar->setSliderPosition(hexEditor->offset / hexEditor->columns);
object->locked = false;
}
void HexEditor::setColumns(unsigned columns) {
hexEditor->columns = columns;
}
void HexEditor::setRows(unsigned rows) {
hexEditor->rows = rows;
hexEditor->scrollBar->setPageStep(hexEditor->rows);
}
void HexEditor::update() {
if(!onRead) {
hexEditor->setPlainText("");
return;
}
unsigned cursorPosition = hexEditor->textCursor().position();
string output;
unsigned offset = hexEditor->offset;
for(unsigned row = 0; row < hexEditor->rows; row++) {
output.append(hex<8>(offset));
output.append(" ");
string hexdata;
string ansidata = " ";
for(unsigned column = 0; column < hexEditor->columns; column++) {
if(offset < hexEditor->size) {
uint8_t data = onRead(offset++);
hexdata.append(hex<2>(data));
hexdata.append(" ");
char buffer[2] = { data >= 0x20 && data <= 0x7e ? (char)data : '.', 0 };
ansidata.append(buffer);
} else {
hexdata.append(" ");
ansidata.append(" ");
}
}
output.append(hexdata);
output.append(ansidata);
if(offset >= hexEditor->size) break;
if(row != hexEditor->rows - 1) output.append("\n");
}
hexEditor->setPlainText((const char*)output);
QTextCursor cursor = hexEditor->textCursor();
cursor.setPosition(cursorPosition);
hexEditor->setTextCursor(cursor);
}
void HexEditor::Data::keyPressEvent(QKeyEvent *event) {
if(!self.onRead || !self.onWrite) return;
QTextCursor cursor = textCursor();
unsigned lineWidth = 10 + (columns * 3) + 1 + (columns) + 1;
unsigned cursorY = cursor.position() / lineWidth;
unsigned cursorX = cursor.position() % lineWidth;
unsigned nibble;
switch(event->key()) {
case Qt::Key_0: nibble = 0; break;
case Qt::Key_1: nibble = 1; break;
case Qt::Key_2: nibble = 2; break;
case Qt::Key_3: nibble = 3; break;
case Qt::Key_4: nibble = 4; break;
case Qt::Key_5: nibble = 5; break;
case Qt::Key_6: nibble = 6; break;
case Qt::Key_7: nibble = 7; break;
case Qt::Key_8: nibble = 8; break;
case Qt::Key_9: nibble = 9; break;
case Qt::Key_A: nibble = 10; break;
case Qt::Key_B: nibble = 11; break;
case Qt::Key_C: nibble = 12; break;
case Qt::Key_D: nibble = 13; break;
case Qt::Key_E: nibble = 14; break;
case Qt::Key_F: nibble = 15; break;
default: {
//allow navigation keys to move cursor, but block text input
setTextInteractionFlags(Qt::TextInteractionFlags(
Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse
));
QTextEdit::keyPressEvent(event);
setTextInteractionFlags(Qt::TextEditorInteraction);
return;
}
}
if(cursorX >= 10) {
//not on an offset
cursorX -= 10;
if((cursorX % 3) != 2) {
//not on a space
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
cursorX /= 3;
if(cursorX < columns) {
//not in ANSI region
unsigned currentOffset = offset + (cursorY * columns + cursorX);
if(currentOffset >= size) return; //do not edit past end of file
uint8_t data = self.onRead(currentOffset);
//write modified value
if(cursorNibble == 1) {
data = (data & 0xf0) | (nibble << 0);
} else {
data = (data & 0x0f) | (nibble << 4);
}
self.onWrite(currentOffset, data);
//auto-advance cursor to next nibble/byte
unsigned step = 1;
if(cursorNibble && cursorX != columns - 1) step = 2;
cursor.setPosition(cursor.position() + step);
setTextCursor(cursor);
//refresh output to reflect modified data
self.update();
}
}
}
}
void HexEditor::Data::scrollEvent() {
if(self.object->locked) return;
unsigned currentOffset = scrollBar->sliderPosition();
offset = currentOffset * columns;
self.update();
}
HexEditor::HexEditor() {
hexEditor = new HexEditor::Data(*this);
widget->widget = hexEditor;
hexEditor->size = 0;
hexEditor->offset = 0;
hexEditor->columns = 16;
hexEditor->rows = 16;
hexEditor->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
hexEditor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
hexEditor->layout = new QHBoxLayout;
hexEditor->layout->setAlignment(Qt::AlignRight);
hexEditor->layout->setMargin(0);
hexEditor->layout->setSpacing(0);
hexEditor->setLayout(hexEditor->layout);
hexEditor->scrollBar = new QScrollBar(Qt::Vertical);
hexEditor->scrollBar->setSingleStep(1);
hexEditor->layout->addWidget(hexEditor->scrollBar);
hexEditor->scrollBar->connect(
hexEditor->scrollBar, SIGNAL(actionTriggered(int)), hexEditor, SLOT(scrollEvent())
);
}

View File

@ -1,19 +1,25 @@
void HorizontalSlider::setLength(unsigned length) {
length = length + (length == 0);
horizontalSlider->setRange(0, length - 1);
horizontalSlider->setPageStep(length >> 3);
unsigned pHorizontalSlider::position() {
return qtSlider->value();
}
unsigned HorizontalSlider::position() {
return horizontalSlider->value();
void pHorizontalSlider::setLength(unsigned length) {
length += length == 0;
qtSlider->setRange(0, length - 1);
qtSlider->setPageStep(length >> 3);
}
void HorizontalSlider::setPosition(unsigned position) {
horizontalSlider->setValue(position);
void pHorizontalSlider::setPosition(unsigned position) {
qtSlider->setValue(position);
}
HorizontalSlider::HorizontalSlider() {
horizontalSlider = new HorizontalSlider::Data(*this);
widget->widget = horizontalSlider;
horizontalSlider->connect(horizontalSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
pHorizontalSlider::pHorizontalSlider(HorizontalSlider &horizontalSlider) : horizontalSlider(horizontalSlider), pWidget(horizontalSlider) {
qtWidget = qtSlider = new QSlider(Qt::Horizontal);
qtSlider->setRange(0, 100);
qtSlider->setPageStep(101 >> 3);
connect(qtSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
}
void pHorizontalSlider::onChange() {
horizontalSlider.state.position = position();
if(horizontalSlider.onChange) horizontalSlider.onChange();
}

View File

@ -1,8 +1,7 @@
void Label::setText(const string &text) {
label->setText(QString::fromUtf8(text));
void pLabel::setText(const string &text) {
qtLabel->setText(QString::fromUtf8(text));
}
Label::Label() {
label = new Label::Data(*this);
widget->widget = label;
pLabel::pLabel(Label &label) : label(label), pWidget(label) {
qtWidget = qtLabel = new QLabel;
}

View File

@ -0,0 +1,26 @@
void pLineEdit::setEditable(bool editable) {
qtLineEdit->setReadOnly(!editable);
}
void pLineEdit::setText(const string &text) {
qtLineEdit->setText(QString::fromUtf8(text));
}
string pLineEdit::text() {
return qtLineEdit->text().toUtf8().constData();
}
pLineEdit::pLineEdit(LineEdit &lineEdit) : lineEdit(lineEdit), pWidget(lineEdit) {
qtWidget = qtLineEdit = new QLineEdit;
connect(qtLineEdit, SIGNAL(returnPressed()), SLOT(onActivate()));
connect(qtLineEdit, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
}
void pLineEdit::onActivate() {
if(lineEdit.onActivate) lineEdit.onActivate();
}
void pLineEdit::onChange() {
lineEdit.state.text = text();
if(lineEdit.onChange) lineEdit.onChange();
}

View File

@ -1,97 +1,120 @@
void ListBox::setHeaderText(const string &text) {
lstring list;
list.split("\t", text);
QStringList labels;
foreach(item, list) labels << QString::fromUtf8(item);
listBox->setColumnCount(list.size());
listBox->setHeaderLabels(labels);
for(unsigned i = 0; i < list.size(); i++) listBox->resizeColumnToContents(i);
listBox->setAlternatingRowColors(list.size() >= 2);
void pListBox::append(const lstring &text) {
locked = true;
auto items = qtListBox->findItems("", Qt::MatchContains);
QTreeWidgetItem *item = new QTreeWidgetItem(qtListBox);
item->setData(0, Qt::UserRole, (unsigned)items.size());
if(listBox.state.checkable) item->setCheckState(0, Qt::Unchecked);
for(unsigned n = 0; n < text.size(); n++) {
item->setText(n, QString::fromUtf8(text[n]));
}
locked = false;
}
void ListBox::setHeaderVisible(bool headerVisible) {
listBox->setHeaderHidden(headerVisible == false);
void pListBox::autosizeColumns() {
for(unsigned n = 0; n < listBox.state.headerText.size(); n++) qtListBox->resizeColumnToContents(n);
}
void ListBox::setCheckable(bool checkable) {
listBox->checkable = checkable;
if(listBox->checkable) {
auto items = listBox->findItems("", Qt::MatchContains);
for(unsigned i = 0; i < items.size(); i++) items[i]->setCheckState(0, Qt::Unchecked);
bool pListBox::checked(unsigned row) {
QTreeWidgetItem *item = qtListBox->topLevelItem(row);
return item ? item->checkState(0) == Qt::Checked : false;
}
void pListBox::modify(unsigned row, const lstring &text) {
QTreeWidgetItem *item = qtListBox->topLevelItem(row);
if(!item) return;
for(unsigned n = 0; n < text.size(); n++) {
item->setText(n, QString::fromUtf8(text[n]));
}
}
void ListBox::reset() {
listBox->clear();
void pListBox::modify(unsigned row, unsigned column, const string &text) {
QTreeWidgetItem *item = qtListBox->topLevelItem(row);
if(!item) return;
item->setText(column, QString::fromUtf8(text));
}
void ListBox::resizeColumnsToContent() {
for(unsigned i = 0; i < listBox->columnCount(); i++) listBox->resizeColumnToContents(i);
void pListBox::reset() {
qtListBox->clear();
}
void ListBox::addItem(const string &text) {
object->locked = true;
auto items = listBox->findItems("", Qt::MatchContains);
QTreeWidgetItem *item = new QTreeWidgetItem(listBox);
if(listBox->checkable) item->setCheckState(0, Qt::Unchecked);
item->setData(0, Qt::UserRole, (unsigned)items.size());
lstring list;
list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, QString::fromUtf8(list[i]));
object->locked = false;
}
void ListBox::setItem(unsigned row, const string &text) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row);
lstring list;
list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) item->setText(i, QString::fromUtf8(list[i]));
object->locked = false;
}
bool ListBox::checked(unsigned row) {
QTreeWidgetItem *item = listBox->topLevelItem(row);
return (item ? item->checkState(0) == Qt::Checked : false);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
QTreeWidgetItem *item = listBox->topLevelItem(row);
if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
object->locked = false;
}
optional<unsigned> ListBox::selection() {
QTreeWidgetItem *item = listBox->currentItem();
optional<unsigned> pListBox::selection() {
QTreeWidgetItem *item = qtListBox->currentItem();
if(item == 0) return { false, 0 };
if(item->isSelected() == false) return { false, 0 };
unsigned row = item->data(0, Qt::UserRole).toUInt();
return { true, row };
return { true, item->data(0, Qt::UserRole).toUInt() };
}
void ListBox::setSelection(unsigned row) {
object->locked = true;
QTreeWidgetItem *item = listBox->currentItem();
void pListBox::setCheckable(bool checkable) {
if(checkable) {
auto items = qtListBox->findItems("", Qt::MatchContains);
for(unsigned n = 0; n < items.size(); n++) items[n]->setCheckState(0, Qt::Unchecked);
}
}
void pListBox::setChecked(unsigned row, bool checked) {
locked = true;
QTreeWidgetItem *item = qtListBox->topLevelItem(row);
if(item) item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
locked = false;
}
void pListBox::setHeaderText(const lstring &text) {
QStringList labels;
foreach(column, text) labels << QString::fromUtf8(column);
qtListBox->setColumnCount(text.size());
qtListBox->setAlternatingRowColors(text.size() >= 2);
qtListBox->setHeaderLabels(labels);
autosizeColumns();
}
void pListBox::setHeaderVisible(bool visible) {
qtListBox->setHeaderHidden(!visible);
autosizeColumns();
}
void pListBox::setSelection(unsigned row) {
locked = true;
QTreeWidgetItem *item = qtListBox->currentItem();
if(item) item->setSelected(false);
auto items = listBox->findItems("", Qt::MatchContains);
for(unsigned i = 0; i < items.size(); i++) {
if(items[i]->data(0, Qt::UserRole).toUInt() == row) {
listBox->setCurrentItem(items[i]);
auto items = qtListBox->findItems("", Qt::MatchContains);
for(unsigned n = 0; n < items.size(); n++) {
if(items[n]->data(0, Qt::UserRole).toUInt() == row) {
qtListBox->setCurrentItem(items[n]);
break;
}
}
object->locked = false;
locked = false;
}
ListBox::ListBox() {
listBox = new ListBox::Data(*this);
widget->widget = listBox;
pListBox::pListBox(ListBox &listBox) : listBox(listBox), pWidget(listBox) {
qtWidget = qtListBox = new QTreeWidget;
qtListBox->setHeaderLabels(QStringList() << "");
qtListBox->setHeaderHidden(true);
qtListBox->setAllColumnsShowFocus(true);
qtListBox->setRootIsDecorated(false);
listBox->setAllColumnsShowFocus(true);
listBox->setRootIsDecorated(false);
listBox->setHeaderHidden(true);
listBox->connect(listBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
listBox->connect(listBox, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
listBox->connect(listBox, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
connect(qtListBox, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
connect(qtListBox, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
connect(qtListBox, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
}
void pListBox::onActivate() {
if(locked == false && listBox.onActivate) listBox.onActivate();
}
void pListBox::onChange() {
if(auto position = selection()) {
listBox.state.selection = { true, position() };
} else {
listBox.state.selection = { false, 0 };
}
if(locked == false && listBox.onChange) listBox.onChange();
}
void pListBox::onTick(QTreeWidgetItem *item) {
unsigned row = item->data(0, Qt::UserRole).toUInt();
bool checkState = checked(row);
listBox.state.checked[row] = checkState;
if(locked == false && listBox.onTick) listBox.onTick(row);
}

View File

@ -1,10 +1,9 @@
void ProgressBar::setPosition(unsigned position) {
progressBar->setValue(position);
void pProgressBar::setPosition(unsigned position) {
qtProgressBar->setValue(position);
}
ProgressBar::ProgressBar() {
progressBar = new ProgressBar::Data(*this);
widget->widget = progressBar;
progressBar->setRange(0, 100);
progressBar->setTextVisible(false);
pProgressBar::pProgressBar(ProgressBar &progressBar) : progressBar(progressBar), pWidget(progressBar) {
qtWidget = qtProgressBar = new QProgressBar;
qtProgressBar->setRange(0, 100);
qtProgressBar->setTextVisible(false);
}

View File

@ -1,25 +1,43 @@
void RadioBox::setParent(RadioBox &parent) {
parent.radioBox->buttonGroup->addButton(radioBox);
parent.radioBox->setChecked(true);
bool pRadioBox::checked() {
return qtRadioBox->isChecked();
}
void RadioBox::setText(const string &text) {
radioBox->setText(QString::fromUtf8(text));
void pRadioBox::setChecked() {
locked = true;
foreach(item, radioBox.state.group) {
bool checkState = item->p.qtRadioBox == qtRadioBox;
item->state.checked = checkState;
item->p.qtRadioBox->setChecked(checkState);
}
locked = false;
}
bool RadioBox::checked() {
return radioBox->isChecked();
void pRadioBox::setGroup(const array<RadioBox*> &group) {
locked = true;
if(qtGroup) {
delete qtGroup;
qtGroup = 0;
}
if(qtRadioBox == group[0]->p.qtRadioBox) {
qtGroup = new QButtonGroup;
foreach(item, group) qtGroup->addButton(item->p.qtRadioBox);
setChecked();
}
locked = false;
}
void RadioBox::setChecked() {
radioBox->setChecked(true);
void pRadioBox::setText(const string &text) {
qtRadioBox->setText(QString::fromUtf8(text));
}
RadioBox::RadioBox() {
radioBox = new RadioBox::Data(*this);
widget->widget = radioBox;
radioBox->buttonGroup = new QButtonGroup;
radioBox->buttonGroup->addButton(radioBox);
radioBox->setChecked(true);
radioBox->connect(radioBox, SIGNAL(toggled(bool)), SLOT(onTick()));
pRadioBox::pRadioBox(RadioBox &radioBox) : radioBox(radioBox), pWidget(radioBox) {
qtWidget = qtRadioBox = new QRadioButton;
qtGroup = new QButtonGroup;
qtGroup->addButton(qtRadioBox);
qtRadioBox->setChecked(true);
connect(qtRadioBox, SIGNAL(toggled(bool)), SLOT(onTick()));
}
void pRadioBox::onTick() {
if(locked == false && checked() && radioBox.onTick) radioBox.onTick();
}

View File

@ -1,18 +0,0 @@
void TextBox::setEditable(bool editable) {
textBox->setReadOnly(editable == false);
}
string TextBox::text() {
return textBox->text().toUtf8().constData();
}
void TextBox::setText(const string &text) {
textBox->setText(QString::fromUtf8(text));
}
TextBox::TextBox() {
textBox = new TextBox::Data(*this);
widget->widget = textBox;
textBox->connect(textBox, SIGNAL(returnPressed()), SLOT(onActivate()));
textBox->connect(textBox, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
}

View File

@ -0,0 +1,32 @@
void pTextEdit::setCursorPosition(unsigned position) {
QTextCursor cursor = qtTextEdit->textCursor();
unsigned lastCharacter = strlen(qtTextEdit->toPlainText().toUtf8().constData());
cursor.setPosition(min(position, lastCharacter));
qtTextEdit->setTextCursor(cursor);
}
void pTextEdit::setEditable(bool editable) {
qtTextEdit->setReadOnly(!editable);
}
void pTextEdit::setText(const string &text) {
qtTextEdit->setPlainText(QString::fromUtf8(text));
}
void pTextEdit::setWordWrap(bool wordWrap) {
qtTextEdit->setWordWrapMode(wordWrap ? QTextOption::WordWrap : QTextOption::NoWrap);
}
string pTextEdit::text() {
return qtTextEdit->toPlainText().toUtf8().constData();
}
pTextEdit::pTextEdit(TextEdit &textEdit) : textEdit(textEdit), pWidget(textEdit) {
qtWidget = qtTextEdit = new QTextEdit;
connect(qtTextEdit, SIGNAL(textChanged()), SLOT(onChange()));
}
void pTextEdit::onChange() {
textEdit.state.text = text();
if(textEdit.onChange) textEdit.onChange();
}

View File

@ -1,21 +1,25 @@
void VerticalSlider::setLength(unsigned length) {
length = length + (length == 0);
verticalSlider->setRange(0, length - 1);
verticalSlider->setPageStep(length >> 3);
unsigned pVerticalSlider::position() {
return qtSlider->value();
}
unsigned VerticalSlider::position() {
return verticalSlider->value();
void pVerticalSlider::setLength(unsigned length) {
length += length == 0;
qtSlider->setRange(0, length - 1);
qtSlider->setPageStep(length >> 3);
}
void VerticalSlider::setPosition(unsigned position) {
verticalSlider->setValue(position);
void pVerticalSlider::setPosition(unsigned position) {
qtSlider->setValue(position);
}
VerticalSlider::VerticalSlider() {
verticalSlider = new VerticalSlider::Data(*this);
widget->widget = verticalSlider;
verticalSlider->setInvertedAppearance(true);
verticalSlider->setInvertedControls(true);
verticalSlider->connect(verticalSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
pVerticalSlider::pVerticalSlider(VerticalSlider &verticalSlider) : verticalSlider(verticalSlider), pWidget(verticalSlider) {
qtWidget = qtSlider = new QSlider(Qt::Vertical);
qtSlider->setRange(0, 100);
qtSlider->setPageStep(101 >> 3);
connect(qtSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
}
void pVerticalSlider::onChange() {
verticalSlider.state.position = position();
if(verticalSlider.onChange) verticalSlider.onChange();
}

View File

@ -1,10 +1,9 @@
uintptr_t Viewport::handle() {
return (uintptr_t)viewport->winId();
uintptr_t pViewport::handle() {
return (uintptr_t)qtWidget->winId();
}
Viewport::Viewport() {
viewport = new Viewport::Data(*this);
widget->widget = viewport;
viewport->setAttribute(Qt::WA_PaintOnScreen, true);
viewport->setStyleSheet("background: #000000");
pViewport::pViewport(Viewport &viewport) : viewport(viewport), pWidget(viewport) {
qtWidget = new QWidget;
qtWidget->setAttribute(Qt::WA_PaintOnScreen, true);
qtWidget->setStyleSheet("background: #000000");
}

View File

@ -1,43 +1,26 @@
Geometry Widget::geometry() {
return {
widget->widget->x(), widget->widget->y(),
widget->widget->width(), widget->widget->height()
};
bool pWidget::enabled() {
return qtWidget->isEnabled();
}
void Widget::setGeometry(unsigned x, unsigned y, unsigned width, unsigned height) {
widget->widget->setGeometry(x, y, width, height);
void pWidget::setEnabled(bool enabled) {
qtWidget->setEnabled(enabled);
}
void Widget::setFont(Font &font) {
widget->font = &font;
widget->widget->setFont(*font.font);
void pWidget::setFocused() {
qtWidget->setFocus(Qt::OtherFocusReason);
}
bool Widget::visible() {
return widget->widget->isVisible();
void pWidget::setFont(Font &font) {
qtWidget->setFont(*font.p.qtFont);
}
void Widget::setVisible(bool visible) {
widget->widget->setVisible(visible);
void pWidget::setGeometry(const Geometry &geometry) {
qtWidget->setGeometry(geometry.x, geometry.y, geometry.width, geometry.height);
}
bool Widget::enabled() {
return widget->widget->isEnabled();
void pWidget::setVisible(bool visible) {
qtWidget->setVisible(visible);
}
void Widget::setEnabled(bool enabled) {
widget->widget->setEnabled(enabled);
}
bool Widget::focused() {
return widget->widget->hasFocus();
}
void Widget::setFocused() {
widget->widget->setFocus(Qt::OtherFocusReason);
}
Widget::Widget() {
widget = new Widget::Data(*this);
pWidget::pWidget(Widget &widget) : widget(widget) {
}

View File

@ -1,191 +1,222 @@
void Window::append(Menu &menu) {
menu.menu->parent = this;
if(window->defaultFont) menu.menu->setFont(*window->defaultFont);
window->menuBar->addMenu(menu.menu);
void pWindow::append(Menu &menu) {
qtMenu->addMenu(menu.p.qtMenu);
}
void Window::setLayout(Layout &layout) {
window->layout = &layout;
Geometry geom = geometry();
geom.x = geom.y = 0;
layout.setParent(*this);
layout.setGeometry(geom);
}
void Window::setResizable(bool resizable) {
window->resizable = resizable;
if(window->resizable) {
window->vlayout->setSizeConstraint(QLayout::SetDefaultConstraint);
window->container->setMinimumSize(window->width, window->height);
} else {
window->vlayout->setSizeConstraint(QLayout::SetFixedSize);
window->container->setFixedSize(window->width, window->height);
}
}
Geometry Window::frameGeometry() {
if(window->fullscreen) return { 0, 0, OS::desktopWidth(), OS::desktopHeight() };
Geometry pWindow::frameGeometry() {
if(window.state.fullScreen) return { 0, 0, OS::desktopWidth(), OS::desktopHeight() };
return {
window->x - settings.frameGeometryX, window->y - settings.frameGeometryY,
window->width + settings.frameGeometryWidth, window->height + settings.frameGeometryHeight
window.state.geometry.x - settings.frameGeometryX,
window.state.geometry.y - settings.frameGeometryY,
window.state.geometry.width + settings.frameGeometryWidth,
window.state.geometry.height + settings.frameGeometryHeight
};
}
Geometry Window::geometry() {
if(window->fullscreen) return { 0, 0, OS::desktopWidth(), OS::desktopHeight() };
return { window->x, window->y, window->width, window->height };
bool pWindow::focused() {
return qtWindow->isActiveWindow() && !qtWindow->isMinimized();
}
void Window::setFrameGeometry(signed x, signed y, unsigned width, unsigned height) {
setGeometry(
x + settings.frameGeometryX, y + settings.frameGeometryY,
width - settings.frameGeometryWidth, height - settings.frameGeometryHeight
);
Geometry pWindow::geometry() {
if(window.state.fullScreen) {
unsigned width = OS::desktopWidth(), height = OS::desktopHeight();
if(window.state.menuVisible) height -= qtMenu->height();
if(window.state.statusVisible) height -= qtStatus->height();
return { 0, 0, width, height };
}
return window.state.geometry;
}
void Window::setGeometry(signed x, signed y, unsigned width, unsigned height) {
object->locked = true;
window->x = x;
window->y = y;
window->width = width;
window->height = height;
setResizable(window->resizable);
window->move(x - settings.frameGeometryX, y - settings.frameGeometryY);
window->adjustSize();
object->locked = false;
}
void Window::setDefaultFont(Font &font) {
window->defaultFont = font.font;
window->menuBar->setFont(*font.font);
}
void Window::setFont(Font &font) {
window->statusBar->setFont(*font.font);
}
void Window::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
void pWindow::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) {
QPalette palette;
palette.setColor(QPalette::Window, QColor(red, green, blue));
window->container->setPalette(palette);
window->container->setAutoFillBackground(true);
qtContainer->setPalette(palette);
qtContainer->setAutoFillBackground(true);
}
void Window::setTitle(const string &text) {
window->setWindowTitle(QString::fromUtf8(text));
void pWindow::setFrameGeometry(const Geometry &geometry) {
window.state.geometry = {
geometry.x + settings.frameGeometryX,
geometry.y + settings.frameGeometryY,
geometry.width - settings.frameGeometryWidth,
geometry.height - settings.frameGeometryHeight
};
if(window.state.menuVisible) window.state.geometry.height -= qtMenu->height();
if(window.state.statusVisible) window.state.geometry.height -= qtStatus->height();
setGeometry(window.state.geometry);
}
void Window::setStatusText(const string &text) {
window->statusBar->showMessage(QString::fromUtf8(text), 0);
void pWindow::setFocused() {
qtWindow->raise();
qtWindow->activateWindow();
}
void Window::setVisible(bool visible) {
object->locked = true;
void pWindow::setFullScreen(bool fullScreen) {
if(fullScreen == false) {
setResizable(window.state.resizable);
qtWindow->showNormal();
qtWindow->adjustSize();
} else {
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
qtContainer->setFixedSize(OS::desktopWidth(), OS::desktopHeight());
qtWindow->showFullScreen();
if(window.state.statusVisible) setStatusVisible(true); //work around for Qt/Xlib bug
}
}
void pWindow::setGeometry(const Geometry &geometry_) {
locked = true;
Geometry geometry = geometry_;
setResizable(window.state.resizable);
qtWindow->move(geometry.x - settings.frameGeometryX, geometry.y - settings.frameGeometryY);
qtWindow->adjustSize();
geometry.x = geometry.y = 0;
if(layout) layout->setGeometry(geometry);
locked = false;
}
void pWindow::setLayout(Layout &layout) {
this->layout = &layout;
layout.p.parent = this;
layout.setParent(window);
Geometry geometry = window.state.geometry;
geometry.x = geometry.y = 0;
layout.setGeometry(geometry);
}
void pWindow::setMenuFont(Font &font) {
qtMenu->setFont(*font.p.qtFont);
}
void pWindow::setMenuVisible(bool visible) {
qtMenu->setVisible(visible);
setGeometry(window.state.geometry);
}
void pWindow::setResizable(bool resizable) {
if(resizable) {
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
qtContainer->setMinimumSize(window.state.geometry.width, window.state.geometry.height);
} else {
qtLayout->setSizeConstraint(QLayout::SetFixedSize);
qtContainer->setFixedSize(window.state.geometry.width, window.state.geometry.height);
}
qtStatus->setSizeGripEnabled(resizable);
}
void pWindow::setStatusFont(Font &font) {
qtStatus->setFont(*font.p.qtFont);
}
void pWindow::setStatusText(const string &text) {
qtStatus->showMessage(QString::fromUtf8(text), 0);
}
void pWindow::setStatusVisible(bool visible) {
qtStatus->setVisible(visible);
setGeometry(window.state.geometry);
}
void pWindow::setTitle(const string &text) {
qtWindow->setWindowTitle(QString::fromUtf8(text));
}
void pWindow::setVisible(bool visible) {
locked = true;
qtWindow->setVisible(visible);
if(visible) {
window->show();
updateFrameGeometry();
setGeometry(window->x, window->y, window->width, window->height);
} else {
window->hide();
setGeometry(window.state.geometry);
}
object->locked = false;
locked = false;
}
void Window::setMenuVisible(bool visible) {
window->menuVisible = visible;
if(visible) window->menuBar->show();
else window->menuBar->hide();
pWindow::pWindow(Window &window) : window(window) {
layout = 0;
qtWindow = new QtWindow(*this);
qtWindow->setWindowTitle(" ");
qtLayout = new QVBoxLayout(qtWindow);
qtLayout->setMargin(0);
qtLayout->setSpacing(0);
qtWindow->setLayout(qtLayout);
qtMenu = new QMenuBar(qtWindow);
if(OS::state->defaultFont) qtMenu->setFont(*OS::state->defaultFont->p.qtFont);
qtMenu->setVisible(false);
qtLayout->addWidget(qtMenu);
qtContainer = new QWidget(qtWindow);
qtContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
qtContainer->setVisible(true);
qtLayout->addWidget(qtContainer);
qtStatus = new QStatusBar(qtWindow);
if(OS::state->defaultFont) qtStatus->setFont(*OS::state->defaultFont->p.qtFont);
qtStatus->setSizeGripEnabled(true);
qtStatus->setVisible(false);
qtLayout->addWidget(qtStatus);
setGeometry(window.state.geometry);
}
void Window::setStatusVisible(bool visible) {
window->statusVisible = visible;
if(visible) window->statusBar->show();
else window->statusBar->hide();
}
bool Window::focused() {
return window->isActiveWindow() && !window->isMinimized();
}
bool Window::fullscreen() {
return window->isFullScreen();
}
void Window::setFullscreen(bool fullscreen) {
window->fullscreen = fullscreen;
if(fullscreen == false) {
setResizable(window->resizable);
window->showNormal();
window->adjustSize();
} else {
window->vlayout->setSizeConstraint(QLayout::SetDefaultConstraint);
window->container->setFixedSize(OS::desktopWidth(), OS::desktopHeight());
window->showFullScreen();
void pWindow::updateFrameGeometry() {
if(window.state.fullScreen == false) for(unsigned n = 0; n < 100; n++) {
if(qtWindow->geometry().x() > qtWindow->frameGeometry().x()) break;
usleep(100);
QApplication::processEvents();
}
}
Window::Window() {
window = new Window::Data(*this);
window->defaultFont = 0;
window->vlayout = new QVBoxLayout(window);
window->vlayout->setMargin(0);
window->vlayout->setSpacing(0);
window->setLayout(window->vlayout);
window->menuBar = new QMenuBar(window);
window->menuBar->setVisible(false);
window->vlayout->addWidget(window->menuBar);
window->container = new QWidget(window);
window->container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
window->container->setVisible(true);
window->vlayout->addWidget(window->container);
window->statusBar = new QStatusBar(window);
window->statusBar->setSizeGripEnabled(false);
window->statusBar->setVisible(false);
window->vlayout->addWidget(window->statusBar);
setGeometry(128, 128, 256, 256);
}
//
void Window::updateFrameGeometry() {
//Qt does not even attempt to cache frameGeometry, so if this is called before
//a window is visible onscreen, it is equivalent to geometry(). Without proper
//frameGeometry, phoenix's set(Frame)Geometry functions will not work
//properly. Attempting to detect frame geometry after the window is visible
//would require moving a visible window, causing a slight jitter effect.
//This routine is called every time a new window is shown, and attempts to
//cache frame geometry for the next set(Frame)Geometry call. The information
//is stored to disk, so that hopefully a phoenix window will never jitter more
//than once.
//The information is constantly updated after each window show to detect theme
//changes that may adjust frame geometry.
if(window->fullscreen == false) {
for(unsigned n = 0; n < 100; n++) {
if(window->geometry().x() > window->frameGeometry().x()) break;
usleep(100);
QApplication::processEvents();
}
}
QRect border = window->frameGeometry();
QRect client = window->geometry();
QRect border = qtWindow->frameGeometry();
QRect client = qtWindow->geometry();
settings.frameGeometryX = client.x() - border.x();
settings.frameGeometryY = client.y() - border.y();
settings.frameGeometryWidth = border.width() - client.width();
settings.frameGeometryHeight = border.height() - client.height();
}
void pWindow::QtWindow::closeEvent(QCloseEvent *event) {
event->ignore();
hide();
if(self.window.onClose) self.window.onClose();
}
void pWindow::QtWindow::moveEvent(QMoveEvent *event) {
if(self.locked == false && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) {
self.window.state.geometry.x += event->pos().x() - event->oldPos().x();
self.window.state.geometry.y += event->pos().y() - event->oldPos().y();
}
if(self.locked == false) {
if(self.window.onMove) self.window.onMove();
}
}
void pWindow::QtWindow::resizeEvent(QResizeEvent*) {
if(self.locked == false && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) {
self.window.state.geometry.width = self.qtContainer->geometry().width();
self.window.state.geometry.height = self.qtContainer->geometry().height();
}
if(self.layout) {
Geometry geometry = self.geometry();
geometry.x = geometry.y = 0;
self.layout->setGeometry(geometry);
}
if(self.locked == false) {
if(self.window.onSize) self.window.onSize();
}
}
QSize pWindow::QtWindow::sizeHint() const {
unsigned width = self.window.state.geometry.width;
unsigned height = self.window.state.geometry.height;
if(self.window.state.menuVisible) height += self.qtMenu->height();
if(self.window.state.statusVisible) height += self.qtStatus->height();
return QSize(width, height);
}

8
bsnes/phoenix/sync.sh Executable file
View File

@ -0,0 +1,8 @@
synchronize() {
if [ -d ../"$1" ]; then
test -d "$1" && rm -r "$1"
cp -r ../"$1" ./"$1"
fi
}
synchronize "nall"

View File

@ -1,4 +0,0 @@
Action::Action() {
OS::os->objects.append(this);
action = new Action::Data;
}

View File

@ -1,30 +0,0 @@
void MenuCheckItem::setText(const string &text) {
action->text = text;
}
bool MenuCheckItem::enabled() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return (info.fState & MFS_GRAYED) == 0;
}
void MenuCheckItem::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}
bool MenuCheckItem::checked() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return info.fState & MFS_CHECKED;
}
void MenuCheckItem::setChecked(bool checked) {
action->checked = checked;
if(action->parent) CheckMenuItem(action->parent->action->menu, object->id, checked ? MF_CHECKED : MF_UNCHECKED);
}

View File

@ -1,16 +0,0 @@
void MenuItem::setText(const string &text) {
action->text = text;
}
bool MenuItem::enabled() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return (info.fState & MFS_GRAYED) == 0;
}
void MenuItem::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}

View File

@ -1,49 +0,0 @@
void MenuRadioItem::setText(const string &text) {
action->text = text;
}
void MenuRadioItem::setParent(MenuRadioItem &parent) {
action->checked = false;
action->radioParent = parent.action->radioParent;
action->radioParent->action->items.append(this);
}
bool MenuRadioItem::enabled() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return (info.fState & MFS_GRAYED) == 0;
}
void MenuRadioItem::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}
bool MenuRadioItem::checked() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return info.fState & MFS_CHECKED;
}
void MenuRadioItem::setChecked() {
action->checked = true;
MenuRadioItem *parent = action->radioParent;
foreach(item, parent->action->items) {
if(action->parent) CheckMenuRadioItem(
action->parent->action->menu,
item->object->id, item->object->id, item->object->id + (item != this),
MF_BYCOMMAND
);
}
}
MenuRadioItem::MenuRadioItem() {
action->radioParent = this;
action->items.append(this);
action->checked = true;
}

View File

@ -1,12 +0,0 @@
bool MenuSeparator::enabled() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parent->action->menu, object->id, false, &info);
return (info.fState & MFS_GRAYED) == 0;
}
void MenuSeparator::setEnabled(bool enabled) {
EnableMenuItem(action->parent->action->menu, object->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}

View File

@ -1,51 +0,0 @@
void Menu::setText(const string &text) {
action->text = text;
}
void Menu::append(Action &item) {
menu->children.append(&item);
}
bool Menu::enabled() {
MENUITEMINFO info;
memset(&info, 0, sizeof(MENUITEMINFO));
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_STATE;
GetMenuItemInfo(action->parentMenu, (UINT_PTR)action->menu, false, &info);
return (info.fState & MFS_GRAYED) == 0;
}
void Menu::setEnabled(bool enabled) {
EnableMenuItem(action->parentMenu, (UINT_PTR)action->menu, MF_BYCOMMAND | (enabled ? MF_ENABLED : MF_GRAYED));
}
Menu::Menu() {
menu = new Menu::Data;
}
//internal
void Menu::create() {
action->menu = CreatePopupMenu();
foreach(child, menu->children) {
child->action->parent = this;
if(dynamic_cast<Menu*>(child)) {
Menu &item = *(Menu*)child;
item.action->parentMenu = action->menu;
item.create();
AppendMenu(action->menu, MF_STRING | MF_POPUP, (UINT_PTR)item.action->menu, utf16_t(item.action->text));
} else if(dynamic_cast<MenuSeparator*>(child)) {
AppendMenu(action->menu, MF_SEPARATOR, child->object->id, L"");
} else if(dynamic_cast<MenuItem*>(child)) {
AppendMenu(action->menu, MF_STRING, child->object->id, utf16_t(child->action->text));
} else if(dynamic_cast<MenuCheckItem*>(child)) {
AppendMenu(action->menu, MF_STRING, child->object->id, utf16_t(child->action->text));
MenuCheckItem &item = *(MenuCheckItem*)child;
if(item.action->checked) item.setChecked();
} else if(dynamic_cast<MenuRadioItem*>(child)) {
AppendMenu(action->menu, MF_STRING, child->object->id, utf16_t(child->action->text));
MenuRadioItem &item = *(MenuRadioItem*)child;
if(item.action->checked) item.setChecked();
}
}
}

View File

@ -1,26 +0,0 @@
static HFONT Font_createFont(const string &name, unsigned size, bool bold, bool italic) {
return CreateFont(
-(size * 96.0 / 72.0 + 0.5),
0, 0, 0, bold == false ? FW_NORMAL : FW_BOLD, italic, 0, 0, 0, 0, 0, 0, 0,
utf16_t(name)
);
}
bool Font::create(const string &name, unsigned size, Font::Style style) {
font->font = Font_createFont(
name, size,
(style & Font::Style::Bold) == Font::Style::Bold,
(style & Font::Style::Italic) == Font::Style::Italic
);
return font->font;
}
Font::Font() {
font = new Font::Data;
font->font = 0;
}
Font::~Font() {
if(font->font) DeleteObject(font->font);
delete font;
}

View File

@ -1,16 +0,0 @@
void Layout::setParent(Window &parent) {
layout->parent = &parent;
}
void Layout::append(Widget &child) {
SetParent(child.widget->window, layout->parent->window->window);
SendMessage(
child.widget->window, WM_SETFONT,
(WPARAM)(layout->parent->window->defaultFont ? layout->parent->window->defaultFont : OS::os->proportionalFont), 0
);
}
Layout::Layout() {
layout = new Layout::Data;
layout->parent = 0;
}

View File

@ -1,41 +0,0 @@
static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons buttons, UINT response) {
if(response == IDOK) return MessageWindow::Response::Ok;
if(response == IDCANCEL) return MessageWindow::Response::Cancel;
if(response == IDYES) return MessageWindow::Response::Yes;
if(response == IDNO) return MessageWindow::Response::No;
if(buttons == MessageWindow::Buttons::OkCancel) return MessageWindow::Response::Cancel;
if(buttons == MessageWindow::Buttons::YesNo) return MessageWindow::Response::No;
return MessageWindow::Response::Ok;
}
MessageWindow::Response MessageWindow::information(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONINFORMATION;
if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
if(buttons == Buttons::YesNo) flags |= MB_YESNO;
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.window->window : 0, utf16_t(text), L"", flags));
}
MessageWindow::Response MessageWindow::question(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONQUESTION;
if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
if(buttons == Buttons::YesNo) flags |= MB_YESNO;
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.window->window : 0, utf16_t(text), L"", flags));
}
MessageWindow::Response MessageWindow::warning(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONWARNING;
if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
if(buttons == Buttons::YesNo) flags |= MB_YESNO;
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.window->window : 0, utf16_t(text), L"", flags));
}
MessageWindow::Response MessageWindow::critical(Window &parent, const string &text, MessageWindow::Buttons buttons) {
UINT flags = MB_ICONERROR;
if(buttons == Buttons::Ok) flags |= MB_OK;
if(buttons == Buttons::OkCancel) flags |= MB_OKCANCEL;
if(buttons == Buttons::YesNo) flags |= MB_YESNO;
return MessageWindow_response(buttons, MessageBox(&parent != &Window::None ? parent.window->window : 0, utf16_t(text), L"", flags));
}

View File

@ -1,134 +0,0 @@
struct Object::Data {
unsigned id;
bool locked;
};
struct Font::Data {
HFONT font;
};
struct Action::Data {
Menu *parent;
HMENU parentMenu;
HMENU menu;
MenuRadioItem *radioParent;
array<MenuRadioItem*> items;
string text;
bool checked;
Data() {
parent = 0;
parentMenu = 0;
menu = 0;
radioParent = 0;
checked = false;
}
};
struct Menu::Data {
array<Action*> children;
};
struct Window::Data {
HWND window;
Layout *layout;
HFONT defaultFont;
HBRUSH brush;
COLORREF brushColor;
HMENU menu;
HWND status;
bool resizable;
bool fullscreen;
unsigned x;
unsigned y;
unsigned width;
unsigned height;
Data() {
window = 0;
layout = 0;
defaultFont = 0;
brush = 0;
brushColor = 0;
menu = 0;
status = 0;
resizable = true;
fullscreen = false;
x = y = 0;
width = height = 0;
}
};
struct Widget::Data {
HWND window;
HFONT font;
};
struct Layout::Data {
Window *parent;
};
struct Canvas::Data {
uint32_t *buffer;
BITMAPINFO bmi;
unsigned pitch;
unsigned width;
unsigned height;
};
struct ComboBox::Data {
unsigned selection;
};
struct EditBox::Data {
bool wordWrap;
unsigned x;
unsigned y;
unsigned width;
unsigned height;
};
struct HexEditor::Data {
LRESULT CALLBACK (*windowProc)(HWND, UINT, LPARAM, WPARAM);
unsigned size;
unsigned offset;
unsigned columns;
unsigned rows;
};
struct HorizontalSlider::Data {
unsigned position;
};
struct ListBox::Data {
unsigned columns;
bool lostFocus;
};
struct RadioBox::Data {
Window *parentWindow;
RadioBox *parent;
array<RadioBox*> items;
};
struct VerticalSlider::Data {
unsigned position;
};
struct OS::Data {
nall::array<Object*> objects;
HWND nullWindow;
HFONT proportionalFont;
HFONT monospaceFont;
};
void Object::unused() {
}
Object::Object() {
OS::initialize();
static unsigned guid = 100;
object = new Object::Data;
object->id = guid++;
object->locked = false;
}

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="phoenix" version="1.0.0.0" processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
</assembly>

View File

@ -1 +0,0 @@
1 24 "phoenix.Manifest"

View File

@ -1,13 +0,0 @@
void Button::setText(const string &text) {
SetWindowText(widget->window, utf16_t(text));
}
Button::Button() {
widget->window = CreateWindow(
L"BUTTON", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}

View File

@ -1,60 +0,0 @@
void Canvas::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
canvas->buffer = new uint32_t[width * height]();
canvas->pitch = width * sizeof(uint32_t);
canvas->width = width;
canvas->height = height;
memset(&canvas->bmi, 0, sizeof(BITMAPINFO));
canvas->bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
canvas->bmi.bmiHeader.biPlanes = 1;
canvas->bmi.bmiHeader.biBitCount = 32;
canvas->bmi.bmiHeader.biCompression = BI_RGB;
canvas->bmi.bmiHeader.biWidth = width;
canvas->bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside down; negative height flips bitmap
canvas->bmi.bmiHeader.biSizeImage = canvas->pitch * canvas->height;
widget->window = CreateWindow(
L"phoenix_canvas", L"",
WS_CHILD | WS_VISIBLE,
x, y, width, height,
parent.window->window, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}
uint32_t* Canvas::buffer() {
return canvas->buffer;
}
void Canvas::redraw() {
PAINTSTRUCT ps;
BeginPaint(widget->window, &ps);
SetDIBitsToDevice(ps.hdc, 0, 0, canvas->width, canvas->height, 0, 0, 0, canvas->height, (void*)canvas->buffer, &canvas->bmi, DIB_RGB_COLORS);
EndPaint(widget->window, &ps);
InvalidateRect(widget->window, 0, false);
}
Canvas::Canvas() {
canvas = new Canvas::Data;
canvas->buffer = 0;
}
Canvas::~Canvas() {
delete[] canvas->buffer;
delete canvas;
}
static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch(msg) {
case WM_PAINT: {
Object *object_ptr = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(object_ptr) {
if(dynamic_cast<Canvas*>(object_ptr)) {
Canvas &canvas = (Canvas&)*object_ptr;
canvas.redraw();
}
}
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}

View File

@ -1,21 +0,0 @@
bool CheckBox::checked() {
return SendMessage(widget->window, BM_GETCHECK, 0, 0);
}
void CheckBox::setChecked(bool checked) {
SendMessage(widget->window, BM_SETCHECK, (WPARAM)checked, 0);
}
void CheckBox::setText(const string &text) {
SetWindowText(widget->window, utf16_t(text));
}
CheckBox::CheckBox() {
widget->window = CreateWindow(
L"BUTTON", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}

View File

@ -1,45 +0,0 @@
void ComboBox::reset() {
SendMessage(widget->window, CB_RESETCONTENT, 0, 0);
}
void ComboBox::addItem(const string &text) {
SendMessage(widget->window, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16_t(text));
if(SendMessage(widget->window, CB_GETCOUNT, 0, 0) == 1) setSelection(0);
}
unsigned ComboBox::selection() {
return SendMessage(widget->window, CB_GETCURSEL, 0, 0);
}
void ComboBox::setSelection(unsigned row) {
SendMessage(widget->window, CB_SETCURSEL, comboBox->selection = row, 0);
}
ComboBox::ComboBox() {
comboBox = new ComboBox::Data;
comboBox->selection = 0;
widget->window = CreateWindowEx(
0, L"COMBOBOX", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
0, 0, 64, 200,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
//CreateWindow height parameter is the height of the expanded list box;
//need additional code to override default ComboBox control height
#if 0
RECT rc;
GetWindowRect(widget->window, &rc);
unsigned adjustedHeight = height - ((rc.bottom - rc.top) - SendMessage(widget->window, CB_GETITEMHEIGHT, (WPARAM)-1, 0));
SendMessage(widget->window, CB_SETITEMHEIGHT, (WPARAM)-1, adjustedHeight);
if(*text) {
lstring list;
list.split("\n", text);
foreach(item, list) addItem(item);
}
#endif
}

View File

@ -1,55 +0,0 @@
string EditBox::getText() {
unsigned length = GetWindowTextLength(widget->window);
wchar_t buffer[length + 1];
GetWindowText(widget->window, buffer, length + 1);
buffer[length] = 0;
string text = utf8_t(buffer);
text.replace("\r", "");
return text;
}
void EditBox::setText(const string &text) {
string output = text;
output.replace("\r", "");
output.replace("\n", "\r\n");
object->locked = true;
SetWindowText(widget->window, utf16_t(output));
object->locked = false;
}
void EditBox::setCursorPosition(unsigned position) {
Edit_SetSel(widget->window, position, position);
}
void EditBox::setEditable(bool editable) {
SendMessage(widget->window, EM_SETREADONLY, editable == false, (LPARAM)0);
}
void EditBox::setWordWrap(bool wordWrap) {
editBox->wordWrap = wordWrap;
if(widget->window == 0) return;
//ES_AUTOSCROLL options cannot be changed after control has been created;
//so destroy the control and recreate it with desired options
#if 0
HWND hparent = GetParent(widget->window);
Window *parent = (Window*)GetWindowLongPtr(hparent, GWLP_USERDATA);
string text = getText();
DestroyWindow(widget->window);
create(*parent, editBox->x, editBox->y, editBox->width, editBox->height, text);
#endif
}
EditBox::EditBox() {
editBox = new EditBox::Data;
editBox->wordWrap = true;
widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, L"EDIT", L"",
WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN |
(editBox->wordWrap == false ? ES_AUTOHSCROLL : 0),
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}

View File

@ -1,146 +0,0 @@
static LRESULT CALLBACK HexEditor_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
HexEditor &self = *(HexEditor*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
switch(msg) {
case WM_CHAR: {
if(self.keyPress(wparam)) return 0;
}
}
return self.hexEditor->windowProc(hwnd, msg, wparam, lparam);
}
void HexEditor::setSize(unsigned size) {
hexEditor->size = size;
update();
}
void HexEditor::setOffset(unsigned offset) {
hexEditor->offset = offset;
update();
}
void HexEditor::setColumns(unsigned columns) {
hexEditor->columns = columns;
update();
}
void HexEditor::setRows(unsigned rows) {
hexEditor->rows = rows;
update();
}
void HexEditor::update() {
if(!onRead) {
SetWindowText(widget->window, L"");
return;
}
//modifying text resets cursor position to zero, save position so we can restore it later
unsigned cursorPosition = Edit_GetSel(widget->window);
string output;
unsigned offset = hexEditor->offset;
for(unsigned row = 0; row < hexEditor->rows; row++) {
output.append(hex<8>(offset));
output.append(" ");
string hexdata;
string ansidata = " ";
for(unsigned column = 0; column < hexEditor->columns; column++) {
if(offset < hexEditor->size) {
uint8_t data = onRead(offset++);
hexdata.append(hex<2>(data));
hexdata.append(" ");
char buffer[2] = { data >= 0x20 && data <= 0x7e ? (char)data : '.', 0 };
ansidata.append(buffer);
} else {
hexdata.append(" ");
ansidata.append(" ");
}
}
output.append(hexdata);
output.append(ansidata);
if(offset >= hexEditor->size) break;
if(row != hexEditor->rows - 1) output.append("\r\n");
}
SetWindowText(widget->window, utf16_t(output));
Edit_SetSel(widget->window, LOWORD(cursorPosition), HIWORD(cursorPosition));
}
bool HexEditor::keyPress(unsigned scancode) {
if(!onRead || !onWrite) return false;
unsigned position = LOWORD(Edit_GetSel(widget->window));
unsigned lineWidth = 10 + (hexEditor->columns * 3) + 1 + (hexEditor->columns) + 2;
unsigned cursorY = position / lineWidth;
unsigned cursorX = position % lineWidth;
//convert scancode to hex nibble
if(scancode >= '0' && scancode <= '9') scancode = scancode - '0';
else if(scancode >= 'A' && scancode <= 'F') scancode = scancode - 'A' + 10;
else if(scancode >= 'a' && scancode <= 'f') scancode = scancode - 'a' + 10;
else return false;
if(cursorX >= 10) {
//not on an offset
cursorX -= 10;
if((cursorX % 3) != 2) {
//not on a space
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
cursorX /= 3;
if(cursorX < hexEditor->columns) {
//not in ANSI region
unsigned offset = hexEditor->offset + (cursorY * hexEditor->columns + cursorX);
if(offset >= hexEditor->size) return false; //do not edit past end of file
uint8_t data = onRead(offset);
//write modified value
if(cursorNibble == 1) {
data = (data & 0xf0) | (scancode << 0);
} else {
data = (data & 0x0f) | (scancode << 4);
}
onWrite(offset, data);
//auto-advance cursor to next nibble/byte
position++;
if(cursorNibble && cursorX != hexEditor->columns - 1) position++;
Edit_SetSel(widget->window, position, position);
//refresh output to reflect modified data
update();
}
}
}
return true;
}
HexEditor::HexEditor() {
hexEditor = new HexEditor::Data;
hexEditor->windowProc = 0;
hexEditor->size = 0;
hexEditor->offset = 0;
hexEditor->columns = 16;
hexEditor->rows = 16;
widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"EDIT", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_WANTRETURN,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
hexEditor->windowProc = (LRESULT CALLBACK (*)(HWND, UINT, LPARAM, WPARAM))GetWindowLongPtr(widget->window, GWLP_WNDPROC);
SetWindowLongPtr(widget->window, GWLP_WNDPROC, (LONG_PTR)HexEditor_WindowProc);
}
HexEditor::~HexEditor() {
delete[] hexEditor;
}

View File

@ -1,26 +0,0 @@
unsigned HorizontalSlider::position() {
return SendMessage(widget->window, TBM_GETPOS, 0, 0);
}
void HorizontalSlider::setLength(unsigned length) {
length += (length == 0);
SendMessage(widget->window, TBM_SETRANGE, (WPARAM)true, (LPARAM)MAKELONG(0, length - 1));
SendMessage(widget->window, TBM_SETPAGESIZE, 0, (LPARAM)(length >> 3));
setPosition(0);
}
void HorizontalSlider::setPosition(unsigned position) {
SendMessage(widget->window, TBM_SETPOS, (WPARAM)true, (LPARAM)(horizontalSlider->position = position));
}
HorizontalSlider::HorizontalSlider() {
horizontalSlider = new HorizontalSlider::Data;
widget->window = CreateWindow(
TRACKBAR_CLASS, L"",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_NOTICKS | TBS_BOTH | TBS_HORZ,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}

View File

@ -1,49 +0,0 @@
void Label::setText(const string &text) {
SetWindowText(widget->window, utf16_t(text));
InvalidateRect(widget->window, 0, false);
}
Label::Label() {
widget->window = CreateWindow(
L"phoenix_label", L"",
WS_CHILD | WS_VISIBLE,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}
//all of this for want of a STATIC SS_VCENTER flag ...
LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
Window *window_ptr = (Window*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
if(!window_ptr) return DefWindowProc(hwnd, msg, wparam, lparam);
Label *label_ptr = (Label*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if(!label_ptr) return DefWindowProc(hwnd, msg, wparam, lparam);
Window &window = *window_ptr;
Label &label = *label_ptr;
switch(msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
RECT rc;
BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
FillRect(ps.hdc, &rc, window.window->brush ? window.window->brush : GetSysColorBrush(COLOR_3DFACE));
SetBkColor(ps.hdc, window.window->brush ? window.window->brushColor : GetSysColor(COLOR_3DFACE));
SelectObject(ps.hdc, label.widget->font);
unsigned length = GetWindowTextLength(hwnd);
wchar_t text[length + 1];
GetWindowText(hwnd, text, length + 1);
text[length] = 0;
DrawText(ps.hdc, text, -1, &rc, DT_CALCRECT | DT_END_ELLIPSIS);
unsigned height = rc.bottom;
GetClientRect(hwnd, &rc);
rc.top = (rc.bottom - height) / 2;
rc.bottom = rc.top + height;
DrawText(ps.hdc, text, -1, &rc, DT_LEFT | DT_END_ELLIPSIS);
EndPaint(hwnd, &ps);
}
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}

View File

@ -1,117 +0,0 @@
void ListBox::setHeaderText(const string &text) {
//delete all existing columns
while(ListView_DeleteColumn(widget->window, 0));
lstring list;
list.split("\t", text);
listBox->columns = list.size();
for(unsigned i = 0; i < list.size(); i++) {
LVCOLUMN column;
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM;
column.fmt = LVCFMT_LEFT;
column.iSubItem = list.size();
utf16_t text(list[i]);
column.pszText = text;
ListView_InsertColumn(widget->window, i, &column);
}
resizeColumnsToContent();
}
void ListBox::setHeaderVisible(bool headerVisible) {
SetWindowLong(
widget->window,
GWL_STYLE,
(GetWindowLong(widget->window, GWL_STYLE) & ~LVS_NOCOLUMNHEADER) |
(headerVisible == false ? LVS_NOCOLUMNHEADER : 0)
);
}
void ListBox::setCheckable(bool checkable) {
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT | (checkable ? LVS_EX_CHECKBOXES : 0));
}
void ListBox::reset() {
ListView_DeleteAllItems(widget->window);
}
void ListBox::resizeColumnsToContent() {
for(unsigned i = 0; i < listBox->columns; i++) {
ListView_SetColumnWidth(widget->window, i, LVSCW_AUTOSIZE_USEHEADER);
}
}
void ListBox::addItem(const string &text) {
lstring list;
list.split("\t", text);
LVITEM item;
unsigned row = ListView_GetItemCount(widget->window);
item.mask = LVIF_TEXT;
item.iItem = row;
item.iSubItem = 0;
utf16_t wtext(list[0]);
item.pszText = wtext;
object->locked = true;
ListView_InsertItem(widget->window, &item);
object->locked = false;
for(unsigned i = 1; i < list.size(); i++) {
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 string &text) {
lstring list;
list.split("\t", text);
for(unsigned i = 0; i < list.size(); i++) {
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() {
unsigned count = ListView_GetItemCount(widget->window);
for(unsigned i = 0; i < count; i++) {
if(ListView_GetItemState(widget->window, i, LVIS_SELECTED)) return { true, i };
}
return { false, 0 };
}
void ListBox::setSelection(unsigned row) {
unsigned count = ListView_GetItemCount(widget->window);
for(unsigned i = 0; i < count; i++) {
ListView_SetItemState(widget->window, i, LVIS_FOCUSED, (i == row ? LVIS_FOCUSED : 0));
ListView_SetItemState(widget->window, i, LVIS_SELECTED, (i == row ? LVIS_SELECTED : 0));
}
}
bool ListBox::checked(unsigned row) {
return ListView_GetCheckState(widget->window, row);
}
void ListBox::setChecked(unsigned row, bool checked) {
object->locked = true;
ListView_SetCheckState(widget->window, row, checked);
object->locked = false;
}
ListBox::ListBox() {
listBox = new ListBox::Data;
listBox->lostFocus = false;
widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE |
LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_NOCOLUMNHEADER,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
ListView_SetExtendedListViewStyle(widget->window, LVS_EX_FULLROWSELECT);
setHeaderText("");
}

View File

@ -1,18 +0,0 @@
unsigned ProgressBar::position() {
return SendMessage(widget->window, PBM_GETPOS, 0, 0);
}
void ProgressBar::setPosition(unsigned position) {
SendMessage(widget->window, PBM_SETPOS, (WPARAM)position, 0);
}
ProgressBar::ProgressBar() {
widget->window = CreateWindow(
PROGRESS_CLASS, L"",
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SendMessage(widget->window, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
SendMessage(widget->window, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
}

View File

@ -1,34 +0,0 @@
void RadioBox::setParent(RadioBox &parent) {
radioBox->parent = parent.radioBox->parent;
radioBox->parent->radioBox->items.append(this);
parent.setChecked();
}
void RadioBox::setText(const string &text) {
SetWindowText(widget->window, utf16_t(text));
}
bool RadioBox::checked() {
return SendMessage(widget->window, BM_GETCHECK, 0, 0);
}
void RadioBox::setChecked() {
foreach(item, radioBox->parent->radioBox->items) {
SendMessage(item->widget->window, BM_SETCHECK, (WPARAM)(item == this), 0);
}
}
RadioBox::RadioBox() {
radioBox = new RadioBox::Data;
radioBox->parent = this;
radioBox->parent->radioBox->items.append(this);
widget->window = CreateWindow(
L"BUTTON", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_RADIOBUTTON,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
setChecked();
}

View File

@ -1,27 +0,0 @@
string TextBox::text() {
unsigned length = GetWindowTextLength(widget->window);
wchar_t text[length + 1];
GetWindowText(widget->window, text, length + 1);
text[length] = 0;
return utf8_t(text);
}
void TextBox::setText(const string &text) {
object->locked = true;
SetWindowText(widget->window, utf16_t(text));
object->locked = false;
}
void TextBox::setEditable(bool editable) {
SendMessage(widget->window, EM_SETREADONLY, editable == false, 0);
}
TextBox::TextBox() {
widget->window = CreateWindowEx(
WS_EX_CLIENTEDGE, L"EDIT", L"",
WS_CHILD | WS_TABSTOP | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
0, 0, 64, 64,
OS::os->nullWindow, (HMENU)object->id, GetModuleHandle(0), 0
);
SetWindowLongPtr(widget->window, GWLP_USERDATA, (LONG_PTR)this);
}

Some files were not shown because too many files have changed in this diff Show More