Update to v094r27 release.

byuu says:

Added AWJ's fixes for alt/cpu (Tetris Attack framelines issue) and
alt/dsp (Thread::clock reset)

Added fix so that the taskbar entry appears when the application first
starts on Windows.

Fixed checkbox toggling inside of list views on Windows.

Updated nall/image to properly protect variables that should not be
written externally.

New Object syntax for hiro is in.

Fixed the backwards-typing on Windows with the state manager.
NOTE: the list view isn't redrawing when you change the description
text. It does so on the cheat editor because of the resizeColumns call;
but that shouldn't be necessary. I'll try and fix this for the next WIP.
This commit is contained in:
Tim Allen 2015-06-18 20:48:53 +10:00
parent a21ff570ee
commit 20cc6148cb
62 changed files with 1580 additions and 1569 deletions

View File

@ -1,48 +1,27 @@
#ifndef EMULATOR_HPP #ifndef EMULATOR_HPP
#define EMULATOR_HPP #define EMULATOR_HPP
#include <nall/nall.hpp>
#include <nall/dsp.hpp>
#include <nall/priority-queue.hpp>
using namespace nall;
namespace Emulator { namespace Emulator {
static const char Name[] = "higan"; static const string Name = "higan";
static const char Version[] = "094.26"; static const string Version = "094.27";
static const char Author[] = "byuu"; static const string Author = "byuu";
static const char License[] = "GPLv3"; static const string License = "GPLv3";
static const char Website[] = "http://byuu.org/"; static const string Website = "http://byuu.org/";
#if defined(PROFILE_ACCURACY) #if defined(PROFILE_ACCURACY)
static const char Profile[] = "Accuracy"; static const string Profile = "Accuracy";
#elif defined(PROFILE_BALANCED) #elif defined(PROFILE_BALANCED)
static const char Profile[] = "Balanced"; static const string Profile = "Balanced";
#elif defined(PROFILE_PERFORMANCE) #elif defined(PROFILE_PERFORMANCE)
static const char Profile[] = "Performance"; static const string Profile = "Performance";
#endif #endif
} }
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/base64.hpp>
#include <nall/directory.hpp>
#include <nall/dl.hpp>
#include <nall/dsp.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/image.hpp>
#include <nall/invoke.hpp>
#include <nall/priority-queue.hpp>
#include <nall/property.hpp>
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/set.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/hash/sha256.hpp>
#include <nall/stream/memory.hpp>
#include <nall/stream/vector.hpp>
using namespace nall;
#include "interface.hpp" #include "interface.hpp"
//debugging function hook: //debugging function hook:

View File

@ -6,7 +6,7 @@
namespace Famicom { namespace Famicom {
namespace Info { namespace Info {
static const char Name[] = "bnes"; static const string Name = "bnes";
static const unsigned SerializerVersion = 2; static const unsigned SerializerVersion = 2;
} }
} }
@ -22,28 +22,25 @@ namespace Famicom {
namespace Famicom { namespace Famicom {
struct Thread { struct Thread {
cothread_t thread; ~Thread() {
unsigned frequency; if(thread) co_delete(thread);
int64 clock; }
inline void create(void (*entrypoint)(), unsigned frequency) { auto create(void (*entrypoint)(), unsigned frequency) -> void {
if(thread) co_delete(thread); if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint); thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency; this->frequency = frequency;
clock = 0; clock = 0;
} }
inline void serialize(serializer& s) { auto serialize(serializer& s) -> void {
s.integer(frequency); s.integer(frequency);
s.integer(clock); s.integer(clock);
} }
inline Thread() : thread(nullptr) { cothread_t thread = nullptr;
} unsigned frequency = 0;
int64 clock = 0;
inline ~Thread() {
if(thread) co_delete(thread);
}
}; };
#include <fc/system/system.hpp> #include <fc/system/system.hpp>

View File

@ -6,7 +6,7 @@
namespace GameBoy { namespace GameBoy {
namespace Info { namespace Info {
static const char Name[] = "bgb"; static const string Name = "bgb";
static const unsigned SerializerVersion = 4; static const unsigned SerializerVersion = 4;
} }
} }
@ -22,28 +22,25 @@ namespace GameBoy {
namespace GameBoy { namespace GameBoy {
struct Thread { struct Thread {
cothread_t thread; ~Thread() {
unsigned frequency; if(thread) co_delete(thread);
int64_t clock; }
inline void create(void (*entrypoint)(), unsigned frequency) { auto create(void (*entrypoint)(), unsigned frequency) -> void {
if(thread) co_delete(thread); if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint); thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency; this->frequency = frequency;
clock = 0; clock = 0;
} }
inline void serialize(serializer& s) { auto serialize(serializer& s) -> void {
s.integer(frequency); s.integer(frequency);
s.integer(clock); s.integer(clock);
} }
inline Thread() : thread(nullptr) { cothread_t thread = nullptr;
} unsigned frequency = 0;
int64_t clock = 0;
inline ~Thread() {
if(thread) co_delete(thread);
}
}; };
#include <gb/memory/memory.hpp> #include <gb/memory/memory.hpp>

View File

@ -6,7 +6,7 @@
namespace GameBoyAdvance { namespace GameBoyAdvance {
namespace Info { namespace Info {
static const char Name[] = "bgba"; static const string Name = "bgba";
static const unsigned SerializerVersion = 2; static const unsigned SerializerVersion = 2;
} }
} }
@ -24,28 +24,25 @@ namespace GameBoyAdvance {
enum : unsigned { Byte = 8, Half = 16, Word = 32 }; enum : unsigned { Byte = 8, Half = 16, Word = 32 };
struct Thread { struct Thread {
cothread_t thread; ~Thread() {
unsigned frequency; if(thread) co_delete(thread);
signed clock; }
inline void create(void (*entrypoint)(), unsigned frequency) { auto create(void (*entrypoint)(), unsigned frequency) -> void {
if(thread) co_delete(thread); if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint); thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency; this->frequency = frequency;
clock = 0; clock = 0;
} }
inline void serialize(serializer& s) { auto serialize(serializer& s) -> void {
s.integer(frequency); s.integer(frequency);
s.integer(clock); s.integer(clock);
} }
inline Thread() : thread(nullptr) { cothread_t thread = nullptr;
} unsigned frequency = 0;
signed clock = 0;
inline ~Thread() {
if(thread) co_delete(thread);
}
}; };
#include <gba/memory/memory.hpp> #include <gba/memory/memory.hpp>

View File

@ -14,7 +14,7 @@ auto mMenuRadioItem::doActivate() const -> void {
if(state.onActivate) return state.onActivate(); if(state.onActivate) return state.onActivate();
} }
auto mMenuRadioItem::group() const -> sGroup { auto mMenuRadioItem::group() const -> Group {
return state.group; return state.group;
} }

View File

@ -11,9 +11,9 @@ auto mMenu::destruct() -> void {
// //
auto mMenu::action(unsigned position) const -> sAction { auto mMenu::action(unsigned position) const -> Action {
if(position >= actions()) throw; if(position < actions()) return state.actions[position];
return state.actions[position]; return {};
} }
auto mMenu::actions() const -> unsigned { auto mMenu::actions() const -> unsigned {

View File

@ -24,6 +24,7 @@ using nall::vector;
namespace hiro { namespace hiro {
#define Declare(Name) \ #define Declare(Name) \
struct Name; \
struct m##Name; \ struct m##Name; \
struct p##Name; \ struct p##Name; \
using s##Name = shared_pointer<m##Name>; \ using s##Name = shared_pointer<m##Name>; \
@ -302,7 +303,7 @@ struct Keyboard {
Keyboard() = delete; Keyboard() = delete;
static auto append(sHotkey hotkey) -> void; static auto append(sHotkey hotkey) -> void;
static auto hotkey(unsigned position) -> sHotkey; static auto hotkey(unsigned position) -> Hotkey;
static auto hotkeys() -> unsigned; static auto hotkeys() -> unsigned;
static auto poll() -> vector<bool>; static auto poll() -> vector<bool>;
static auto pressed(const string& key) -> bool; static auto pressed(const string& key) -> bool;
@ -410,7 +411,7 @@ struct mObject {
auto enabled(bool recursive = false) const -> bool; auto enabled(bool recursive = false) const -> bool;
virtual auto focused() const -> bool; virtual auto focused() const -> bool;
auto font(bool recursive = false) const -> string; auto font(bool recursive = false) const -> string;
virtual auto group() const -> sGroup; virtual auto group() const -> Group;
auto offset() const -> signed; auto offset() const -> signed;
auto parent() const -> mObject*; auto parent() const -> mObject*;
auto parentComboButton(bool recursive = false) const -> mComboButton*; auto parentComboButton(bool recursive = false) const -> mComboButton*;
@ -462,7 +463,7 @@ struct mGroup : mObject {
using mObject::remove; using mObject::remove;
auto append(sObject object) -> type&; auto append(sObject object) -> type&;
auto object(unsigned offset) const -> sObject; auto object(unsigned offset) const -> Object;
auto objects() const -> unsigned; auto objects() const -> unsigned;
auto remove(sObject object) -> type&; auto remove(sObject object) -> type&;
@ -535,8 +536,8 @@ struct mWindow : mObject {
auto frameGeometry() const -> Geometry; auto frameGeometry() const -> Geometry;
auto fullScreen() const -> bool; auto fullScreen() const -> bool;
auto geometry() const -> Geometry; auto geometry() const -> Geometry;
auto layout() const -> sLayout; auto layout() const -> Layout;
auto menuBar() const -> sMenuBar; auto menuBar() const -> MenuBar;
auto modal() const -> bool; auto modal() const -> bool;
auto onClose(const function<void ()>& callback = {}) -> type&; auto onClose(const function<void ()>& callback = {}) -> type&;
auto onDrop(const function<void (lstring)>& callback = {}) -> type&; auto onDrop(const function<void (lstring)>& callback = {}) -> type&;
@ -563,7 +564,7 @@ struct mWindow : mObject {
auto setResizable(bool resizable = true) -> type&; auto setResizable(bool resizable = true) -> type&;
auto setSize(Size size) -> type&; auto setSize(Size size) -> type&;
auto setTitle(const string& title = "") -> type&; auto setTitle(const string& title = "") -> type&;
auto statusBar() const -> sStatusBar; auto statusBar() const -> StatusBar;
auto title() const -> string; auto title() const -> string;
//private: //private:
@ -610,7 +611,7 @@ struct mMenuBar : mObject {
Declare(MenuBar) Declare(MenuBar)
auto append(sMenu menu) -> type&; auto append(sMenu menu) -> type&;
auto menu(unsigned position) const -> sMenu; auto menu(unsigned position) const -> Menu;
auto menus() const -> unsigned; auto menus() const -> unsigned;
auto remove() -> type& override; auto remove() -> type& override;
auto remove(sMenu menu) -> type&; auto remove(sMenu menu) -> type&;
@ -631,7 +632,7 @@ struct mPopupMenu : mObject {
Declare(PopupMenu) Declare(PopupMenu)
using mObject::remove; using mObject::remove;
auto action(unsigned position) const -> sAction; auto action(unsigned position) const -> Action;
auto actions() const -> unsigned; auto actions() const -> unsigned;
auto append(sAction action) -> type&; auto append(sAction action) -> type&;
auto remove(sAction action) -> type&; auto remove(sAction action) -> type&;
@ -665,7 +666,7 @@ struct mMenu : mAction {
Declare(Menu) Declare(Menu)
using mObject::remove; using mObject::remove;
auto action(unsigned position) const -> sAction; auto action(unsigned position) const -> Action;
auto actions() const -> unsigned; auto actions() const -> unsigned;
auto append(sAction action) -> type&; auto append(sAction action) -> type&;
auto icon() const -> image; auto icon() const -> image;
@ -743,7 +744,7 @@ struct mMenuRadioItem : mAction {
auto checked() const -> bool; auto checked() const -> bool;
auto doActivate() const -> void; auto doActivate() const -> void;
auto group() const -> sGroup override; auto group() const -> Group override;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
auto setChecked() -> type&; auto setChecked() -> type&;
auto setGroup(sGroup group = {}) -> type& override; auto setGroup(sGroup group = {}) -> type& override;
@ -784,7 +785,7 @@ struct mLayout : mSizable {
virtual auto remove(sSizable sizable) -> type&; virtual auto remove(sSizable sizable) -> type&;
virtual auto reset() -> type&; virtual auto reset() -> type&;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override; auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
auto sizable(unsigned position) const -> sSizable; auto sizable(unsigned position) const -> Sizable;
auto sizables() const -> unsigned; auto sizables() const -> unsigned;
//private: //private:
@ -939,12 +940,12 @@ struct mComboButton : mWidget {
auto append(sComboButtonItem item) -> type&; auto append(sComboButtonItem item) -> type&;
auto doChange() const -> void; auto doChange() const -> void;
auto item(unsigned position) const -> sComboButtonItem; auto item(unsigned position) const -> ComboButtonItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto onChange(const function<void ()>& callback = {}) -> type&; auto onChange(const function<void ()>& callback = {}) -> type&;
auto remove(sComboButtonItem item) -> type&; auto remove(sComboButtonItem item) -> type&;
auto reset() -> type&; auto reset() -> type&;
auto selected() const -> sComboButtonItem; auto selected() const -> ComboButtonItem;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override; auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
//private: //private:
@ -1009,7 +1010,7 @@ struct mFrame : mWidget {
using mObject::remove; using mObject::remove;
auto append(sLayout layout) -> type&; auto append(sLayout layout) -> type&;
auto layout() const -> sLayout; auto layout() const -> Layout;
auto remove(sLayout layout) -> type&; auto remove(sLayout layout) -> type&;
auto reset() -> type&; auto reset() -> type&;
//TODO setParent() //TODO setParent()
@ -1114,7 +1115,7 @@ struct mIconView : mWidget {
auto doContext() const -> void; auto doContext() const -> void;
auto flow() const -> Orientation; auto flow() const -> Orientation;
auto foregroundColor() const -> Color; auto foregroundColor() const -> Color;
auto item(unsigned position) const -> sIconViewItem; auto item(unsigned position) const -> IconViewItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto multiSelect() const -> bool; auto multiSelect() const -> bool;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
@ -1231,8 +1232,8 @@ struct mListView : mWidget {
auto batchable() const -> bool; auto batchable() const -> bool;
auto checkable() const -> bool; auto checkable() const -> bool;
auto checkAll() -> type&; auto checkAll() -> type&;
auto checked() const -> vector<sListViewItem>; auto checked() const -> vector<ListViewItem>;
auto column(unsigned position) const -> sListViewColumn; auto column(unsigned position) const -> ListViewColumn;
auto columns() const -> unsigned; auto columns() const -> unsigned;
auto doActivate() const -> void; auto doActivate() const -> void;
auto doChange() const -> void; auto doChange() const -> void;
@ -1243,21 +1244,21 @@ struct mListView : mWidget {
auto foregroundColor() const -> Color; auto foregroundColor() const -> Color;
auto gridVisible() const -> bool; auto gridVisible() const -> bool;
auto headerVisible() const -> bool; auto headerVisible() const -> bool;
auto item(unsigned position) const -> sListViewItem; auto item(unsigned position) const -> ListViewItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
auto onChange(const function<void ()>& callback = {}) -> type&; auto onChange(const function<void ()>& callback = {}) -> type&;
auto onContext(const function<void ()>& callback = {}) -> type&; auto onContext(const function<void ()>& callback = {}) -> type&;
auto onEdit(const function<void (sListViewCell)>& callback = {}) -> type&; auto onEdit(const function<void (ListViewCell)>& callback = {}) -> type&;
auto onSort(const function<void (sListViewColumn)>& callback = {}) -> type&; auto onSort(const function<void (ListViewColumn)>& callback = {}) -> type&;
auto onToggle(const function<void (sListViewItem)>& callback = {}) -> type&; auto onToggle(const function<void (ListViewItem)>& callback = {}) -> type&;
auto remove(sListViewColumn column) -> type&; auto remove(sListViewColumn column) -> type&;
auto remove(sListViewItem item) -> type&; auto remove(sListViewItem item) -> type&;
auto reset() -> type&; auto reset() -> type&;
auto resizeColumns() -> type&; auto resizeColumns() -> type&;
auto selectAll() -> type&; auto selectAll() -> type&;
auto selected() const -> sListViewItem; auto selected() const -> ListViewItem;
auto selectedItems() const -> vector<sListViewItem>; auto selectedItems() const -> vector<ListViewItem>;
auto setBackgroundColor(Color color = {}) -> type&; auto setBackgroundColor(Color color = {}) -> type&;
auto setBatchable(bool batchable = true) -> type&; auto setBatchable(bool batchable = true) -> type&;
auto setCheckable(bool checkable = true) -> type&; auto setCheckable(bool checkable = true) -> type&;
@ -1284,9 +1285,9 @@ struct mListView : mWidget {
function<void ()> onActivate; function<void ()> onActivate;
function<void ()> onChange; function<void ()> onChange;
function<void ()> onContext; function<void ()> onContext;
function<void (sListViewCell)> onEdit; function<void (ListViewCell)> onEdit;
function<void (sListViewColumn)> onSort; function<void (ListViewColumn)> onSort;
function<void (sListViewItem)> onToggle; function<void (ListViewItem)> onToggle;
bool sortable = false; bool sortable = false;
} state; } state;
@ -1348,7 +1349,7 @@ struct mListViewItem : mObject {
auto append(sListViewCell cell) -> type&; auto append(sListViewCell cell) -> type&;
auto backgroundColor() const -> Color; auto backgroundColor() const -> Color;
auto cell(unsigned position) const -> sListViewCell; auto cell(unsigned position) const -> ListViewCell;
auto cells() const -> unsigned; auto cells() const -> unsigned;
auto checked() const -> bool; auto checked() const -> bool;
auto foregroundColor() const -> Color; auto foregroundColor() const -> Color;
@ -1417,7 +1418,7 @@ struct mRadioButton : mWidget {
auto bordered() const -> bool; auto bordered() const -> bool;
auto checked() const -> bool; auto checked() const -> bool;
auto doActivate() const -> void; auto doActivate() const -> void;
auto group() const -> sGroup override; auto group() const -> Group override;
auto icon() const -> image; auto icon() const -> image;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
auto orientation() const -> Orientation; auto orientation() const -> Orientation;
@ -1448,7 +1449,7 @@ struct mRadioLabel : mWidget {
auto checked() const -> bool; auto checked() const -> bool;
auto doActivate() const -> void; auto doActivate() const -> void;
auto group() const -> sGroup override; auto group() const -> Group override;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
auto setChecked() -> type&; auto setChecked() -> type&;
auto setGroup(sGroup group = {}) -> type& override; auto setGroup(sGroup group = {}) -> type& override;
@ -1501,14 +1502,14 @@ struct mTabFrame : mWidget {
auto doClose(sTabFrameItem item) const -> void; auto doClose(sTabFrameItem item) const -> void;
auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void; auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void;
auto edge() const -> Edge; auto edge() const -> Edge;
auto item(unsigned position) const -> sTabFrameItem; auto item(unsigned position) const -> TabFrameItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto onChange(const function<void ()>& callback = {}) -> type&; auto onChange(const function<void ()>& callback = {}) -> type&;
auto onClose(const function<void (sTabFrameItem)>& callback = {}) -> type&; auto onClose(const function<void (TabFrameItem)>& callback = {}) -> type&;
auto onMove(const function<void (sTabFrameItem, sTabFrameItem)>& callback = {}) -> type&; auto onMove(const function<void (TabFrameItem, TabFrameItem)>& callback = {}) -> type&;
auto remove(sTabFrameItem item) -> type&; auto remove(sTabFrameItem item) -> type&;
auto reset() -> type&; auto reset() -> type&;
auto selected() const -> sTabFrameItem; auto selected() const -> TabFrameItem;
auto setEdge(Edge edge = Edge::Top) -> type&; auto setEdge(Edge edge = Edge::Top) -> type&;
auto setParent(mObject* object = nullptr, signed offset = -1) -> type& override; auto setParent(mObject* object = nullptr, signed offset = -1) -> type& override;
@ -1517,8 +1518,8 @@ struct mTabFrame : mWidget {
Edge edge = Edge::Top; Edge edge = Edge::Top;
vector<sTabFrameItem> items; vector<sTabFrameItem> items;
function<void ()> onChange; function<void ()> onChange;
function<void (sTabFrameItem)> onClose; function<void (TabFrameItem)> onClose;
function<void (sTabFrameItem, sTabFrameItem)> onMove; function<void (TabFrameItem, TabFrameItem)> onMove;
} state; } state;
auto destruct() -> void override; auto destruct() -> void override;
@ -1532,7 +1533,7 @@ struct mTabFrameItem : mObject {
auto append(sLayout layout) -> type&; auto append(sLayout layout) -> type&;
auto closable() const -> bool; auto closable() const -> bool;
auto icon() const -> image; auto icon() const -> image;
auto layout() const -> sLayout; auto layout() const -> Layout;
auto movable() const -> bool; auto movable() const -> bool;
auto remove() -> type& override; auto remove() -> type& override;
auto remove(sLayout layout) -> type&; auto remove(sLayout layout) -> type&;
@ -1610,7 +1611,7 @@ struct mTreeView : mWidget {
auto doToggle(sTreeViewItem item) const -> void; auto doToggle(sTreeViewItem item) const -> void;
auto expand() -> type&; auto expand() -> type&;
auto foregroundColor() const -> Color; auto foregroundColor() const -> Color;
auto item(const string& path) const -> sTreeViewItem; auto item(const string& path) const -> TreeViewItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto onActivate(const function<void ()>& callback = {}) -> type&; auto onActivate(const function<void ()>& callback = {}) -> type&;
auto onChange(const function<void ()>& callback = {}) -> type&; auto onChange(const function<void ()>& callback = {}) -> type&;
@ -1618,7 +1619,7 @@ struct mTreeView : mWidget {
auto onToggle(const function<void (sTreeViewItem)>& callback = {}) -> type&; auto onToggle(const function<void (sTreeViewItem)>& callback = {}) -> type&;
auto remove(sTreeViewItem item) -> type&; auto remove(sTreeViewItem item) -> type&;
auto reset() -> type&; auto reset() -> type&;
auto selected() const -> sTreeViewItem; auto selected() const -> TreeViewItem;
auto setBackgroundColor(Color color = {}) -> type&; auto setBackgroundColor(Color color = {}) -> type&;
auto setCheckable(bool checkable = true) -> type&; auto setCheckable(bool checkable = true) -> type&;
auto setForegroundColor(Color color = {}) -> type&; auto setForegroundColor(Color color = {}) -> type&;
@ -1648,7 +1649,7 @@ struct mTreeViewItem : mObject {
auto append(sTreeViewItem item) -> type&; auto append(sTreeViewItem item) -> type&;
auto checked() const -> bool; auto checked() const -> bool;
auto icon() const -> image; auto icon() const -> image;
auto item(const string& path) const -> sTreeViewItem; auto item(const string& path) const -> TreeViewItem;
auto items() const -> unsigned; auto items() const -> unsigned;
auto path() const -> string; auto path() const -> string;
auto remove() -> type& override; auto remove() -> type& override;
@ -1746,4 +1747,6 @@ struct mViewport : mWidget {
#undef Declare #undef Declare
#include "shared.hpp"
} }

View File

@ -14,8 +14,12 @@ auto mGroup::append(sObject object) -> type& {
return *this; return *this;
} }
auto mGroup::object(unsigned position) const -> sObject { auto mGroup::object(unsigned position) const -> Object {
if(position < state.objects.size()) return state.objects[position]; if(position < state.objects.size()) {
if(auto object = state.objects[position].acquire()) {
return object;
}
}
return {}; return {};
} }

View File

@ -29,9 +29,9 @@ auto Keyboard::append(sHotkey hotkey) -> void {
state.hotkeys.append(hotkey); state.hotkeys.append(hotkey);
} }
auto Keyboard::hotkey(unsigned position) -> sHotkey { auto Keyboard::hotkey(unsigned position) -> Hotkey {
if(position >= hotkeys()) throw; if(position < hotkeys()) return state.hotkeys[position];
return state.hotkeys[position]; return {};
} }
auto Keyboard::hotkeys() -> unsigned { auto Keyboard::hotkeys() -> unsigned {

View File

@ -11,7 +11,7 @@ auto mLayout::destruct() -> void {
// //
auto mLayout::append(shared_pointer<mSizable> sizable) -> type& { auto mLayout::append(sSizable sizable) -> type& {
state.sizables.append(sizable); state.sizables.append(sizable);
sizable->setParent(this, sizables() - 1); sizable->setParent(this, sizables() - 1);
setGeometry(geometry()); setGeometry(geometry());
@ -29,7 +29,7 @@ auto mLayout::remove() -> type& {
return *this; return *this;
} }
auto mLayout::remove(shared_pointer<mSizable> sizable) -> type& { auto mLayout::remove(sSizable sizable) -> type& {
auto offset = sizable->offset(); auto offset = sizable->offset();
sizable->setParent(); sizable->setParent();
state.sizables.remove(offset); state.sizables.remove(offset);
@ -52,9 +52,9 @@ auto mLayout::setParent(mObject* parent, signed offset) -> type& {
return *this; return *this;
} }
auto mLayout::sizable(unsigned position) const -> shared_pointer<mSizable> { auto mLayout::sizable(unsigned position) const -> Sizable {
if(position >= sizables()) throw; if(position < sizables()) return state.sizables[position];
return state.sizables[position]; return {};
} }
auto mLayout::sizables() const -> unsigned { auto mLayout::sizables() const -> unsigned {

View File

@ -11,16 +11,16 @@ auto mMenuBar::destruct() -> void {
// //
auto mMenuBar::append(shared_pointer<mMenu> menu) -> type& { auto mMenuBar::append(sMenu menu) -> type& {
state.menus.append(menu); state.menus.append(menu);
menu->setParent(this, menus() - 1); menu->setParent(this, menus() - 1);
signal(append, menu); signal(append, menu);
return *this; return *this;
} }
auto mMenuBar::menu(unsigned position) const -> shared_pointer<mMenu> { auto mMenuBar::menu(unsigned position) const -> Menu {
if(position >= menus()) throw; if(position < menus()) return state.menus[position];
return state.menus[position]; return {};
} }
auto mMenuBar::menus() const -> unsigned { auto mMenuBar::menus() const -> unsigned {
@ -32,7 +32,7 @@ auto mMenuBar::remove() -> type& {
return *this; return *this;
} }
auto mMenuBar::remove(shared_pointer<mMenu> menu) -> type& { auto mMenuBar::remove(sMenu menu) -> type& {
signed offset = menu->offset(); signed offset = menu->offset();
signal(remove, *menu); signal(remove, *menu);
state.menus.remove(offset); state.menus.remove(offset);

View File

@ -69,7 +69,7 @@ auto mObject::font(bool recursive) const -> string {
return Application::font(); return Application::font();
} }
auto mObject::group() const -> sGroup { auto mObject::group() const -> Group {
return {}; return {};
} }

View File

@ -11,9 +11,9 @@ auto mPopupMenu::destruct() -> void {
// //
auto mPopupMenu::action(unsigned position) const -> sAction { auto mPopupMenu::action(unsigned position) const -> Action {
if(position >= actions()) throw; if(position < actions()) return state.actions[position];
return state.actions[position]; return {};
} }
auto mPopupMenu::actions() const -> unsigned { auto mPopupMenu::actions() const -> unsigned {

868
hiro/core/shared.hpp Normal file
View File

@ -0,0 +1,868 @@
#define DeclareShared(Name) \
using type = Name; \
Name() : s##Name(new m##Name, [](auto p) { \
p->unbind(); \
delete p; \
}) { \
(*this)->bind(*this); \
} \
Name(std::nullptr_t) {} \
Name(const s##Name& source) : s##Name(source) {} \
explicit operator bool() const { return !empty(); } \
auto self() const -> m##Name& { return (m##Name&)operator*(); } \
#define DeclareSharedObject(Name) \
DeclareShared(Name) \
template<typename T, typename... P> Name(T* parent, P&&... p) : Name() { \
if(parent && *parent) (*parent)->append(*this, std::forward<P>(p)...); \
} \
auto enabled(bool recursive = false) const { return self().enabled(recursive); } \
auto focused() const { return self().focused(); } \
auto font(bool recursive = false) const { return self().font(recursive); } \
auto offset() { return self().offset(); } \
auto remove() { return self().remove(), *this; } \
auto setEnabled(bool enabled = true) { return self().setEnabled(enabled), *this; } \
auto setFocused() { return self().setFocused(), *this; } \
auto setFont(const string& font = "") { return self().setFont(font), *this; } \
auto setVisible(bool visible = true) { return self().setVisible(visible), *this; } \
auto visible(bool recursive = false) const { return self().visible(recursive); } \
#define DeclareSharedAction(Name) \
DeclareSharedObject(Name) \
#define DeclareSharedSizable(Name) \
DeclareSharedObject(Name) \
auto geometry() const { return self().geometry(); } \
auto minimumSize() const { return self().minimumSize(); } \
auto setGeometry(Geometry geometry) { return self().setGeometry(geometry), *this; } \
#define DeclareSharedLayout(Name) \
DeclareSharedSizable(Name) \
auto append(sSizable sizable) { return self().append(sizable), *this; } \
auto remove(sSizable sizable) { return self().remove(sizable), *this; } \
auto reset() { return self().reset(), *this; } \
auto sizable(unsigned position) { return self().sizable(position); } \
auto sizables() const { return self().sizables(); } \
#define DeclareSharedWidget(Name) \
DeclareSharedSizable(Name) \
auto doSize() const { return self().doSize(); } \
auto onSize(const function<void ()>& callback = {}) { return self().onSize(callback), *this; } \
#if defined(Hiro_Object)
struct Object : sObject {
DeclareSharedObject(Object)
};
#endif
#if defined(Hiro_Group)
struct Group : sGroup {
DeclareShared(Group)
template<typename... P> Group(P&&... p) : Group() { _append(std::forward<P>(p)...); }
auto append(sObject object) -> type& { return self().append(object), *this; }
auto object(unsigned position) const { return self().object(position); }
auto objects() const { return self().objects(); }
auto remove(sObject object) -> type& { return self().remove(object), *this; }
private:
auto _append() {}
template<typename T, typename... P> auto _append(T* object, P&&... p) {
append(*object);
_append(std::forward<P>(p)...);
}
};
#endif
#if defined(Hiro_Hotkey)
struct Hotkey : sHotkey {
DeclareSharedObject(Hotkey)
auto doPress() const { return self().doPress(); }
auto doRelease() const { return self().doRelease(); }
auto onPress(const function<void ()>& callback = {}) { return self().onPress(callback), *this; }
auto onRelease(const function<void ()>& callback = {}) { return self().onRelease(callback), *this; }
auto parent() const { return self().parent(); }
auto sequence() const { return self().sequence(); }
auto setParent(sObject object) { return self().setParent(object), *this; }
auto setSequence(const string& sequence = "") { return self().setSequence(sequence), *this; }
};
#endif
#if defined(Hiro_Timer)
struct Timer : sTimer {
DeclareSharedObject(Timer)
auto doActivate() const { return self().doActivate(); }
auto interval() const { return self().interval(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto setInterval(unsigned interval = 0) { return self().setInterval(interval), *this; }
};
#endif
#if defined(Hiro_Action)
struct Action : sAction {
DeclareSharedAction(Action)
};
#endif
#if defined(Hiro_Menu)
struct Menu : sMenu {
DeclareSharedAction(Menu)
auto action(unsigned position) const { return self().action(position); }
auto actions() const { return self().actions(); }
auto append(sAction action) { return self().append(action), *this; }
auto icon() const { return self().icon(); }
auto remove(sAction action) { return self().remove(action), *this; }
auto reset() { return self().reset(), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_MenuSeparator)
struct MenuSeparator : sMenuSeparator {
DeclareSharedAction(MenuSeparator)
};
#endif
#if defined(Hiro_MenuItem)
struct MenuItem : sMenuItem {
DeclareSharedAction(MenuItem)
auto doActivate() const { return self().doActivate(); }
auto icon() const { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_MenuCheckItem)
struct MenuCheckItem : sMenuCheckItem {
DeclareSharedAction(MenuCheckItem)
auto checked() const { return self().checked(); }
auto doToggle() const { return self().doToggle(); }
auto onToggle(const function<void ()>& callback = {}) { return self().onToggle(callback), *this; }
auto setChecked(bool checked = true) { return self().setChecked(checked), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_MenuRadioItem)
struct MenuRadioItem : sMenuRadioItem {
DeclareSharedAction(MenuRadioItem)
auto checked() const { return self().checked(); }
auto doActivate() const { return self().doActivate(); }
auto group() const { return self().group(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto setChecked() { return self().setChecked(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_Sizable)
struct Sizable : sSizable {
DeclareSharedSizable(Sizable)
};
#endif
#if defined(Hiro_Layout)
struct Layout : sLayout {
DeclareSharedLayout(Layout)
};
#endif
#if defined(Hiro_Widget)
struct Widget : sWidget {
DeclareSharedWidget(Widget)
};
#endif
#if defined(Hiro_Button)
struct Button : sButton {
DeclareSharedWidget(Button)
auto bordered() const { return self().bordered(); }
auto doActivate() const { return self().doActivate(); }
auto icon() const { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto orientation() const { return self().orientation(); }
auto setBordered(bool bordered = true) { return self().setBordered(bordered), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_Canvas)
struct Canvas : sCanvas {
DeclareSharedWidget(Canvas)
auto color() const { return self().color(); }
auto data() { return self().data(); }
auto droppable() const { return self().droppable(); }
auto doDrop(lstring names) { return self().doDrop(names); }
auto doMouseLeave() const { return self().doMouseLeave(); }
auto doMouseMove(Position position) const { return self().doMouseMove(position); }
auto doMousePress(Mouse::Button button) const { return self().doMousePress(button); }
auto doMouseRelease(Mouse::Button button) const { return self().doMouseRelease(button); }
auto gradient() const { return self().gradient(); }
auto icon() const { return self().icon(); }
auto onDrop(const function<void (lstring)>& callback = {}) { return self().onDrop(callback), *this; }
auto onMouseLeave(const function<void ()>& callback = {}) { return self().onMouseLeave(callback), *this; }
auto onMouseMove(const function<void (Position)>& callback = {}) { return self().onMouseMove(callback), *this; }
auto onMousePress(const function<void (Mouse::Button)>& callback = {}) { return self().onMousePress(callback), *this; }
auto onMouseRelease(const function<void (Mouse::Button)>& callback = {}) { return self().onMouseRelease(callback), *this; }
auto setColor(Color color) { return self().setColor(color), *this; }
auto setData(Size size) { return self().setData(size), *this; }
auto setDroppable(bool droppable = true) { return self().setDroppable(droppable), *this; }
auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) { return self().setGradient(topLeft, topRight, bottomLeft, bottomRight), *this; }
auto setHorizontalGradient(Color left, Color right) { return self().setGradient(left, right, left, right), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setVerticalGradient(Color top, Color bottom) { return self().setGradient(top, top, bottom, bottom), *this; }
auto size() const { return self().size(); }
auto update() { return self().update(), *this; }
};
#endif
#if defined(Hiro_CheckButton)
struct CheckButton : sCheckButton {
DeclareSharedWidget(CheckButton)
auto bordered() const { return self().bordered(); }
auto checked() const { return self().checked(); }
auto doToggle() const { return self().doToggle(); }
auto icon() const { return self().icon(); }
auto onToggle(const function<void ()>& callback = {}) { return self().onToggle(callback), *this; }
auto orientation() const { return self().orientation(); }
auto setBordered(bool bordered = true) { return self().setBordered(bordered), *this; }
auto setChecked(bool checked = true) { return self().setChecked(checked), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_CheckLabel)
struct CheckLabel : sCheckLabel {
DeclareSharedWidget(CheckLabel)
auto checked() const { return self().checked(); }
auto doToggle() const { return self().doToggle(); }
auto onToggle(const function<void ()>& callback = {}) { return self().onToggle(callback), *this; }
auto setChecked(bool checked = true) { return self().setChecked(checked), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_ComboButton)
struct ComboButtonItem : sComboButtonItem {
DeclareSharedObject(ComboButtonItem)
auto icon() const { return self().icon(); }
auto selected() const { return self().selected(); }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setSelected() { return self().setSelected(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_ComboButton)
struct ComboButton : sComboButton {
DeclareSharedWidget(ComboButton)
auto append(sComboButtonItem item) { return self().append(item), *this; }
auto doChange() const { return self().doChange(); }
auto item(unsigned position) const { return self().item(position); }
auto items() const { return self().items(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto remove(sComboButtonItem item) { return self().remove(item), *this; }
auto reset() { return self().reset(), *this; }
auto selected() const { return self().selected(); }
auto setParent(mObject* parent = nullptr, signed offset = -1) { return self().setParent(parent, offset), *this; }
};
#endif
#if defined(Hiro_Console)
struct Console : sConsole {
DeclareSharedWidget(Console)
auto backgroundColor() const { return self().backgroundColor(); }
auto doActivate(string command) const { return self().doActivate(command); }
auto foregroundColor() const { return self().foregroundColor(); }
auto onActivate(const function<void (string)>& callback = {}) { return self().onActivate(callback), *this; }
auto print(const string& text) { return self().print(text), *this; }
auto prompt() const { return self().prompt(); }
auto reset() { return self().reset(), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setPrompt(const string& prompt = "") { return self().setPrompt(prompt), *this; }
};
#endif
#if defined(Hiro_Frame)
struct Frame : sFrame {
DeclareSharedWidget(Frame)
auto append(sLayout layout) { return self().append(layout), *this; }
auto layout() const { return self().layout(); }
auto remove(sLayout layout) { return self().remove(layout), *this; }
auto reset() { return self().reset(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_HexEdit)
struct HexEdit : sHexEdit {
DeclareSharedWidget(HexEdit)
auto backgroundColor() const { return self().backgroundColor(); }
auto columns() const { return self().columns(); }
auto doRead(unsigned offset) const { return self().doRead(offset); }
auto doWrite(unsigned offset, uint8_t data) const { return self().doWrite(offset, data); }
auto foregroundColor() const { return self().foregroundColor(); }
auto length() const { return self().length(); }
auto offset() const { return self().offset(); }
auto onRead(const function<uint8_t (unsigned)>& callback = {}) { return self().onRead(callback), *this; }
auto onWrite(const function<void (unsigned, uint8_t)>& callback = {}) { return self().onWrite(callback), *this; }
auto rows() const { return self().rows(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setColumns(unsigned columns = 16) { return self().setColumns(columns), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setLength(unsigned length) { return self().setLength(length), *this; }
auto setOffset(unsigned offset) { return self().setOffset(offset), *this; }
auto setRows(unsigned rows = 16) { return self().setRows(rows), *this; }
auto update() { return self().update(), *this; }
};
#endif
#if defined(Hiro_HorizontalScroller)
struct HorizontalScroller : sHorizontalScroller {
DeclareSharedWidget(HorizontalScroller)
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto position() const { return self().position(); }
auto setLength(unsigned length = 101) { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_HorizontalSlider)
struct HorizontalSlider : sHorizontalSlider {
DeclareSharedWidget(HorizontalSlider)
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto position() const { return self().position(); }
auto setLength(unsigned length = 101) { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_IconView)
struct IconViewItem : sIconViewItem {
DeclareSharedObject(IconViewItem)
auto icon() const { return self().icon(); }
auto selected() const { return self().selected(); }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setSelected(bool selected = true) { return self().setSelected(selected), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_IconView)
struct IconView : sIconView {
DeclareSharedWidget(IconView)
auto append(sIconViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
auto doActivate() const { return self().doActivate(); }
auto doChange() const { return self().doChange(); }
auto doContext() const { return self().doContext(); }
auto flow() const { return self().flow(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto item(unsigned position) const { return self().item(position); }
auto items() const { return self().items(); }
auto multiSelect() const { return self().multiSelect(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) { return self().onContext(callback), *this; }
auto orientation() const { return self().orientation(); }
auto remove(sIconViewItem item) { return self().remove(item), *this; }
auto reset() { return self().reset(), *this; }
auto selected() const { return self().selected(); }
auto selectedItems() const { return self().selectedItems(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setFlow(Orientation orientation = Orientation::Vertical) { return self().setFlow(orientation), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setMultiSelect(bool multiSelect = true) { return self().setMultiSelect(multiSelect), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) { return self().setOrientation(orientation), *this; }
auto setSelected(const vector<signed>& selections) { return self().setSelected(selections), *this; }
};
#endif
#if defined(Hiro_Label)
struct Label : sLabel {
DeclareSharedWidget(Label)
auto horizontalAlignment() const { return self().horizontalAlignment(); }
auto setHorizontalAlignment(double alignment = 0.0) { return self().setHorizontalAlignment(alignment), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto setVerticalAlignment(double alignment = 0.5) { return self().setVerticalAlignment(alignment), *this; }
auto text() const { return self().text(); }
auto verticalAlignment() const { return self().verticalAlignment(); }
};
#endif
#if defined(Hiro_LineEdit)
struct LineEdit : sLineEdit {
DeclareSharedWidget(LineEdit)
auto backgroundColor() const { return self().backgroundColor(); }
auto doActivate() const { return self().doActivate(); }
auto doChange() const { return self().doChange(); }
auto editable() const { return self().editable(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setEditable(bool editable = true) { return self().setEditable(editable), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_ListView)
struct ListViewColumn : sListViewColumn {
DeclareSharedObject(ListViewColumn)
auto active() const { return self().active(); }
auto backgroundColor() const { return self().backgroundColor(); }
auto editable() const { return self().editable(); }
auto expandable() const { return self().expandable(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto horizontalAlignment() const { return self().horizontalAlignment(); }
auto icon() const { return self().icon(); }
auto resizable() const { return self().resizable(); }
auto setActive() { return self().setActive(), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setEditable(bool editable = true) { return self().setEditable(editable), *this; }
auto setExpandable(bool expandable = true) { return self().setExpandable(expandable), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setHorizontalAlignment(double alignment = 0.0) { return self().setHorizontalAlignment(alignment), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setResizable(bool resizable = true) { return self().setResizable(resizable), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto setVerticalAlignment(double alignment = 0.5) { return self().setVerticalAlignment(alignment), *this; }
auto setWidth(signed width = 0) { return self().setWidth(width), *this; }
auto text() const { return self().text(); }
auto verticalAlignment() const { return self().verticalAlignment(); }
auto width() const { return self().width(); }
};
#endif
#if defined(Hiro_ListView)
struct ListViewCell : sListViewCell {
DeclareSharedObject(ListViewCell)
auto backgroundColor() const { return self().backgroundColor(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto icon() const { return self().icon(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_ListView)
struct ListViewItem : sListViewItem {
DeclareSharedObject(ListViewItem)
auto append(sListViewCell cell) { return self().append(cell), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
auto cell(unsigned position) const { return self().cell(position); }
auto cells() const { return self().cells(); }
auto checked() const { return self().checked(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto remove(sListViewCell cell) { return self().remove(cell), *this; }
auto selected() const { return self().selected(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setChecked(bool checked = true) { return self().setChecked(checked), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setSelected(bool selected = true) { return self().setSelected(selected), *this; }
};
#endif
#if defined(Hiro_ListView)
struct ListView : sListView {
DeclareSharedWidget(ListView)
auto append(sListViewColumn column) { return self().append(column), *this; }
auto append(sListViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
auto batchable() const { return self().batchable(); }
auto checkable() const { return self().checkable(); }
auto checkAll() { return self().checkAll(), *this; }
auto checked() const { return self().checked(); }
auto column(unsigned position) { return self().column(position); }
auto columns() const { return self().columns(); }
auto doActivate() const { return self().doActivate(); }
auto doChange() const { return self().doChange(); }
auto doContext() const { return self().doContext(); }
auto doEdit(sListViewCell cell) const { return self().doEdit(cell); }
auto doSort(sListViewColumn column) const { return self().doSort(column); }
auto doToggle(sListViewItem item) const { return self().doToggle(item); }
auto foregroundColor() const { return self().foregroundColor(); }
auto gridVisible() const { return self().gridVisible(); }
auto headerVisible() const { return self().headerVisible(); }
auto item(unsigned position) { return self().item(position); }
auto items() const { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) { return self().onContext(callback), *this; }
auto onEdit(const function<void (ListViewCell)>& callback = {}) { return self().onEdit(callback), *this; }
auto onSort(const function<void (ListViewColumn)>& callback = {}) { return self().onSort(callback), *this; }
auto onToggle(const function<void (ListViewItem)>& callback = {}) { return self().onToggle(callback), *this; }
auto remove(sListViewColumn column) { return self().remove(column), *this; }
auto remove(sListViewItem item) { return self().remove(item), *this; }
auto reset() { return self().reset(), *this; }
auto resizeColumns() { return self().resizeColumns(), *this; }
auto selectAll() { return self().selectAll(), *this; }
auto selected() const { return self().selected(); }
auto selectedItems() const { return self().selectedItems(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setBatchable(bool batchable = true) { return self().setBatchable(batchable), *this; }
auto setCheckable(bool checkable = true) { return self().setCheckable(checkable), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setGridVisible(bool visible = true) { return self().setGridVisible(visible), *this; }
auto setHeaderVisible(bool visible = true) { return self().setHeaderVisible(visible), *this; }
auto setSortable(bool sortable = true) { return self().setSortable(sortable), *this; }
auto sortable() const { return self().sortable(); }
auto uncheckAll() { return self().uncheckAll(), *this; }
auto unselectAll() { return self().unselectAll(), *this; }
};
#endif
#if defined(Hiro_ProgressBar)
struct ProgressBar : sProgressBar {
DeclareSharedWidget(ProgressBar)
auto position() const { return self().position(); }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_RadioButton)
struct RadioButton : sRadioButton {
DeclareSharedWidget(RadioButton)
auto bordered() const { return self().bordered(); }
auto checked() const { return self().checked(); }
auto doActivate() const { return self().doActivate(); }
auto group() const { return self().group(); }
auto icon() const { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto orientation() const { return self().orientation(); }
auto setBordered(bool bordered = true) { return self().setBordered(bordered), *this; }
auto setChecked() { return self().setChecked(), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_RadioLabel)
struct RadioLabel : sRadioLabel {
DeclareSharedWidget(RadioLabel)
auto checked() const { return self().checked(); }
auto doActivate() const { return self().doActivate(); }
auto group() const { return self().group(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto setChecked() { return self().setChecked(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_SourceEdit)
struct SourceEdit : sSourceEdit {
DeclareSharedWidget(SourceEdit)
auto doChange() const { return self().doChange(); }
auto doMove() const { return self().doMove(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onMove(const function<void ()>& callback = {}) { return self().onMove(callback), *this; }
auto position() const { return self().position(); }
auto setPosition(signed position) { return self().setPosition(position), *this; }
auto setSelected(Position selected) { return self().setSelected(selected), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_TabFrame)
struct TabFrameItem : sTabFrameItem {
DeclareSharedObject(TabFrameItem)
auto append(sLayout layout) { return self().append(layout), *this; }
auto closable() const { return self().closable(); }
auto icon() const { return self().icon(); }
auto layout() const { return self().layout(); }
auto movable() const { return self().movable(); }
auto remove(sLayout layout) { return self().remove(layout), *this; }
auto reset() { return self().reset(), *this; }
auto selected() const { return self().selected(); }
auto setClosable(bool closable = true) { return self().setClosable(closable), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setMovable(bool movable = true) { return self().setMovable(movable), *this; }
auto setSelected() { return self().setSelected(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_TabFrame)
struct TabFrame : sTabFrame {
DeclareSharedWidget(TabFrame)
auto append(sTabFrameItem item) { return self().append(item), *this; }
auto doChange() const { return self().doChange(); }
auto doClose(sTabFrameItem item) const { return self().doClose(item); }
auto doMove(sTabFrameItem from, sTabFrameItem to) const { return self().doMove(from, to); }
auto edge() const { return self().edge(); }
auto item(unsigned position) const { return self().item(position); }
auto items() const { return self().items(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onClose(const function<void (sTabFrameItem)>& callback = {}) { return self().onClose(callback), *this; }
auto onMove(const function<void (sTabFrameItem, sTabFrameItem)>& callback = {}) { return self().onMove(callback), *this; }
auto remove(sTabFrameItem item) { return self().remove(item), *this; }
auto reset() { return self().reset(), *this; }
auto selected() const { return self().selected(); }
auto setEdge(Edge edge = Edge::Top) { return self().setEdge(edge), *this; }
};
#endif
#if defined(Hiro_TextEdit)
struct TextEdit : sTextEdit {
DeclareSharedWidget(TextEdit)
auto backgroundColor() const { return self().backgroundColor(); }
auto cursorPosition() const { return self().cursorPosition(); }
auto doChange() const { return self().doChange(); }
auto doMove() const { return self().doMove(); }
auto editable() const { return self().editable(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onMove(const function<void ()>& callback = {}) { return self().onMove(callback), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setCursorPosition(unsigned position) { return self().setCursorPosition(position), *this; }
auto setEditable(bool editable = true) { return self().setEditable(editable), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto setWordWrap(bool wordWrap = true) { return self().setWordWrap(wordWrap), *this; }
auto text() const { return self().text(); }
auto wordWrap() const { return self().wordWrap(); }
};
#endif
#if defined(Hiro_TreeView)
struct TreeViewItem : sTreeViewItem {
DeclareSharedObject(TreeViewItem)
auto append(sTreeViewItem item) { return self().append(item), *this; }
auto checked() const { return self().checked(); }
auto icon() const { return self().icon(); }
auto item(const string& path) const { return self().item(path); }
auto items() const { return self().items(); }
auto path() const { return self().path(); }
auto remove(sTreeViewItem item) { return self().remove(item), *this; }
auto selected() const { return self().selected(); }
auto setChecked(bool checked = true) { return self().setChecked(checked), *this; }
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
auto setSelected() { return self().setSelected(), *this; }
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_TreeView)
struct TreeView : sTreeView {
DeclareSharedWidget(TreeView)
auto append(sTreeViewItem item) { return self().append(item), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
auto checkable() const { return self().checkable(); }
auto collapse() { return self().collapse(), *this; }
auto doActivate() const { return self().doActivate(); }
auto doChange() const { return self().doChange(); }
auto doContext() const { return self().doContext(); }
auto doToggle(sTreeViewItem item) const { return self().doToggle(item); }
auto expand() { return self().expand(), *this; }
auto foregroundColor() const { return self().foregroundColor(); }
auto item(const string& path) const { return self().item(path); }
auto items() const { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) { return self().onContext(callback), *this; }
auto onToggle(const function<void (sTreeViewItem)>& callback = {}) { return self().onToggle(callback), *this; }
auto remove(sTreeViewItem item) { return self().remove(item), *this; }
auto reset() { return self().reset(), *this; }
auto selected() const { return self().selected(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setCheckable(bool checkable = true) { return self().setCheckable(checkable), *this; }
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
};
#endif
#if defined(Hiro_VerticalScroller)
struct VerticalScroller : sVerticalScroller {
DeclareSharedWidget(VerticalScroller)
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto position() const { return self().position(); }
auto setLength(unsigned length = 101) { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_VerticalSlider)
struct VerticalSlider : sVerticalSlider {
DeclareSharedWidget(VerticalSlider)
auto doChange() const { return self().doChange(); }
auto length() const { return self().length(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto position() const { return self().position(); }
auto setLength(unsigned length = 101) { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_Viewport)
struct Viewport : sViewport {
DeclareSharedWidget(Viewport)
auto doDrop(lstring names) const { return self().doDrop(names); }
auto doMouseLeave() const { return self().doMouseLeave(); }
auto doMouseMove(Position position) const { return self().doMouseMove(position); }
auto doMousePress(Mouse::Button button) const { return self().doMousePress(button); }
auto doMouseRelease(Mouse::Button button) const { return self().doMouseRelease(button); }
auto droppable() const { return self().droppable(); }
auto handle() const { return self().handle(); }
auto onDrop(const function<void (lstring)>& callback = {}) { return self().onDrop(callback), *this; }
auto onMouseLeave(const function<void ()>& callback = {}) { return self().onMouseLeave(callback), *this; }
auto onMouseMove(const function<void (Position)>& callback = {}) { return self().onMouseMove(callback), *this; }
auto onMousePress(const function<void (Mouse::Button)>& callback = {}) { return self().onMousePress(callback), *this; }
auto onMouseRelease(const function<void (Mouse::Button)>& callback = {}) { return self().onMouseRelease(callback), *this; }
auto setDroppable(bool droppable = true) { return self().setDroppable(droppable), *this; }
};
#endif
#if defined(Hiro_StatusBar)
struct StatusBar : sStatusBar {
DeclareSharedObject(StatusBar)
auto setText(const string& text = "") { return self().setText(text), *this; }
auto text() const { return self().text(); }
};
#endif
#if defined(Hiro_PopupMenu)
struct PopupMenu : sPopupMenu {
DeclareSharedObject(PopupMenu)
auto action(unsigned position) const { return self().action(position); }
auto actions() const { return self().actions(); }
auto append(sAction action) { return self().append(action), *this; }
auto remove(sAction action) { return self().remove(action), *this; }
auto reset() { return self().reset(), *this; }
};
#endif
#if defined(Hiro_MenuBar)
struct MenuBar : sMenuBar {
DeclareSharedObject(MenuBar)
auto append(sMenu menu) { return self().append(menu), *this; }
auto menu(unsigned position) const { return self().menu(position); }
auto menus() const { return self().menus(); }
auto remove(sMenu menu) { return self().remove(menu), *this; }
auto reset() { return self().reset(), *this; }
};
#endif
#if defined(Hiro_Window)
struct Window : sWindow {
DeclareSharedObject(Window)
auto append(sLayout layout) { return self().append(layout), *this; }
auto append(sMenuBar menuBar) { return self().append(menuBar), *this; }
auto append(sStatusBar statusBar) { return self().append(statusBar), *this; }
auto backgroundColor() const { return self().backgroundColor(); }
auto doClose() const { return self().doClose(); }
auto doDrop(lstring names) const { return self().doDrop(names); }
auto doKeyPress(signed key) const { return self().doKeyPress(key); }
auto doKeyRelease(signed key) const { return self().doKeyRelease(key); }
auto doMove() const { return self().doMove(); }
auto doSize() const { return self().doSize(); }
auto droppable() const { return self().droppable(); }
auto frameGeometry() const { return self().frameGeometry(); }
auto fullScreen() const { return self().fullScreen(); }
auto geometry() const { return self().geometry(); }
auto layout() const { return self().layout(); }
auto menuBar() const { return self().menuBar(); }
auto modal() const { return self().modal(); }
auto onClose(const function<void ()>& callback = {}) { return self().onClose(callback), *this; }
auto onDrop(const function<void (lstring)>& callback = {}) { return self().onDrop(callback), *this; }
auto onKeyPress(const function<void (signed)>& callback = {}) { return self().onKeyPress(callback), *this; }
auto onKeyRelease(const function<void (signed)>& callback = {}) { return self().onKeyRelease(callback), *this; }
auto onMove(const function<void ()>& callback = {}) { return self().onMove(callback), *this; }
auto onSize(const function<void ()>& callback = {}) { return self().onSize(callback), *this; }
auto remove(sLayout layout) { return self().remove(layout), *this; }
auto remove(sMenuBar menuBar) { return self().remove(menuBar), *this; }
auto remove(sStatusBar statusBar) { return self().remove(statusBar), *this; }
auto reset() { return self().reset(), *this; }
auto resizable() const { return self().resizable(); }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setCentered(sWindow parent = {}) { return self().setCentered(parent), *this; }
auto setDroppable(bool droppable = true) { return self().setDroppable(droppable), *this; }
auto setFrameGeometry(Geometry geometry) { return self().setFrameGeometry(geometry), *this; }
auto setFramePosition(Position position) { return self().setFramePosition(position), *this; }
auto setFrameSize(Size size) { return self().setFrameSize(size), *this; }
auto setFullScreen(bool fullScreen = true) { return self().setFullScreen(fullScreen), *this; }
auto setGeometry(Geometry geometry) { return self().setGeometry(geometry), *this; }
auto setModal(bool modal = true) { return self().setModal(modal), *this; }
auto setPlacement(double x, double y) { return self().setPlacement(x, y), *this; }
auto setPosition(Position position) { return self().setPosition(position), *this; }
auto setResizable(bool resizable = true) { return self().setResizable(resizable), *this; }
auto setSize(Size size) { return self().setSize(size), *this; }
auto setTitle(const string& title = "") { return self().setTitle(title), *this; }
auto statusBar() const { return self().statusBar(); }
auto title() const { return self().title(); }
};
#endif

View File

@ -107,7 +107,7 @@ auto mCanvas::setHorizontalGradient(Color left, Color right) -> type& {
} }
auto mCanvas::setIcon(const image& icon) -> type& { auto mCanvas::setIcon(const image& icon) -> type& {
state.size = {(signed)icon.width, (signed)icon.height}; state.size = {(signed)icon.width(), (signed)icon.height()};
state.icon = icon; state.icon = icon;
signal(setIcon, icon); signal(setIcon, icon);
return *this; return *this;

View File

@ -22,7 +22,7 @@ auto mComboButton::doChange() const -> void {
if(state.onChange) return state.onChange(); if(state.onChange) return state.onChange();
} }
auto mComboButton::item(unsigned position) const -> sComboButtonItem { auto mComboButton::item(unsigned position) const -> ComboButtonItem {
if(position < items()) return state.items[position]; if(position < items()) return state.items[position];
return {}; return {};
} }
@ -53,11 +53,11 @@ auto mComboButton::reset() -> type& {
return *this; return *this;
} }
auto mComboButton::selected() const -> sComboButtonItem { auto mComboButton::selected() const -> ComboButtonItem {
for(auto& item : state.items) { for(auto& item : state.items) {
if(item->selected()) return item; if(item->selected()) return item;
} }
return {}; return {nullptr};
} }
auto mComboButton::setParent(mObject* parent, signed offset) -> type& { auto mComboButton::setParent(mObject* parent, signed offset) -> type& {

View File

@ -11,18 +11,18 @@ auto mFrame::destruct() -> void {
// //
auto mFrame::append(shared_pointer<mLayout> layout) -> type& { auto mFrame::append(sLayout layout) -> type& {
if(auto& layout = state.layout) remove(layout); if(auto& layout = state.layout) remove(layout);
state.layout = layout; state.layout = layout;
layout->setParent(this, 0); layout->setParent(this, 0);
return *this; return *this;
} }
auto mFrame::layout() const -> shared_pointer<mLayout> { auto mFrame::layout() const -> Layout {
return state.layout; return state.layout;
} }
auto mFrame::remove(shared_pointer<mLayout> layout) -> type& { auto mFrame::remove(sLayout layout) -> type& {
layout->setParent(); layout->setParent();
state.layout.reset(); state.layout.reset();
return *this; return *this;

View File

@ -11,7 +11,7 @@ auto mIconView::destruct() -> void {
// //
auto mIconView::append(shared_pointer<mIconViewItem> item) -> type& { auto mIconView::append(sIconViewItem item) -> type& {
state.items.append(item); state.items.append(item);
item->setParent(this, items() - 1); item->setParent(this, items() - 1);
signal(append, item); signal(append, item);
@ -42,9 +42,9 @@ auto mIconView::foregroundColor() const -> Color {
return state.foregroundColor; return state.foregroundColor;
} }
auto mIconView::item(unsigned position) const -> shared_pointer<mIconViewItem> { auto mIconView::item(unsigned position) const -> IconViewItem {
if(position >= items()) throw; if(position < items()) return state.items[position];
return state.items[position]; return {};
} }
auto mIconView::items() const -> unsigned { auto mIconView::items() const -> unsigned {
@ -74,7 +74,7 @@ auto mIconView::orientation() const -> Orientation {
return state.orientation; return state.orientation;
} }
auto mIconView::remove(shared_pointer<mIconViewItem> item) -> type& { auto mIconView::remove(sIconViewItem item) -> type& {
signal(remove, item); signal(remove, item);
state.items.remove(item->offset()); state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) { for(auto n : range(item->offset(), items())) {

View File

@ -17,7 +17,7 @@ auto mListViewItem::backgroundColor() const -> Color {
return state.backgroundColor; return state.backgroundColor;
} }
auto mListViewItem::cell(unsigned position) const -> sListViewCell { auto mListViewItem::cell(unsigned position) const -> ListViewCell {
if(position < cells()) return state.cells[position]; if(position < cells()) return state.cells[position];
return {}; return {};
} }

View File

@ -44,15 +44,15 @@ auto mListView::checkAll() -> type& {
return *this; return *this;
} }
auto mListView::checked() const -> vector<sListViewItem> { auto mListView::checked() const -> vector<ListViewItem> {
vector<sListViewItem> items; vector<ListViewItem> items;
for(auto& item : state.items) { for(auto& item : state.items) {
if(item->checked()) items.append(item); if(item->checked()) items.append(item);
} }
return items; return items;
} }
auto mListView::column(unsigned position) const -> sListViewColumn { auto mListView::column(unsigned position) const -> ListViewColumn {
if(position < columns()) return state.columns[position]; if(position < columns()) return state.columns[position];
return {}; return {};
} }
@ -97,7 +97,7 @@ auto mListView::headerVisible() const -> bool {
return state.headerVisible; return state.headerVisible;
} }
auto mListView::item(unsigned position) const -> sListViewItem { auto mListView::item(unsigned position) const -> ListViewItem {
if(position < items()) return state.items[position]; if(position < items()) return state.items[position];
return {}; return {};
} }
@ -121,17 +121,17 @@ auto mListView::onContext(const function<void ()>& callback) -> type& {
return *this; return *this;
} }
auto mListView::onEdit(const function<void (sListViewCell)>& callback) -> type& { auto mListView::onEdit(const function<void (ListViewCell)>& callback) -> type& {
state.onEdit = callback; state.onEdit = callback;
return *this; return *this;
} }
auto mListView::onSort(const function<void (sListViewColumn)>& callback) -> type& { auto mListView::onSort(const function<void (ListViewColumn)>& callback) -> type& {
state.onSort = callback; state.onSort = callback;
return *this; return *this;
} }
auto mListView::onToggle(const function<void (sListViewItem)>& callback) -> type& { auto mListView::onToggle(const function<void (ListViewItem)>& callback) -> type& {
state.onToggle = callback; state.onToggle = callback;
return *this; return *this;
} }
@ -178,15 +178,15 @@ auto mListView::selectAll() -> type& {
return *this; return *this;
} }
auto mListView::selected() const -> sListViewItem { auto mListView::selected() const -> ListViewItem {
for(auto& item : state.items) { for(auto& item : state.items) {
if(item->selected()) return item; if(item->selected()) return item;
} }
return {}; return {nullptr};
} }
auto mListView::selectedItems() const -> vector<sListViewItem> { auto mListView::selectedItems() const -> vector<ListViewItem> {
vector<sListViewItem> items; vector<ListViewItem> items;
for(auto& item : state.items) { for(auto& item : state.items) {
if(item->selected()) items.append(item); if(item->selected()) items.append(item);
} }

View File

@ -18,7 +18,7 @@ auto mRadioButton::doActivate() const -> void {
if(state.onActivate) return state.onActivate(); if(state.onActivate) return state.onActivate();
} }
auto mRadioButton::group() const -> sGroup { auto mRadioButton::group() const -> Group {
return state.group; return state.group;
} }

View File

@ -14,7 +14,7 @@ auto mRadioLabel::doActivate() const -> void {
if(state.onActivate) return state.onActivate(); if(state.onActivate) return state.onActivate();
} }
auto mRadioLabel::group() const -> sGroup { auto mRadioLabel::group() const -> Group {
return state.group; return state.group;
} }

View File

@ -27,7 +27,7 @@ auto mTabFrameItem::icon() const -> image {
return state.icon; return state.icon;
} }
auto mTabFrameItem::layout() const -> sLayout { auto mTabFrameItem::layout() const -> Layout {
return state.layout; return state.layout;
} }

View File

@ -34,7 +34,7 @@ auto mTabFrame::edge() const -> Edge {
return state.edge; return state.edge;
} }
auto mTabFrame::item(unsigned position) const -> sTabFrameItem { auto mTabFrame::item(unsigned position) const -> TabFrameItem {
if(position < items()) return state.items[position]; if(position < items()) return state.items[position];
return {}; return {};
} }
@ -48,12 +48,12 @@ auto mTabFrame::onChange(const function<void ()>& callback) -> type& {
return *this; return *this;
} }
auto mTabFrame::onClose(const function<void (sTabFrameItem)>& callback) -> type& { auto mTabFrame::onClose(const function<void (TabFrameItem)>& callback) -> type& {
state.onClose = callback; state.onClose = callback;
return *this; return *this;
} }
auto mTabFrame::onMove(const function<void (sTabFrameItem, sTabFrameItem)>& callback) -> type& { auto mTabFrame::onMove(const function<void (TabFrameItem, TabFrameItem)>& callback) -> type& {
state.onMove = callback; state.onMove = callback;
return *this; return *this;
} }
@ -74,11 +74,11 @@ auto mTabFrame::reset() -> type& {
return *this; return *this;
} }
auto mTabFrame::selected() const -> sTabFrameItem { auto mTabFrame::selected() const -> TabFrameItem {
for(auto& item : state.items) { for(auto& item : state.items) {
if(item->selected()) return item; if(item->selected()) return item;
} }
return {}; return {nullptr};
} }
auto mTabFrame::setEdge(Edge edge) -> type& { auto mTabFrame::setEdge(Edge edge) -> type& {

View File

@ -26,7 +26,7 @@ auto mTreeViewItem::icon() const -> image {
return state.icon; return state.icon;
} }
auto mTreeViewItem::item(const string& path) const -> sTreeViewItem { auto mTreeViewItem::item(const string& path) const -> TreeViewItem {
if(path.empty()) return {}; if(path.empty()) return {};
auto paths = path.split("/"); auto paths = path.split("/");
unsigned position = decimal(paths.takeFirst()); unsigned position = decimal(paths.takeFirst());

View File

@ -56,7 +56,7 @@ auto mTreeView::foregroundColor() const -> Color {
return state.foregroundColor; return state.foregroundColor;
} }
auto mTreeView::item(const string& path) const -> sTreeViewItem { auto mTreeView::item(const string& path) const -> TreeViewItem {
if(path.empty()) return {}; if(path.empty()) return {};
auto paths = path.split("/"); auto paths = path.split("/");
unsigned position = decimal(paths.takeFirst()); unsigned position = decimal(paths.takeFirst());
@ -107,7 +107,7 @@ auto mTreeView::reset() -> type& {
return *this; return *this;
} }
auto mTreeView::selected() const -> sTreeViewItem { auto mTreeView::selected() const -> TreeViewItem {
return item(state.selectedPath); return item(state.selectedPath);
} }

View File

@ -87,11 +87,11 @@ auto mWindow::geometry() const -> Geometry {
return state.geometry; return state.geometry;
} }
auto mWindow::layout() const -> shared_pointer<mLayout> { auto mWindow::layout() const -> Layout {
return state.layout; return state.layout;
} }
auto mWindow::menuBar() const -> shared_pointer<mMenuBar> { auto mWindow::menuBar() const -> MenuBar {
return state.menuBar; return state.menuBar;
} }
@ -266,7 +266,7 @@ auto mWindow::setTitle(const string& title) -> type& {
return *this; return *this;
} }
auto mWindow::statusBar() const -> shared_pointer<mStatusBar> { auto mWindow::statusBar() const -> StatusBar {
return state.statusBar; return state.statusBar;
} }

View File

@ -1,906 +1,32 @@
#define Declare(Name) \
using type = Name; \
Name() : s##Name(new m##Name, [](auto p) { \
p->unbind(); \
delete p; \
}) { \
(*this)->bind(*this); \
} \
template<typename T, typename... P> Name(T* parent, P&&... p) : Name() { \
if(parent && *parent) (*parent)->append(*this, std::forward<P>(p)...); \
} \
auto self() const -> m##Name& { return (m##Name&)operator*(); } \
#define DeclareObject(Name) \
Declare(Name) \
auto enabled(bool recursive = false) const -> bool { return self().enabled(recursive); } \
auto focused() const -> bool { return self().focused(); } \
auto font(bool recursive = false) const -> string { return self().font(recursive); } \
auto remove() -> type& { return self().remove(), *this; } \
auto setEnabled(bool enabled = true) -> type& { return self().setEnabled(enabled), *this; } \
auto setFocused() -> type& { return self().setFocused(), *this; } \
auto setFont(const string& font = "") -> type& { return self().setFont(font), *this; } \
auto setVisible(bool visible = true) -> type& { return self().setVisible(visible), *this; } \
auto visible(bool recursive = false) const -> bool { return self().visible(recursive); } \
#define DeclareAction(Name) \
DeclareObject(Name) \
#define DeclareSizable(Name) \
DeclareObject(Name) \
auto geometry() const -> Geometry { return self().geometry(); } \
auto minimumSize() const -> Size { return self().minimumSize(); } \
auto setGeometry(Geometry geometry) -> type& { return self().setGeometry(geometry), *this; } \
#define DeclareLayout(Name) \
DeclareSizable(Name) \
auto append(sSizable sizable) -> type& { return self().append(sizable), *this; } \
auto remove(sSizable sizable) -> type& { return self().remove(sizable), *this; } \
auto reset() -> type& { return self().reset(), *this; } \
auto sizable(unsigned position) -> sSizable { return self().sizable(position); } \
auto sizables() const -> unsigned { return self().sizables(); } \
#define DeclareWidget(Name) \
DeclareSizable(Name) \
auto doSize() const -> void { return self().doSize(); } \
auto onSize(const function<void ()>& callback = {}) -> type& { return self().onSize(callback), *this; } \
#if defined(Hiro_Object)
struct Object : sObject {
DeclareObject(Object)
};
#endif
#if defined(Hiro_Group)
struct Group : sGroup {
using type = Group;
Group() : sGroup(new mGroup, [](auto p) { p->unbind(); delete p; }) { (*this)->bind(*this); }
template<typename... P> Group(P&&... p) : Group() { _append(std::forward<P>(p)...); }
auto self() const -> mGroup& { return (mGroup&)operator*(); }
auto append(sObject object) -> type& { return self().append(object), *this; }
auto object(unsigned position) const -> sObject { return self().object(position); }
auto objects() const -> unsigned { return self().objects(); }
auto remove(sObject object) -> type& { return self().remove(object), *this; }
private:
auto _append() -> void {}
template<typename T, typename... P> auto _append(T* object, P&&... p) -> void {
append(*object);
_append(std::forward<P>(p)...);
}
};
#endif
#if defined(Hiro_Hotkey)
struct Hotkey : sHotkey {
DeclareObject(Hotkey)
auto doPress() const -> void { return self().doPress(); }
auto doRelease() const -> void { return self().doRelease(); }
auto onPress(const function<void ()>& callback = {}) -> type& { return self().onPress(callback), *this; }
auto onRelease(const function<void ()>& callback = {}) -> type& { return self().onRelease(callback), *this; }
auto parent() const -> wObject { return self().parent(); }
auto sequence() const -> string { return self().sequence(); }
auto setParent(sObject object) -> type& { return self().setParent(object), *this; }
auto setSequence(const string& sequence = "") -> type& { return self().setSequence(sequence), *this; }
};
#endif
#if defined(Hiro_Timer)
struct Timer : sTimer {
DeclareObject(Timer)
auto doActivate() const -> void { return self().doActivate(); }
auto interval() const -> unsigned { return self().interval(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto setInterval(unsigned interval = 0) -> type& { return self().setInterval(interval), *this; }
};
#endif
#if defined(Hiro_Window)
struct Window : sWindow {
DeclareObject(Window)
auto append(sLayout layout) -> type& { return self().append(layout), *this; }
auto append(sMenuBar menuBar) -> type& { return self().append(menuBar), *this; }
auto append(sStatusBar statusBar) -> type& { return self().append(statusBar), *this; }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto doClose() const -> void { return self().doClose(); }
auto doDrop(lstring names) const -> void { return self().doDrop(names); }
auto doKeyPress(signed key) const -> void { return self().doKeyPress(key); }
auto doKeyRelease(signed key) const -> void { return self().doKeyRelease(key); }
auto doMove() const -> void { return self().doMove(); }
auto doSize() const -> void { return self().doSize(); }
auto droppable() const -> bool { return self().droppable(); }
auto frameGeometry() const -> Geometry { return self().frameGeometry(); }
auto fullScreen() const -> bool { return self().fullScreen(); }
auto geometry() const -> Geometry { return self().geometry(); }
auto layout() const -> sLayout { return self().layout(); }
auto menuBar() const -> sMenuBar { return self().menuBar(); }
auto modal() const -> bool { return self().modal(); }
auto onClose(const function<void ()>& callback = {}) -> type& { return self().onClose(callback), *this; }
auto onDrop(const function<void (lstring)>& callback = {}) -> type& { return self().onDrop(callback), *this; }
auto onKeyPress(const function<void (signed)>& callback = {}) -> type& { return self().onKeyPress(callback), *this; }
auto onKeyRelease(const function<void (signed)>& callback = {}) -> type& { return self().onKeyRelease(callback), *this; }
auto onMove(const function<void ()>& callback = {}) -> type& { return self().onMove(callback), *this; }
auto onSize(const function<void ()>& callback = {}) -> type& { return self().onSize(callback), *this; }
auto remove(sLayout layout) -> type& { return self().remove(layout), *this; }
auto remove(sMenuBar menuBar) -> type& { return self().remove(menuBar), *this; }
auto remove(sStatusBar statusBar) -> type& { return self().remove(statusBar), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto resizable() const -> bool { return self().resizable(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setCentered(sWindow parent = {}) -> type& { return self().setCentered(parent), *this; }
auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; }
auto setFrameGeometry(Geometry geometry) -> type& { return self().setFrameGeometry(geometry), *this; }
auto setFramePosition(Position position) -> type& { return self().setFramePosition(position), *this; }
auto setFrameSize(Size size) -> type& { return self().setFrameSize(size), *this; }
auto setFullScreen(bool fullScreen = true) -> type& { return self().setFullScreen(fullScreen), *this; }
auto setGeometry(Geometry geometry) -> type& { return self().setGeometry(geometry), *this; }
auto setModal(bool modal = true) -> type& { return self().setModal(modal), *this; }
auto setPlacement(double x, double y) -> type& { return self().setPlacement(x, y), *this; }
auto setPosition(Position position) -> type& { return self().setPosition(position), *this; }
auto setResizable(bool resizable = true) -> type& { return self().setResizable(resizable), *this; }
auto setSize(Size size) -> type& { return self().setSize(size), *this; }
auto setTitle(const string& title = "") -> type& { return self().setTitle(title), *this; }
auto statusBar() const -> sStatusBar { return self().statusBar(); }
auto title() const -> string { return self().title(); }
};
#endif
#if defined(Hiro_StatusBar)
struct StatusBar : sStatusBar {
DeclareObject(StatusBar)
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_MenuBar)
struct MenuBar : sMenuBar {
DeclareObject(MenuBar)
auto append(sMenu menu) -> type& { return self().append(menu), *this; }
auto menu(unsigned position) const -> sMenu { return self().menu(position); }
auto menus() const -> unsigned { return self().menus(); }
auto remove(sMenu menu) -> type& { return self().remove(menu), *this; }
auto reset() -> type& { return self().reset(), *this; }
};
#endif
#if defined(Hiro_PopupMenu)
struct PopupMenu : sPopupMenu {
DeclareObject(PopupMenu)
auto action(unsigned position) const -> sAction { return self().action(position); }
auto actions() const -> unsigned { return self().actions(); }
auto append(sAction action) -> type& { return self().append(action), *this; }
auto remove(sAction action) -> type& { return self().remove(action), *this; }
auto reset() -> type& { return self().reset(), *this; }
};
#endif
#if defined(Hiro_Action)
struct Action : sAction {
DeclareAction(Action)
};
#endif
#if defined(Hiro_Menu)
struct Menu : sMenu {
DeclareAction(Menu)
auto action(unsigned position) const -> sAction { return self().action(position); }
auto actions() const -> unsigned { return self().actions(); }
auto append(sAction action) -> type& { return self().append(action), *this; }
auto icon() const -> image { return self().icon(); }
auto remove(sAction action) -> type& { return self().remove(action), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_MenuSeparator)
struct MenuSeparator : sMenuSeparator {
DeclareAction(MenuSeparator)
};
#endif
#if defined(Hiro_MenuItem)
struct MenuItem : sMenuItem {
DeclareAction(MenuItem)
auto doActivate() const -> void { return self().doActivate(); }
auto icon() const -> image { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_MenuCheckItem)
struct MenuCheckItem : sMenuCheckItem {
DeclareAction(MenuCheckItem)
auto checked() const -> bool { return self().checked(); }
auto doToggle() const -> void { return self().doToggle(); }
auto onToggle(const function<void ()>& callback = {}) -> type& { return self().onToggle(callback), *this; }
auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_MenuRadioItem)
struct MenuRadioItem : sMenuRadioItem {
DeclareAction(MenuRadioItem)
auto checked() const -> bool { return self().checked(); }
auto doActivate() const -> void { return self().doActivate(); }
auto group() const -> sGroup { return self().group(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto setChecked() -> type& { return self().setChecked(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_Sizable)
struct Sizable : sSizable {
DeclareSizable(Sizable)
};
#endif
#if defined(Hiro_Layout)
struct Layout : sLayout {
DeclareLayout(Layout)
};
#endif
#if defined(Hiro_Widget)
struct Widget : sWidget {
DeclareWidget(Widget)
};
#endif
#if defined(Hiro_Button)
struct Button : sButton {
DeclareWidget(Button)
auto bordered() const -> bool { return self().bordered(); }
auto doActivate() const -> void { return self().doActivate(); }
auto icon() const -> image { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto orientation() const -> Orientation { return self().orientation(); }
auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_Canvas)
struct Canvas : sCanvas {
DeclareWidget(Canvas)
auto color() const -> Color { return self().color(); }
auto data() -> uint32_t* { return self().data(); }
auto droppable() const -> bool { return self().droppable(); }
auto doDrop(lstring names) -> void { return self().doDrop(names); }
auto doMouseLeave() const -> void { return self().doMouseLeave(); }
auto doMouseMove(Position position) const -> void { return self().doMouseMove(position); }
auto doMousePress(Mouse::Button button) const -> void { return self().doMousePress(button); }
auto doMouseRelease(Mouse::Button button) const -> void { return self().doMouseRelease(button); }
auto gradient() const -> vector<Color> { return self().gradient(); }
auto icon() const -> image { return self().icon(); }
auto onDrop(const function<void (lstring)>& callback = {}) -> type& { return self().onDrop(callback), *this; }
auto onMouseLeave(const function<void ()>& callback = {}) -> type& { return self().onMouseLeave(callback), *this; }
auto onMouseMove(const function<void (Position)>& callback = {}) -> type& { return self().onMouseMove(callback), *this; }
auto onMousePress(const function<void (Mouse::Button)>& callback = {}) -> type& { return self().onMousePress(callback), *this; }
auto onMouseRelease(const function<void (Mouse::Button)>& callback = {}) -> type& { return self().onMouseRelease(callback), *this; }
auto setColor(Color color) -> type& { return self().setColor(color), *this; }
auto setData(Size size) -> type& { return self().setData(size), *this; }
auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; }
auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> type& { return self().setGradient(topLeft, topRight, bottomLeft, bottomRight), *this; }
auto setHorizontalGradient(Color left, Color right) -> type& { return self().setGradient(left, right, left, right), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setVerticalGradient(Color top, Color bottom) -> type& { return self().setGradient(top, top, bottom, bottom), *this; }
auto size() const -> Size { return self().size(); }
auto update() -> type& { return self().update(), *this; }
};
#endif
#if defined(Hiro_CheckButton)
struct CheckButton : sCheckButton {
DeclareWidget(CheckButton)
auto bordered() const -> bool { return self().bordered(); }
auto checked() const -> bool { return self().checked(); }
auto doToggle() const -> void { return self().doToggle(); }
auto icon() const -> image { return self().icon(); }
auto onToggle(const function<void ()>& callback = {}) -> type& { return self().onToggle(callback), *this; }
auto orientation() const -> Orientation { return self().orientation(); }
auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; }
auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_CheckLabel)
struct CheckLabel : sCheckLabel {
DeclareWidget(CheckLabel)
auto checked() const -> bool { return self().checked(); }
auto doToggle() const -> void { return self().doToggle(); }
auto onToggle(const function<void ()>& callback = {}) -> type& { return self().onToggle(callback), *this; }
auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_ComboButton)
struct ComboButton : sComboButton {
DeclareWidget(ComboButton)
auto append(sComboButtonItem item) -> type& { return self().append(item), *this; }
auto doChange() const -> void { return self().doChange(); }
auto item(unsigned position) const -> sComboButtonItem { return self().item(position); }
auto items() const -> unsigned { return self().items(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto remove(sComboButtonItem item) -> type& { return self().remove(item), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto selected() const -> sComboButtonItem { return self().selected(); }
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& { return self().setParent(parent, offset), *this; }
};
#endif
#if defined(Hiro_ComboButton)
struct ComboButtonItem : sComboButtonItem {
DeclareObject(ComboButtonItem)
auto icon() const -> image { return self().icon(); }
auto selected() const -> bool { return self().selected(); }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setSelected() -> type& { return self().setSelected(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_Console)
struct Console : sConsole {
DeclareWidget(Console)
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto doActivate(string command) const -> void { return self().doActivate(command); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto onActivate(const function<void (string)>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto print(const string& text) -> type& { return self().print(text), *this; }
auto prompt() const -> string { return self().prompt(); }
auto reset() -> type& { return self().reset(), *this; }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setPrompt(const string& prompt = "") -> type& { return self().setPrompt(prompt), *this; }
};
#endif
#if defined(Hiro_Frame)
struct Frame : sFrame {
DeclareWidget(Frame)
auto append(sLayout layout) -> type& { return self().append(layout), *this; }
auto layout() const -> sLayout { return self().layout(); }
auto remove(sLayout layout) -> type& { return self().remove(layout), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_HexEdit)
struct HexEdit : sHexEdit {
DeclareWidget(HexEdit)
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto columns() const -> unsigned { return self().columns(); }
auto doRead(unsigned offset) const -> uint8_t { return self().doRead(offset); }
auto doWrite(unsigned offset, uint8_t data) const -> void { return self().doWrite(offset, data); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto length() const -> unsigned { return self().length(); }
auto offset() const -> unsigned { return self().offset(); }
auto onRead(const function<uint8_t (unsigned)>& callback = {}) -> type& { return self().onRead(callback), *this; }
auto onWrite(const function<void (unsigned, uint8_t)>& callback = {}) -> type& { return self().onWrite(callback), *this; }
auto rows() const -> unsigned { return self().rows(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setColumns(unsigned columns = 16) -> type& { return self().setColumns(columns), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setLength(unsigned length) -> type& { return self().setLength(length), *this; }
auto setOffset(unsigned offset) -> type& { return self().setOffset(offset), *this; }
auto setRows(unsigned rows = 16) -> type& { return self().setRows(rows), *this; }
auto update() -> type& { return self().update(), *this; }
};
#endif
#if defined(Hiro_HorizontalScroller)
struct HorizontalScroller : sHorizontalScroller {
DeclareWidget(HorizontalScroller)
auto doChange() const -> void { return self().doChange(); }
auto length() const -> unsigned { return self().length(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto position() const -> unsigned { return self().position(); }
auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_HorizontalSlider)
struct HorizontalSlider : sHorizontalSlider {
DeclareWidget(HorizontalSlider)
auto doChange() const -> void { return self().doChange(); }
auto length() const -> unsigned { return self().length(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto position() const -> unsigned { return self().position(); }
auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_IconView)
struct IconView : sIconView {
DeclareWidget(IconView)
auto append(sIconViewItem item) -> type& { return self().append(item), *this; }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto doActivate() const -> void { return self().doActivate(); }
auto doChange() const -> void { return self().doChange(); }
auto doContext() const -> void { return self().doContext(); }
auto flow() const -> Orientation { return self().flow(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto item(unsigned position) const -> sIconViewItem { return self().item(position); }
auto items() const -> unsigned { return self().items(); }
auto multiSelect() const -> bool { return self().multiSelect(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) -> type& { return self().onContext(callback), *this; }
auto orientation() const -> Orientation { return self().orientation(); }
auto remove(sIconViewItem item) -> type& { return self().remove(item), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto selected() const -> maybe<unsigned> { return self().selected(); }
auto selectedItems() const -> vector<unsigned> { return self().selectedItems(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setFlow(Orientation orientation = Orientation::Vertical) -> type& { return self().setFlow(orientation), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setMultiSelect(bool multiSelect = true) -> type& { return self().setMultiSelect(multiSelect), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; }
auto setSelected(const vector<signed>& selections) -> type& { return self().setSelected(selections), *this; }
};
#endif
#if defined(Hiro_IconView)
struct IconViewItem : sIconViewItem {
DeclareObject(IconViewItem)
auto icon() const -> image { return self().icon(); }
auto selected() const -> bool { return self().selected(); }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setSelected(bool selected = true) -> type& { return self().setSelected(selected), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_Label)
struct Label : sLabel {
DeclareWidget(Label)
auto horizontalAlignment() const -> double { return self().horizontalAlignment(); }
auto setHorizontalAlignment(double alignment = 0.0) -> type& { return self().setHorizontalAlignment(alignment), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto setVerticalAlignment(double alignment = 0.5) -> type& { return self().setVerticalAlignment(alignment), *this; }
auto text() const -> string { return self().text(); }
auto verticalAlignment() const -> double { return self().verticalAlignment(); }
};
#endif
#if defined(Hiro_LineEdit)
struct LineEdit : sLineEdit {
DeclareWidget(LineEdit)
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto doActivate() const -> void { return self().doActivate(); }
auto doChange() const -> void { return self().doChange(); }
auto editable() const -> bool { return self().editable(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_ListView)
struct ListView : sListView {
DeclareWidget(ListView)
auto append(sListViewColumn column) -> type& { return self().append(column), *this; }
auto append(sListViewItem item) -> type& { return self().append(item), *this; }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto batchable() const -> bool { return self().batchable(); }
auto checkable() const -> bool { return self().checkable(); }
auto checkAll() -> type& { return self().checkAll(), *this; }
auto checked() const -> vector<sListViewItem> { return self().checked(); }
auto column(unsigned position) -> sListViewColumn { return self().column(position); }
auto columns() const -> unsigned { return self().columns(); }
auto doActivate() const -> void { return self().doActivate(); }
auto doChange() const -> void { return self().doChange(); }
auto doContext() const -> void { return self().doContext(); }
auto doEdit(sListViewCell cell) const -> void { return self().doEdit(cell); }
auto doSort(sListViewColumn column) const -> void { return self().doSort(column); }
auto doToggle(sListViewItem item) const -> void { return self().doToggle(item); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto gridVisible() const -> bool { return self().gridVisible(); }
auto headerVisible() const -> bool { return self().headerVisible(); }
auto item(unsigned position) -> sListViewItem { return self().item(position); }
auto items() const -> unsigned { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) -> type& { return self().onContext(callback), *this; }
auto onEdit(const function<void (sListViewCell)>& callback = {}) -> type& { return self().onEdit(callback), *this; }
auto onSort(const function<void (sListViewColumn)>& callback = {}) -> type& { return self().onSort(callback), *this; }
auto onToggle(const function<void (sListViewItem)>& callback = {}) -> type& { return self().onToggle(callback), *this; }
auto remove(sListViewColumn column) -> type& { return self().remove(column), *this; }
auto remove(sListViewItem item) -> type& { return self().remove(item), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto resizeColumns() -> type& { return self().resizeColumns(), *this; }
auto selectAll() -> type& { return self().selectAll(), *this; }
auto selected() const -> sListViewItem { return self().selected(); }
auto selectedItems() const -> vector<sListViewItem> { return self().selectedItems(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setBatchable(bool batchable = true) -> type& { return self().setBatchable(batchable), *this; }
auto setCheckable(bool checkable = true) -> type& { return self().setCheckable(checkable), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setGridVisible(bool visible = true) -> type& { return self().setGridVisible(visible), *this; }
auto setHeaderVisible(bool visible = true) -> type& { return self().setHeaderVisible(visible), *this; }
auto setSortable(bool sortable = true) -> type& { return self().setSortable(sortable), *this; }
auto sortable() const -> bool { return self().sortable(); }
auto uncheckAll() -> type& { return self().uncheckAll(), *this; }
auto unselectAll() -> type& { return self().unselectAll(), *this; }
};
#endif
#if defined(Hiro_ListView)
struct ListViewColumn : sListViewColumn {
DeclareObject(ListViewColumn)
auto active() const -> bool { return self().active(); }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto editable() const -> bool { return self().editable(); }
auto expandable() const -> bool { return self().expandable(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto horizontalAlignment() const -> double { return self().horizontalAlignment(); }
auto icon() const -> image { return self().icon(); }
auto resizable() const -> bool { return self().resizable(); }
auto setActive() -> type& { return self().setActive(), *this; }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; }
auto setExpandable(bool expandable = true) -> type& { return self().setExpandable(expandable), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setHorizontalAlignment(double alignment = 0.0) -> type& { return self().setHorizontalAlignment(alignment), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setResizable(bool resizable = true) -> type& { return self().setResizable(resizable), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto setVerticalAlignment(double alignment = 0.5) -> type& { return self().setVerticalAlignment(alignment), *this; }
auto setWidth(signed width = 0) -> type& { return self().setWidth(width), *this; }
auto text() const -> string { return self().text(); }
auto verticalAlignment() const -> double { return self().verticalAlignment(); }
auto width() const -> signed { return self().width(); }
};
#endif
#if defined(Hiro_ListView)
struct ListViewItem : sListViewItem {
DeclareObject(ListViewItem)
auto append(sListViewCell cell) -> type& { return self().append(cell), *this; }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto cell(unsigned position) const -> sListViewCell { return self().cell(position); }
auto cells() const -> unsigned { return self().cells(); }
auto checked() const -> bool { return self().checked(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto remove(sListViewCell cell) -> type& { return self().remove(cell), *this; }
auto selected() const -> bool { return self().selected(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setSelected(bool selected = true) -> type& { return self().setSelected(selected), *this; }
};
#endif
#if defined(Hiro_ListView)
struct ListViewCell : sListViewCell {
DeclareObject(ListViewCell)
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto icon() const -> image { return self().icon(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_ProgressBar)
struct ProgressBar : sProgressBar {
DeclareWidget(ProgressBar)
auto position() const -> unsigned { return self().position(); }
auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_RadioButton)
struct RadioButton : sRadioButton {
DeclareWidget(RadioButton)
auto bordered() const -> bool { return self().bordered(); }
auto checked() const -> bool { return self().checked(); }
auto doActivate() const -> void { return self().doActivate(); }
auto group() const -> sGroup { return self().group(); }
auto icon() const -> image { return self().icon(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto orientation() const -> Orientation { return self().orientation(); }
auto setBordered(bool bordered = true) -> type& { return self().setBordered(bordered), *this; }
auto setChecked() -> type& { return self().setChecked(), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setOrientation(Orientation orientation = Orientation::Horizontal) -> type& { return self().setOrientation(orientation), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_RadioLabel)
struct RadioLabel : sRadioLabel {
DeclareWidget(RadioLabel)
auto checked() const -> bool { return self().checked(); }
auto doActivate() const -> void { return self().doActivate(); }
auto group() const -> sGroup { return self().group(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto setChecked() -> type& { return self().setChecked(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_SourceEdit)
struct SourceEdit : sSourceEdit {
DeclareWidget(SourceEdit)
auto doChange() const -> void { return self().doChange(); }
auto doMove() const -> void { return self().doMove(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onMove(const function<void ()>& callback = {}) -> type& { return self().onMove(callback), *this; }
auto position() const -> unsigned { return self().position(); }
auto setPosition(signed position) -> type& { return self().setPosition(position), *this; }
auto setSelected(Position selected) -> type& { return self().setSelected(selected), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_TabFrame)
struct TabFrame : sTabFrame {
DeclareWidget(TabFrame)
auto append(sTabFrameItem item) -> type& { return self().append(item), *this; }
auto doChange() const -> void { return self().doChange(); }
auto doClose(sTabFrameItem item) const -> void { return self().doClose(item); }
auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void { return self().doMove(from, to); }
auto edge() const -> Edge;
auto item(unsigned position) const -> sTabFrameItem { return self().item(position); }
auto items() const -> unsigned { return self().items(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onClose(const function<void (sTabFrameItem)>& callback = {}) -> type& { return self().onClose(callback), *this; }
auto onMove(const function<void (sTabFrameItem, sTabFrameItem)>& callback = {}) -> type& { return self().onMove(callback), *this; }
auto remove(sTabFrameItem item) -> type& { return self().remove(item), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto selected() const -> sTabFrameItem { return self().selected(); }
auto setEdge(Edge edge = Edge::Top) -> type& { return self().setEdge(edge), *this; }
};
#endif
#if defined(Hiro_TabFrame)
struct TabFrameItem : sTabFrameItem {
DeclareObject(TabFrameItem)
auto append(sLayout layout) -> type& { return self().append(layout), *this; }
auto closable() const -> bool { return self().closable(); }
auto icon() const -> image { return self().icon(); }
auto layout() const -> sLayout { return self().layout(); }
auto movable() const -> bool { return self().movable(); }
auto remove(sLayout layout) -> type& { return self().remove(layout), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto selected() const -> bool { return self().selected(); }
auto setClosable(bool closable = true) -> type& { return self().setClosable(closable), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setMovable(bool movable = true) -> type& { return self().setMovable(movable), *this; }
auto setSelected() -> type& { return self().setSelected(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_TextEdit)
struct TextEdit : sTextEdit {
DeclareWidget(TextEdit)
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto cursorPosition() const -> unsigned { return self().cursorPosition(); }
auto doChange() const -> void { return self().doChange(); }
auto doMove() const -> void { return self().doMove(); }
auto editable() const -> bool { return self().editable(); }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onMove(const function<void ()>& callback = {}) -> type& { return self().onMove(callback), *this; }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setCursorPosition(unsigned position) -> type& { return self().setCursorPosition(position), *this; }
auto setEditable(bool editable = true) -> type& { return self().setEditable(editable), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto setWordWrap(bool wordWrap = true) -> type& { return self().setWordWrap(wordWrap), *this; }
auto text() const -> string { return self().text(); }
auto wordWrap() const -> bool { return self().wordWrap(); }
};
#endif
#if defined(Hiro_TreeView)
struct TreeView : sTreeView {
DeclareWidget(TreeView)
auto append(sTreeViewItem item) -> type& { return self().append(item), *this; }
auto backgroundColor() const -> Color { return self().backgroundColor(); }
auto checkable() const -> bool { return self().checkable(); }
auto collapse() -> type& { return self().collapse(), *this; }
auto doActivate() const -> void { return self().doActivate(); }
auto doChange() const -> void { return self().doChange(); }
auto doContext() const -> void { return self().doContext(); }
auto doToggle(sTreeViewItem item) const -> void { return self().doToggle(item); }
auto expand() -> type& { return self().expand(), *this; }
auto foregroundColor() const -> Color { return self().foregroundColor(); }
auto item(const string& path) const -> sTreeViewItem { return self().item(path); }
auto items() const -> unsigned { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) -> type& { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) -> type& { return self().onContext(callback), *this; }
auto onToggle(const function<void (sTreeViewItem)>& callback = {}) -> type& { return self().onToggle(callback), *this; }
auto remove(sTreeViewItem item) -> type& { return self().remove(item), *this; }
auto reset() -> type& { return self().reset(), *this; }
auto selected() const -> sTreeViewItem { return self().selected(); }
auto setBackgroundColor(Color color = {}) -> type& { return self().setBackgroundColor(color), *this; }
auto setCheckable(bool checkable = true) -> type& { return self().setCheckable(checkable), *this; }
auto setForegroundColor(Color color = {}) -> type& { return self().setForegroundColor(color), *this; }
};
#endif
#if defined(Hiro_TreeView)
struct TreeViewItem : sTreeViewItem {
DeclareObject(TreeViewItem)
auto append(sTreeViewItem item) -> type& { return self().append(item), *this; }
auto checked() const -> bool { return self().checked(); }
auto icon() const -> image { return self().icon(); }
auto item(const string& path) const -> sTreeViewItem { return self().item(path); }
auto items() const -> unsigned { return self().items(); }
auto path() const -> string { return self().path(); }
auto remove(sTreeViewItem item) -> type& { return self().remove(item), *this; }
auto selected() const -> bool { return self().selected(); }
auto setChecked(bool checked = true) -> type& { return self().setChecked(checked), *this; }
auto setIcon(const image& icon = {}) -> type& { return self().setIcon(icon), *this; }
auto setSelected() -> type& { return self().setSelected(), *this; }
auto setText(const string& text = "") -> type& { return self().setText(text), *this; }
auto text() const -> string { return self().text(); }
};
#endif
#if defined(Hiro_VerticalScroller)
struct VerticalScroller : sVerticalScroller {
DeclareWidget(VerticalScroller)
auto doChange() const -> void { return self().doChange(); }
auto length() const -> unsigned { return self().length(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto position() const -> unsigned { return self().position(); }
auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_VerticalSlider)
struct VerticalSlider : sVerticalSlider {
DeclareWidget(VerticalSlider)
auto doChange() const -> void { return self().doChange(); }
auto length() const -> unsigned { return self().length(); }
auto onChange(const function<void ()>& callback = {}) -> type& { return self().onChange(callback), *this; }
auto position() const -> unsigned { return self().position(); }
auto setLength(unsigned length = 101) -> type& { return self().setLength(length), *this; }
auto setPosition(unsigned position = 0) -> type& { return self().setPosition(position), *this; }
};
#endif
#if defined(Hiro_Viewport)
struct Viewport : sViewport {
DeclareWidget(Viewport)
auto doDrop(lstring names) const -> void { return self().doDrop(names); }
auto doMouseLeave() const -> void { return self().doMouseLeave(); }
auto doMouseMove(Position position) const -> void { return self().doMouseMove(position); }
auto doMousePress(Mouse::Button button) const -> void { return self().doMousePress(button); }
auto doMouseRelease(Mouse::Button button) const -> void { return self().doMouseRelease(button); }
auto droppable() const -> bool { return self().droppable(); }
auto handle() const -> uintptr_t { return self().handle(); }
auto onDrop(const function<void (lstring)>& callback = {}) -> type& { return self().onDrop(callback), *this; }
auto onMouseLeave(const function<void ()>& callback = {}) -> type& { return self().onMouseLeave(callback), *this; }
auto onMouseMove(const function<void (Position)>& callback = {}) -> type& { return self().onMouseMove(callback), *this; }
auto onMousePress(const function<void (Mouse::Button)>& callback = {}) -> type& { return self().onMousePress(callback), *this; }
auto onMouseRelease(const function<void (Mouse::Button)>& callback = {}) -> type& { return self().onMouseRelease(callback), *this; }
auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; }
};
#endif
#if defined(Hiro_FixedLayout) #if defined(Hiro_FixedLayout)
using sFixedLayout = shared_pointer<mFixedLayout>; using sFixedLayout = shared_pointer<mFixedLayout>;
struct FixedLayout : sFixedLayout { struct FixedLayout : sFixedLayout {
DeclareLayout(FixedLayout) DeclareSharedLayout(FixedLayout)
auto append(sSizable sizable, Geometry geometry) -> type& { return self().append(sizable, geometry), *this; } auto append(sSizable sizable, Geometry geometry) { return self().append(sizable, geometry), *this; }
}; };
#endif #endif
#if defined(Hiro_HorizontalLayout) #if defined(Hiro_HorizontalLayout)
using sHorizontalLayout = shared_pointer<mHorizontalLayout>; using sHorizontalLayout = shared_pointer<mHorizontalLayout>;
struct HorizontalLayout : sHorizontalLayout { struct HorizontalLayout : sHorizontalLayout {
DeclareLayout(HorizontalLayout) DeclareSharedLayout(HorizontalLayout)
auto append(sSizable sizable, Size size, signed spacing = 5) -> type& { return self().append(sizable, size, spacing), *this; } auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; }
auto setAlignment(double alignment = 0.5) -> type& { return self().setAlignment(alignment), *this; } auto setAlignment(double alignment = 0.5) { return self().setAlignment(alignment), *this; }
auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; }
auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; }
}; };
#endif #endif
#if defined(Hiro_VerticalLayout) #if defined(Hiro_VerticalLayout)
using sVerticalLayout = shared_pointer<mVerticalLayout>; using sVerticalLayout = shared_pointer<mVerticalLayout>;
struct VerticalLayout : sVerticalLayout { struct VerticalLayout : sVerticalLayout {
DeclareLayout(VerticalLayout) DeclareSharedLayout(VerticalLayout)
auto append(sSizable sizable, Size size, signed spacing = 5) -> type& { return self().append(sizable, size, spacing), *this; } auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; }
auto setAlignment(double alignment = 0.0) -> type& { return self().setAlignment(alignment), *this; } auto setAlignment(double alignment = 0.0) { return self().setAlignment(alignment), *this; }
auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; }
auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; }
}; };
#endif #endif
#undef Declare
#undef DeclareObject
#undef DeclareAction
#undef DeclareSizable
#undef DeclareLayout
#undef DeclareWidget

View File

@ -11,22 +11,21 @@ static auto CreateColor(const Color& color) -> GdkColor {
} }
#endif #endif
static auto CreatePixbuf(const nall::image& image, bool scale = false) -> GdkPixbuf* { static auto CreatePixbuf(image icon, bool scale = false) -> GdkPixbuf* {
if(!image) return nullptr; if(!icon) return nullptr;
nall::image gdkImage = image; if(scale) icon.scale(15, 15);
gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); icon.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); //GTK stores images in ABGR format
if(scale) gdkImage.scale(15, 15);
GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height); auto pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, icon.width(), icon.height());
memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4); memory::copy(gdk_pixbuf_get_pixels(pixbuf), icon.data(), icon.size());
return pixbuf; return pixbuf;
} }
static auto CreateImage(const nall::image& image, bool scale = false) -> GtkImage* { static auto CreateImage(const nall::image& image, bool scale = false) -> GtkImage* {
GdkPixbuf* pixbuf = CreatePixbuf(image, scale); auto pixbuf = CreatePixbuf(image, scale);
GtkImage* gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf); auto gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf);
g_object_unref(pixbuf); g_object_unref(pixbuf);
return gtkImage; return gtkImage;
} }

View File

@ -26,13 +26,13 @@ auto pButton::minimumSize() const -> Size {
Size size = pFont::size(self().font(true), state().text); Size size = pFont::size(self().font(true), state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + (state().text ? 24 : 12), size.height() + 12}; return {size.width() + (state().text ? 24 : 12), size.height() + 12};

View File

@ -174,14 +174,14 @@ auto pCanvas::_rasterize() -> void {
fill.gradient( fill.gradient(
state().gradient[0].value(), state().gradient[1].value(), state().gradient[2].value(), state().gradient[3].value() state().gradient[0].value(), state().gradient[1].value(), state().gradient[2].value(), state().gradient[3].value()
); );
memory::copy(buffer, fill.data, fill.size); memory::copy(buffer, fill.data(), fill.size());
} }
if(mode == Mode::Icon) { if(mode == Mode::Icon) {
auto icon = state().icon; auto icon = state().icon;
icon.scale(width, height); icon.scale(width, height);
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
memory::copy(buffer, icon.data, icon.size); memory::copy(buffer, icon.data(), icon.size());
} }
if(mode == Mode::Data) { if(mode == Mode::Data) {

View File

@ -29,13 +29,13 @@ auto pCheckButton::minimumSize() const -> Size {
Size size = pFont::size(self().font(true), state().text); Size size = pFont::size(self().font(true), state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + 24, size.height() + 12}; return {size.width() + 24, size.height() + 12};

View File

@ -224,7 +224,7 @@ auto pListView::_cellWidth(unsigned _row, unsigned _column) -> unsigned {
if(auto item = self().item(_row)) { if(auto item = self().item(_row)) {
if(auto cell = item->cell(_column)) { if(auto cell = item->cell(_column)) {
if(auto& icon = cell->state.icon) { if(auto& icon = cell->state.icon) {
width += icon.width + 2; width += icon.width() + 2;
} }
if(auto& text = cell->state.text) { if(auto& text = cell->state.text) {
width += Font::size(cell->font(true), text).width(); width += Font::size(cell->font(true), text).width();
@ -243,7 +243,7 @@ auto pListView::_columnWidth(unsigned _column) -> unsigned {
unsigned width = 8; //margin unsigned width = 8; //margin
if(auto column = self().column(_column)) { if(auto column = self().column(_column)) {
if(auto& icon = column->state.icon) { if(auto& icon = column->state.icon) {
width += icon.width + 2; width += icon.width() + 2;
} }
if(auto& text = column->state.text) { if(auto& text = column->state.text) {
width += Font::size(column->font(true), text).width(); width += Font::size(column->font(true), text).width();

View File

@ -30,13 +30,13 @@ auto pRadioButton::minimumSize() const -> Size {
Size size = pFont::size(self().font(true), state().text); Size size = pFont::size(self().font(true), state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + 24, size.height() + 12}; return {size.width() + 24, size.height() + 12};

View File

@ -369,9 +369,9 @@ auto pWindow::_setIcon(const string& pathname) -> bool {
filename = {pathname, Application::state.name, ".png"}; filename = {pathname, Application::state.name, ".png"};
if(file::exists(filename)) { if(file::exists(filename)) {
//maximum image size GTK+ supports is 256x256; scale image down if necessary to prevent error //maximum image size GTK+ supports is 256x256; scale image down if necessary to prevent error
nall::image icon(filename); image icon(filename);
icon.scale(min(256u, icon.width), min(256u, icon.height), true); icon.scale(min(256u, icon.width()), min(256u, icon.height()), true);
GdkPixbuf* pixbuf = CreatePixbuf(icon); auto pixbuf = CreatePixbuf(icon);
gtk_window_set_icon(GTK_WINDOW(widget), pixbuf); gtk_window_set_icon(GTK_WINDOW(widget), pixbuf);
g_object_unref(G_OBJECT(pixbuf)); g_object_unref(G_OBJECT(pixbuf));
return true; return true;

View File

@ -14,4 +14,11 @@
#include "core/core.hpp" #include "core/core.hpp"
#include "extension/extension.hpp" #include "extension/extension.hpp"
#undef DeclareShared
#undef DeclareSharedObject
#undef DeclareSharedAction
#undef DeclareSharedSizable
#undef DeclareSharedLayout
#undef DeclareSharedWidget
#endif #endif

View File

@ -27,7 +27,7 @@ auto pMenuItem::_createBitmap() -> void {
if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; } if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; }
if(auto icon = state().icon) { if(auto icon = state().icon) {
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
icon.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline) icon.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline)
icon.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear); icon.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
hbitmap = CreateBitmap(icon); hbitmap = CreateBitmap(icon);

View File

@ -32,7 +32,7 @@ auto pMenu::_createBitmap() -> void {
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; } if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
if(auto icon = state().icon) { if(auto icon = state().icon) {
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
icon.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline) icon.alphaBlend(GetSysColor(COLOR_MENU)); //Windows does not alpha blend menu icons properly (leaves black outline)
icon.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear); icon.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear);
hbitmap = CreateBitmap(icon); hbitmap = CreateBitmap(icon);

View File

@ -12,20 +12,20 @@ static auto OsVersion() -> unsigned {
return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0); return (versionInfo.dwMajorVersion << 8) + (versionInfo.dwMajorVersion << 0);
} }
static auto CreateBitmap(const image& image) -> HBITMAP { static auto CreateBitmap(const image& icon) -> HBITMAP {
HDC hdc = GetDC(0); HDC hdc = GetDC(0);
BITMAPINFO bitmapInfo; BITMAPINFO bitmapInfo;
memset(&bitmapInfo, 0, sizeof(BITMAPINFO)); memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = image.width; bitmapInfo.bmiHeader.biWidth = icon.width();
bitmapInfo.bmiHeader.biHeight = -image.height; //bitmaps are stored upside down unless we negate height bitmapInfo.bmiHeader.biHeight = -(signed)icon.height(); //bitmaps are stored upside down unless we negate height
bitmapInfo.bmiHeader.biPlanes = 1; bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32; bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB; bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = image.width * image.height * 4; bitmapInfo.bmiHeader.biSizeImage = icon.size();
void* bits = nullptr; void* bits = nullptr;
HBITMAP hbitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0); HBITMAP hbitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
if(bits) memcpy(bits, image.data, image.width * image.height * 4); if(bits) memory::copy(bits, icon.data(), icon.size());
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
return hbitmap; return hbitmap;
} }
@ -68,7 +68,7 @@ static auto ImageList_Append(HIMAGELIST imageList, const image& source, unsigned
image.allocate(scale, scale); image.allocate(scale, scale);
image.fill(GetSysColor(COLOR_WINDOW)); image.fill(GetSysColor(COLOR_WINDOW));
} }
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); image.transform();
image.scale(scale, scale); image.scale(scale, scale);
HBITMAP bitmap = CreateBitmap(image); HBITMAP bitmap = CreateBitmap(image);
ImageList_Add(imageList, bitmap, NULL); ImageList_Add(imageList, bitmap, NULL);

View File

@ -24,13 +24,13 @@ auto pButton::minimumSize() const -> Size {
auto size = pFont::size(hfont, state().text); auto size = pFont::size(hfont, state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + (state().text ? 20 : 13), size.height() + 10}; return {size.width() + (state().text ? 20 : 13), size.height() + 10};
@ -58,7 +58,7 @@ auto pButton::onActivate() -> void {
//performs setIcon, setOrientation, setText //performs setIcon, setOrientation, setText
auto pButton::_setState() -> void { auto pButton::_setState() -> void {
image icon = state().icon; image icon = state().icon;
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; } if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; }
if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; }
@ -68,7 +68,7 @@ auto pButton::_setState() -> void {
if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE));
hbitmap = CreateBitmap(icon); hbitmap = CreateBitmap(icon);
himagelist = ImageList_Create(icon.width, icon.height, ILC_COLOR32, 1, 0); himagelist = ImageList_Create(icon.width(), icon.height(), ILC_COLOR32, 1, 0);
ImageList_Add(himagelist, hbitmap, NULL); ImageList_Add(himagelist, hbitmap, NULL);
BUTTON_IMAGELIST list; BUTTON_IMAGELIST list;
list.himl = himagelist; list.himl = himagelist;

View File

@ -162,14 +162,14 @@ auto pCanvas::_rasterize() -> void {
state().gradient[0].value(), state().gradient[1].value(), state().gradient[0].value(), state().gradient[1].value(),
state().gradient[2].value(), state().gradient[3].value() state().gradient[2].value(), state().gradient[3].value()
); );
memory::copy(pixels.data(), fill.data, fill.size); memory::copy(pixels.data(), fill.data(), fill.size());
} }
if(mode == Mode::Icon) { if(mode == Mode::Icon) {
auto icon = state().icon; auto icon = state().icon;
icon.scale(width, height); icon.scale(width, height);
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
memory::copy(pixels.data(), icon.data, icon.size); memory::copy(pixels.data(), icon.data(), icon.size());
} }
if(mode == Mode::Data) { if(mode == Mode::Data) {

View File

@ -23,13 +23,13 @@ auto pCheckButton::minimumSize() -> Size {
auto size = pFont::size(hfont, state().text); auto size = pFont::size(hfont, state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + (state().text ? 20 : 10), size.height() + 10}; return {size.width() + (state().text ? 20 : 10), size.height() + 10};
@ -62,16 +62,16 @@ auto pCheckButton::onToggle() -> void {
auto pCheckButton::_setState() -> void { auto pCheckButton::_setState() -> void {
image icon = state().icon; image icon = state().icon;
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; } if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; }
if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } if(himagelist) { ImageList_Destroy(himagelist); himagelist = nullptr; }
if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE));
hbitmap = CreateBitmap(icon); hbitmap = CreateBitmap(icon);
himagelist = ImageList_Create(icon.width, icon.height, ILC_COLOR32, 1, 0); himagelist = ImageList_Create(icon.width(), icon.height(), ILC_COLOR32, 1, 0);
ImageList_Add(himagelist, hbitmap, NULL); ImageList_Add(himagelist, hbitmap, nullptr);
BUTTON_IMAGELIST list; BUTTON_IMAGELIST list;
list.himl = himagelist; list.himl = himagelist;
switch(state().orientation) { switch(state().orientation) {

View File

@ -232,14 +232,19 @@ auto pListView::onChange(LPARAM lparam) -> void {
PostMessageOnce(_parentHandle(), AppMessage::ListView_onChange, 0, (LPARAM)&reference); PostMessageOnce(_parentHandle(), AppMessage::ListView_onChange, 0, (LPARAM)&reference);
} }
if(!locked()) {
unsigned row = nmlistview->iItem; unsigned row = nmlistview->iItem;
unsigned mask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1; unsigned mask = nmlistview->uNewState & LVIS_STATEIMAGEMASK;
if((mask == 0 || mask == 1) && !locked()) { if(mask == 0x1000 || mask == 0x2000) {
bool checked = mask == 0x2000;
if(auto item = self().item(row)) { if(auto item = self().item(row)) {
item->state.checked = !item->state.checked; if(checked != item->state.checked) { //WC_LISTVIEW sends this message twice
item->state.checked = checked;
self().doToggle(item); self().doToggle(item);
} }
} }
}
}
} }
auto pListView::onContext(LPARAM lparam) -> void { auto pListView::onContext(LPARAM lparam) -> void {
@ -288,7 +293,7 @@ auto pListView::onCustomDraw(LPARAM lparam) -> LRESULT {
if(!cell) continue; if(!cell) continue;
if(auto icon = cell->state.icon) { if(auto icon = cell->state.icon) {
icon.scale(iconSize, iconSize); icon.scale(iconSize, iconSize);
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
auto bitmap = CreateBitmap(icon); auto bitmap = CreateBitmap(icon);
SelectBitmap(hdcSource, bitmap); SelectBitmap(hdcSource, bitmap);
BLENDFUNCTION blend{AC_SRC_OVER, 0, (BYTE)(selected ? 128 : 255), AC_SRC_ALPHA}; BLENDFUNCTION blend{AC_SRC_OVER, 0, (BYTE)(selected ? 128 : 255), AC_SRC_ALPHA};
@ -413,7 +418,7 @@ auto pListView::_setIcons() -> void {
auto icon = state().columns(column)->state.icon; auto icon = state().columns(column)->state.icon;
if(icon) { if(icon) {
icon.scale(16, 16); icon.scale(16, 16);
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
} else { } else {
icon.allocate(16, 16); icon.allocate(16, 16);
icon.fill(0x00ffffff); icon.fill(0x00ffffff);

View File

@ -23,13 +23,13 @@ auto pRadioButton::minimumSize() -> Size {
auto size = pFont::size(hfont, state().text); auto size = pFont::size(hfont, state().text);
if(state().orientation == Orientation::Horizontal) { if(state().orientation == Orientation::Horizontal) {
size.setWidth(size.width() + state().icon.width); size.setWidth(size.width() + state().icon.width());
size.setHeight(max(size.height(), state().icon.height)); size.setHeight(max(size.height(), state().icon.height()));
} }
if(state().orientation == Orientation::Vertical) { if(state().orientation == Orientation::Vertical) {
size.setWidth(max(size.width(), state().icon.width)); size.setWidth(max(size.width(), state().icon.width()));
size.setHeight(size.height() + state().icon.height); size.setHeight(size.height() + state().icon.height());
} }
return {size.width() + (state().text ? 20 : 10), size.height() + 10}; return {size.width() + (state().text ? 20 : 10), size.height() + 10};
@ -75,16 +75,16 @@ void pRadioButton::onActivate() {
auto pRadioButton::_setState() -> void { auto pRadioButton::_setState() -> void {
image icon = state().icon; image icon = state().icon;
icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); icon.transform();
if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; } if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; }
if(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } if(himagelist) { ImageList_Destroy(himagelist); himagelist = nullptr; }
if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE));
hbitmap = CreateBitmap(icon); hbitmap = CreateBitmap(icon);
himagelist = ImageList_Create(icon.width, icon.height, ILC_COLOR32, 1, 0); himagelist = ImageList_Create(icon.width(), icon.height(), ILC_COLOR32, 1, 0);
ImageList_Add(himagelist, hbitmap, NULL); ImageList_Add(himagelist, hbitmap, nullptr);
BUTTON_IMAGELIST list; BUTTON_IMAGELIST list;
list.himl = himagelist; list.himl = himagelist;
switch(state().orientation) { switch(state().orientation) {

View File

@ -89,9 +89,10 @@ auto pWindow::setFont(const string& font) -> void {
} }
auto pWindow::setFullScreen(bool fullScreen) -> void { auto pWindow::setFullScreen(bool fullScreen) -> void {
auto style = GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VISIBLE;
lock(); lock();
if(fullScreen == false) { if(fullScreen == false) {
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | (state().resizable ? ResizableStyle : FixedStyle)); SetWindowLongPtr(hwnd, GWL_STYLE, style | (state().resizable ? ResizableStyle : FixedStyle));
setGeometry(state().geometry); setGeometry(state().geometry);
} else { } else {
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
@ -101,7 +102,7 @@ auto pWindow::setFullScreen(bool fullScreen) -> void {
GetMonitorInfo(monitor, &info); GetMonitorInfo(monitor, &info);
RECT rc = info.rcMonitor; RECT rc = info.rcMonitor;
Geometry geometry = {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top}; Geometry geometry = {rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top};
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_POPUP);
Geometry margin = frameMargin(); Geometry margin = frameMargin();
setGeometry({ setGeometry({
geometry.x() + margin.x(), geometry.y() + margin.y(), geometry.x() + margin.x(), geometry.y() + margin.y(),
@ -147,7 +148,8 @@ auto pWindow::setModal(bool modality) -> void {
} }
auto pWindow::setResizable(bool resizable) -> void { auto pWindow::setResizable(bool resizable) -> void {
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | (state().resizable ? ResizableStyle : FixedStyle)); auto style = GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VISIBLE;
SetWindowLongPtr(hwnd, GWL_STYLE, style | (state().resizable ? ResizableStyle : FixedStyle));
setGeometry(state().geometry); setGeometry(state().geometry);
} }

View File

@ -4,35 +4,6 @@
namespace nall { namespace nall {
struct image { struct image {
uint8_t* data = nullptr;
unsigned width = 0;
unsigned height = 0;
unsigned pitch = 0;
unsigned size = 0;
bool endian = 0; //0 = lsb, 1 = msb
unsigned depth = 32;
unsigned stride = 4;
struct channel {
uint64_t mask;
unsigned depth;
unsigned shift;
inline bool operator==(const channel& source) const {
return mask == source.mask && depth == source.depth && shift == source.shift;
}
inline bool operator!=(const channel& source) const {
return !operator==(source);
}
};
channel alpha = {255u << 24, 8u, 24u};
channel red = {255u << 16, 8u, 16u};
channel green = {255u << 8, 8u, 8u};
channel blue = {255u << 0, 8u, 0u};
enum class blend : unsigned { enum class blend : unsigned {
add, add,
sourceAlpha, //color = sourceColor * sourceAlpha + targetColor * (1 - sourceAlpha) sourceAlpha, //color = sourceColor * sourceAlpha + targetColor * (1 - sourceAlpha)
@ -41,18 +12,29 @@ struct image {
targetColor, //color = targetColor targetColor, //color = targetColor
}; };
//static.hpp struct channel {
static inline unsigned bitDepth(uint64_t color); channel(uint64_t mask, unsigned depth, unsigned shift) : _mask(mask), _depth(depth), _shift(shift) {
static inline unsigned bitShift(uint64_t color); }
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
auto operator==(const channel& source) const -> bool {
return _mask == source._mask && _depth == source._depth && _shift == source._shift;
}
auto operator!=(const channel& source) const -> bool {
return !operator==(source);
}
alwaysinline auto mask() const { return _mask; }
alwaysinline auto depth() const { return _depth; }
alwaysinline auto shift() const { return _shift; }
private:
uint64_t _mask;
unsigned _depth;
unsigned _shift;
};
//core.hpp //core.hpp
inline explicit operator bool() const;
inline bool operator==(const image& source) const;
inline bool operator!=(const image& source) const;
inline image& operator=(const image& source);
inline image& operator=(image&& source);
inline image(const image& source); inline image(const image& source);
inline image(image&& source); inline image(image&& source);
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
@ -62,63 +44,106 @@ struct image {
inline image(); inline image();
inline ~image(); inline ~image();
inline uint64_t read(const uint8_t* data) const; inline auto operator=(const image& source) -> image&;
inline void write(uint8_t* data, uint64_t value) const; inline auto operator=(image&& source) -> image&;
inline void free(); inline explicit operator bool() const;
inline bool empty() const; inline auto operator==(const image& source) const -> bool;
inline bool load(const string& filename); inline auto operator!=(const image& source) const -> bool;
inline void allocate(unsigned width, unsigned height);
inline auto read(const uint8_t* data) const -> uint64_t;
inline auto write(uint8_t* data, uint64_t value) const -> void;
inline auto free() -> void;
inline auto empty() const -> bool;
inline auto load(const string& filename) -> bool;
inline auto allocate(unsigned width, unsigned height) -> void;
//fill.hpp //fill.hpp
inline void fill(uint64_t color = 0); inline auto fill(uint64_t color = 0) -> void;
inline void gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d); inline auto gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) -> void;
inline void gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function<double (double, double)> callback); inline auto gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function<double (double, double)> callback) -> void;
inline void crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
inline void verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); inline auto verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void;
//scale.hpp //scale.hpp
inline void scale(unsigned width, unsigned height, bool linear = true); inline auto scale(unsigned width, unsigned height, bool linear = true) -> void;
//blend.hpp //blend.hpp
inline void impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned x, unsigned y, unsigned width, unsigned height); inline auto impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned x, unsigned y, unsigned width, unsigned height) -> void;
//utility.hpp //utility.hpp
inline bool crop(unsigned x, unsigned y, unsigned width, unsigned height); inline auto crop(unsigned x, unsigned y, unsigned width, unsigned height) -> bool;
inline void alphaBlend(uint64_t alphaColor); inline auto alphaBlend(uint64_t alphaColor) -> void;
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); inline auto transform(const image& source = {}) -> void;
inline auto transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) -> void;
protected: //static.hpp
static inline auto bitDepth(uint64_t color) -> unsigned;
static inline auto bitShift(uint64_t color) -> unsigned;
static inline auto normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) -> uint64_t;
//access
alwaysinline auto data() { return _data; }
alwaysinline auto data() const { return _data; }
alwaysinline auto width() const { return _width; }
alwaysinline auto height() const { return _height; }
alwaysinline auto endian() const { return _endian; }
alwaysinline auto depth() const { return _depth; }
alwaysinline auto stride() const { return (_depth + 7) >> 3; }
alwaysinline auto pitch() const { return _width * stride(); }
alwaysinline auto size() const { return _height * pitch(); }
alwaysinline auto alpha() const { return _alpha; }
alwaysinline auto red() const { return _red; }
alwaysinline auto green() const { return _green; }
alwaysinline auto blue() const { return _blue; }
private:
//core.hpp //core.hpp
inline uint8_t* allocate(unsigned width, unsigned height, unsigned stride); inline auto allocate(unsigned width, unsigned height, unsigned stride) -> uint8_t*;
//scale.hpp //scale.hpp
inline void scaleLinearWidth(unsigned width); inline auto scaleLinearWidth(unsigned width) -> void;
inline void scaleLinearHeight(unsigned height); inline auto scaleLinearHeight(unsigned height) -> void;
inline void scaleLinear(unsigned width, unsigned height); inline auto scaleLinear(unsigned width, unsigned height) -> void;
inline void scaleNearest(unsigned width, unsigned height); inline auto scaleNearest(unsigned width, unsigned height) -> void;
//load.hpp //load.hpp
inline bool loadBMP(const string& filename); inline auto loadBMP(const string& filename) -> bool;
inline bool loadPNG(const string& filename); inline auto loadPNG(const string& filename) -> bool;
inline bool loadPNG(const uint8_t* data, unsigned size); inline auto loadPNG(const uint8_t* data, unsigned size) -> bool;
//interpolation.hpp //interpolation.hpp
alwaysinline void isplit(uint64_t* component, uint64_t color); alwaysinline auto isplit(uint64_t* component, uint64_t color) -> void;
alwaysinline uint64_t imerge(const uint64_t* component); alwaysinline auto imerge(const uint64_t* component) -> uint64_t;
alwaysinline uint64_t interpolate1f(uint64_t a, uint64_t b, double x); alwaysinline auto interpolate1f(uint64_t a, uint64_t b, double x) -> uint64_t;
alwaysinline uint64_t interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y); alwaysinline auto interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t;
alwaysinline uint64_t interpolate1i(int64_t a, int64_t b, uint32_t x); alwaysinline auto interpolate1i(int64_t a, int64_t b, uint32_t x) -> uint64_t;
alwaysinline uint64_t interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y); alwaysinline auto interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y) -> uint64_t;
inline uint64_t interpolate4f(uint64_t a, uint64_t b, double x); inline auto interpolate4f(uint64_t a, uint64_t b, double x) -> uint64_t;
inline uint64_t interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y); inline auto interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t;
inline uint64_t interpolate4i(uint64_t a, uint64_t b, uint32_t x); inline auto interpolate4i(uint64_t a, uint64_t b, uint32_t x) -> uint64_t;
inline uint64_t interpolate4i(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint32_t x, uint32_t y); inline auto interpolate4i(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint32_t x, uint32_t y) -> uint64_t;
uint8_t* _data = nullptr;
unsigned _width = 0;
unsigned _height = 0;
bool _endian = 0; //0 = lsb, 1 = msb
unsigned _depth = 32;
channel _alpha{255u << 24, 8, 24};
channel _red {255u << 16, 8, 16};
channel _green{255u << 8, 8, 8};
channel _blue {255u << 0, 8, 0};
}; };
} }

View File

@ -3,41 +3,42 @@
namespace nall { namespace nall {
void image::impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned sourceX, unsigned sourceY, unsigned sourceWidth, unsigned sourceHeight) { auto image::impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned sourceX, unsigned sourceY, unsigned sourceWidth, unsigned sourceHeight) -> void {
source.transform(endian, depth, alpha.mask, red.mask, green.mask, blue.mask); source.transform(_endian, _depth, _alpha.mask(), _red.mask(), _green.mask(), _blue.mask());
#pragma omp parallel for
for(unsigned y = 0; y < sourceHeight; y++) { for(unsigned y = 0; y < sourceHeight; y++) {
const uint8_t* sp = source.data + source.pitch * (sourceY + y) + source.stride * sourceX; const uint8_t* sp = source._data + source.pitch() * (sourceY + y) + source.stride() * sourceX;
uint8_t* dp = data + pitch * (targetY + y) + stride * targetX; uint8_t* dp = _data + pitch() * (targetY + y) + stride() * targetX;
for(unsigned x = 0; x < sourceWidth; x++) { for(unsigned x = 0; x < sourceWidth; x++) {
uint64_t sourceColor = source.read(sp); uint64_t sourceColor = source.read(sp);
uint64_t targetColor = read(dp); uint64_t targetColor = read(dp);
int64_t sa = (sourceColor & alpha.mask) >> alpha.shift; int64_t sa = (sourceColor & _alpha.mask()) >> _alpha.shift();
int64_t sr = (sourceColor & red.mask ) >> red.shift; int64_t sr = (sourceColor & _red.mask() ) >> _red.shift();
int64_t sg = (sourceColor & green.mask) >> green.shift; int64_t sg = (sourceColor & _green.mask()) >> _green.shift();
int64_t sb = (sourceColor & blue.mask ) >> blue.shift; int64_t sb = (sourceColor & _blue.mask() ) >> _blue.shift();
int64_t da = (targetColor & alpha.mask) >> alpha.shift; int64_t da = (targetColor & _alpha.mask()) >> _alpha.shift();
int64_t dr = (targetColor & red.mask ) >> red.shift; int64_t dr = (targetColor & _red.mask() ) >> _red.shift();
int64_t dg = (targetColor & green.mask) >> green.shift; int64_t dg = (targetColor & _green.mask()) >> _green.shift();
int64_t db = (targetColor & blue.mask ) >> blue.shift; int64_t db = (targetColor & _blue.mask() ) >> _blue.shift();
uint64_t a, r, g, b; uint64_t a, r, g, b;
switch(mode) { switch(mode) {
case blend::add: case blend::add:
a = max(sa, da); a = max(sa, da);
r = min(red.mask >> red.shift, ((sr * sa) >> alpha.depth) + ((dr * da) >> alpha.depth)); r = min(_red.mask() >> _red.shift(), ((sr * sa) >> _alpha.depth()) + ((dr * da) >> _alpha.depth()));
g = min(green.mask >> green.shift, ((sg * sa) >> alpha.depth) + ((dg * da) >> alpha.depth)); g = min(_green.mask() >> _green.shift(), ((sg * sa) >> _alpha.depth()) + ((dg * da) >> _alpha.depth()));
b = min(blue.mask >> blue.shift, ((sb * sa) >> alpha.depth) + ((db * da) >> alpha.depth)); b = min(_blue.mask() >> _blue.shift(), ((sb * sa) >> _alpha.depth()) + ((db * da) >> _alpha.depth()));
break; break;
case blend::sourceAlpha: case blend::sourceAlpha:
a = max(sa, da); a = max(sa, da);
r = dr + (((sr - dr) * sa) >> alpha.depth); r = dr + (((sr - dr) * sa) >> _alpha.depth());
g = dg + (((sg - dg) * sa) >> alpha.depth); g = dg + (((sg - dg) * sa) >> _alpha.depth());
b = db + (((sb - db) * sa) >> alpha.depth); b = db + (((sb - db) * sa) >> _alpha.depth());
break; break;
case blend::sourceColor: case blend::sourceColor:
@ -49,9 +50,9 @@ void image::impose(blend mode, unsigned targetX, unsigned targetY, image source,
case blend::targetAlpha: case blend::targetAlpha:
a = max(sa, da); a = max(sa, da);
r = sr + (((dr - sr) * da) >> alpha.depth); r = sr + (((dr - sr) * da) >> _alpha.depth());
g = sg + (((dg - sg) * da) >> alpha.depth); g = sg + (((dg - sg) * da) >> _alpha.depth());
b = sb + (((db - sb) * da) >> alpha.depth); b = sb + (((db - sb) * da) >> _alpha.depth());
break; break;
case blend::targetColor: case blend::targetColor:
@ -62,9 +63,9 @@ void image::impose(blend mode, unsigned targetX, unsigned targetY, image source,
break; break;
} }
write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); write(dp, (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift()));
sp += source.stride; sp += source.stride();
dp += stride; dp += stride();
} }
} }
} }

View File

@ -3,91 +3,22 @@
namespace nall { namespace nall {
image::operator bool() const {
return !empty();
}
bool image::operator==(const image& source) const {
if(width != source.width) return false;
if(height != source.height) return false;
if(pitch != source.pitch) return false;
if(endian != source.endian) return false;
if(stride != source.stride) return false;
if(alpha != source.alpha) return false;
if(red != source.red) return false;
if(green != source.green) return false;
if(blue != source.blue) return false;
return memcmp(data, source.data, width * height * stride) == 0;
}
bool image::operator!=(const image& source) const {
return !operator==(source);
}
image& image::operator=(const image& source) {
if(this == &source) return *this;
free();
width = source.width;
height = source.height;
pitch = source.pitch;
size = source.size;
endian = source.endian;
stride = source.stride;
alpha = source.alpha;
red = source.red;
green = source.green;
blue = source.blue;
data = allocate(width, height, stride);
memcpy(data, source.data, source.size);
return *this;
}
image& image::operator=(image&& source) {
if(this == &source) return *this;
free();
width = source.width;
height = source.height;
pitch = source.pitch;
size = source.size;
endian = source.endian;
stride = source.stride;
alpha = source.alpha;
red = source.red;
green = source.green;
blue = source.blue;
data = source.data;
source.data = nullptr;
return *this;
}
image::image(const image& source) { image::image(const image& source) {
operator=(source); operator=(source);
} }
image::image(image&& source) { image::image(image&& source) {
operator=(std::forward<image>(source)); operator=(forward<image>(source));
} }
image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) { image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) {
this->endian = endian; _endian = endian;
this->depth = depth; _depth = depth;
this->stride = (depth / 8) + ((depth & 7) > 0);
alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)}; _alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)};
red = {redMask, bitDepth(redMask), bitShift(redMask )}; _red = {redMask, bitDepth(redMask), bitShift(redMask )};
green = {greenMask, bitDepth(greenMask), bitShift(greenMask)}; _green = {greenMask, bitDepth(greenMask), bitShift(greenMask)};
blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )}; _blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )};
} }
image::image(const string& filename) { image::image(const string& filename) {
@ -109,63 +40,122 @@ image::~image() {
free(); free();
} }
uint64_t image::read(const uint8_t* data) const { auto image::operator=(const image& source) -> image& {
if(this == &source) return *this;
free();
_width = source._width;
_height = source._height;
_endian = source._endian;
_depth = source._depth;
_alpha = source._alpha;
_red = source._red;
_green = source._green;
_blue = source._blue;
_data = allocate(_width, _height, stride());
memory::copy(_data, source._data, source.size());
return *this;
}
auto image::operator=(image&& source) -> image& {
if(this == &source) return *this;
free();
_width = source._width;
_height = source._height;
_endian = source._endian;
_depth = source._depth;
_alpha = source._alpha;
_red = source._red;
_green = source._green;
_blue = source._blue;
_data = source._data;
source._data = nullptr;
return *this;
}
image::operator bool() const {
return !empty();
}
auto image::operator==(const image& source) const -> bool {
if(_width != source._width) return false;
if(_height != source._height) return false;
if(_endian != source._endian) return false;
if(_depth != source._depth) return false;
if(_alpha != source._alpha) return false;
if(_red != source._red) return false;
if(_green != source._green) return false;
if(_blue != source._blue) return false;
return memory::compare(_data, source._data, size()) == 0;
}
auto image::operator!=(const image& source) const -> bool {
return !operator==(source);
}
auto image::read(const uint8_t* data) const -> uint64_t {
uint64_t result = 0; uint64_t result = 0;
if(endian == 0) { if(_endian == 0) {
for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n]; for(signed n = stride() - 1; n >= 0; n--) result = (result << 8) | data[n];
} else { } else {
for(signed n = 0; n < stride; n++) result = (result << 8) | data[n]; for(signed n = 0; n < stride(); n++) result = (result << 8) | data[n];
} }
return result; return result;
} }
void image::write(uint8_t* data, uint64_t value) const { auto image::write(uint8_t* data, uint64_t value) const -> void {
if(endian == 0) { if(_endian == 0) {
for(signed n = 0; n < stride; n++) { for(signed n = 0; n < stride(); n++) {
data[n] = value; data[n] = value;
value >>= 8; value >>= 8;
} }
} else { } else {
for(signed n = stride - 1; n >= 0; n--) { for(signed n = stride() - 1; n >= 0; n--) {
data[n] = value; data[n] = value;
value >>= 8; value >>= 8;
} }
} }
} }
void image::free() { auto image::free() -> void {
if(data) delete[] data; if(_data) delete[] _data;
data = nullptr; _data = nullptr;
} }
bool image::empty() const { auto image::empty() const -> bool {
if(data == nullptr) return true; return !_data || !_width || !_height;
if(width == 0 || height == 0) return true;
return false;
} }
bool image::load(const string& filename) { auto image::load(const string& filename) -> bool {
if(loadBMP(filename) == true) return true; if(loadBMP(filename) == true) return true;
if(loadPNG(filename) == true) return true; if(loadPNG(filename) == true) return true;
return false; return false;
} }
void image::allocate(unsigned width, unsigned height) { auto image::allocate(unsigned width, unsigned height) -> void {
if(data != nullptr && this->width == width && this->height == height) return; if(_data && _width == width && _height == height) return;
free(); free();
data = allocate(width, height, stride); _width = width;
pitch = width * stride; _height = height;
size = height * pitch; _data = allocate(_width, _height, stride());
this->width = width;
this->height = height;
} }
uint8_t* image::allocate(unsigned width, unsigned height, unsigned stride) { auto image::allocate(unsigned width, unsigned height, unsigned stride) -> uint8_t* {
//allocate 1x1 larger than requested; so that linear interpolation does not require bounds-checking //allocate 1x1 larger than requested; so that linear interpolation does not require bounds-checking
unsigned size = width * height * stride; unsigned size = width * height * stride;
unsigned padding = width * stride + stride; unsigned padding = width * stride + stride;
uint8_t* data = new uint8_t[size + padding]; auto data = new uint8_t[size + padding];
memset(data + size, 0x00, padding); memory::fill(data + size, padding);
return data; return data;
} }

View File

@ -3,81 +3,80 @@
namespace nall { namespace nall {
void image::fill(uint64_t color) { auto image::fill(uint64_t color) -> void {
uint8_t* dp = data; for(unsigned y = 0; y < _height; y++) {
for(unsigned y = 0; y < height; y++) { uint8_t* dp = _data + pitch() * y;
uint8_t* dp = data + pitch * y; for(unsigned x = 0; x < _width; x++) {
for(unsigned x = 0; x < width; x++) {
write(dp, color); write(dp, color);
dp += stride; dp += stride();
} }
} }
} }
void image::gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) { auto image::gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) -> void {
for(unsigned y = 0; y < height; y++) { for(unsigned y = 0; y < _height; y++) {
uint8_t* dp = data + pitch * y; uint8_t* dp = _data + pitch() * y;
double muY = (double)y / (double)height; double muY = (double)y / (double)_height;
for(unsigned x = 0; x < width; x++) { for(unsigned x = 0; x < _width; x++) {
double muX = (double)x / (double)width; double muX = (double)x / (double)_width;
write(dp, interpolate4f(a, b, c, d, muX, muY)); write(dp, interpolate4f(a, b, c, d, muX, muY));
dp += stride; dp += stride();
} }
} }
} }
void image::gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function<double (double, double)> callback) { auto image::gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function<double (double, double)> callback) -> void {
for(signed y = 0; y < height; y++) { for(signed y = 0; y < _height; y++) {
uint8_t* dp = data + pitch * y; uint8_t* dp = _data + pitch() * y;
double py = max(-radiusY, min(+radiusY, y - centerY)) * 1.0 / radiusY; double py = max(-radiusY, min(+radiusY, y - centerY)) * 1.0 / radiusY;
for(signed x = 0; x < width; x++) { for(signed x = 0; x < _width; x++) {
double px = max(-radiusX, min(+radiusX, x - centerX)) * 1.0 / radiusX; double px = max(-radiusX, min(+radiusX, x - centerX)) * 1.0 / radiusX;
double mu = max(0.0, min(1.0, callback(px, py))); double mu = max(0.0, min(1.0, callback(px, py)));
if(mu != mu) mu = 1.0; //NaN if(mu != mu) mu = 1.0; //NaN
write(dp, interpolate4f(a, b, mu)); write(dp, interpolate4f(a, b, mu));
dp += stride; dp += stride();
} }
} }
} }
void image::crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
x = fabs(x), y = fabs(y); x = fabs(x), y = fabs(y);
return min(x, y) * min(x, y); return min(x, y) * min(x, y);
}); });
} }
void image::diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return fabs(x) + fabs(y); return fabs(x) + fabs(y);
}); });
} }
void image::horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return fabs(x); return fabs(x);
}); });
} }
void image::radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return sqrt(x * x + y * y); return sqrt(x * x + y * y);
}); });
} }
void image::sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return x * x + y * y; return x * x + y * y;
}); });
} }
void image::squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return max(fabs(x), fabs(y)); return max(fabs(x), fabs(y));
}); });
} }
void image::verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) { auto image::verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void {
return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double { return gradient(a, b, radiusX, radiusY, centerX, centerY, [](double x, double y) -> double {
return fabs(y); return fabs(y);
}); });

View File

@ -3,57 +3,57 @@
namespace nall { namespace nall {
void image::isplit(uint64_t* c, uint64_t color) { auto image::isplit(uint64_t* c, uint64_t color) -> void {
c[0] = (color & alpha.mask) >> alpha.shift; c[0] = (color & _alpha.mask()) >> _alpha.shift();
c[1] = (color & red.mask ) >> red.shift; c[1] = (color & _red.mask() ) >> _red.shift();
c[2] = (color & green.mask) >> green.shift; c[2] = (color & _green.mask()) >> _green.shift();
c[3] = (color & blue.mask ) >> blue.shift; c[3] = (color & _blue.mask() ) >> _blue.shift();
} }
uint64_t image::imerge(const uint64_t* c) { auto image::imerge(const uint64_t* c) -> uint64_t {
return c[0] << alpha.shift | c[1] << red.shift | c[2] << green.shift | c[3] << blue.shift; return c[0] << _alpha.shift() | c[1] << _red.shift() | c[2] << _green.shift() | c[3] << _blue.shift();
} }
uint64_t image::interpolate1f(uint64_t a, uint64_t b, double x) { auto image::interpolate1f(uint64_t a, uint64_t b, double x) -> uint64_t {
return a * (1.0 - x) + b * x; return a * (1.0 - x) + b * x;
} }
uint64_t image::interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) { auto image::interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t {
return a * (1.0 - x) * (1.0 - y) + b * x * (1.0 - y) + c * (1.0 - x) * y + d * x * y; return a * (1.0 - x) * (1.0 - y) + b * x * (1.0 - y) + c * (1.0 - x) * y + d * x * y;
} }
uint64_t image::interpolate1i(int64_t a, int64_t b, uint32_t x) { auto image::interpolate1i(int64_t a, int64_t b, uint32_t x) -> uint64_t {
return a + (((b - a) * x) >> 32); //a + (b - a) * x return a + (((b - a) * x) >> 32); //a + (b - a) * x
} }
uint64_t image::interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y) { auto image::interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y) -> uint64_t {
a = a + (((b - a) * x) >> 32); //a + (b - a) * x a = a + (((b - a) * x) >> 32); //a + (b - a) * x
c = c + (((d - c) * x) >> 32); //c + (d - c) * x c = c + (((d - c) * x) >> 32); //c + (d - c) * x
return a + (((c - a) * y) >> 32); //a + (c - a) * y return a + (((c - a) * y) >> 32); //a + (c - a) * y
} }
uint64_t image::interpolate4f(uint64_t a, uint64_t b, double x) { auto image::interpolate4f(uint64_t a, uint64_t b, double x) -> uint64_t {
uint64_t o[4], pa[4], pb[4]; uint64_t o[4], pa[4], pb[4];
isplit(pa, a), isplit(pb, b); isplit(pa, a), isplit(pb, b);
for(unsigned n = 0; n < 4; n++) o[n] = interpolate1f(pa[n], pb[n], x); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1f(pa[n], pb[n], x);
return imerge(o); return imerge(o);
} }
uint64_t image::interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) { auto image::interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t {
uint64_t o[4], pa[4], pb[4], pc[4], pd[4]; uint64_t o[4], pa[4], pb[4], pc[4], pd[4];
isplit(pa, a), isplit(pb, b), isplit(pc, c), isplit(pd, d); isplit(pa, a), isplit(pb, b), isplit(pc, c), isplit(pd, d);
for(unsigned n = 0; n < 4; n++) o[n] = interpolate1f(pa[n], pb[n], pc[n], pd[n], x, y); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1f(pa[n], pb[n], pc[n], pd[n], x, y);
return imerge(o); return imerge(o);
} }
uint64_t image::interpolate4i(uint64_t a, uint64_t b, uint32_t x) { auto image::interpolate4i(uint64_t a, uint64_t b, uint32_t x) -> uint64_t {
uint64_t o[4], pa[4], pb[4]; uint64_t o[4], pa[4], pb[4];
isplit(pa, a), isplit(pb, b); isplit(pa, a), isplit(pb, b);
for(unsigned n = 0; n < 4; n++) o[n] = interpolate1i(pa[n], pb[n], x); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1i(pa[n], pb[n], x);
return imerge(o); return imerge(o);
} }
uint64_t image::interpolate4i(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint32_t x, uint32_t y) { auto image::interpolate4i(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint32_t x, uint32_t y) -> uint64_t {
uint64_t o[4], pa[4], pb[4], pc[4], pd[4]; uint64_t o[4], pa[4], pb[4], pc[4], pd[4];
isplit(pa, a), isplit(pb, b), isplit(pc, c), isplit(pd, d); isplit(pa, a), isplit(pb, b), isplit(pc, c), isplit(pd, d);
for(unsigned n = 0; n < 4; n++) o[n] = interpolate1i(pa[n], pb[n], pc[n], pd[n], x, y); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1i(pa[n], pb[n], pc[n], pd[n], x, y);

View File

@ -3,24 +3,24 @@
namespace nall { namespace nall {
bool image::loadBMP(const string& filename) { auto image::loadBMP(const string& filename) -> bool {
uint32_t* outputData; uint32_t* outputData;
unsigned outputWidth, outputHeight; unsigned outputWidth, outputHeight;
if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false; if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false;
allocate(outputWidth, outputHeight); allocate(outputWidth, outputHeight);
const uint32_t* sp = outputData; const uint32_t* sp = outputData;
uint8_t* dp = data; uint8_t* dp = _data;
for(unsigned y = 0; y < outputHeight; y++) { for(unsigned y = 0; y < outputHeight; y++) {
for(unsigned x = 0; x < outputWidth; x++) { for(unsigned x = 0; x < outputWidth; x++) {
uint32_t color = *sp++; uint32_t color = *sp++;
uint64_t a = normalize((uint8_t)(color >> 24), 8, alpha.depth); uint64_t a = normalize((uint8_t)(color >> 24), 8, _alpha.depth());
uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth); uint64_t r = normalize((uint8_t)(color >> 16), 8, _red.depth());
uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth); uint64_t g = normalize((uint8_t)(color >> 8), 8, _green.depth());
uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth); uint64_t b = normalize((uint8_t)(color >> 0), 8, _blue.depth());
write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); write(dp, (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift()));
dp += stride; dp += stride();
} }
} }
@ -28,19 +28,19 @@ bool image::loadBMP(const string& filename) {
return true; return true;
} }
bool image::loadPNG(const string& filename) { auto image::loadPNG(const string& filename) -> bool {
if(!file::exists(filename)) return false; if(!file::exists(filename)) return false;
auto buffer = file::read(filename); auto buffer = file::read(filename);
return loadPNG(buffer.data(), buffer.size()); return loadPNG(buffer.data(), buffer.size());
} }
bool image::loadPNG(const uint8_t* pngData, unsigned pngSize) { auto image::loadPNG(const uint8_t* pngData, unsigned pngSize) -> bool {
Decode::PNG source; Decode::PNG source;
if(source.decode(pngData, pngSize) == false) return false; if(source.decode(pngData, pngSize) == false) return false;
allocate(source.info.width, source.info.height); allocate(source.info.width, source.info.height);
const uint8_t* sp = source.data; const uint8_t* sp = source.data;
uint8_t* dp = data; uint8_t* dp = _data;
auto decode = [&]() -> uint64_t { auto decode = [&]() -> uint64_t {
uint64_t p, r, g, b, a; uint64_t p, r, g, b, a;
@ -75,18 +75,18 @@ bool image::loadPNG(const uint8_t* pngData, unsigned pngSize) {
break; break;
} }
a = normalize(a, source.info.bitDepth, alpha.depth); a = normalize(a, source.info.bitDepth, _alpha.depth());
r = normalize(r, source.info.bitDepth, red.depth); r = normalize(r, source.info.bitDepth, _red.depth());
g = normalize(g, source.info.bitDepth, green.depth); g = normalize(g, source.info.bitDepth, _green.depth());
b = normalize(b, source.info.bitDepth, blue.depth); b = normalize(b, source.info.bitDepth, _blue.depth());
return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift); return (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift());
}; };
for(unsigned y = 0; y < height; y++) { for(unsigned y = 0; y < _height; y++) {
for(unsigned x = 0; x < width; x++) { for(unsigned x = 0; x < _width; x++) {
write(dp, decode()); write(dp, decode());
dp += stride; dp += stride();
} }
} }

View File

@ -3,18 +3,18 @@
namespace nall { namespace nall {
void image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) { auto image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) -> void {
if(width == outputWidth && height == outputHeight) return; //no scaling necessary if(_width == outputWidth && _height == outputHeight) return; //no scaling necessary
if(linear == false) return scaleNearest(outputWidth, outputHeight); if(linear == false) return scaleNearest(outputWidth, outputHeight);
if(width == outputWidth ) return scaleLinearHeight(outputHeight); if(_width == outputWidth ) return scaleLinearHeight(outputHeight);
if(height == outputHeight) return scaleLinearWidth(outputWidth); if(_height == outputHeight) return scaleLinearWidth(outputWidth);
//find fastest scaling method, based on number of interpolation operations required //find fastest scaling method, based on number of interpolation operations required
//magnification usually benefits from two-pass linear interpolation //magnification usually benefits from two-pass linear interpolation
//minification usually benefits from one-pass bilinear interpolation //minification usually benefits from one-pass bilinear interpolation
unsigned d1wh = ((width * outputWidth ) + (outputWidth * outputHeight)) * 1; unsigned d1wh = ((_width * outputWidth ) + (outputWidth * outputHeight)) * 1;
unsigned d1hw = ((height * outputHeight) + (outputWidth * outputHeight)) * 1; unsigned d1hw = ((_height * outputHeight) + (outputWidth * outputHeight)) * 1;
unsigned d2wh = (outputWidth * outputHeight) * 3; unsigned d2wh = (outputWidth * outputHeight) * 3;
if(d1wh <= d1hw && d1wh <= d2wh) return scaleLinearWidth(outputWidth), scaleLinearHeight(outputHeight); if(d1wh <= d1hw && d1wh <= d2wh) return scaleLinearWidth(outputWidth), scaleLinearHeight(outputHeight);
@ -22,32 +22,32 @@ void image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) {
return scaleLinear(outputWidth, outputHeight); return scaleLinear(outputWidth, outputHeight);
} }
void image::scaleLinearWidth(unsigned outputWidth) { auto image::scaleLinearWidth(unsigned outputWidth) -> void {
uint8_t* outputData = allocate(outputWidth, height, stride); uint8_t* outputData = allocate(outputWidth, _height, stride());
unsigned outputPitch = outputWidth * stride; unsigned outputPitch = outputWidth * stride();
uint64_t xstride = ((uint64_t)(width - 1) << 32) / max(1u, outputWidth - 1); uint64_t xstride = ((uint64_t)(_width - 1) << 32) / max(1u, outputWidth - 1);
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < height; y++) { for(unsigned y = 0; y < _height; y++) {
uint64_t xfraction = 0; uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * y; const uint8_t* sp = _data + pitch() * y;
uint8_t* dp = outputData + outputPitch * y; uint8_t* dp = outputData + outputPitch * y;
uint64_t a = read(sp); uint64_t a = read(sp);
uint64_t b = read(sp + stride); uint64_t b = read(sp + stride());
sp += stride; sp += stride();
unsigned x = 0; unsigned x = 0;
while(true) { while(true) {
while(xfraction < 0x100000000 && x++ < outputWidth) { while(xfraction < 0x100000000 && x++ < outputWidth) {
write(dp, interpolate4i(a, b, xfraction)); write(dp, interpolate4i(a, b, xfraction));
dp += stride; dp += stride();
xfraction += xstride; xfraction += xstride;
} }
if(x >= outputWidth) break; if(x >= outputWidth) break;
sp += stride; sp += stride();
a = b; a = b;
b = read(sp); b = read(sp);
xfraction -= 0x100000000; xfraction -= 0x100000000;
@ -55,37 +55,35 @@ void image::scaleLinearWidth(unsigned outputWidth) {
} }
free(); free();
data = outputData; _data = outputData;
width = outputWidth; _width = outputWidth;
pitch = outputPitch;
size = height * pitch;
} }
void image::scaleLinearHeight(unsigned outputHeight) { auto image::scaleLinearHeight(unsigned outputHeight) -> void {
uint8_t* outputData = allocate(width, outputHeight, stride); uint8_t* outputData = allocate(_width, outputHeight, stride());
uint64_t ystride = ((uint64_t)(height - 1) << 32) / max(1u, outputHeight - 1); uint64_t ystride = ((uint64_t)(_height - 1) << 32) / max(1u, outputHeight - 1);
#pragma omp parallel for #pragma omp parallel for
for(unsigned x = 0; x < width; x++) { for(unsigned x = 0; x < _width; x++) {
uint64_t yfraction = 0; uint64_t yfraction = 0;
const uint8_t* sp = data + stride * x; const uint8_t* sp = _data + stride() * x;
uint8_t* dp = outputData + stride * x; uint8_t* dp = outputData + stride() * x;
uint64_t a = read(sp); uint64_t a = read(sp);
uint64_t b = read(sp + pitch); uint64_t b = read(sp + pitch());
sp += pitch; sp += pitch();
unsigned y = 0; unsigned y = 0;
while(true) { while(true) {
while(yfraction < 0x100000000 && y++ < outputHeight) { while(yfraction < 0x100000000 && y++ < outputHeight) {
write(dp, interpolate4i(a, b, yfraction)); write(dp, interpolate4i(a, b, yfraction));
dp += pitch; dp += pitch();
yfraction += ystride; yfraction += ystride;
} }
if(y >= outputHeight) break; if(y >= outputHeight) break;
sp += pitch; sp += pitch();
a = b; a = b;
b = read(sp); b = read(sp);
yfraction -= 0x100000000; yfraction -= 0x100000000;
@ -93,71 +91,68 @@ void image::scaleLinearHeight(unsigned outputHeight) {
} }
free(); free();
data = outputData; _data = outputData;
height = outputHeight; _height = outputHeight;
size = height * pitch;
} }
void image::scaleLinear(unsigned outputWidth, unsigned outputHeight) { auto image::scaleLinear(unsigned outputWidth, unsigned outputHeight) -> void {
uint8_t* outputData = allocate(outputWidth, outputHeight, stride); uint8_t* outputData = allocate(outputWidth, outputHeight, stride());
unsigned outputPitch = outputWidth * stride; unsigned outputPitch = outputWidth * stride();
uint64_t xstride = ((uint64_t)(width - 1) << 32) / max(1u, outputWidth - 1); uint64_t xstride = ((uint64_t)(_width - 1) << 32) / max(1u, outputWidth - 1);
uint64_t ystride = ((uint64_t)(height - 1) << 32) / max(1u, outputHeight - 1); uint64_t ystride = ((uint64_t)(_height - 1) << 32) / max(1u, outputHeight - 1);
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) { for(unsigned y = 0; y < outputHeight; y++) {
uint64_t yfraction = ystride * y; uint64_t yfraction = ystride * y;
uint64_t xfraction = 0; uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * (yfraction >> 32); const uint8_t* sp = _data + pitch() * (yfraction >> 32);
uint8_t* dp = outputData + outputPitch * y; uint8_t* dp = outputData + outputPitch * y;
uint64_t a = read(sp); uint64_t a = read(sp);
uint64_t b = read(sp + stride); uint64_t b = read(sp + stride());
uint64_t c = read(sp + pitch); uint64_t c = read(sp + pitch());
uint64_t d = read(sp + pitch + stride); uint64_t d = read(sp + pitch() + stride());
sp += stride; sp += stride();
unsigned x = 0; unsigned x = 0;
while(true) { while(true) {
while(xfraction < 0x100000000 && x++ < outputWidth) { while(xfraction < 0x100000000 && x++ < outputWidth) {
write(dp, interpolate4i(a, b, c, d, xfraction, yfraction)); write(dp, interpolate4i(a, b, c, d, xfraction, yfraction));
dp += stride; dp += stride();
xfraction += xstride; xfraction += xstride;
} }
if(x >= outputWidth) break; if(x >= outputWidth) break;
sp += stride; sp += stride();
a = b; a = b;
c = d; c = d;
b = read(sp); b = read(sp);
d = read(sp + pitch); d = read(sp + pitch());
xfraction -= 0x100000000; xfraction -= 0x100000000;
} }
} }
free(); free();
data = outputData; _data = outputData;
width = outputWidth; _width = outputWidth;
height = outputHeight; _height = outputHeight;
pitch = outputPitch;
size = height * pitch;
} }
void image::scaleNearest(unsigned outputWidth, unsigned outputHeight) { auto image::scaleNearest(unsigned outputWidth, unsigned outputHeight) -> void {
uint8_t* outputData = allocate(outputWidth, outputHeight, stride); uint8_t* outputData = allocate(outputWidth, outputHeight, stride());
unsigned outputPitch = outputWidth * stride; unsigned outputPitch = outputWidth * stride();
uint64_t xstride = ((uint64_t)width << 32) / outputWidth; uint64_t xstride = ((uint64_t)_width << 32) / outputWidth;
uint64_t ystride = ((uint64_t)height << 32) / outputHeight; uint64_t ystride = ((uint64_t)_height << 32) / outputHeight;
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) { for(unsigned y = 0; y < outputHeight; y++) {
uint64_t yfraction = ystride * y; uint64_t yfraction = ystride * y;
uint64_t xfraction = 0; uint64_t xfraction = 0;
const uint8_t* sp = data + pitch * (yfraction >> 32); const uint8_t* sp = _data + pitch() * (yfraction >> 32);
uint8_t* dp = outputData + outputPitch * y; uint8_t* dp = outputData + outputPitch * y;
uint64_t a = read(sp); uint64_t a = read(sp);
@ -166,23 +161,21 @@ void image::scaleNearest(unsigned outputWidth, unsigned outputHeight) {
while(true) { while(true) {
while(xfraction < 0x100000000 && x++ < outputWidth) { while(xfraction < 0x100000000 && x++ < outputWidth) {
write(dp, a); write(dp, a);
dp += stride; dp += stride();
xfraction += xstride; xfraction += xstride;
} }
if(x >= outputWidth) break; if(x >= outputWidth) break;
sp += stride; sp += stride();
a = read(sp); a = read(sp);
xfraction -= 0x100000000; xfraction -= 0x100000000;
} }
} }
free(); free();
data = outputData; _data = outputData;
width = outputWidth; _width = outputWidth;
height = outputHeight; _height = outputHeight;
pitch = outputPitch;
size = height * pitch;
} }
} }

View File

@ -3,20 +3,20 @@
namespace nall { namespace nall {
unsigned image::bitDepth(uint64_t color) { auto image::bitDepth(uint64_t color) -> unsigned {
unsigned depth = 0; unsigned depth = 0;
if(color) while((color & 1) == 0) color >>= 1; if(color) while((color & 1) == 0) color >>= 1;
while((color & 1) == 1) { color >>= 1; depth++; } while((color & 1) == 1) { color >>= 1; depth++; }
return depth; return depth;
} }
unsigned image::bitShift(uint64_t color) { auto image::bitShift(uint64_t color) -> unsigned {
unsigned shift = 0; unsigned shift = 0;
if(color) while((color & 1) == 0) { color >>= 1; shift++; } if(color) while((color & 1) == 0) { color >>= 1; shift++; }
return shift; return shift;
} }
uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) { auto image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) -> uint64_t {
if(sourceDepth == 0 || targetDepth == 0) return 0; if(sourceDepth == 0 || targetDepth == 0) return 0;
while(sourceDepth < targetDepth) { while(sourceDepth < targetDepth) {
color = (color << sourceDepth) | color; color = (color << sourceDepth) | color;

View File

@ -3,91 +3,93 @@
namespace nall { namespace nall {
bool image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) { auto image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) -> bool {
if(outputX + outputWidth > width) return false; if(outputX + outputWidth > _width) return false;
if(outputY + outputHeight > height) return false; if(outputY + outputHeight > _height) return false;
uint8_t* outputData = allocate(outputWidth, outputHeight, stride); uint8_t* outputData = allocate(outputWidth, outputHeight, stride());
unsigned outputPitch = outputWidth * stride; unsigned outputPitch = outputWidth * stride();
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < outputHeight; y++) { for(unsigned y = 0; y < outputHeight; y++) {
const uint8_t* sp = data + pitch * (outputY + y) + stride * outputX; const uint8_t* sp = _data + pitch() * (outputY + y) + stride() * outputX;
uint8_t* dp = outputData + outputPitch * y; uint8_t* dp = outputData + outputPitch * y;
for(unsigned x = 0; x < outputWidth; x++) { for(unsigned x = 0; x < outputWidth; x++) {
write(dp, read(sp)); write(dp, read(sp));
sp += stride; sp += stride();
dp += stride; dp += stride();
} }
} }
delete[] data; delete[] _data;
data = outputData; _data = outputData;
width = outputWidth; _width = outputWidth;
height = outputHeight; _height = outputHeight;
pitch = outputPitch;
size = width * pitch;
return true; return true;
} }
void image::alphaBlend(uint64_t alphaColor) { auto image::alphaBlend(uint64_t alphaColor) -> void {
uint64_t alphaR = (alphaColor & red.mask ) >> red.shift; uint64_t alphaR = (alphaColor & _red.mask() ) >> _red.shift();
uint64_t alphaG = (alphaColor & green.mask) >> green.shift; uint64_t alphaG = (alphaColor & _green.mask()) >> _green.shift();
uint64_t alphaB = (alphaColor & blue.mask ) >> blue.shift; uint64_t alphaB = (alphaColor & _blue.mask() ) >> _blue.shift();
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < height; y++) { for(unsigned y = 0; y < _height; y++) {
uint8_t* dp = data + pitch * y; uint8_t* dp = _data + pitch() * y;
for(unsigned x = 0; x < width; x++) { for(unsigned x = 0; x < _width; x++) {
uint64_t color = read(dp); uint64_t color = read(dp);
uint64_t colorA = (color & alpha.mask) >> alpha.shift; uint64_t colorA = (color & _alpha.mask()) >> _alpha.shift();
uint64_t colorR = (color & red.mask ) >> red.shift; uint64_t colorR = (color & _red.mask() ) >> _red.shift();
uint64_t colorG = (color & green.mask) >> green.shift; uint64_t colorG = (color & _green.mask()) >> _green.shift();
uint64_t colorB = (color & blue.mask ) >> blue.shift; uint64_t colorB = (color & _blue.mask() ) >> _blue.shift();
double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1); double alphaScale = (double)colorA / (double)((1 << _alpha.depth()) - 1);
colorA = (1 << alpha.depth) - 1; colorA = (1 << _alpha.depth()) - 1;
colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale)); colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale));
colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale)); colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale));
colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale)); colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale));
write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift)); write(dp, (colorA << _alpha.shift()) | (colorR << _red.shift()) | (colorG << _green.shift()) | (colorB << _blue.shift()));
dp += stride; dp += stride();
} }
} }
} }
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) { auto image::transform(const image& source) -> void {
if(endian == outputEndian && depth == outputDepth && alpha.mask == outputAlphaMask && red.mask == outputRedMask && green.mask == outputGreenMask && blue.mask == outputBlueMask) return; return transform(source._endian, source._depth, source._alpha.mask(), source._red.mask(), source._green.mask(), source._blue.mask());
}
auto image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) -> void {
if(_endian == outputEndian && _depth == outputDepth && _alpha.mask() == outputAlphaMask && _red.mask() == outputRedMask && _green.mask() == outputGreenMask && _blue.mask() == outputBlueMask) return;
image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask); image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask);
output.allocate(width, height); output.allocate(_width, _height);
#pragma omp parallel for #pragma omp parallel for
for(unsigned y = 0; y < height; y++) { for(unsigned y = 0; y < _height; y++) {
const uint8_t* sp = data + pitch * y; const uint8_t* sp = _data + pitch() * y;
uint8_t* dp = output.data + output.pitch * y; uint8_t* dp = output._data + output.pitch() * y;
for(unsigned x = 0; x < width; x++) { for(unsigned x = 0; x < _width; x++) {
uint64_t color = read(sp); uint64_t color = read(sp);
sp += stride; sp += stride();
uint64_t a = (color & alpha.mask) >> alpha.shift; uint64_t a = (color & _alpha.mask()) >> _alpha.shift();
uint64_t r = (color & red.mask) >> red.shift; uint64_t r = (color & _red.mask() ) >> _red.shift();
uint64_t g = (color & green.mask) >> green.shift; uint64_t g = (color & _green.mask()) >> _green.shift();
uint64_t b = (color & blue.mask) >> blue.shift; uint64_t b = (color & _blue.mask() ) >> _blue.shift();
a = normalize(a, alpha.depth, output.alpha.depth); a = normalize(a, _alpha.depth(), output._alpha.depth());
r = normalize(r, red.depth, output.red.depth); r = normalize(r, _red.depth(), output._red.depth());
g = normalize(g, green.depth, output.green.depth); g = normalize(g, _green.depth(), output._green.depth());
b = normalize(b, blue.depth, output.blue.depth); b = normalize(b, _blue.depth(), output._blue.depth());
output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift)); output.write(dp, (a << output._alpha.shift()) | (r << output._red.shift()) | (g << output._green.shift()) | (b << output._blue.shift()));
dp += output.stride; dp += output.stride();
} }
} }
operator=(std::move(output)); operator=(move(output));
} }
} }

View File

@ -16,7 +16,7 @@ struct parser {
//import from canvas to bitstream //import from canvas to bitstream
bool save(bitstream& stream, uint64_t offset, context& ctx) { bool save(bitstream& stream, uint64_t offset, context& ctx) {
if(stream.readonly) return false; if(stream.readonly) return false;
parse(0, stream, offset, ctx, canvas.width, canvas.height); parse(0, stream, offset, ctx, canvas.width(), canvas.height());
return true; return true;
} }
@ -25,16 +25,16 @@ struct parser {
private: private:
uint32_t read(unsigned x, unsigned y) const { uint32_t read(unsigned x, unsigned y) const {
unsigned addr = y * canvas.width + x; unsigned addr = y * canvas.width() + x;
if(addr >= canvas.width * canvas.height) return 0u; if(addr >= canvas.width() * canvas.height()) return 0u;
uint32_t *buffer = (uint32_t*)canvas.data; uint32_t *buffer = (uint32_t*)canvas.data();
return buffer[addr]; return buffer[addr];
} }
void write(unsigned x, unsigned y, uint32_t data) { void write(unsigned x, unsigned y, uint32_t data) {
unsigned addr = y * canvas.width + x; unsigned addr = y * canvas.width() + x;
if(addr >= canvas.width * canvas.height) return; if(addr >= canvas.width() * canvas.height()) return;
uint32_t *buffer = (uint32_t*)canvas.data; uint32_t *buffer = (uint32_t*)canvas.data();
buffer[addr] = data; buffer[addr] = data;
} }

View File

@ -41,7 +41,7 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
for(auto& leaf : node.find("pixmap")) { for(auto& leaf : node.find("pixmap")) {
nall::image image({pathname, leaf.text()}); nall::image image({pathname, leaf.text()});
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); image.transform();
if(image.empty()) continue; if(image.empty()) continue;
GLuint texture; GLuint texture;
@ -49,8 +49,8 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
unsigned n = pixmaps.size(); unsigned n = pixmaps.size();
pixmaps(n).texture = texture; pixmaps(n).texture = texture;
pixmaps(n).width = image.width; pixmaps(n).width = image.width();
pixmaps(n).height = image.height; pixmaps(n).height = image.height();
pixmaps(n).format = format; pixmaps(n).format = format;
pixmaps(n).filter = filter; pixmaps(n).filter = filter;
pixmaps(n).wrap = wrap; pixmaps(n).wrap = wrap;
@ -58,11 +58,11 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin
if(leaf["filter"]) pixmaps(n).filter = glrFilter(leaf["filter"].text()); if(leaf["filter"]) pixmaps(n).filter = glrFilter(leaf["filter"].text());
if(leaf["wrap"]) pixmaps(n).wrap = glrWrap(leaf["wrap"].text()); if(leaf["wrap"]) pixmaps(n).wrap = glrWrap(leaf["wrap"].text());
unsigned w = glrSize(image.width), h = glrSize(image.height); unsigned w = glrSize(image.width()), h = glrSize(image.height());
uint32_t* buffer = new uint32_t[w * h](); uint32_t* buffer = new uint32_t[w * h]();
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, pixmaps(n).format, w, h, 0, pixmaps(n).getFormat(), pixmaps(n).getType(), buffer); glTexImage2D(GL_TEXTURE_2D, 0, pixmaps(n).format, w, h, 0, pixmaps(n).getFormat(), pixmaps(n).getType(), buffer);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width, image.height, getFormat(), getType(), image.data); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width(), image.height(), getFormat(), getType(), image.data());
delete[] buffer; delete[] buffer;
} }

View File

@ -31,7 +31,7 @@ void CPU::add_clocks(unsigned clocks) {
if(status.virq_enabled) { if(status.virq_enabled) {
unsigned cpu_time = vcounter() * 1364 + hcounter(); unsigned cpu_time = vcounter() * 1364 + hcounter();
unsigned irq_time = status.vtime * 1364 + status.htime * 4; unsigned irq_time = status.vtime * 1364 + status.htime * 4;
unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + field(); unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + (ppu.interlace() && !field());
if(cpu_time > irq_time) irq_time += framelines * 1364; if(cpu_time > irq_time) irq_time += framelines * 1364;
bool irq_valid = status.irq_valid; bool irq_valid = status.irq_valid;
status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time; status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time;

View File

@ -50,6 +50,7 @@ void DSP::power() {
} }
void DSP::reset() { void DSP::reset() {
Thread::clock = 0;
spc_dsp.soft_reset(); spc_dsp.soft_reset();
spc_dsp.set_output(samplebuffer, 8192); spc_dsp.set_output(samplebuffer, 8192);
} }

View File

@ -11,7 +11,7 @@
namespace SuperFamicom { namespace SuperFamicom {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const string Name = "bsnes";
static const unsigned SerializerVersion = 28; static const unsigned SerializerVersion = 28;
} }
} }
@ -28,28 +28,25 @@ namespace SuperFamicom {
namespace SuperFamicom { namespace SuperFamicom {
struct Thread { struct Thread {
cothread_t thread; ~Thread() {
unsigned frequency; if(thread) co_delete(thread);
int64 clock; }
inline void create(void (*entrypoint)(), unsigned frequency) { auto create(void (*entrypoint)(), unsigned frequency) -> void {
if(thread) co_delete(thread); if(thread) co_delete(thread);
thread = co_create(65536 * sizeof(void*), entrypoint); thread = co_create(65536 * sizeof(void*), entrypoint);
this->frequency = frequency; this->frequency = frequency;
clock = 0; clock = 0;
} }
inline void serialize(serializer& s) { auto serialize(serializer& s) -> void {
s.integer(frequency); s.integer(frequency);
s.integer(clock); s.integer(clock);
} }
inline Thread() : thread(nullptr) { cothread_t thread = nullptr;
} unsigned frequency = 0;
int64 clock = 0;
inline ~Thread() {
if(thread) co_delete(thread);
}
}; };
#include <sfc/memory/memory.hpp> #include <sfc/memory/memory.hpp>

View File

@ -16,8 +16,8 @@ CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) {
cheatList.setCheckable(); cheatList.setCheckable();
cheatList.setHeaderVisible(); cheatList.setHeaderVisible();
cheatList.onChange([&] { doChangeSelected(); }); cheatList.onChange([&] { doChangeSelected(); });
cheatList.onToggle([&](sListViewItem item) { cheatList.onToggle([&](ListViewItem item) {
cheats[item->offset()].enabled = item->checked(); cheats[item.offset()].enabled = item.checked();
synchronizeCodes(); synchronizeCodes();
}); });
codeLabel.setText("Code(s):"); codeLabel.setText("Code(s):");
@ -31,7 +31,7 @@ CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) {
auto CheatEditor::doChangeSelected() -> void { auto CheatEditor::doChangeSelected() -> void {
if(auto item = cheatList.selected()) { if(auto item = cheatList.selected()) {
auto& cheat = cheats[item->offset()]; auto& cheat = cheats[item.offset()];
codeValue.setEnabled(true).setText(cheat.code); codeValue.setEnabled(true).setText(cheat.code);
descriptionValue.setEnabled(true).setText(cheat.description); descriptionValue.setEnabled(true).setText(cheat.description);
eraseButton.setEnabled(true); eraseButton.setEnabled(true);
@ -44,7 +44,7 @@ auto CheatEditor::doChangeSelected() -> void {
auto CheatEditor::doModify() -> void { auto CheatEditor::doModify() -> void {
if(auto item = cheatList.selected()) { if(auto item = cheatList.selected()) {
auto& cheat = cheats[item->offset()]; auto& cheat = cheats[item.offset()];
cheat.code = codeValue.text(); cheat.code = codeValue.text();
cheat.description = descriptionValue.text(); cheat.description = descriptionValue.text();
doRefresh(); doRefresh();
@ -58,13 +58,13 @@ auto CheatEditor::doRefresh() -> void {
if(cheat.code || cheat.description) { if(cheat.code || cheat.description) {
lstring codes = cheat.code.split("+"); lstring codes = cheat.code.split("+");
if(codes.size() > 1) codes[0].append("+..."); if(codes.size() > 1) codes[0].append("+...");
cheatList.item(slot)->setChecked(cheat.enabled); cheatList.item(slot).setChecked(cheat.enabled);
cheatList.item(slot)->cell(1)->setText(codes[0]); cheatList.item(slot).cell(1).setText(codes[0]);
cheatList.item(slot)->cell(2)->setText(cheat.description); cheatList.item(slot).cell(2).setText(cheat.description).setForegroundColor({0, 0, 0});
} else { } else {
cheatList.item(slot)->setChecked(false); cheatList.item(slot).setChecked(false);
cheatList.item(slot)->cell(1)->setText(""); cheatList.item(slot).cell(1).setText("");
cheatList.item(slot)->cell(2)->setText("(empty)"); cheatList.item(slot).cell(2).setText("(empty)").setForegroundColor({128, 128, 128});
} }
} }
@ -87,7 +87,7 @@ auto CheatEditor::doReset(bool force) -> void {
auto CheatEditor::doErase() -> void { auto CheatEditor::doErase() -> void {
if(auto item = cheatList.selected()) { if(auto item = cheatList.selected()) {
auto& cheat = cheats[item->offset()]; auto& cheat = cheats[item.offset()];
cheat.enabled = false; cheat.enabled = false;
cheat.code = ""; cheat.code = "";
cheat.description = ""; cheat.description = "";

View File

@ -13,19 +13,36 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) {
} }
stateList.setHeaderVisible(); stateList.setHeaderVisible();
stateList.onActivate([&] { doLoad(); }); stateList.onActivate([&] { doLoad(); });
stateList.onChange([&] { doChange(); }); stateList.onChange([&] { doChangeSelected(); });
descriptionLabel.setText("Description:"); descriptionLabel.setText("Description:");
descriptionValue.onChange([&] { doLabel(); }); descriptionValue.onChange([&] { doChangeDescription(); });
saveButton.setText("Save").onActivate([&] { doSave(); }); saveButton.setText("Save").onActivate([&] { doSave(); });
loadButton.setText("Load").onActivate([&] { doLoad(); }); loadButton.setText("Load").onActivate([&] { doLoad(); });
resetButton.setText("Reset").onActivate([&] { doReset(); }); resetButton.setText("Reset").onActivate([&] { doReset(); });
eraseButton.setText("Erase").onActivate([&] { doErase(); }); eraseButton.setText("Erase").onActivate([&] { doErase(); });
} }
auto StateManager::doChange() -> void { auto StateManager::doUpdateControls() -> void {
vector<uint8> buffer; vector<uint8> buffer;
if(auto item = stateList.selected()) { if(auto item = stateList.selected()) {
buffer = file::read(program->stateName(1 + item->offset(), true)); buffer = file::read(program->stateName(1 + item.offset(), true));
}
if(buffer.size() >= 584) {
descriptionValue.setEnabled(true);
loadButton.setEnabled(true);
eraseButton.setEnabled(true);
} else {
descriptionValue.setEnabled(false);
loadButton.setEnabled(false);
eraseButton.setEnabled(false);
}
}
auto StateManager::doChangeSelected() -> void {
vector<uint8> buffer;
if(auto item = stateList.selected()) {
buffer = file::read(program->stateName(1 + item.offset(), true));
} }
if(buffer.size() >= 584) { if(buffer.size() >= 584) {
@ -33,56 +50,55 @@ auto StateManager::doChange() -> void {
description.reserve(512); description.reserve(512);
memory::copy(description.pointer(), buffer.data() + 72, 512); memory::copy(description.pointer(), buffer.data() + 72, 512);
description.resize(description.length()); description.resize(description.length());
descriptionValue.setEnabled(true).setText(description); descriptionValue.setText(description);
loadButton.setEnabled(true);
eraseButton.setEnabled(true);
} else { } else {
descriptionValue.setEnabled(false).setText(""); descriptionValue.setText("");
loadButton.setEnabled(false);
eraseButton.setEnabled(false);
} }
doUpdateControls();
} }
auto StateManager::doRefresh() -> void { auto StateManager::doRefresh() -> void {
for(unsigned slot = 0; slot < Slots; slot++) { for(auto slot : range(Slots)) {
auto buffer = file::read(program->stateName(1 + slot, true)); auto buffer = file::read(program->stateName(1 + slot, true));
if(buffer.size() >= 584) { if(buffer.size() >= 584) {
string description; string description;
description.reserve(512); description.reserve(512);
memory::copy(description.pointer(), buffer.data() + 72, 512); memory::copy(description.pointer(), buffer.data() + 72, 512);
description.resize(description.length()); description.resize(description.length());
stateList.item(slot)->cell(1)->setText(description); stateList.item(slot).cell(1).setText(description).setForegroundColor({0, 0, 0});
} else { } else {
stateList.item(slot)->cell(1)->setText("(empty)"); stateList.item(slot).cell(1).setText("(empty)").setForegroundColor({128, 128, 128});
} }
} }
doChange();
} }
auto StateManager::doLabel() -> void { auto StateManager::doChangeDescription() -> void {
if(auto item = stateList.selected()) { if(auto item = stateList.selected()) {
auto buffer = file::read(program->stateName(1 + item->offset(), true)); auto buffer = file::read(program->stateName(1 + item.offset(), true));
if(buffer.size() >= 584) { if(buffer.size() >= 584) {
string description = descriptionValue.text(); string description = descriptionValue.text();
description.reserve(512); description.reserve(512);
memory::copy(buffer.data() + 72, description.data(), 512); memory::copy(buffer.data() + 72, description.data(), 512);
file::write(program->stateName(1 + item->offset(), true), buffer); file::write(program->stateName(1 + item.offset(), true), buffer);
doRefresh(); doRefresh();
doUpdateControls();
} }
} }
} }
auto StateManager::doLoad() -> void { auto StateManager::doLoad() -> void {
if(auto item = stateList.selected()) { if(auto item = stateList.selected()) {
program->loadState(1 + item->offset(), true); program->loadState(1 + item.offset(), true);
} }
} }
auto StateManager::doSave() -> void { auto StateManager::doSave() -> void {
if(auto item = stateList.selected()) { if(auto item = stateList.selected()) {
program->saveState(1 + item->offset(), true); program->saveState(1 + item.offset(), true);
doRefresh(); doRefresh();
descriptionValue.setFocused(); doUpdateControls();
descriptionValue.setText("").setFocused();
} }
} }
@ -90,12 +106,14 @@ auto StateManager::doReset() -> void {
if(MessageDialog().setParent(*toolsManager).setText("Permanently erase all slots?").question() == "Yes") { if(MessageDialog().setParent(*toolsManager).setText("Permanently erase all slots?").question() == "Yes") {
for(auto slot : range(Slots)) file::remove(program->stateName(1 + slot, true)); for(auto slot : range(Slots)) file::remove(program->stateName(1 + slot, true));
doRefresh(); doRefresh();
doUpdateControls();
} }
} }
auto StateManager::doErase() -> void { auto StateManager::doErase() -> void {
if(auto item = stateList.selected()) { if(auto item = stateList.selected()) {
file::remove(program->stateName(1 + item->offset(), true)); file::remove(program->stateName(1 + item.offset(), true));
doRefresh(); doRefresh();
doUpdateControls();
} }
} }

View File

@ -54,9 +54,10 @@ struct StateManager : TabFrameItem {
enum : unsigned { Slots = 32 }; enum : unsigned { Slots = 32 };
StateManager(TabFrame*); StateManager(TabFrame*);
auto doChange() -> void; auto doChangeSelected() -> void;
auto doRefresh() -> void; auto doRefresh() -> void;
auto doLabel() -> void; auto doUpdateControls() -> void;
auto doChangeDescription() -> void;
auto doLoad() -> void; auto doLoad() -> void;
auto doSave() -> void; auto doSave() -> void;
auto doReset() -> void; auto doReset() -> void;