From 20cc6148cb0a81465d7b7b6307d47e4c694e89d8 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 18 Jun 2015 20:48:53 +1000 Subject: [PATCH] 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. --- emulator/emulator.hpp | 47 +- fc/fc.hpp | 21 +- gb/gb.hpp | 21 +- gba/gba.hpp | 21 +- hiro/core/action/menu-radio-item.cpp | 2 +- hiro/core/action/menu.cpp | 6 +- hiro/core/core.hpp | 81 +-- hiro/core/group.cpp | 8 +- hiro/core/keyboard.cpp | 6 +- hiro/core/layout.cpp | 10 +- hiro/core/menu-bar.cpp | 10 +- hiro/core/object.cpp | 2 +- hiro/core/popup-menu.cpp | 6 +- hiro/core/shared.hpp | 868 +++++++++++++++++++++++++ hiro/core/widget/canvas.cpp | 2 +- hiro/core/widget/combo-button.cpp | 6 +- hiro/core/widget/frame.cpp | 6 +- hiro/core/widget/icon-view.cpp | 10 +- hiro/core/widget/list-view-item.cpp | 2 +- hiro/core/widget/list-view.cpp | 22 +- hiro/core/widget/radio-button.cpp | 2 +- hiro/core/widget/radio-label.cpp | 2 +- hiro/core/widget/tab-frame-item.cpp | 2 +- hiro/core/widget/tab-frame.cpp | 10 +- hiro/core/widget/tree-view-item.cpp | 2 +- hiro/core/widget/tree-view.cpp | 4 +- hiro/core/window.cpp | 6 +- hiro/extension/shared.hpp | 898 +------------------------- hiro/gtk/utility.cpp | 17 +- hiro/gtk/widget/button.cpp | 8 +- hiro/gtk/widget/canvas.cpp | 6 +- hiro/gtk/widget/check-button.cpp | 8 +- hiro/gtk/widget/list-view.cpp | 4 +- hiro/gtk/widget/radio-button.cpp | 8 +- hiro/gtk/window.cpp | 6 +- hiro/hiro.hpp | 7 + hiro/windows/action/menu-item.cpp | 2 +- hiro/windows/action/menu.cpp | 2 +- hiro/windows/utility.cpp | 12 +- hiro/windows/widget/button.cpp | 12 +- hiro/windows/widget/canvas.cpp | 6 +- hiro/windows/widget/check-button.cpp | 18 +- hiro/windows/widget/list-view.cpp | 21 +- hiro/windows/widget/radio-button.cpp | 18 +- hiro/windows/window.cpp | 8 +- nall/image/base.hpp | 183 +++--- nall/image/blend.hpp | 49 +- nall/image/core.hpp | 194 +++--- nall/image/fill.hpp | 49 +- nall/image/interpolation.hpp | 30 +- nall/image/load.hpp | 38 +- nall/image/scale.hpp | 121 ++-- nall/image/static.hpp | 6 +- nall/image/utility.hpp | 98 +-- nall/mosaic/parser.hpp | 14 +- ruby/video/opengl/program.hpp | 10 +- sfc/alt/cpu/timing.cpp | 2 +- sfc/alt/dsp/dsp.cpp | 1 + sfc/sfc.hpp | 21 +- target-tomoko/tools/cheat-editor.cpp | 22 +- target-tomoko/tools/state-manager.cpp | 60 +- target-tomoko/tools/tools.hpp | 5 +- 62 files changed, 1580 insertions(+), 1569 deletions(-) create mode 100644 hiro/core/shared.hpp diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 38c23a05..a101de6b 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -1,48 +1,27 @@ #ifndef EMULATOR_HPP #define EMULATOR_HPP +#include +#include +#include +using namespace nall; + namespace Emulator { - static const char Name[] = "higan"; - static const char Version[] = "094.26"; - static const char Author[] = "byuu"; - static const char License[] = "GPLv3"; - static const char Website[] = "http://byuu.org/"; + static const string Name = "higan"; + static const string Version = "094.27"; + static const string Author = "byuu"; + static const string License = "GPLv3"; + static const string Website = "http://byuu.org/"; #if defined(PROFILE_ACCURACY) - static const char Profile[] = "Accuracy"; + static const string Profile = "Accuracy"; #elif defined(PROFILE_BALANCED) - static const char Profile[] = "Balanced"; + static const string Profile = "Balanced"; #elif defined(PROFILE_PERFORMANCE) - static const char Profile[] = "Performance"; + static const string Profile = "Performance"; #endif } -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace nall; - #include "interface.hpp" //debugging function hook: diff --git a/fc/fc.hpp b/fc/fc.hpp index 3fce8b02..b19bac2d 100644 --- a/fc/fc.hpp +++ b/fc/fc.hpp @@ -6,7 +6,7 @@ namespace Famicom { namespace Info { - static const char Name[] = "bnes"; + static const string Name = "bnes"; static const unsigned SerializerVersion = 2; } } @@ -22,28 +22,25 @@ namespace Famicom { namespace Famicom { struct Thread { - cothread_t thread; - unsigned frequency; - int64 clock; + ~Thread() { + if(thread) co_delete(thread); + } - inline void create(void (*entrypoint)(), unsigned frequency) { + auto create(void (*entrypoint)(), unsigned frequency) -> void { if(thread) co_delete(thread); thread = co_create(65536 * sizeof(void*), entrypoint); this->frequency = frequency; clock = 0; } - inline void serialize(serializer& s) { + auto serialize(serializer& s) -> void { s.integer(frequency); s.integer(clock); } - inline Thread() : thread(nullptr) { - } - - inline ~Thread() { - if(thread) co_delete(thread); - } + cothread_t thread = nullptr; + unsigned frequency = 0; + int64 clock = 0; }; #include diff --git a/gb/gb.hpp b/gb/gb.hpp index 10980cfa..68d172c6 100644 --- a/gb/gb.hpp +++ b/gb/gb.hpp @@ -6,7 +6,7 @@ namespace GameBoy { namespace Info { - static const char Name[] = "bgb"; + static const string Name = "bgb"; static const unsigned SerializerVersion = 4; } } @@ -22,28 +22,25 @@ namespace GameBoy { namespace GameBoy { struct Thread { - cothread_t thread; - unsigned frequency; - int64_t clock; + ~Thread() { + if(thread) co_delete(thread); + } - inline void create(void (*entrypoint)(), unsigned frequency) { + auto create(void (*entrypoint)(), unsigned frequency) -> void { if(thread) co_delete(thread); thread = co_create(65536 * sizeof(void*), entrypoint); this->frequency = frequency; clock = 0; } - inline void serialize(serializer& s) { + auto serialize(serializer& s) -> void { s.integer(frequency); s.integer(clock); } - inline Thread() : thread(nullptr) { - } - - inline ~Thread() { - if(thread) co_delete(thread); - } + cothread_t thread = nullptr; + unsigned frequency = 0; + int64_t clock = 0; }; #include diff --git a/gba/gba.hpp b/gba/gba.hpp index db5c97f0..11d50dc2 100644 --- a/gba/gba.hpp +++ b/gba/gba.hpp @@ -6,7 +6,7 @@ namespace GameBoyAdvance { namespace Info { - static const char Name[] = "bgba"; + static const string Name = "bgba"; static const unsigned SerializerVersion = 2; } } @@ -24,28 +24,25 @@ namespace GameBoyAdvance { enum : unsigned { Byte = 8, Half = 16, Word = 32 }; struct Thread { - cothread_t thread; - unsigned frequency; - signed clock; + ~Thread() { + if(thread) co_delete(thread); + } - inline void create(void (*entrypoint)(), unsigned frequency) { + auto create(void (*entrypoint)(), unsigned frequency) -> void { if(thread) co_delete(thread); thread = co_create(65536 * sizeof(void*), entrypoint); this->frequency = frequency; clock = 0; } - inline void serialize(serializer& s) { + auto serialize(serializer& s) -> void { s.integer(frequency); s.integer(clock); } - inline Thread() : thread(nullptr) { - } - - inline ~Thread() { - if(thread) co_delete(thread); - } + cothread_t thread = nullptr; + unsigned frequency = 0; + signed clock = 0; }; #include diff --git a/hiro/core/action/menu-radio-item.cpp b/hiro/core/action/menu-radio-item.cpp index 73916523..bd97c094 100644 --- a/hiro/core/action/menu-radio-item.cpp +++ b/hiro/core/action/menu-radio-item.cpp @@ -14,7 +14,7 @@ auto mMenuRadioItem::doActivate() const -> void { if(state.onActivate) return state.onActivate(); } -auto mMenuRadioItem::group() const -> sGroup { +auto mMenuRadioItem::group() const -> Group { return state.group; } diff --git a/hiro/core/action/menu.cpp b/hiro/core/action/menu.cpp index 6882ffd6..018fd376 100644 --- a/hiro/core/action/menu.cpp +++ b/hiro/core/action/menu.cpp @@ -11,9 +11,9 @@ auto mMenu::destruct() -> void { // -auto mMenu::action(unsigned position) const -> sAction { - if(position >= actions()) throw; - return state.actions[position]; +auto mMenu::action(unsigned position) const -> Action { + if(position < actions()) return state.actions[position]; + return {}; } auto mMenu::actions() const -> unsigned { diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 9eb41b83..de83339f 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -24,6 +24,7 @@ using nall::vector; namespace hiro { #define Declare(Name) \ + struct Name; \ struct m##Name; \ struct p##Name; \ using s##Name = shared_pointer; \ @@ -302,7 +303,7 @@ struct Keyboard { Keyboard() = delete; static auto append(sHotkey hotkey) -> void; - static auto hotkey(unsigned position) -> sHotkey; + static auto hotkey(unsigned position) -> Hotkey; static auto hotkeys() -> unsigned; static auto poll() -> vector; static auto pressed(const string& key) -> bool; @@ -410,7 +411,7 @@ struct mObject { auto enabled(bool recursive = false) const -> bool; virtual auto focused() const -> bool; auto font(bool recursive = false) const -> string; - virtual auto group() const -> sGroup; + virtual auto group() const -> Group; auto offset() const -> signed; auto parent() const -> mObject*; auto parentComboButton(bool recursive = false) const -> mComboButton*; @@ -462,7 +463,7 @@ struct mGroup : mObject { using mObject::remove; auto append(sObject object) -> type&; - auto object(unsigned offset) const -> sObject; + auto object(unsigned offset) const -> Object; auto objects() const -> unsigned; auto remove(sObject object) -> type&; @@ -535,8 +536,8 @@ struct mWindow : mObject { auto frameGeometry() const -> Geometry; auto fullScreen() const -> bool; auto geometry() const -> Geometry; - auto layout() const -> sLayout; - auto menuBar() const -> sMenuBar; + auto layout() const -> Layout; + auto menuBar() const -> MenuBar; auto modal() const -> bool; auto onClose(const function& callback = {}) -> type&; auto onDrop(const function& callback = {}) -> type&; @@ -563,7 +564,7 @@ struct mWindow : mObject { auto setResizable(bool resizable = true) -> type&; auto setSize(Size size) -> type&; auto setTitle(const string& title = "") -> type&; - auto statusBar() const -> sStatusBar; + auto statusBar() const -> StatusBar; auto title() const -> string; //private: @@ -610,7 +611,7 @@ struct mMenuBar : mObject { Declare(MenuBar) auto append(sMenu menu) -> type&; - auto menu(unsigned position) const -> sMenu; + auto menu(unsigned position) const -> Menu; auto menus() const -> unsigned; auto remove() -> type& override; auto remove(sMenu menu) -> type&; @@ -631,7 +632,7 @@ struct mPopupMenu : mObject { Declare(PopupMenu) using mObject::remove; - auto action(unsigned position) const -> sAction; + auto action(unsigned position) const -> Action; auto actions() const -> unsigned; auto append(sAction action) -> type&; auto remove(sAction action) -> type&; @@ -665,7 +666,7 @@ struct mMenu : mAction { Declare(Menu) using mObject::remove; - auto action(unsigned position) const -> sAction; + auto action(unsigned position) const -> Action; auto actions() const -> unsigned; auto append(sAction action) -> type&; auto icon() const -> image; @@ -743,7 +744,7 @@ struct mMenuRadioItem : mAction { auto checked() const -> bool; auto doActivate() const -> void; - auto group() const -> sGroup override; + auto group() const -> Group override; auto onActivate(const function& callback = {}) -> type&; auto setChecked() -> type&; auto setGroup(sGroup group = {}) -> type& override; @@ -784,7 +785,7 @@ struct mLayout : mSizable { virtual auto remove(sSizable sizable) -> type&; virtual auto reset() -> type&; 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; //private: @@ -939,12 +940,12 @@ struct mComboButton : mWidget { auto append(sComboButtonItem item) -> type&; auto doChange() const -> void; - auto item(unsigned position) const -> sComboButtonItem; + auto item(unsigned position) const -> ComboButtonItem; auto items() const -> unsigned; auto onChange(const function& callback = {}) -> type&; auto remove(sComboButtonItem item) -> type&; auto reset() -> type&; - auto selected() const -> sComboButtonItem; + auto selected() const -> ComboButtonItem; auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override; //private: @@ -1009,7 +1010,7 @@ struct mFrame : mWidget { using mObject::remove; auto append(sLayout layout) -> type&; - auto layout() const -> sLayout; + auto layout() const -> Layout; auto remove(sLayout layout) -> type&; auto reset() -> type&; //TODO setParent() @@ -1114,7 +1115,7 @@ struct mIconView : mWidget { auto doContext() const -> void; auto flow() const -> Orientation; auto foregroundColor() const -> Color; - auto item(unsigned position) const -> sIconViewItem; + auto item(unsigned position) const -> IconViewItem; auto items() const -> unsigned; auto multiSelect() const -> bool; auto onActivate(const function& callback = {}) -> type&; @@ -1231,8 +1232,8 @@ struct mListView : mWidget { auto batchable() const -> bool; auto checkable() const -> bool; auto checkAll() -> type&; - auto checked() const -> vector; - auto column(unsigned position) const -> sListViewColumn; + auto checked() const -> vector; + auto column(unsigned position) const -> ListViewColumn; auto columns() const -> unsigned; auto doActivate() const -> void; auto doChange() const -> void; @@ -1243,21 +1244,21 @@ struct mListView : mWidget { auto foregroundColor() const -> Color; auto gridVisible() const -> bool; auto headerVisible() const -> bool; - auto item(unsigned position) const -> sListViewItem; + auto item(unsigned position) const -> ListViewItem; auto items() const -> unsigned; auto onActivate(const function& callback = {}) -> type&; auto onChange(const function& callback = {}) -> type&; auto onContext(const function& callback = {}) -> type&; - auto onEdit(const function& callback = {}) -> type&; - auto onSort(const function& callback = {}) -> type&; - auto onToggle(const function& callback = {}) -> type&; + auto onEdit(const function& callback = {}) -> type&; + auto onSort(const function& callback = {}) -> type&; + auto onToggle(const function& callback = {}) -> type&; auto remove(sListViewColumn column) -> type&; auto remove(sListViewItem item) -> type&; auto reset() -> type&; auto resizeColumns() -> type&; auto selectAll() -> type&; - auto selected() const -> sListViewItem; - auto selectedItems() const -> vector; + auto selected() const -> ListViewItem; + auto selectedItems() const -> vector; auto setBackgroundColor(Color color = {}) -> type&; auto setBatchable(bool batchable = true) -> type&; auto setCheckable(bool checkable = true) -> type&; @@ -1284,9 +1285,9 @@ struct mListView : mWidget { function onActivate; function onChange; function onContext; - function onEdit; - function onSort; - function onToggle; + function onEdit; + function onSort; + function onToggle; bool sortable = false; } state; @@ -1348,7 +1349,7 @@ struct mListViewItem : mObject { auto append(sListViewCell cell) -> type&; auto backgroundColor() const -> Color; - auto cell(unsigned position) const -> sListViewCell; + auto cell(unsigned position) const -> ListViewCell; auto cells() const -> unsigned; auto checked() const -> bool; auto foregroundColor() const -> Color; @@ -1417,7 +1418,7 @@ struct mRadioButton : mWidget { auto bordered() const -> bool; auto checked() const -> bool; auto doActivate() const -> void; - auto group() const -> sGroup override; + auto group() const -> Group override; auto icon() const -> image; auto onActivate(const function& callback = {}) -> type&; auto orientation() const -> Orientation; @@ -1448,7 +1449,7 @@ struct mRadioLabel : mWidget { auto checked() const -> bool; auto doActivate() const -> void; - auto group() const -> sGroup override; + auto group() const -> Group override; auto onActivate(const function& callback = {}) -> type&; auto setChecked() -> type&; auto setGroup(sGroup group = {}) -> type& override; @@ -1501,14 +1502,14 @@ struct mTabFrame : mWidget { auto doClose(sTabFrameItem item) const -> void; auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void; auto edge() const -> Edge; - auto item(unsigned position) const -> sTabFrameItem; + auto item(unsigned position) const -> TabFrameItem; auto items() const -> unsigned; auto onChange(const function& callback = {}) -> type&; - auto onClose(const function& callback = {}) -> type&; - auto onMove(const function& callback = {}) -> type&; + auto onClose(const function& callback = {}) -> type&; + auto onMove(const function& callback = {}) -> type&; auto remove(sTabFrameItem item) -> type&; auto reset() -> type&; - auto selected() const -> sTabFrameItem; + auto selected() const -> TabFrameItem; auto setEdge(Edge edge = Edge::Top) -> type&; auto setParent(mObject* object = nullptr, signed offset = -1) -> type& override; @@ -1517,8 +1518,8 @@ struct mTabFrame : mWidget { Edge edge = Edge::Top; vector items; function onChange; - function onClose; - function onMove; + function onClose; + function onMove; } state; auto destruct() -> void override; @@ -1532,7 +1533,7 @@ struct mTabFrameItem : mObject { auto append(sLayout layout) -> type&; auto closable() const -> bool; auto icon() const -> image; - auto layout() const -> sLayout; + auto layout() const -> Layout; auto movable() const -> bool; auto remove() -> type& override; auto remove(sLayout layout) -> type&; @@ -1610,7 +1611,7 @@ struct mTreeView : mWidget { auto doToggle(sTreeViewItem item) const -> void; auto expand() -> type&; auto foregroundColor() const -> Color; - auto item(const string& path) const -> sTreeViewItem; + auto item(const string& path) const -> TreeViewItem; auto items() const -> unsigned; auto onActivate(const function& callback = {}) -> type&; auto onChange(const function& callback = {}) -> type&; @@ -1618,7 +1619,7 @@ struct mTreeView : mWidget { auto onToggle(const function& callback = {}) -> type&; auto remove(sTreeViewItem item) -> type&; auto reset() -> type&; - auto selected() const -> sTreeViewItem; + auto selected() const -> TreeViewItem; auto setBackgroundColor(Color color = {}) -> type&; auto setCheckable(bool checkable = true) -> type&; auto setForegroundColor(Color color = {}) -> type&; @@ -1648,7 +1649,7 @@ struct mTreeViewItem : mObject { auto append(sTreeViewItem item) -> type&; auto checked() const -> bool; auto icon() const -> image; - auto item(const string& path) const -> sTreeViewItem; + auto item(const string& path) const -> TreeViewItem; auto items() const -> unsigned; auto path() const -> string; auto remove() -> type& override; @@ -1746,4 +1747,6 @@ struct mViewport : mWidget { #undef Declare +#include "shared.hpp" + } diff --git a/hiro/core/group.cpp b/hiro/core/group.cpp index c13f2b40..25c00deb 100644 --- a/hiro/core/group.cpp +++ b/hiro/core/group.cpp @@ -14,8 +14,12 @@ auto mGroup::append(sObject object) -> type& { return *this; } -auto mGroup::object(unsigned position) const -> sObject { - if(position < state.objects.size()) return state.objects[position]; +auto mGroup::object(unsigned position) const -> Object { + if(position < state.objects.size()) { + if(auto object = state.objects[position].acquire()) { + return object; + } + } return {}; } diff --git a/hiro/core/keyboard.cpp b/hiro/core/keyboard.cpp index ea595fcb..41ad1e01 100644 --- a/hiro/core/keyboard.cpp +++ b/hiro/core/keyboard.cpp @@ -29,9 +29,9 @@ auto Keyboard::append(sHotkey hotkey) -> void { state.hotkeys.append(hotkey); } -auto Keyboard::hotkey(unsigned position) -> sHotkey { - if(position >= hotkeys()) throw; - return state.hotkeys[position]; +auto Keyboard::hotkey(unsigned position) -> Hotkey { + if(position < hotkeys()) return state.hotkeys[position]; + return {}; } auto Keyboard::hotkeys() -> unsigned { diff --git a/hiro/core/layout.cpp b/hiro/core/layout.cpp index 2298c5a6..ffeeefe0 100644 --- a/hiro/core/layout.cpp +++ b/hiro/core/layout.cpp @@ -11,7 +11,7 @@ auto mLayout::destruct() -> void { // -auto mLayout::append(shared_pointer sizable) -> type& { +auto mLayout::append(sSizable sizable) -> type& { state.sizables.append(sizable); sizable->setParent(this, sizables() - 1); setGeometry(geometry()); @@ -29,7 +29,7 @@ auto mLayout::remove() -> type& { return *this; } -auto mLayout::remove(shared_pointer sizable) -> type& { +auto mLayout::remove(sSizable sizable) -> type& { auto offset = sizable->offset(); sizable->setParent(); state.sizables.remove(offset); @@ -52,9 +52,9 @@ auto mLayout::setParent(mObject* parent, signed offset) -> type& { return *this; } -auto mLayout::sizable(unsigned position) const -> shared_pointer { - if(position >= sizables()) throw; - return state.sizables[position]; +auto mLayout::sizable(unsigned position) const -> Sizable { + if(position < sizables()) return state.sizables[position]; + return {}; } auto mLayout::sizables() const -> unsigned { diff --git a/hiro/core/menu-bar.cpp b/hiro/core/menu-bar.cpp index d8c06775..fec4e748 100644 --- a/hiro/core/menu-bar.cpp +++ b/hiro/core/menu-bar.cpp @@ -11,16 +11,16 @@ auto mMenuBar::destruct() -> void { // -auto mMenuBar::append(shared_pointer menu) -> type& { +auto mMenuBar::append(sMenu menu) -> type& { state.menus.append(menu); menu->setParent(this, menus() - 1); signal(append, menu); return *this; } -auto mMenuBar::menu(unsigned position) const -> shared_pointer { - if(position >= menus()) throw; - return state.menus[position]; +auto mMenuBar::menu(unsigned position) const -> Menu { + if(position < menus()) return state.menus[position]; + return {}; } auto mMenuBar::menus() const -> unsigned { @@ -32,7 +32,7 @@ auto mMenuBar::remove() -> type& { return *this; } -auto mMenuBar::remove(shared_pointer menu) -> type& { +auto mMenuBar::remove(sMenu menu) -> type& { signed offset = menu->offset(); signal(remove, *menu); state.menus.remove(offset); diff --git a/hiro/core/object.cpp b/hiro/core/object.cpp index b8623f6e..ede32e67 100644 --- a/hiro/core/object.cpp +++ b/hiro/core/object.cpp @@ -69,7 +69,7 @@ auto mObject::font(bool recursive) const -> string { return Application::font(); } -auto mObject::group() const -> sGroup { +auto mObject::group() const -> Group { return {}; } diff --git a/hiro/core/popup-menu.cpp b/hiro/core/popup-menu.cpp index bb5bc4f4..2c9c5423 100644 --- a/hiro/core/popup-menu.cpp +++ b/hiro/core/popup-menu.cpp @@ -11,9 +11,9 @@ auto mPopupMenu::destruct() -> void { // -auto mPopupMenu::action(unsigned position) const -> sAction { - if(position >= actions()) throw; - return state.actions[position]; +auto mPopupMenu::action(unsigned position) const -> Action { + if(position < actions()) return state.actions[position]; + return {}; } auto mPopupMenu::actions() const -> unsigned { diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp new file mode 100644 index 00000000..77db6d51 --- /dev/null +++ b/hiro/core/shared.hpp @@ -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 Name(T* parent, P&&... p) : Name() { \ + if(parent && *parent) (*parent)->append(*this, std::forward

(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& 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 Group(P&&... p) : Group() { _append(std::forward

(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 auto _append(T* object, P&&... p) { + append(*object); + _append(std::forward

(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& callback = {}) { return self().onPress(callback), *this; } + auto onRelease(const function& 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& 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& 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& 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& 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& 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& callback = {}) { return self().onDrop(callback), *this; } + auto onMouseLeave(const function& callback = {}) { return self().onMouseLeave(callback), *this; } + auto onMouseMove(const function& callback = {}) { return self().onMouseMove(callback), *this; } + auto onMousePress(const function& callback = {}) { return self().onMousePress(callback), *this; } + auto onMouseRelease(const function& 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& 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& 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& 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& 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& callback = {}) { return self().onRead(callback), *this; } + auto onWrite(const function& 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& 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& 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& callback = {}) { return self().onActivate(callback), *this; } + auto onChange(const function& callback = {}) { return self().onChange(callback), *this; } + auto onContext(const function& 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& 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& callback = {}) { return self().onActivate(callback), *this; } + auto onChange(const function& 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& callback = {}) { return self().onActivate(callback), *this; } + auto onChange(const function& callback = {}) { return self().onChange(callback), *this; } + auto onContext(const function& callback = {}) { return self().onContext(callback), *this; } + auto onEdit(const function& callback = {}) { return self().onEdit(callback), *this; } + auto onSort(const function& callback = {}) { return self().onSort(callback), *this; } + auto onToggle(const function& 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& 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& 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& callback = {}) { return self().onChange(callback), *this; } + auto onMove(const function& 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& callback = {}) { return self().onChange(callback), *this; } + auto onClose(const function& callback = {}) { return self().onClose(callback), *this; } + auto onMove(const function& 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& callback = {}) { return self().onChange(callback), *this; } + auto onMove(const function& 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& callback = {}) { return self().onActivate(callback), *this; } + auto onChange(const function& callback = {}) { return self().onChange(callback), *this; } + auto onContext(const function& callback = {}) { return self().onContext(callback), *this; } + auto onToggle(const function& 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& 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& 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& callback = {}) { return self().onDrop(callback), *this; } + auto onMouseLeave(const function& callback = {}) { return self().onMouseLeave(callback), *this; } + auto onMouseMove(const function& callback = {}) { return self().onMouseMove(callback), *this; } + auto onMousePress(const function& callback = {}) { return self().onMousePress(callback), *this; } + auto onMouseRelease(const function& 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& callback = {}) { return self().onClose(callback), *this; } + auto onDrop(const function& callback = {}) { return self().onDrop(callback), *this; } + auto onKeyPress(const function& callback = {}) { return self().onKeyPress(callback), *this; } + auto onKeyRelease(const function& callback = {}) { return self().onKeyRelease(callback), *this; } + auto onMove(const function& callback = {}) { return self().onMove(callback), *this; } + auto onSize(const function& 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 diff --git a/hiro/core/widget/canvas.cpp b/hiro/core/widget/canvas.cpp index b0e699a2..f7ab59ce 100644 --- a/hiro/core/widget/canvas.cpp +++ b/hiro/core/widget/canvas.cpp @@ -107,7 +107,7 @@ auto mCanvas::setHorizontalGradient(Color left, Color right) -> 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; signal(setIcon, icon); return *this; diff --git a/hiro/core/widget/combo-button.cpp b/hiro/core/widget/combo-button.cpp index 4f6426e5..1ac2e285 100644 --- a/hiro/core/widget/combo-button.cpp +++ b/hiro/core/widget/combo-button.cpp @@ -22,7 +22,7 @@ auto mComboButton::doChange() const -> void { 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]; return {}; } @@ -53,11 +53,11 @@ auto mComboButton::reset() -> type& { return *this; } -auto mComboButton::selected() const -> sComboButtonItem { +auto mComboButton::selected() const -> ComboButtonItem { for(auto& item : state.items) { if(item->selected()) return item; } - return {}; + return {nullptr}; } auto mComboButton::setParent(mObject* parent, signed offset) -> type& { diff --git a/hiro/core/widget/frame.cpp b/hiro/core/widget/frame.cpp index eed50a3b..e21b2b30 100644 --- a/hiro/core/widget/frame.cpp +++ b/hiro/core/widget/frame.cpp @@ -11,18 +11,18 @@ auto mFrame::destruct() -> void { // -auto mFrame::append(shared_pointer layout) -> type& { +auto mFrame::append(sLayout layout) -> type& { if(auto& layout = state.layout) remove(layout); state.layout = layout; layout->setParent(this, 0); return *this; } -auto mFrame::layout() const -> shared_pointer { +auto mFrame::layout() const -> Layout { return state.layout; } -auto mFrame::remove(shared_pointer layout) -> type& { +auto mFrame::remove(sLayout layout) -> type& { layout->setParent(); state.layout.reset(); return *this; diff --git a/hiro/core/widget/icon-view.cpp b/hiro/core/widget/icon-view.cpp index 9dc1c762..1fba9052 100644 --- a/hiro/core/widget/icon-view.cpp +++ b/hiro/core/widget/icon-view.cpp @@ -11,7 +11,7 @@ auto mIconView::destruct() -> void { // -auto mIconView::append(shared_pointer item) -> type& { +auto mIconView::append(sIconViewItem item) -> type& { state.items.append(item); item->setParent(this, items() - 1); signal(append, item); @@ -42,9 +42,9 @@ auto mIconView::foregroundColor() const -> Color { return state.foregroundColor; } -auto mIconView::item(unsigned position) const -> shared_pointer { - if(position >= items()) throw; - return state.items[position]; +auto mIconView::item(unsigned position) const -> IconViewItem { + if(position < items()) return state.items[position]; + return {}; } auto mIconView::items() const -> unsigned { @@ -74,7 +74,7 @@ auto mIconView::orientation() const -> Orientation { return state.orientation; } -auto mIconView::remove(shared_pointer item) -> type& { +auto mIconView::remove(sIconViewItem item) -> type& { signal(remove, item); state.items.remove(item->offset()); for(auto n : range(item->offset(), items())) { diff --git a/hiro/core/widget/list-view-item.cpp b/hiro/core/widget/list-view-item.cpp index 94033df2..d3629fe0 100644 --- a/hiro/core/widget/list-view-item.cpp +++ b/hiro/core/widget/list-view-item.cpp @@ -17,7 +17,7 @@ auto mListViewItem::backgroundColor() const -> Color { return state.backgroundColor; } -auto mListViewItem::cell(unsigned position) const -> sListViewCell { +auto mListViewItem::cell(unsigned position) const -> ListViewCell { if(position < cells()) return state.cells[position]; return {}; } diff --git a/hiro/core/widget/list-view.cpp b/hiro/core/widget/list-view.cpp index e823080a..207083df 100644 --- a/hiro/core/widget/list-view.cpp +++ b/hiro/core/widget/list-view.cpp @@ -44,15 +44,15 @@ auto mListView::checkAll() -> type& { return *this; } -auto mListView::checked() const -> vector { - vector items; +auto mListView::checked() const -> vector { + vector items; for(auto& item : state.items) { if(item->checked()) items.append(item); } return items; } -auto mListView::column(unsigned position) const -> sListViewColumn { +auto mListView::column(unsigned position) const -> ListViewColumn { if(position < columns()) return state.columns[position]; return {}; } @@ -97,7 +97,7 @@ auto mListView::headerVisible() const -> bool { return state.headerVisible; } -auto mListView::item(unsigned position) const -> sListViewItem { +auto mListView::item(unsigned position) const -> ListViewItem { if(position < items()) return state.items[position]; return {}; } @@ -121,17 +121,17 @@ auto mListView::onContext(const function& callback) -> type& { return *this; } -auto mListView::onEdit(const function& callback) -> type& { +auto mListView::onEdit(const function& callback) -> type& { state.onEdit = callback; return *this; } -auto mListView::onSort(const function& callback) -> type& { +auto mListView::onSort(const function& callback) -> type& { state.onSort = callback; return *this; } -auto mListView::onToggle(const function& callback) -> type& { +auto mListView::onToggle(const function& callback) -> type& { state.onToggle = callback; return *this; } @@ -178,15 +178,15 @@ auto mListView::selectAll() -> type& { return *this; } -auto mListView::selected() const -> sListViewItem { +auto mListView::selected() const -> ListViewItem { for(auto& item : state.items) { if(item->selected()) return item; } - return {}; + return {nullptr}; } -auto mListView::selectedItems() const -> vector { - vector items; +auto mListView::selectedItems() const -> vector { + vector items; for(auto& item : state.items) { if(item->selected()) items.append(item); } diff --git a/hiro/core/widget/radio-button.cpp b/hiro/core/widget/radio-button.cpp index cd6fca67..4fdf1dc1 100644 --- a/hiro/core/widget/radio-button.cpp +++ b/hiro/core/widget/radio-button.cpp @@ -18,7 +18,7 @@ auto mRadioButton::doActivate() const -> void { if(state.onActivate) return state.onActivate(); } -auto mRadioButton::group() const -> sGroup { +auto mRadioButton::group() const -> Group { return state.group; } diff --git a/hiro/core/widget/radio-label.cpp b/hiro/core/widget/radio-label.cpp index 1607651f..503fe9d3 100644 --- a/hiro/core/widget/radio-label.cpp +++ b/hiro/core/widget/radio-label.cpp @@ -14,7 +14,7 @@ auto mRadioLabel::doActivate() const -> void { if(state.onActivate) return state.onActivate(); } -auto mRadioLabel::group() const -> sGroup { +auto mRadioLabel::group() const -> Group { return state.group; } diff --git a/hiro/core/widget/tab-frame-item.cpp b/hiro/core/widget/tab-frame-item.cpp index 593828b2..2c6998f4 100644 --- a/hiro/core/widget/tab-frame-item.cpp +++ b/hiro/core/widget/tab-frame-item.cpp @@ -27,7 +27,7 @@ auto mTabFrameItem::icon() const -> image { return state.icon; } -auto mTabFrameItem::layout() const -> sLayout { +auto mTabFrameItem::layout() const -> Layout { return state.layout; } diff --git a/hiro/core/widget/tab-frame.cpp b/hiro/core/widget/tab-frame.cpp index 82bbca49..0e3b253b 100644 --- a/hiro/core/widget/tab-frame.cpp +++ b/hiro/core/widget/tab-frame.cpp @@ -34,7 +34,7 @@ auto mTabFrame::edge() const -> 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]; return {}; } @@ -48,12 +48,12 @@ auto mTabFrame::onChange(const function& callback) -> type& { return *this; } -auto mTabFrame::onClose(const function& callback) -> type& { +auto mTabFrame::onClose(const function& callback) -> type& { state.onClose = callback; return *this; } -auto mTabFrame::onMove(const function& callback) -> type& { +auto mTabFrame::onMove(const function& callback) -> type& { state.onMove = callback; return *this; } @@ -74,11 +74,11 @@ auto mTabFrame::reset() -> type& { return *this; } -auto mTabFrame::selected() const -> sTabFrameItem { +auto mTabFrame::selected() const -> TabFrameItem { for(auto& item : state.items) { if(item->selected()) return item; } - return {}; + return {nullptr}; } auto mTabFrame::setEdge(Edge edge) -> type& { diff --git a/hiro/core/widget/tree-view-item.cpp b/hiro/core/widget/tree-view-item.cpp index 92616839..c7d5c112 100644 --- a/hiro/core/widget/tree-view-item.cpp +++ b/hiro/core/widget/tree-view-item.cpp @@ -26,7 +26,7 @@ auto mTreeViewItem::icon() const -> image { return state.icon; } -auto mTreeViewItem::item(const string& path) const -> sTreeViewItem { +auto mTreeViewItem::item(const string& path) const -> TreeViewItem { if(path.empty()) return {}; auto paths = path.split("/"); unsigned position = decimal(paths.takeFirst()); diff --git a/hiro/core/widget/tree-view.cpp b/hiro/core/widget/tree-view.cpp index 05453d07..81433d8a 100644 --- a/hiro/core/widget/tree-view.cpp +++ b/hiro/core/widget/tree-view.cpp @@ -56,7 +56,7 @@ auto mTreeView::foregroundColor() const -> Color { return state.foregroundColor; } -auto mTreeView::item(const string& path) const -> sTreeViewItem { +auto mTreeView::item(const string& path) const -> TreeViewItem { if(path.empty()) return {}; auto paths = path.split("/"); unsigned position = decimal(paths.takeFirst()); @@ -107,7 +107,7 @@ auto mTreeView::reset() -> type& { return *this; } -auto mTreeView::selected() const -> sTreeViewItem { +auto mTreeView::selected() const -> TreeViewItem { return item(state.selectedPath); } diff --git a/hiro/core/window.cpp b/hiro/core/window.cpp index 8d04ec9e..6a4e13b2 100644 --- a/hiro/core/window.cpp +++ b/hiro/core/window.cpp @@ -87,11 +87,11 @@ auto mWindow::geometry() const -> Geometry { return state.geometry; } -auto mWindow::layout() const -> shared_pointer { +auto mWindow::layout() const -> Layout { return state.layout; } -auto mWindow::menuBar() const -> shared_pointer { +auto mWindow::menuBar() const -> MenuBar { return state.menuBar; } @@ -266,7 +266,7 @@ auto mWindow::setTitle(const string& title) -> type& { return *this; } -auto mWindow::statusBar() const -> shared_pointer { +auto mWindow::statusBar() const -> StatusBar { return state.statusBar; } diff --git a/hiro/extension/shared.hpp b/hiro/extension/shared.hpp index 6352192c..b432b451 100644 --- a/hiro/extension/shared.hpp +++ b/hiro/extension/shared.hpp @@ -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 Name(T* parent, P&&... p) : Name() { \ - if(parent && *parent) (*parent)->append(*this, std::forward

(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& 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 Group(P&&... p) : Group() { _append(std::forward

(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 auto _append(T* object, P&&... p) -> void { - append(*object); - _append(std::forward

(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& callback = {}) -> type& { return self().onPress(callback), *this; } - auto onRelease(const function& 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& 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& callback = {}) -> type& { return self().onClose(callback), *this; } - auto onDrop(const function& callback = {}) -> type& { return self().onDrop(callback), *this; } - auto onKeyPress(const function& callback = {}) -> type& { return self().onKeyPress(callback), *this; } - auto onKeyRelease(const function& callback = {}) -> type& { return self().onKeyRelease(callback), *this; } - auto onMove(const function& callback = {}) -> type& { return self().onMove(callback), *this; } - auto onSize(const function& 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& 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& 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& 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& 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 { return self().gradient(); } - auto icon() const -> image { return self().icon(); } - auto onDrop(const function& callback = {}) -> type& { return self().onDrop(callback), *this; } - auto onMouseLeave(const function& callback = {}) -> type& { return self().onMouseLeave(callback), *this; } - auto onMouseMove(const function& callback = {}) -> type& { return self().onMouseMove(callback), *this; } - auto onMousePress(const function& callback = {}) -> type& { return self().onMousePress(callback), *this; } - auto onMouseRelease(const function& 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& 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& 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& 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& 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& callback = {}) -> type& { return self().onRead(callback), *this; } - auto onWrite(const function& 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& 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& 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& callback = {}) -> type& { return self().onActivate(callback), *this; } - auto onChange(const function& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onContext(const function& 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 { return self().selected(); } - auto selectedItems() const -> vector { 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& 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& callback = {}) -> type& { return self().onActivate(callback), *this; } - auto onChange(const function& 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 { 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& callback = {}) -> type& { return self().onActivate(callback), *this; } - auto onChange(const function& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onContext(const function& callback = {}) -> type& { return self().onContext(callback), *this; } - auto onEdit(const function& callback = {}) -> type& { return self().onEdit(callback), *this; } - auto onSort(const function& callback = {}) -> type& { return self().onSort(callback), *this; } - auto onToggle(const function& 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 { 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& 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& 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& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onMove(const function& 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& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onClose(const function& callback = {}) -> type& { return self().onClose(callback), *this; } - auto onMove(const function& 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& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onMove(const function& 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& callback = {}) -> type& { return self().onActivate(callback), *this; } - auto onChange(const function& callback = {}) -> type& { return self().onChange(callback), *this; } - auto onContext(const function& callback = {}) -> type& { return self().onContext(callback), *this; } - auto onToggle(const function& 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& 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& 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& callback = {}) -> type& { return self().onDrop(callback), *this; } - auto onMouseLeave(const function& callback = {}) -> type& { return self().onMouseLeave(callback), *this; } - auto onMouseMove(const function& callback = {}) -> type& { return self().onMouseMove(callback), *this; } - auto onMousePress(const function& callback = {}) -> type& { return self().onMousePress(callback), *this; } - auto onMouseRelease(const function& callback = {}) -> type& { return self().onMouseRelease(callback), *this; } - auto setDroppable(bool droppable = true) -> type& { return self().setDroppable(droppable), *this; } -}; -#endif - #if defined(Hiro_FixedLayout) using sFixedLayout = shared_pointer; 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 #if defined(Hiro_HorizontalLayout) using sHorizontalLayout = shared_pointer; 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 setAlignment(double alignment = 0.5) -> type& { return self().setAlignment(alignment), *this; } - auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } - auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } + auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; } + auto setAlignment(double alignment = 0.5) { return self().setAlignment(alignment), *this; } + auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; } + auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; } }; #endif #if defined(Hiro_VerticalLayout) using sVerticalLayout = shared_pointer; 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 setAlignment(double alignment = 0.0) -> type& { return self().setAlignment(alignment), *this; } - auto setMargin(signed margin = 0) -> type& { return self().setMargin(margin), *this; } - auto setSpacing(signed spacing = 5) -> type& { return self().setSpacing(spacing), *this; } + auto append(sSizable sizable, Size size, signed spacing = 5) { return self().append(sizable, size, spacing), *this; } + auto setAlignment(double alignment = 0.0) { return self().setAlignment(alignment), *this; } + auto setMargin(signed margin = 0) { return self().setMargin(margin), *this; } + auto setSpacing(signed spacing = 5) { return self().setSpacing(spacing), *this; } }; #endif - -#undef Declare -#undef DeclareObject -#undef DeclareAction -#undef DeclareSizable -#undef DeclareLayout -#undef DeclareWidget diff --git a/hiro/gtk/utility.cpp b/hiro/gtk/utility.cpp index 49453b7f..8593481b 100644 --- a/hiro/gtk/utility.cpp +++ b/hiro/gtk/utility.cpp @@ -11,22 +11,21 @@ static auto CreateColor(const Color& color) -> GdkColor { } #endif -static auto CreatePixbuf(const nall::image& image, bool scale = false) -> GdkPixbuf* { - if(!image) return nullptr; +static auto CreatePixbuf(image icon, bool scale = false) -> GdkPixbuf* { + if(!icon) return nullptr; - nall::image gdkImage = image; - gdkImage.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); - if(scale) gdkImage.scale(15, 15); + if(scale) icon.scale(15, 15); + icon.transform(0, 32, 255u << 24, 255u << 0, 255u << 8, 255u << 16); //GTK stores images in ABGR format - GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, gdkImage.width, gdkImage.height); - memcpy(gdk_pixbuf_get_pixels(pixbuf), gdkImage.data, gdkImage.width * gdkImage.height * 4); + auto pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, icon.width(), icon.height()); + memory::copy(gdk_pixbuf_get_pixels(pixbuf), icon.data(), icon.size()); return pixbuf; } static auto CreateImage(const nall::image& image, bool scale = false) -> GtkImage* { - GdkPixbuf* pixbuf = CreatePixbuf(image, scale); - GtkImage* gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf); + auto pixbuf = CreatePixbuf(image, scale); + auto gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf); g_object_unref(pixbuf); return gtkImage; } diff --git a/hiro/gtk/widget/button.cpp b/hiro/gtk/widget/button.cpp index f5d9512b..764af857 100644 --- a/hiro/gtk/widget/button.cpp +++ b/hiro/gtk/widget/button.cpp @@ -26,13 +26,13 @@ auto pButton::minimumSize() const -> Size { Size size = pFont::size(self().font(true), state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + (state().text ? 24 : 12), size.height() + 12}; diff --git a/hiro/gtk/widget/canvas.cpp b/hiro/gtk/widget/canvas.cpp index 2992dd7c..2761c1c2 100644 --- a/hiro/gtk/widget/canvas.cpp +++ b/hiro/gtk/widget/canvas.cpp @@ -174,14 +174,14 @@ auto pCanvas::_rasterize() -> void { fill.gradient( 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) { auto icon = state().icon; icon.scale(width, height); - icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); - memory::copy(buffer, icon.data, icon.size); + icon.transform(); + memory::copy(buffer, icon.data(), icon.size()); } if(mode == Mode::Data) { diff --git a/hiro/gtk/widget/check-button.cpp b/hiro/gtk/widget/check-button.cpp index ac1e75d3..3ff37aa9 100644 --- a/hiro/gtk/widget/check-button.cpp +++ b/hiro/gtk/widget/check-button.cpp @@ -29,13 +29,13 @@ auto pCheckButton::minimumSize() const -> Size { Size size = pFont::size(self().font(true), state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + 24, size.height() + 12}; diff --git a/hiro/gtk/widget/list-view.cpp b/hiro/gtk/widget/list-view.cpp index 5a002b44..5308645b 100644 --- a/hiro/gtk/widget/list-view.cpp +++ b/hiro/gtk/widget/list-view.cpp @@ -224,7 +224,7 @@ auto pListView::_cellWidth(unsigned _row, unsigned _column) -> unsigned { if(auto item = self().item(_row)) { if(auto cell = item->cell(_column)) { if(auto& icon = cell->state.icon) { - width += icon.width + 2; + width += icon.width() + 2; } if(auto& text = cell->state.text) { width += Font::size(cell->font(true), text).width(); @@ -243,7 +243,7 @@ auto pListView::_columnWidth(unsigned _column) -> unsigned { unsigned width = 8; //margin if(auto column = self().column(_column)) { if(auto& icon = column->state.icon) { - width += icon.width + 2; + width += icon.width() + 2; } if(auto& text = column->state.text) { width += Font::size(column->font(true), text).width(); diff --git a/hiro/gtk/widget/radio-button.cpp b/hiro/gtk/widget/radio-button.cpp index 89020da6..74a5d0f8 100644 --- a/hiro/gtk/widget/radio-button.cpp +++ b/hiro/gtk/widget/radio-button.cpp @@ -30,13 +30,13 @@ auto pRadioButton::minimumSize() const -> Size { Size size = pFont::size(self().font(true), state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + 24, size.height() + 12}; diff --git a/hiro/gtk/window.cpp b/hiro/gtk/window.cpp index b36280d3..787e5f19 100644 --- a/hiro/gtk/window.cpp +++ b/hiro/gtk/window.cpp @@ -369,9 +369,9 @@ auto pWindow::_setIcon(const string& pathname) -> bool { filename = {pathname, Application::state.name, ".png"}; if(file::exists(filename)) { //maximum image size GTK+ supports is 256x256; scale image down if necessary to prevent error - nall::image icon(filename); - icon.scale(min(256u, icon.width), min(256u, icon.height), true); - GdkPixbuf* pixbuf = CreatePixbuf(icon); + image icon(filename); + icon.scale(min(256u, icon.width()), min(256u, icon.height()), true); + auto pixbuf = CreatePixbuf(icon); gtk_window_set_icon(GTK_WINDOW(widget), pixbuf); g_object_unref(G_OBJECT(pixbuf)); return true; diff --git a/hiro/hiro.hpp b/hiro/hiro.hpp index 5acf48a4..3f122a6f 100644 --- a/hiro/hiro.hpp +++ b/hiro/hiro.hpp @@ -14,4 +14,11 @@ #include "core/core.hpp" #include "extension/extension.hpp" +#undef DeclareShared +#undef DeclareSharedObject +#undef DeclareSharedAction +#undef DeclareSharedSizable +#undef DeclareSharedLayout +#undef DeclareSharedWidget + #endif diff --git a/hiro/windows/action/menu-item.cpp b/hiro/windows/action/menu-item.cpp index d01b3bc7..fa67aefc 100644 --- a/hiro/windows/action/menu-item.cpp +++ b/hiro/windows/action/menu-item.cpp @@ -27,7 +27,7 @@ auto pMenuItem::_createBitmap() -> void { if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; } 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.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear); hbitmap = CreateBitmap(icon); diff --git a/hiro/windows/action/menu.cpp b/hiro/windows/action/menu.cpp index 5d7d1eb0..778e8dcd 100644 --- a/hiro/windows/action/menu.cpp +++ b/hiro/windows/action/menu.cpp @@ -32,7 +32,7 @@ auto pMenu::_createBitmap() -> void { if(hbitmap) { DeleteObject(hbitmap); hbitmap = 0; } 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.scale(GetSystemMetrics(SM_CXMENUCHECK), GetSystemMetrics(SM_CYMENUCHECK), Interpolation::Linear); hbitmap = CreateBitmap(icon); diff --git a/hiro/windows/utility.cpp b/hiro/windows/utility.cpp index 430da703..cbe5d8d1 100644 --- a/hiro/windows/utility.cpp +++ b/hiro/windows/utility.cpp @@ -12,20 +12,20 @@ static auto OsVersion() -> unsigned { 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); BITMAPINFO bitmapInfo; memset(&bitmapInfo, 0, sizeof(BITMAPINFO)); bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bitmapInfo.bmiHeader.biWidth = image.width; - bitmapInfo.bmiHeader.biHeight = -image.height; //bitmaps are stored upside down unless we negate height + bitmapInfo.bmiHeader.biWidth = icon.width(); + bitmapInfo.bmiHeader.biHeight = -(signed)icon.height(); //bitmaps are stored upside down unless we negate height bitmapInfo.bmiHeader.biPlanes = 1; bitmapInfo.bmiHeader.biBitCount = 32; bitmapInfo.bmiHeader.biCompression = BI_RGB; - bitmapInfo.bmiHeader.biSizeImage = image.width * image.height * 4; + bitmapInfo.bmiHeader.biSizeImage = icon.size(); void* bits = nullptr; 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); return hbitmap; } @@ -68,7 +68,7 @@ static auto ImageList_Append(HIMAGELIST imageList, const image& source, unsigned image.allocate(scale, scale); image.fill(GetSysColor(COLOR_WINDOW)); } - image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); + image.transform(); image.scale(scale, scale); HBITMAP bitmap = CreateBitmap(image); ImageList_Add(imageList, bitmap, NULL); diff --git a/hiro/windows/widget/button.cpp b/hiro/windows/widget/button.cpp index 98cf7fce..76bc6b1e 100644 --- a/hiro/windows/widget/button.cpp +++ b/hiro/windows/widget/button.cpp @@ -24,13 +24,13 @@ auto pButton::minimumSize() const -> Size { auto size = pFont::size(hfont, state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + (state().text ? 20 : 13), size.height() + 10}; @@ -58,7 +58,7 @@ auto pButton::onActivate() -> void { //performs setIcon, setOrientation, setText auto pButton::_setState() -> void { 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(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } @@ -68,7 +68,7 @@ auto pButton::_setState() -> void { if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); 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); BUTTON_IMAGELIST list; list.himl = himagelist; diff --git a/hiro/windows/widget/canvas.cpp b/hiro/windows/widget/canvas.cpp index a71f7998..b30dd9f9 100644 --- a/hiro/windows/widget/canvas.cpp +++ b/hiro/windows/widget/canvas.cpp @@ -162,14 +162,14 @@ auto pCanvas::_rasterize() -> void { state().gradient[0].value(), state().gradient[1].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) { auto icon = state().icon; icon.scale(width, height); - icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); - memory::copy(pixels.data(), icon.data, icon.size); + icon.transform(); + memory::copy(pixels.data(), icon.data(), icon.size()); } if(mode == Mode::Data) { diff --git a/hiro/windows/widget/check-button.cpp b/hiro/windows/widget/check-button.cpp index 5590b028..66b0f2d1 100644 --- a/hiro/windows/widget/check-button.cpp +++ b/hiro/windows/widget/check-button.cpp @@ -23,13 +23,13 @@ auto pCheckButton::minimumSize() -> Size { auto size = pFont::size(hfont, state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + (state().text ? 20 : 10), size.height() + 10}; @@ -62,16 +62,16 @@ auto pCheckButton::onToggle() -> void { auto pCheckButton::_setState() -> void { 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(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } + if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; } + if(himagelist) { ImageList_Destroy(himagelist); himagelist = nullptr; } if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); hbitmap = CreateBitmap(icon); - himagelist = ImageList_Create(icon.width, icon.height, ILC_COLOR32, 1, 0); - ImageList_Add(himagelist, hbitmap, NULL); + himagelist = ImageList_Create(icon.width(), icon.height(), ILC_COLOR32, 1, 0); + ImageList_Add(himagelist, hbitmap, nullptr); BUTTON_IMAGELIST list; list.himl = himagelist; switch(state().orientation) { diff --git a/hiro/windows/widget/list-view.cpp b/hiro/windows/widget/list-view.cpp index 8d781a39..06edd540 100644 --- a/hiro/windows/widget/list-view.cpp +++ b/hiro/windows/widget/list-view.cpp @@ -232,12 +232,17 @@ auto pListView::onChange(LPARAM lparam) -> void { PostMessageOnce(_parentHandle(), AppMessage::ListView_onChange, 0, (LPARAM)&reference); } - unsigned row = nmlistview->iItem; - unsigned mask = ((nmlistview->uNewState & LVIS_STATEIMAGEMASK) >> 12) - 1; - if((mask == 0 || mask == 1) && !locked()) { - if(auto item = self().item(row)) { - item->state.checked = !item->state.checked; - self().doToggle(item); + if(!locked()) { + unsigned row = nmlistview->iItem; + unsigned mask = nmlistview->uNewState & LVIS_STATEIMAGEMASK; + if(mask == 0x1000 || mask == 0x2000) { + bool checked = mask == 0x2000; + if(auto item = self().item(row)) { + if(checked != item->state.checked) { //WC_LISTVIEW sends this message twice + item->state.checked = checked; + self().doToggle(item); + } + } } } } @@ -288,7 +293,7 @@ auto pListView::onCustomDraw(LPARAM lparam) -> LRESULT { if(!cell) continue; if(auto icon = cell->state.icon) { icon.scale(iconSize, iconSize); - icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); + icon.transform(); auto bitmap = CreateBitmap(icon); SelectBitmap(hdcSource, bitmap); 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; if(icon) { icon.scale(16, 16); - icon.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); + icon.transform(); } else { icon.allocate(16, 16); icon.fill(0x00ffffff); diff --git a/hiro/windows/widget/radio-button.cpp b/hiro/windows/widget/radio-button.cpp index 284eb559..01021a7c 100644 --- a/hiro/windows/widget/radio-button.cpp +++ b/hiro/windows/widget/radio-button.cpp @@ -23,13 +23,13 @@ auto pRadioButton::minimumSize() -> Size { auto size = pFont::size(hfont, state().text); if(state().orientation == Orientation::Horizontal) { - size.setWidth(size.width() + state().icon.width); - size.setHeight(max(size.height(), state().icon.height)); + size.setWidth(size.width() + state().icon.width()); + size.setHeight(max(size.height(), state().icon.height())); } if(state().orientation == Orientation::Vertical) { - size.setWidth(max(size.width(), state().icon.width)); - size.setHeight(size.height() + state().icon.height); + size.setWidth(max(size.width(), state().icon.width())); + size.setHeight(size.height() + state().icon.height()); } return {size.width() + (state().text ? 20 : 10), size.height() + 10}; @@ -75,16 +75,16 @@ void pRadioButton::onActivate() { auto pRadioButton::_setState() -> void { 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(himagelist) { ImageList_Destroy(himagelist); himagelist = 0; } + if(hbitmap) { DeleteObject(hbitmap); hbitmap = nullptr; } + if(himagelist) { ImageList_Destroy(himagelist); himagelist = nullptr; } if(OsVersion() < WindowsVista) icon.alphaBlend(GetSysColor(COLOR_BTNFACE)); hbitmap = CreateBitmap(icon); - himagelist = ImageList_Create(icon.width, icon.height, ILC_COLOR32, 1, 0); - ImageList_Add(himagelist, hbitmap, NULL); + himagelist = ImageList_Create(icon.width(), icon.height(), ILC_COLOR32, 1, 0); + ImageList_Add(himagelist, hbitmap, nullptr); BUTTON_IMAGELIST list; list.himl = himagelist; switch(state().orientation) { diff --git a/hiro/windows/window.cpp b/hiro/windows/window.cpp index 7ffa206b..4b247c75 100644 --- a/hiro/windows/window.cpp +++ b/hiro/windows/window.cpp @@ -89,9 +89,10 @@ auto pWindow::setFont(const string& font) -> void { } auto pWindow::setFullScreen(bool fullScreen) -> void { + auto style = GetWindowLongPtr(hwnd, GWL_STYLE) & WS_VISIBLE; lock(); 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); } else { HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); @@ -101,7 +102,7 @@ auto pWindow::setFullScreen(bool fullScreen) -> void { GetMonitorInfo(monitor, &info); RECT rc = info.rcMonitor; 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(); setGeometry({ geometry.x() + margin.x(), geometry.y() + margin.y(), @@ -147,7 +148,8 @@ auto pWindow::setModal(bool modality) -> 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); } diff --git a/nall/image/base.hpp b/nall/image/base.hpp index f05ede90..e20ee1b1 100644 --- a/nall/image/base.hpp +++ b/nall/image/base.hpp @@ -4,35 +4,6 @@ namespace nall { 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 { add, sourceAlpha, //color = sourceColor * sourceAlpha + targetColor * (1 - sourceAlpha) @@ -41,18 +12,29 @@ struct image { targetColor, //color = targetColor }; - //static.hpp - static inline unsigned bitDepth(uint64_t color); - static inline unsigned bitShift(uint64_t color); - static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth); + struct channel { + channel(uint64_t mask, unsigned depth, unsigned shift) : _mask(mask), _depth(depth), _shift(shift) { + } + + 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 - 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(image&& source); 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 uint64_t read(const uint8_t* data) const; - inline void write(uint8_t* data, uint64_t value) const; + inline auto operator=(const image& source) -> image&; + inline auto operator=(image&& source) -> image&; - inline void free(); - inline bool empty() const; - inline bool load(const string& filename); - inline void allocate(unsigned width, unsigned height); + inline explicit operator bool() const; + inline auto operator==(const image& source) const -> bool; + inline auto operator!=(const image& source) const -> bool; + + 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 - inline void fill(uint64_t color = 0); - inline void gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d); - inline void gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function callback); - inline void crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); - inline void verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY); + inline auto fill(uint64_t color = 0) -> void; + inline auto gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) -> void; + inline auto gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function callback) -> void; + inline auto crossGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto diamondGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto horizontalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto radialGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto sphericalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto squareGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; + inline auto verticalGradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY) -> void; //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 - 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 - inline bool crop(unsigned x, unsigned y, unsigned width, unsigned height); - inline void alphaBlend(uint64_t alphaColor); - inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); + inline auto crop(unsigned x, unsigned y, unsigned width, unsigned height) -> bool; + inline auto alphaBlend(uint64_t alphaColor) -> void; + 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 - inline uint8_t* allocate(unsigned width, unsigned height, unsigned stride); + inline auto allocate(unsigned width, unsigned height, unsigned stride) -> uint8_t*; //scale.hpp - inline void scaleLinearWidth(unsigned width); - inline void scaleLinearHeight(unsigned height); - inline void scaleLinear(unsigned width, unsigned height); - inline void scaleNearest(unsigned width, unsigned height); + inline auto scaleLinearWidth(unsigned width) -> void; + inline auto scaleLinearHeight(unsigned height) -> void; + inline auto scaleLinear(unsigned width, unsigned height) -> void; + inline auto scaleNearest(unsigned width, unsigned height) -> void; //load.hpp - inline bool loadBMP(const string& filename); - inline bool loadPNG(const string& filename); - inline bool loadPNG(const uint8_t* data, unsigned size); + inline auto loadBMP(const string& filename) -> bool; + inline auto loadPNG(const string& filename) -> bool; + inline auto loadPNG(const uint8_t* data, unsigned size) -> bool; //interpolation.hpp - alwaysinline void isplit(uint64_t* component, uint64_t color); - alwaysinline uint64_t imerge(const uint64_t* component); - alwaysinline uint64_t interpolate1f(uint64_t a, uint64_t b, double x); - alwaysinline uint64_t interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y); - alwaysinline uint64_t interpolate1i(int64_t a, int64_t b, uint32_t x); - alwaysinline uint64_t interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y); - inline uint64_t interpolate4f(uint64_t a, uint64_t b, double x); - inline uint64_t interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y); - inline uint64_t interpolate4i(uint64_t a, uint64_t b, uint32_t x); - inline uint64_t interpolate4i(uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint32_t x, uint32_t y); + alwaysinline auto isplit(uint64_t* component, uint64_t color) -> void; + alwaysinline auto imerge(const uint64_t* component) -> uint64_t; + alwaysinline auto interpolate1f(uint64_t a, uint64_t b, double x) -> uint64_t; + alwaysinline auto interpolate1f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t; + alwaysinline auto interpolate1i(int64_t a, int64_t b, uint32_t x) -> uint64_t; + alwaysinline auto interpolate1i(int64_t a, int64_t b, int64_t c, int64_t d, uint32_t x, uint32_t y) -> uint64_t; + inline auto interpolate4f(uint64_t a, uint64_t b, double x) -> uint64_t; + inline auto interpolate4f(uint64_t a, uint64_t b, uint64_t c, uint64_t d, double x, double y) -> uint64_t; + inline auto interpolate4i(uint64_t a, uint64_t b, uint32_t x) -> uint64_t; + 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}; }; } diff --git a/nall/image/blend.hpp b/nall/image/blend.hpp index 6c8997a1..0f6b153a 100644 --- a/nall/image/blend.hpp +++ b/nall/image/blend.hpp @@ -3,41 +3,42 @@ namespace nall { -void image::impose(blend mode, unsigned targetX, unsigned targetY, image source, unsigned sourceX, unsigned sourceY, unsigned sourceWidth, unsigned sourceHeight) { - source.transform(endian, depth, alpha.mask, red.mask, green.mask, blue.mask); +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()); + #pragma omp parallel for for(unsigned y = 0; y < sourceHeight; y++) { - const uint8_t* sp = source.data + source.pitch * (sourceY + y) + source.stride * sourceX; - uint8_t* dp = data + pitch * (targetY + y) + stride * targetX; + const uint8_t* sp = source._data + source.pitch() * (sourceY + y) + source.stride() * sourceX; + uint8_t* dp = _data + pitch() * (targetY + y) + stride() * targetX; for(unsigned x = 0; x < sourceWidth; x++) { uint64_t sourceColor = source.read(sp); uint64_t targetColor = read(dp); - int64_t sa = (sourceColor & alpha.mask) >> alpha.shift; - int64_t sr = (sourceColor & red.mask ) >> red.shift; - int64_t sg = (sourceColor & green.mask) >> green.shift; - int64_t sb = (sourceColor & blue.mask ) >> blue.shift; + int64_t sa = (sourceColor & _alpha.mask()) >> _alpha.shift(); + int64_t sr = (sourceColor & _red.mask() ) >> _red.shift(); + int64_t sg = (sourceColor & _green.mask()) >> _green.shift(); + int64_t sb = (sourceColor & _blue.mask() ) >> _blue.shift(); - int64_t da = (targetColor & alpha.mask) >> alpha.shift; - int64_t dr = (targetColor & red.mask ) >> red.shift; - int64_t dg = (targetColor & green.mask) >> green.shift; - int64_t db = (targetColor & blue.mask ) >> blue.shift; + int64_t da = (targetColor & _alpha.mask()) >> _alpha.shift(); + int64_t dr = (targetColor & _red.mask() ) >> _red.shift(); + int64_t dg = (targetColor & _green.mask()) >> _green.shift(); + int64_t db = (targetColor & _blue.mask() ) >> _blue.shift(); uint64_t a, r, g, b; switch(mode) { case blend::add: a = max(sa, da); - 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)); - b = min(blue.mask >> blue.shift, ((sb * sa) >> alpha.depth) + ((db * 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())); + b = min(_blue.mask() >> _blue.shift(), ((sb * sa) >> _alpha.depth()) + ((db * da) >> _alpha.depth())); break; case blend::sourceAlpha: a = max(sa, da); - r = dr + (((sr - dr) * sa) >> alpha.depth); - g = dg + (((sg - dg) * sa) >> alpha.depth); - b = db + (((sb - db) * sa) >> alpha.depth); + r = dr + (((sr - dr) * sa) >> _alpha.depth()); + g = dg + (((sg - dg) * sa) >> _alpha.depth()); + b = db + (((sb - db) * sa) >> _alpha.depth()); break; case blend::sourceColor: @@ -49,9 +50,9 @@ void image::impose(blend mode, unsigned targetX, unsigned targetY, image source, case blend::targetAlpha: a = max(sa, da); - r = sr + (((dr - sr) * da) >> alpha.depth); - g = sg + (((dg - sg) * da) >> alpha.depth); - b = sb + (((db - sb) * da) >> alpha.depth); + r = sr + (((dr - sr) * da) >> _alpha.depth()); + g = sg + (((dg - sg) * da) >> _alpha.depth()); + b = sb + (((db - sb) * da) >> _alpha.depth()); break; case blend::targetColor: @@ -62,9 +63,9 @@ void image::impose(blend mode, unsigned targetX, unsigned targetY, image source, break; } - write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); - sp += source.stride; - dp += stride; + write(dp, (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift())); + sp += source.stride(); + dp += stride(); } } } diff --git a/nall/image/core.hpp b/nall/image/core.hpp index 3d2da38a..9939da5a 100644 --- a/nall/image/core.hpp +++ b/nall/image/core.hpp @@ -3,91 +3,22 @@ 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) { operator=(source); } image::image(image&& source) { - operator=(std::forward(source)); + operator=(forward(source)); } image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) { - this->endian = endian; - this->depth = depth; - this->stride = (depth / 8) + ((depth & 7) > 0); + _endian = endian; + _depth = depth; - alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)}; - red = {redMask, bitDepth(redMask), bitShift(redMask )}; - green = {greenMask, bitDepth(greenMask), bitShift(greenMask)}; - blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )}; + _alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)}; + _red = {redMask, bitDepth(redMask), bitShift(redMask )}; + _green = {greenMask, bitDepth(greenMask), bitShift(greenMask)}; + _blue = {blueMask, bitDepth(blueMask), bitShift(blueMask )}; } image::image(const string& filename) { @@ -109,63 +40,122 @@ image::~image() { 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; - if(endian == 0) { - for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n]; + if(_endian == 0) { + for(signed n = stride() - 1; n >= 0; n--) result = (result << 8) | data[n]; } 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; } -void image::write(uint8_t* data, uint64_t value) const { - if(endian == 0) { - for(signed n = 0; n < stride; n++) { +auto image::write(uint8_t* data, uint64_t value) const -> void { + if(_endian == 0) { + for(signed n = 0; n < stride(); n++) { data[n] = value; value >>= 8; } } else { - for(signed n = stride - 1; n >= 0; n--) { + for(signed n = stride() - 1; n >= 0; n--) { data[n] = value; value >>= 8; } } } -void image::free() { - if(data) delete[] data; - data = nullptr; +auto image::free() -> void { + if(_data) delete[] _data; + _data = nullptr; } -bool image::empty() const { - if(data == nullptr) return true; - if(width == 0 || height == 0) return true; - return false; +auto image::empty() const -> bool { + return !_data || !_width || !_height; } -bool image::load(const string& filename) { +auto image::load(const string& filename) -> bool { if(loadBMP(filename) == true) return true; if(loadPNG(filename) == true) return true; return false; } -void image::allocate(unsigned width, unsigned height) { - if(data != nullptr && this->width == width && this->height == height) return; +auto image::allocate(unsigned width, unsigned height) -> void { + if(_data && _width == width && _height == height) return; free(); - data = allocate(width, height, stride); - pitch = width * stride; - size = height * pitch; - this->width = width; - this->height = height; + _width = width; + _height = height; + _data = allocate(_width, _height, stride()); } -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 unsigned size = width * height * stride; unsigned padding = width * stride + stride; - uint8_t* data = new uint8_t[size + padding]; - memset(data + size, 0x00, padding); + auto data = new uint8_t[size + padding]; + memory::fill(data + size, padding); return data; } diff --git a/nall/image/fill.hpp b/nall/image/fill.hpp index 8009c40a..860f16e0 100644 --- a/nall/image/fill.hpp +++ b/nall/image/fill.hpp @@ -3,81 +3,80 @@ namespace nall { -void image::fill(uint64_t color) { - uint8_t* dp = data; - for(unsigned y = 0; y < height; y++) { - uint8_t* dp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { +auto image::fill(uint64_t color) -> void { + for(unsigned y = 0; y < _height; y++) { + uint8_t* dp = _data + pitch() * y; + for(unsigned x = 0; x < _width; x++) { write(dp, color); - dp += stride; + dp += stride(); } } } -void image::gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) { - for(unsigned y = 0; y < height; y++) { - uint8_t* dp = data + pitch * y; - double muY = (double)y / (double)height; - for(unsigned x = 0; x < width; x++) { - double muX = (double)x / (double)width; +auto image::gradient(uint64_t a, uint64_t b, uint64_t c, uint64_t d) -> void { + for(unsigned y = 0; y < _height; y++) { + uint8_t* dp = _data + pitch() * y; + double muY = (double)y / (double)_height; + for(unsigned x = 0; x < _width; x++) { + double muX = (double)x / (double)_width; 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 callback) { - for(signed y = 0; y < height; y++) { - uint8_t* dp = data + pitch * y; +auto image::gradient(uint64_t a, uint64_t b, signed radiusX, signed radiusY, signed centerX, signed centerY, function callback) -> void { + for(signed y = 0; y < _height; y++) { + uint8_t* dp = _data + pitch() * y; 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 mu = max(0.0, min(1.0, callback(px, py))); if(mu != mu) mu = 1.0; //NaN 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 { x = fabs(x), y = fabs(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 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 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 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 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 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 fabs(y); }); diff --git a/nall/image/interpolation.hpp b/nall/image/interpolation.hpp index 1abe4d94..7350bffe 100644 --- a/nall/image/interpolation.hpp +++ b/nall/image/interpolation.hpp @@ -3,57 +3,57 @@ namespace nall { -void image::isplit(uint64_t* c, uint64_t color) { - c[0] = (color & alpha.mask) >> alpha.shift; - c[1] = (color & red.mask ) >> red.shift; - c[2] = (color & green.mask) >> green.shift; - c[3] = (color & blue.mask ) >> blue.shift; +auto image::isplit(uint64_t* c, uint64_t color) -> void { + c[0] = (color & _alpha.mask()) >> _alpha.shift(); + c[1] = (color & _red.mask() ) >> _red.shift(); + c[2] = (color & _green.mask()) >> _green.shift(); + c[3] = (color & _blue.mask() ) >> _blue.shift(); } -uint64_t image::imerge(const uint64_t* c) { - return c[0] << alpha.shift | c[1] << red.shift | c[2] << green.shift | c[3] << blue.shift; +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(); } -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; } -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; } -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 } -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 c = c + (((d - c) * x) >> 32); //c + (d - c) * x 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]; isplit(pa, a), isplit(pb, b); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1f(pa[n], pb[n], x); 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]; 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); 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]; isplit(pa, a), isplit(pb, b); for(unsigned n = 0; n < 4; n++) o[n] = interpolate1i(pa[n], pb[n], x); 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]; 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); diff --git a/nall/image/load.hpp b/nall/image/load.hpp index 9c5b6f4e..99cab499 100644 --- a/nall/image/load.hpp +++ b/nall/image/load.hpp @@ -3,24 +3,24 @@ namespace nall { -bool image::loadBMP(const string& filename) { +auto image::loadBMP(const string& filename) -> bool { uint32_t* outputData; unsigned outputWidth, outputHeight; if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false; allocate(outputWidth, outputHeight); const uint32_t* sp = outputData; - uint8_t* dp = data; + uint8_t* dp = _data; for(unsigned y = 0; y < outputHeight; y++) { for(unsigned x = 0; x < outputWidth; x++) { uint32_t color = *sp++; - uint64_t a = normalize((uint8_t)(color >> 24), 8, alpha.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 b = normalize((uint8_t)(color >> 0), 8, blue.depth); - write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); - dp += stride; + uint64_t a = normalize((uint8_t)(color >> 24), 8, _alpha.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 b = normalize((uint8_t)(color >> 0), 8, _blue.depth()); + write(dp, (a << _alpha.shift()) | (r << _red.shift()) | (g << _green.shift()) | (b << _blue.shift())); + dp += stride(); } } @@ -28,19 +28,19 @@ bool image::loadBMP(const string& filename) { return true; } -bool image::loadPNG(const string& filename) { +auto image::loadPNG(const string& filename) -> bool { if(!file::exists(filename)) return false; auto buffer = file::read(filename); 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; if(source.decode(pngData, pngSize) == false) return false; allocate(source.info.width, source.info.height); const uint8_t* sp = source.data; - uint8_t* dp = data; + uint8_t* dp = _data; auto decode = [&]() -> uint64_t { uint64_t p, r, g, b, a; @@ -75,18 +75,18 @@ bool image::loadPNG(const uint8_t* pngData, unsigned pngSize) { break; } - a = normalize(a, source.info.bitDepth, alpha.depth); - r = normalize(r, source.info.bitDepth, red.depth); - g = normalize(g, source.info.bitDepth, green.depth); - b = normalize(b, source.info.bitDepth, blue.depth); + a = normalize(a, source.info.bitDepth, _alpha.depth()); + r = normalize(r, source.info.bitDepth, _red.depth()); + g = normalize(g, source.info.bitDepth, _green.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 x = 0; x < width; x++) { + for(unsigned y = 0; y < _height; y++) { + for(unsigned x = 0; x < _width; x++) { write(dp, decode()); - dp += stride; + dp += stride(); } } diff --git a/nall/image/scale.hpp b/nall/image/scale.hpp index 9e6cdda0..4ca810b9 100644 --- a/nall/image/scale.hpp +++ b/nall/image/scale.hpp @@ -3,18 +3,18 @@ namespace nall { -void image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) { - if(width == outputWidth && height == outputHeight) return; //no scaling necessary +auto image::scale(unsigned outputWidth, unsigned outputHeight, bool linear) -> void { + if(_width == outputWidth && _height == outputHeight) return; //no scaling necessary if(linear == false) return scaleNearest(outputWidth, outputHeight); - if(width == outputWidth ) return scaleLinearHeight(outputHeight); - if(height == outputHeight) return scaleLinearWidth(outputWidth); + if(_width == outputWidth ) return scaleLinearHeight(outputHeight); + if(_height == outputHeight) return scaleLinearWidth(outputWidth); //find fastest scaling method, based on number of interpolation operations required //magnification usually benefits from two-pass linear interpolation //minification usually benefits from one-pass bilinear interpolation - unsigned d1wh = ((width * outputWidth ) + (outputWidth * outputHeight)) * 1; - unsigned d1hw = ((height * outputHeight) + (outputWidth * outputHeight)) * 1; + unsigned d1wh = ((_width * outputWidth ) + (outputWidth * outputHeight)) * 1; + unsigned d1hw = ((_height * outputHeight) + (outputWidth * outputHeight)) * 1; unsigned d2wh = (outputWidth * outputHeight) * 3; 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); } -void image::scaleLinearWidth(unsigned outputWidth) { - uint8_t* outputData = allocate(outputWidth, height, stride); - unsigned outputPitch = outputWidth * stride; - uint64_t xstride = ((uint64_t)(width - 1) << 32) / max(1u, outputWidth - 1); +auto image::scaleLinearWidth(unsigned outputWidth) -> void { + uint8_t* outputData = allocate(outputWidth, _height, stride()); + unsigned outputPitch = outputWidth * stride(); + uint64_t xstride = ((uint64_t)(_width - 1) << 32) / max(1u, outputWidth - 1); #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { + for(unsigned y = 0; y < _height; y++) { uint64_t xfraction = 0; - const uint8_t* sp = data + pitch * y; + const uint8_t* sp = _data + pitch() * y; uint8_t* dp = outputData + outputPitch * y; uint64_t a = read(sp); - uint64_t b = read(sp + stride); - sp += stride; + uint64_t b = read(sp + stride()); + sp += stride(); unsigned x = 0; while(true) { while(xfraction < 0x100000000 && x++ < outputWidth) { write(dp, interpolate4i(a, b, xfraction)); - dp += stride; + dp += stride(); xfraction += xstride; } if(x >= outputWidth) break; - sp += stride; + sp += stride(); a = b; b = read(sp); xfraction -= 0x100000000; @@ -55,37 +55,35 @@ void image::scaleLinearWidth(unsigned outputWidth) { } free(); - data = outputData; - width = outputWidth; - pitch = outputPitch; - size = height * pitch; + _data = outputData; + _width = outputWidth; } -void image::scaleLinearHeight(unsigned outputHeight) { - uint8_t* outputData = allocate(width, outputHeight, stride); - uint64_t ystride = ((uint64_t)(height - 1) << 32) / max(1u, outputHeight - 1); +auto image::scaleLinearHeight(unsigned outputHeight) -> void { + uint8_t* outputData = allocate(_width, outputHeight, stride()); + uint64_t ystride = ((uint64_t)(_height - 1) << 32) / max(1u, outputHeight - 1); #pragma omp parallel for - for(unsigned x = 0; x < width; x++) { + for(unsigned x = 0; x < _width; x++) { uint64_t yfraction = 0; - const uint8_t* sp = data + stride * x; - uint8_t* dp = outputData + stride * x; + const uint8_t* sp = _data + stride() * x; + uint8_t* dp = outputData + stride() * x; uint64_t a = read(sp); - uint64_t b = read(sp + pitch); - sp += pitch; + uint64_t b = read(sp + pitch()); + sp += pitch(); unsigned y = 0; while(true) { while(yfraction < 0x100000000 && y++ < outputHeight) { write(dp, interpolate4i(a, b, yfraction)); - dp += pitch; + dp += pitch(); yfraction += ystride; } if(y >= outputHeight) break; - sp += pitch; + sp += pitch(); a = b; b = read(sp); yfraction -= 0x100000000; @@ -93,71 +91,68 @@ void image::scaleLinearHeight(unsigned outputHeight) { } free(); - data = outputData; - height = outputHeight; - size = height * pitch; + _data = outputData; + _height = outputHeight; } -void image::scaleLinear(unsigned outputWidth, unsigned outputHeight) { - uint8_t* outputData = allocate(outputWidth, outputHeight, stride); - unsigned outputPitch = outputWidth * stride; +auto image::scaleLinear(unsigned outputWidth, unsigned outputHeight) -> void { + uint8_t* outputData = allocate(outputWidth, outputHeight, stride()); + unsigned outputPitch = outputWidth * stride(); - 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 xstride = ((uint64_t)(_width - 1) << 32) / max(1u, outputWidth - 1); + uint64_t ystride = ((uint64_t)(_height - 1) << 32) / max(1u, outputHeight - 1); #pragma omp parallel for for(unsigned y = 0; y < outputHeight; y++) { uint64_t yfraction = ystride * y; 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; uint64_t a = read(sp); - uint64_t b = read(sp + stride); - uint64_t c = read(sp + pitch); - uint64_t d = read(sp + pitch + stride); - sp += stride; + uint64_t b = read(sp + stride()); + uint64_t c = read(sp + pitch()); + uint64_t d = read(sp + pitch() + stride()); + sp += stride(); unsigned x = 0; while(true) { while(xfraction < 0x100000000 && x++ < outputWidth) { write(dp, interpolate4i(a, b, c, d, xfraction, yfraction)); - dp += stride; + dp += stride(); xfraction += xstride; } if(x >= outputWidth) break; - sp += stride; + sp += stride(); a = b; c = d; b = read(sp); - d = read(sp + pitch); + d = read(sp + pitch()); xfraction -= 0x100000000; } } free(); - data = outputData; - width = outputWidth; - height = outputHeight; - pitch = outputPitch; - size = height * pitch; + _data = outputData; + _width = outputWidth; + _height = outputHeight; } -void image::scaleNearest(unsigned outputWidth, unsigned outputHeight) { - uint8_t* outputData = allocate(outputWidth, outputHeight, stride); - unsigned outputPitch = outputWidth * stride; +auto image::scaleNearest(unsigned outputWidth, unsigned outputHeight) -> void { + uint8_t* outputData = allocate(outputWidth, outputHeight, stride()); + unsigned outputPitch = outputWidth * stride(); - uint64_t xstride = ((uint64_t)width << 32) / outputWidth; - uint64_t ystride = ((uint64_t)height << 32) / outputHeight; + uint64_t xstride = ((uint64_t)_width << 32) / outputWidth; + uint64_t ystride = ((uint64_t)_height << 32) / outputHeight; #pragma omp parallel for for(unsigned y = 0; y < outputHeight; y++) { uint64_t yfraction = ystride * y; 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; uint64_t a = read(sp); @@ -166,23 +161,21 @@ void image::scaleNearest(unsigned outputWidth, unsigned outputHeight) { while(true) { while(xfraction < 0x100000000 && x++ < outputWidth) { write(dp, a); - dp += stride; + dp += stride(); xfraction += xstride; } if(x >= outputWidth) break; - sp += stride; + sp += stride(); a = read(sp); xfraction -= 0x100000000; } } free(); - data = outputData; - width = outputWidth; - height = outputHeight; - pitch = outputPitch; - size = height * pitch; + _data = outputData; + _width = outputWidth; + _height = outputHeight; } } diff --git a/nall/image/static.hpp b/nall/image/static.hpp index 16140796..301a0982 100644 --- a/nall/image/static.hpp +++ b/nall/image/static.hpp @@ -3,20 +3,20 @@ namespace nall { -unsigned image::bitDepth(uint64_t color) { +auto image::bitDepth(uint64_t color) -> unsigned { unsigned depth = 0; if(color) while((color & 1) == 0) color >>= 1; while((color & 1) == 1) { color >>= 1; depth++; } return depth; } -unsigned image::bitShift(uint64_t color) { +auto image::bitShift(uint64_t color) -> unsigned { unsigned shift = 0; if(color) while((color & 1) == 0) { color >>= 1; 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; while(sourceDepth < targetDepth) { color = (color << sourceDepth) | color; diff --git a/nall/image/utility.hpp b/nall/image/utility.hpp index 7b96ee9f..e70bda2a 100644 --- a/nall/image/utility.hpp +++ b/nall/image/utility.hpp @@ -3,91 +3,93 @@ namespace nall { -bool image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) { - if(outputX + outputWidth > width) return false; - if(outputY + outputHeight > height) return false; +auto image::crop(unsigned outputX, unsigned outputY, unsigned outputWidth, unsigned outputHeight) -> bool { + if(outputX + outputWidth > _width) return false; + if(outputY + outputHeight > _height) return false; - uint8_t* outputData = allocate(outputWidth, outputHeight, stride); - unsigned outputPitch = outputWidth * stride; + uint8_t* outputData = allocate(outputWidth, outputHeight, stride()); + unsigned outputPitch = outputWidth * stride(); #pragma omp parallel for 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; for(unsigned x = 0; x < outputWidth; x++) { write(dp, read(sp)); - sp += stride; - dp += stride; + sp += stride(); + dp += stride(); } } - delete[] data; - data = outputData; - width = outputWidth; - height = outputHeight; - pitch = outputPitch; - size = width * pitch; + delete[] _data; + _data = outputData; + _width = outputWidth; + _height = outputHeight; return true; } -void image::alphaBlend(uint64_t alphaColor) { - uint64_t alphaR = (alphaColor & red.mask ) >> red.shift; - uint64_t alphaG = (alphaColor & green.mask) >> green.shift; - uint64_t alphaB = (alphaColor & blue.mask ) >> blue.shift; +auto image::alphaBlend(uint64_t alphaColor) -> void { + uint64_t alphaR = (alphaColor & _red.mask() ) >> _red.shift(); + uint64_t alphaG = (alphaColor & _green.mask()) >> _green.shift(); + uint64_t alphaB = (alphaColor & _blue.mask() ) >> _blue.shift(); #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t* dp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { + for(unsigned y = 0; y < _height; y++) { + uint8_t* dp = _data + pitch() * y; + for(unsigned x = 0; x < _width; x++) { uint64_t color = read(dp); - uint64_t colorA = (color & alpha.mask) >> alpha.shift; - uint64_t colorR = (color & red.mask ) >> red.shift; - uint64_t colorG = (color & green.mask) >> green.shift; - uint64_t colorB = (color & blue.mask ) >> blue.shift; - double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1); + uint64_t colorA = (color & _alpha.mask()) >> _alpha.shift(); + uint64_t colorR = (color & _red.mask() ) >> _red.shift(); + uint64_t colorG = (color & _green.mask()) >> _green.shift(); + uint64_t colorB = (color & _blue.mask() ) >> _blue.shift(); + 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)); colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale)); colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale)); - write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift)); - dp += stride; + write(dp, (colorA << _alpha.shift()) | (colorR << _red.shift()) | (colorG << _green.shift()) | (colorB << _blue.shift())); + dp += stride(); } } } -void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) { - if(endian == outputEndian && depth == outputDepth && alpha.mask == outputAlphaMask && red.mask == outputRedMask && green.mask == outputGreenMask && blue.mask == outputBlueMask) return; +auto image::transform(const image& source) -> void { + 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); - output.allocate(width, height); + output.allocate(_width, _height); #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - const uint8_t* sp = data + pitch * y; - uint8_t* dp = output.data + output.pitch * y; - for(unsigned x = 0; x < width; x++) { + for(unsigned y = 0; y < _height; y++) { + const uint8_t* sp = _data + pitch() * y; + uint8_t* dp = output._data + output.pitch() * y; + for(unsigned x = 0; x < _width; x++) { uint64_t color = read(sp); - sp += stride; + sp += stride(); - uint64_t a = (color & alpha.mask) >> alpha.shift; - uint64_t r = (color & red.mask) >> red.shift; - uint64_t g = (color & green.mask) >> green.shift; - uint64_t b = (color & blue.mask) >> blue.shift; + uint64_t a = (color & _alpha.mask()) >> _alpha.shift(); + uint64_t r = (color & _red.mask() ) >> _red.shift(); + uint64_t g = (color & _green.mask()) >> _green.shift(); + uint64_t b = (color & _blue.mask() ) >> _blue.shift(); - a = normalize(a, alpha.depth, output.alpha.depth); - r = normalize(r, red.depth, output.red.depth); - g = normalize(g, green.depth, output.green.depth); - b = normalize(b, blue.depth, output.blue.depth); + a = normalize(a, _alpha.depth(), output._alpha.depth()); + r = normalize(r, _red.depth(), output._red.depth()); + g = normalize(g, _green.depth(), output._green.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)); - dp += output.stride; + output.write(dp, (a << output._alpha.shift()) | (r << output._red.shift()) | (g << output._green.shift()) | (b << output._blue.shift())); + dp += output.stride(); } } - operator=(std::move(output)); + operator=(move(output)); } } diff --git a/nall/mosaic/parser.hpp b/nall/mosaic/parser.hpp index 93cfd5b0..c4c20bf8 100644 --- a/nall/mosaic/parser.hpp +++ b/nall/mosaic/parser.hpp @@ -16,7 +16,7 @@ struct parser { //import from canvas to bitstream bool save(bitstream& stream, uint64_t offset, context& ctx) { 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; } @@ -25,16 +25,16 @@ struct parser { private: uint32_t read(unsigned x, unsigned y) const { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return 0u; - uint32_t *buffer = (uint32_t*)canvas.data; + unsigned addr = y * canvas.width() + x; + if(addr >= canvas.width() * canvas.height()) return 0u; + uint32_t *buffer = (uint32_t*)canvas.data(); return buffer[addr]; } void write(unsigned x, unsigned y, uint32_t data) { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return; - uint32_t *buffer = (uint32_t*)canvas.data; + unsigned addr = y * canvas.width() + x; + if(addr >= canvas.width() * canvas.height()) return; + uint32_t *buffer = (uint32_t*)canvas.data(); buffer[addr] = data; } diff --git a/ruby/video/opengl/program.hpp b/ruby/video/opengl/program.hpp index c4044c50..ffed4fc1 100644 --- a/ruby/video/opengl/program.hpp +++ b/ruby/video/opengl/program.hpp @@ -41,7 +41,7 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin for(auto& leaf : node.find("pixmap")) { nall::image image({pathname, leaf.text()}); - image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); + image.transform(); if(image.empty()) continue; GLuint texture; @@ -49,8 +49,8 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin unsigned n = pixmaps.size(); pixmaps(n).texture = texture; - pixmaps(n).width = image.width; - pixmaps(n).height = image.height; + pixmaps(n).width = image.width(); + pixmaps(n).height = image.height(); pixmaps(n).format = format; pixmaps(n).filter = filter; 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["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](); glBindTexture(GL_TEXTURE_2D, texture); 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; } diff --git a/sfc/alt/cpu/timing.cpp b/sfc/alt/cpu/timing.cpp index 88577db2..7964eb78 100644 --- a/sfc/alt/cpu/timing.cpp +++ b/sfc/alt/cpu/timing.cpp @@ -31,7 +31,7 @@ void CPU::add_clocks(unsigned clocks) { if(status.virq_enabled) { unsigned cpu_time = vcounter() * 1364 + hcounter(); 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; bool irq_valid = status.irq_valid; status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time; diff --git a/sfc/alt/dsp/dsp.cpp b/sfc/alt/dsp/dsp.cpp index 1648277e..d3103984 100644 --- a/sfc/alt/dsp/dsp.cpp +++ b/sfc/alt/dsp/dsp.cpp @@ -50,6 +50,7 @@ void DSP::power() { } void DSP::reset() { + Thread::clock = 0; spc_dsp.soft_reset(); spc_dsp.set_output(samplebuffer, 8192); } diff --git a/sfc/sfc.hpp b/sfc/sfc.hpp index a9d4b516..6ca060fa 100644 --- a/sfc/sfc.hpp +++ b/sfc/sfc.hpp @@ -11,7 +11,7 @@ namespace SuperFamicom { namespace Info { - static const char Name[] = "bsnes"; + static const string Name = "bsnes"; static const unsigned SerializerVersion = 28; } } @@ -28,28 +28,25 @@ namespace SuperFamicom { namespace SuperFamicom { struct Thread { - cothread_t thread; - unsigned frequency; - int64 clock; + ~Thread() { + if(thread) co_delete(thread); + } - inline void create(void (*entrypoint)(), unsigned frequency) { + auto create(void (*entrypoint)(), unsigned frequency) -> void { if(thread) co_delete(thread); thread = co_create(65536 * sizeof(void*), entrypoint); this->frequency = frequency; clock = 0; } - inline void serialize(serializer& s) { + auto serialize(serializer& s) -> void { s.integer(frequency); s.integer(clock); } - inline Thread() : thread(nullptr) { - } - - inline ~Thread() { - if(thread) co_delete(thread); - } + cothread_t thread = nullptr; + unsigned frequency = 0; + int64 clock = 0; }; #include diff --git a/target-tomoko/tools/cheat-editor.cpp b/target-tomoko/tools/cheat-editor.cpp index eedb5112..51c00cba 100644 --- a/target-tomoko/tools/cheat-editor.cpp +++ b/target-tomoko/tools/cheat-editor.cpp @@ -16,8 +16,8 @@ CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) { cheatList.setCheckable(); cheatList.setHeaderVisible(); cheatList.onChange([&] { doChangeSelected(); }); - cheatList.onToggle([&](sListViewItem item) { - cheats[item->offset()].enabled = item->checked(); + cheatList.onToggle([&](ListViewItem item) { + cheats[item.offset()].enabled = item.checked(); synchronizeCodes(); }); codeLabel.setText("Code(s):"); @@ -31,7 +31,7 @@ CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) { auto CheatEditor::doChangeSelected() -> void { if(auto item = cheatList.selected()) { - auto& cheat = cheats[item->offset()]; + auto& cheat = cheats[item.offset()]; codeValue.setEnabled(true).setText(cheat.code); descriptionValue.setEnabled(true).setText(cheat.description); eraseButton.setEnabled(true); @@ -44,7 +44,7 @@ auto CheatEditor::doChangeSelected() -> void { auto CheatEditor::doModify() -> void { if(auto item = cheatList.selected()) { - auto& cheat = cheats[item->offset()]; + auto& cheat = cheats[item.offset()]; cheat.code = codeValue.text(); cheat.description = descriptionValue.text(); doRefresh(); @@ -58,13 +58,13 @@ auto CheatEditor::doRefresh() -> void { if(cheat.code || cheat.description) { lstring codes = cheat.code.split("+"); if(codes.size() > 1) codes[0].append("+..."); - cheatList.item(slot)->setChecked(cheat.enabled); - cheatList.item(slot)->cell(1)->setText(codes[0]); - cheatList.item(slot)->cell(2)->setText(cheat.description); + cheatList.item(slot).setChecked(cheat.enabled); + cheatList.item(slot).cell(1).setText(codes[0]); + cheatList.item(slot).cell(2).setText(cheat.description).setForegroundColor({0, 0, 0}); } else { - cheatList.item(slot)->setChecked(false); - cheatList.item(slot)->cell(1)->setText(""); - cheatList.item(slot)->cell(2)->setText("(empty)"); + cheatList.item(slot).setChecked(false); + cheatList.item(slot).cell(1).setText(""); + 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 { if(auto item = cheatList.selected()) { - auto& cheat = cheats[item->offset()]; + auto& cheat = cheats[item.offset()]; cheat.enabled = false; cheat.code = ""; cheat.description = ""; diff --git a/target-tomoko/tools/state-manager.cpp b/target-tomoko/tools/state-manager.cpp index 7797a132..0c739e51 100644 --- a/target-tomoko/tools/state-manager.cpp +++ b/target-tomoko/tools/state-manager.cpp @@ -13,19 +13,36 @@ StateManager::StateManager(TabFrame* parent) : TabFrameItem(parent) { } stateList.setHeaderVisible(); stateList.onActivate([&] { doLoad(); }); - stateList.onChange([&] { doChange(); }); + stateList.onChange([&] { doChangeSelected(); }); descriptionLabel.setText("Description:"); - descriptionValue.onChange([&] { doLabel(); }); + descriptionValue.onChange([&] { doChangeDescription(); }); saveButton.setText("Save").onActivate([&] { doSave(); }); loadButton.setText("Load").onActivate([&] { doLoad(); }); resetButton.setText("Reset").onActivate([&] { doReset(); }); eraseButton.setText("Erase").onActivate([&] { doErase(); }); } -auto StateManager::doChange() -> void { +auto StateManager::doUpdateControls() -> void { vector buffer; 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 buffer; + if(auto item = stateList.selected()) { + buffer = file::read(program->stateName(1 + item.offset(), true)); } if(buffer.size() >= 584) { @@ -33,56 +50,55 @@ auto StateManager::doChange() -> void { description.reserve(512); memory::copy(description.pointer(), buffer.data() + 72, 512); description.resize(description.length()); - descriptionValue.setEnabled(true).setText(description); - loadButton.setEnabled(true); - eraseButton.setEnabled(true); + descriptionValue.setText(description); } else { - descriptionValue.setEnabled(false).setText(""); - loadButton.setEnabled(false); - eraseButton.setEnabled(false); + descriptionValue.setText(""); } + + doUpdateControls(); } 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)); if(buffer.size() >= 584) { string description; description.reserve(512); memory::copy(description.pointer(), buffer.data() + 72, 512); description.resize(description.length()); - stateList.item(slot)->cell(1)->setText(description); + stateList.item(slot).cell(1).setText(description).setForegroundColor({0, 0, 0}); } 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()) { - auto buffer = file::read(program->stateName(1 + item->offset(), true)); + auto buffer = file::read(program->stateName(1 + item.offset(), true)); if(buffer.size() >= 584) { string description = descriptionValue.text(); description.reserve(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(); + doUpdateControls(); } } } auto StateManager::doLoad() -> void { if(auto item = stateList.selected()) { - program->loadState(1 + item->offset(), true); + program->loadState(1 + item.offset(), true); } } auto StateManager::doSave() -> void { if(auto item = stateList.selected()) { - program->saveState(1 + item->offset(), true); + program->saveState(1 + item.offset(), true); 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") { for(auto slot : range(Slots)) file::remove(program->stateName(1 + slot, true)); doRefresh(); + doUpdateControls(); } } auto StateManager::doErase() -> void { if(auto item = stateList.selected()) { - file::remove(program->stateName(1 + item->offset(), true)); + file::remove(program->stateName(1 + item.offset(), true)); doRefresh(); + doUpdateControls(); } } diff --git a/target-tomoko/tools/tools.hpp b/target-tomoko/tools/tools.hpp index 048e949c..3f353417 100644 --- a/target-tomoko/tools/tools.hpp +++ b/target-tomoko/tools/tools.hpp @@ -54,9 +54,10 @@ struct StateManager : TabFrameItem { enum : unsigned { Slots = 32 }; StateManager(TabFrame*); - auto doChange() -> void; + auto doChangeSelected() -> void; auto doRefresh() -> void; - auto doLabel() -> void; + auto doUpdateControls() -> void; + auto doChangeDescription() -> void; auto doLoad() -> void; auto doSave() -> void; auto doReset() -> void;