Update to v094r40 release.

byuu says:

Changelog:
- updated to newest hiro API
- SFC performance profile builds once again
- hiro: Qt port completed

Errata 1: the hiro/Qt target won't run tomoko just yet. Starts by
crashing inside InputSettings because hiro/Qt isn't forcefully selecting
the first item added to a ComboButton just yet. Even with a monkey patch
to get around that, the UI is incredibly unstable. Lots of geometry
calculation bugs, and a crash when you try and access certain folders in
the browser dialog. Lots of work left to be done there, sadly.

Errata 2: the hiro/Windows port has black backgrounds on all ListView
items. It's because I need to test for unassigned colors and grab the
default Windows brush colors in those cases.

Note: alternating row colors on multi-column ListView widgets is gone
now. Not a bug. May add it back later, but I'm not sure. It doesn't
interact nicely with per-cell background colors.

Things left to do:

First, I have to fix the Windows and Qt target bugs.

Next, I need to go through and revise the hiro API even more (nothing
too major.)

Next, I need to update icarus to use the new hiro API, and add support
for the SFC games database.

Next, I have to rewrite my TSV->BML cheat code tool.

Next, I need to post a final WIP of higan+icarus publicly and wait a few
days.

Next, I need to fix any bugs reported from the final WIP that I can.

Finally, I should be able to release v095.
This commit is contained in:
Tim Allen 2015-08-18 20:18:00 +10:00
parent 0271d6a12b
commit 4344b916b6
200 changed files with 7246 additions and 5659 deletions

View File

@ -8,7 +8,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "094.39";
static const string Version = "094.40";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -12,6 +12,7 @@
#define Hiro_Application
#define Hiro_Color
#define Hiro_Alignment
#define Hiro_Position
#define Hiro_Size
#define Hiro_Geometry
@ -50,22 +51,22 @@
#define Hiro_CheckButton
#define Hiro_CheckLabel
#define Hiro_ComboButton
//#define Hiro_Console
#define Hiro_Console
#define Hiro_Frame
#define Hiro_HexEdit
#define Hiro_HorizontalScroller
#define Hiro_HorizontalSlider
//#define Hiro_IconView
#define Hiro_IconView
#define Hiro_Label
#define Hiro_LineEdit
#define Hiro_ListView
#define Hiro_ProgressBar
#define Hiro_RadioButton
#define Hiro_RadioLabel
//#define Hiro_SourceView
#define Hiro_SourceView
#define Hiro_TabFrame
#define Hiro_TextEdit
//#define Hiro_TreeView
#define Hiro_TreeView
#define Hiro_VerticalScroller
#define Hiro_VerticalSlider
#define Hiro_Viewport
@ -81,3 +82,10 @@
#if defined(Hiro_Button) && defined(Hiro_ComboButton) && defined(Hiro_LineEdit) && defined(Hiro_ListView) && defined(Hiro_MessageDialog)
#define Hiro_BrowserDialog
#endif
#if defined(HIRO_WINDOWS) || defined(HIRO_QT)
#undef Hiro_Console
#undef Hiro_IconView
#undef Hiro_SourceView
#undef Hiro_TreeView
#endif

View File

@ -41,7 +41,7 @@ auto mMenuRadioItem::setChecked() -> type& {
auto mMenuRadioItem::setGroup(sGroup group) -> type& {
state.group = group;
signal(setGroup, group);
if(group && group->objects() == 1) setChecked();
if(group && group->objectCount() == 1) setChecked();
return *this;
}

View File

@ -12,17 +12,23 @@ auto mMenu::destruct() -> void {
//
auto mMenu::action(unsigned position) const -> Action {
if(position < actions()) return state.actions[position];
if(position < actionCount()) return state.actions[position];
return {};
}
auto mMenu::actions() const -> unsigned {
auto mMenu::actionCount() const -> unsigned {
return state.actions.size();
}
auto mMenu::actions() const -> vector<Action> {
vector<Action> actions;
for(auto& action : state.actions) actions.append(action);
return actions;
}
auto mMenu::append(sAction action) -> type& {
state.actions.append(action);
action->setParent(this, actions() - 1);
action->setParent(this, actionCount() - 1);
signal(append, *action);
return *this;
}
@ -34,7 +40,7 @@ auto mMenu::icon() const -> image {
auto mMenu::remove(sAction action) -> type& {
signal(remove, *action);
state.actions.remove(action->offset());
for(auto n : range(action->offset(), actions())) {
for(auto n : range(action->offset(), actionCount())) {
state.actions[n]->adjustOffset(-1);
}
action->setParent();

40
hiro/core/alignment.cpp Normal file
View File

@ -0,0 +1,40 @@
#if defined(Hiro_Alignment)
Alignment::Alignment() {
setAlignment(-1.0, -1.0);
}
Alignment::Alignment(double horizontal, double vertical) {
setAlignment(horizontal, vertical);
}
Alignment::operator bool() const {
return state.horizontal >= 0.0 && state.horizontal <= 1.0
&& state.vertical >= 0.0 && state.vertical <= 1.0;
}
auto Alignment::horizontal() const -> double {
return state.horizontal;
}
auto Alignment::setAlignment(double horizontal, double vertical) -> type& {
state.horizontal = horizontal;
state.vertical = vertical;
return *this;
}
auto Alignment::setHorizontal(double horizontal) -> type& {
state.horizontal = horizontal;
return *this;
}
auto Alignment::setVertical(double vertical) -> type& {
state.vertical = vertical;
return *this;
}
auto Alignment::vertical() const -> double {
return state.vertical;
}
#endif

View File

@ -33,6 +33,7 @@ using namespace nall;
namespace hiro {
#include "application.cpp"
#include "color.cpp"
#include "alignment.cpp"
#include "position.cpp"
#include "size.cpp"
#include "geometry.cpp"
@ -81,6 +82,7 @@ namespace hiro {
#include "widget/label.cpp"
#include "widget/line-edit.cpp"
#include "widget/list-view.cpp"
#include "widget/list-view-header.cpp"
#include "widget/list-view-column.cpp"
#include "widget/list-view-item.cpp"
#include "widget/list-view-cell.cpp"

View File

@ -64,6 +64,7 @@ Declare(IconViewItem)
Declare(Label)
Declare(LineEdit)
Declare(ListView)
Declare(ListViewHeader)
Declare(ListViewColumn)
Declare(ListViewItem)
Declare(ListViewCell)
@ -85,6 +86,7 @@ Declare(Viewport)
enum class Edge : unsigned { Top, Bottom, Left, Right };
enum class Orientation : unsigned { Horizontal, Vertical };
enum class Placement : unsigned { Top, Bottom, Left, Right };
#if defined(Hiro_Application)
struct Application {
@ -174,6 +176,31 @@ struct Color {
};
#endif
#if defined(Hiro_Alignment)
struct Alignment {
using type = Alignment;
Alignment();
Alignment(double horizontal, double vertical = 0.5);
explicit operator bool() const;
auto operator==(const Alignment& source) const -> bool;
auto operator!=(const Alignment& source) const -> bool;
auto horizontal() const -> double;
auto setAlignment(double horizontal = -1.0, double vertical = 0.5) -> type&;
auto setHorizontal(double horizontal) -> type&;
auto setVertical(double vertical) -> type&;
auto vertical() const -> double;
//private:
struct State {
double horizontal;
double vertical;
} state;
};
#endif
#if defined(Hiro_Position)
struct Position {
using type = Position;
@ -421,6 +448,7 @@ struct mObject {
auto parentIconView(bool recursive = false) const -> mIconView*;
auto parentLayout(bool recursive = false) const -> mLayout*;
auto parentListView(bool recursive = false) const -> mListView*;
auto parentListViewHeader(bool recursive = false) const -> mListViewHeader*;
auto parentListViewItem(bool recursive = false) const -> mListViewItem*;
auto parentMenu(bool recursive = false) const -> mMenu*;
auto parentMenuBar(bool recursive = false) const -> mMenuBar*;
@ -466,7 +494,8 @@ struct mGroup : mObject {
auto append(sObject object) -> type&;
auto object(unsigned offset) const -> Object;
auto objects() const -> unsigned;
auto objectCount() const -> unsigned;
auto objects() const -> vector<Object>;
auto remove(sObject object) -> type&;
//private:
@ -484,10 +513,10 @@ struct mHotkey : mObject {
auto doRelease() const -> void;
auto onPress(const function<void ()>& callback = {}) -> type&;
auto onRelease(const function<void ()>& callback = {}) -> type&;
auto parent() const -> wObject;
auto owner() const -> wObject;
auto remove() -> type& override;
auto sequence() const -> string;
auto setParent(sObject parent) -> type&;
auto setOwner(sObject owner) -> type&;
auto setSequence(const string& sequence = "") -> type&;
//private:
@ -496,7 +525,7 @@ struct mHotkey : mObject {
vector<unsigned> keys;
function<void ()> onPress;
function<void ()> onRelease;
wObject parent;
wObject owner;
string sequence;
} state;
};
@ -552,6 +581,7 @@ struct mWindow : mObject {
auto remove(sStatusBar statusBar) -> type&;
auto reset() -> type& override;
auto resizable() const -> bool;
auto setAlignment(Alignment alignment) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setCentered(sWindow parent = {}) -> type&;
auto setDroppable(bool droppable = true) -> type&;
@ -561,7 +591,6 @@ struct mWindow : mObject {
auto setFullScreen(bool fullScreen = true) -> type&;
auto setGeometry(Geometry geometry) -> type&;
auto setModal(bool modal = true) -> type&;
auto setPlacement(double x, double y) -> type&;
auto setPosition(Position position) -> type&;
auto setResizable(bool resizable = true) -> type&;
auto setSize(Size size) -> type&;
@ -614,7 +643,8 @@ struct mMenuBar : mObject {
auto append(sMenu menu) -> type&;
auto menu(unsigned position) const -> Menu;
auto menus() const -> unsigned;
auto menuCount() const -> unsigned;
auto menus() const -> vector<Menu>;
auto remove() -> type& override;
auto remove(sMenu menu) -> type&;
auto reset() -> type&;
@ -635,11 +665,12 @@ struct mPopupMenu : mObject {
using mObject::remove;
auto action(unsigned position) const -> Action;
auto actions() const -> unsigned;
auto actionCount() const -> unsigned;
auto actions() const -> vector<Action>;
auto append(sAction action) -> type&;
auto remove(sAction action) -> type&;
auto reset() -> type&;
//TODO setParent
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
auto setVisible(bool visible = true) -> type& override;
//private:
@ -669,7 +700,8 @@ struct mMenu : mAction {
using mObject::remove;
auto action(unsigned position) const -> Action;
auto actions() const -> unsigned;
auto actionCount() const -> unsigned;
auto actions() const -> vector<Action>;
auto append(sAction action) -> type&;
auto icon() const -> image;
auto remove(sAction action) -> type&;
@ -788,7 +820,8 @@ struct mLayout : mSizable {
virtual auto reset() -> type&;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
auto sizable(unsigned position) const -> Sizable;
auto sizables() const -> unsigned;
auto sizableCount() const -> unsigned;
auto sizables() const -> vector<Sizable>;
//private:
struct State {
@ -905,7 +938,7 @@ struct mCheckButton : mWidget {
//private:
struct State {
bool bordered = false;
bool bordered = true;
bool checked = false;
image icon;
function<void ()> onToggle;
@ -943,7 +976,8 @@ struct mComboButton : mWidget {
auto append(sComboButtonItem item) -> type&;
auto doChange() const -> void;
auto item(unsigned position) const -> ComboButtonItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<ComboButtonItem>;
auto onChange(const function<void ()>& callback = {}) -> type&;
auto remove(sComboButtonItem item) -> type&;
auto reset() -> type&;
@ -1033,31 +1067,31 @@ struct mFrame : mWidget {
struct mHexEdit : mWidget {
Declare(HexEdit)
auto address() const -> unsigned;
auto backgroundColor() const -> Color;
auto columns() const -> unsigned;
auto doRead(unsigned offset) const -> uint8_t;
auto doWrite(unsigned offset, uint8_t data) const -> void;
auto foregroundColor() const -> Color;
auto length() const -> unsigned;
auto offset() const -> unsigned;
auto onRead(const function<uint8_t (unsigned)>& callback = {}) -> type&;
auto onWrite(const function<void (unsigned, uint8_t)>& callback = {}) -> type&;
auto rows() const -> unsigned;
auto setAddress(unsigned address = 0) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setColumns(unsigned columns = 16) -> type&;
auto setForegroundColor(Color color = {}) -> type&;
auto setLength(unsigned length) -> type&;
auto setOffset(unsigned offset) -> type&;
auto setRows(unsigned rows = 16) -> type&;
auto update() -> type&;
//private:
struct State {
unsigned address = 0;
Color backgroundColor;
unsigned columns = 16;
Color foregroundColor;
unsigned length = 0;
unsigned offset = 0;
function<uint8_t (unsigned)> onRead;
function<void (unsigned, uint8_t)> onWrite;
unsigned rows = 16;
@ -1118,7 +1152,8 @@ struct mIconView : mWidget {
auto flow() const -> Orientation;
auto foregroundColor() const -> Color;
auto item(unsigned position) const -> IconViewItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<IconViewItem>;
auto multiSelect() const -> bool;
auto onActivate(const function<void ()>& callback = {}) -> type&;
auto onChange(const function<void ()>& callback = {}) -> type&;
@ -1178,18 +1213,15 @@ struct mIconViewItem : mObject {
struct mLabel : mWidget {
Declare(Label)
auto horizontalAlignment() const -> double;
auto setHorizontalAlignment(double alignment = 0.0) -> type&;
auto alignment() const -> Alignment;
auto setAlignment(Alignment alignment = {}) -> type&;
auto setText(const string& text = "") -> type&;
auto setVerticalAlignment(double alignment = 0.5) -> type&;
auto text() const -> string;
auto verticalAlignment() const -> double;
//private:
struct State {
double horizontalAlignment = 0.0;
Alignment alignment;
string text;
double verticalAlignment = 0.5;
} state;
};
#endif
@ -1228,80 +1260,90 @@ struct mListView : mWidget {
Declare(ListView)
using mObject::remove;
auto append(sListViewColumn column) -> type&;
auto alignment() const -> Alignment;
auto append(sListViewHeader column) -> type&;
auto append(sListViewItem item) -> type&;
auto backgroundColor() const -> Color;
auto batchable() const -> bool;
auto checkable() const -> bool;
auto checkAll() -> type&;
auto checked() const -> vector<ListViewItem>;
auto column(unsigned position) const -> ListViewColumn;
auto columns() const -> unsigned;
auto batched() const -> vector<ListViewItem>;
auto bordered() const -> bool;
auto doActivate() const -> void;
auto doChange() const -> void;
auto doContext() const -> void;
auto doEdit(sListViewCell cell) const -> void;
auto doSort(sListViewColumn column) const -> void;
auto doToggle(sListViewItem item) const -> void;
auto doToggle(sListViewCell cell) const -> void;
auto foregroundColor() const -> Color;
auto gridVisible() const -> bool;
auto headerVisible() const -> bool;
auto header() const -> ListViewHeader;
auto item(unsigned position) const -> ListViewItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<ListViewItem>;
auto onActivate(const function<void ()>& callback = {}) -> type&;
auto onChange(const function<void ()>& callback = {}) -> type&;
auto onContext(const function<void ()>& callback = {}) -> type&;
auto onEdit(const function<void (ListViewCell)>& callback = {}) -> type&;
auto onSort(const function<void (ListViewColumn)>& callback = {}) -> type&;
auto onToggle(const function<void (ListViewItem)>& callback = {}) -> type&;
auto remove(sListViewColumn column) -> type&;
auto onToggle(const function<void (ListViewCell)>& callback = {}) -> type&;
auto remove(sListViewHeader column) -> type&;
auto remove(sListViewItem item) -> type&;
auto reset() -> type&;
auto resizeColumns() -> type&;
auto selectAll() -> type&;
auto selected() const -> ListViewItem;
auto selectedItems() const -> vector<ListViewItem>;
auto setAlignment(Alignment alignment = {}) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setBatchable(bool batchable = true) -> type&;
auto setCheckable(bool checkable = true) -> type&;
auto setBordered(bool bordered = true) -> type&;
auto setForegroundColor(Color color = {}) -> type&;
auto setGridVisible(bool visible = true) -> type&;
auto setHeaderVisible(bool visible = true) -> type&;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
auto setSortable(bool sortable = true) -> type&;
auto sortable() const -> bool;
auto uncheckAll() -> type&;
auto unselectAll() -> type&;
//private:
struct State {
unsigned activeColumn = 0;
Alignment alignment;
Color backgroundColor;
bool batchable = false;
bool checkable = false;
vector<sListViewColumn> columns;
bool bordered = false;
Color foregroundColor;
bool gridVisible = false;
bool headerVisible = false;
sListViewHeader header;
vector<sListViewItem> items;
function<void ()> onActivate;
function<void ()> onChange;
function<void ()> onContext;
function<void (ListViewCell)> onEdit;
function<void (ListViewColumn)> onSort;
function<void (ListViewItem)> onToggle;
bool sortable = false;
function<void (ListViewCell)> onToggle;
} state;
auto destruct() -> void override;
};
#endif
#if defined(Hiro_ListView)
struct mListViewHeader : mObject {
Declare(ListViewHeader)
auto append(sListViewColumn column) -> type&;
auto column(unsigned position) const -> ListViewColumn;
auto columnCount() const -> unsigned;
auto columns() const -> vector<ListViewColumn>;
auto remove() -> type& override;
auto remove(sListViewColumn column) -> type&;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
//private:
struct State {
vector<sListViewColumn> columns;
} state;
};
#endif
#if defined(Hiro_ListView)
struct mListViewColumn : mObject {
Declare(ListViewColumn)
auto active() const -> bool;
auto alignment() const -> Alignment;
auto backgroundColor() const -> Color;
auto editable() const -> bool;
auto expandable() const -> bool;
@ -1311,32 +1353,35 @@ struct mListViewColumn : mObject {
auto remove() -> type& override;
auto resizable() const -> bool;
auto setActive() -> type&;
auto setAlignment(Alignment alignment = {}) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setEditable(bool editable = true) -> type&;
auto setExpandable(bool expandable = true) -> type&;
auto setFont(const string& font = "") -> type&;
auto setForegroundColor(Color color = {}) -> type&;
auto setHorizontalAlignment(double alignment = 0.0) -> type&;
auto setIcon(const image& icon = {}) -> type&;
auto setResizable(bool resizable = true) -> type&;
auto setSortable(bool sortable = true) -> type&;
auto setText(const string& text = "") -> type&;
auto setVerticalAlignment(double alignment = 0.5) -> type&;
auto setVisible(bool visible = true) -> type&;
auto setWidth(signed width = 0) -> type&;
auto sortable() const -> bool;
auto text() const -> string;
auto verticalAlignment() const -> double;
auto width() const -> signed;
//private:
struct State {
Alignment alignment;
Color backgroundColor;
bool editable = false;
bool expandable = false;
string font;
Color foregroundColor;
double horizontalAlignment = 0.0;
image icon;
bool resizable = true;
bool sortable = false;
string text;
double verticalAlignment = 0.5;
bool visible = true;
@ -1349,19 +1394,18 @@ struct mListViewColumn : mObject {
struct mListViewItem : mObject {
Declare(ListViewItem)
auto alignment() const -> Alignment;
auto append(sListViewCell cell) -> type&;
auto backgroundColor() const -> Color;
auto cell(unsigned position) const -> ListViewCell;
auto cells() const -> unsigned;
auto checkable() const -> bool;
auto checked() const -> bool;
auto cellCount() const -> unsigned;
auto cells() const -> vector<ListViewCell>;
auto foregroundColor() const -> Color;
auto remove() -> type& override;
auto remove(sListViewCell cell) -> type&;
auto selected() const -> bool;
auto setAlignment(Alignment alignment = {}) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setCheckable(bool checkable = true) -> type&;
auto setChecked(bool checked = true) -> type&;
auto setFocused() -> type& override;
auto setForegroundColor(Color color = {}) -> type&;
auto setParent(mObject* parent = nullptr, signed offset = -1) -> type& override;
@ -1369,10 +1413,9 @@ struct mListViewItem : mObject {
//private:
struct State {
Alignment alignment;
Color backgroundColor;
vector<sListViewCell> cells;
bool checkable = true;
bool checked = false;
Color foregroundColor;
bool selected = false;
} state;
@ -1383,10 +1426,17 @@ struct mListViewItem : mObject {
struct mListViewCell : mObject {
Declare(ListViewCell)
auto backgroundColor() const -> Color;
auto foregroundColor() const -> Color;
auto alignment(bool recursive = false) const -> Alignment;
auto backgroundColor(bool recursive = false) const -> Color;
auto checkable() const -> bool;
auto checked() const -> bool;
auto font(bool recursive = false) const -> string;
auto foregroundColor(bool recursive = false) const -> Color;
auto icon() const -> image;
auto setAlignment(Alignment alignment = {}) -> type&;
auto setBackgroundColor(Color color = {}) -> type&;
auto setCheckable(bool checkable = true) -> type&;
auto setChecked(bool checked = true) -> type&;
auto setForegroundColor(Color color = {}) -> type&;
auto setIcon(const image& icon = {}) -> type&;
auto setText(const string& text = "") -> type&;
@ -1394,7 +1444,10 @@ struct mListViewCell : mObject {
//private:
struct State {
Alignment alignment;
Color backgroundColor;
bool checkable = false;
bool checked = false;
Color foregroundColor;
image icon;
string text;
@ -1508,7 +1561,8 @@ struct mTabFrame : mWidget {
auto doMove(sTabFrameItem from, sTabFrameItem to) const -> void;
auto edge() const -> Edge;
auto item(unsigned position) const -> TabFrameItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<TabFrameItem>;
auto onChange(const function<void ()>& callback = {}) -> type&;
auto onClose(const function<void (TabFrameItem)>& callback = {}) -> type&;
auto onMove(const function<void (TabFrameItem, TabFrameItem)>& callback = {}) -> type&;
@ -1617,7 +1671,8 @@ struct mTreeView : mWidget {
auto expand() -> type&;
auto foregroundColor() const -> Color;
auto item(const string& path) const -> TreeViewItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<TreeViewItem>;
auto onActivate(const function<void ()>& callback = {}) -> type&;
auto onChange(const function<void ()>& callback = {}) -> type&;
auto onContext(const function<void ()>& callback = {}) -> type&;
@ -1655,7 +1710,8 @@ struct mTreeViewItem : mObject {
auto checked() const -> bool;
auto icon() const -> image;
auto item(const string& path) const -> TreeViewItem;
auto items() const -> unsigned;
auto itemCount() const -> unsigned;
auto items() const -> vector<TreeViewItem>;
auto path() const -> string;
auto remove() -> type& override;
auto remove(sTreeViewItem item) -> type&;

View File

@ -15,7 +15,7 @@ auto mGroup::append(sObject object) -> type& {
}
auto mGroup::object(unsigned position) const -> Object {
if(position < state.objects.size()) {
if(position < objectCount()) {
if(auto object = state.objects[position].acquire()) {
return object;
}
@ -23,10 +23,18 @@ auto mGroup::object(unsigned position) const -> Object {
return {};
}
auto mGroup::objects() const -> unsigned {
auto mGroup::objectCount() const -> unsigned {
return state.objects.size();
}
auto mGroup::objects() const -> vector<Object> {
vector<Object> objects;
for(auto& weak : state.objects) {
if(auto object = weak.acquire()) objects.append(object);
}
return objects;
}
auto mGroup::remove(sObject object) -> type& {
object->setGroup();
for(auto offset : range(state.objects)) {

View File

@ -24,8 +24,8 @@ auto mHotkey::onRelease(const function<void ()>& callback) -> type& {
return *this;
}
auto mHotkey::parent() const -> wObject {
return state.parent;
auto mHotkey::owner() const -> wObject {
return state.owner;
}
auto mHotkey::remove() -> type& {
@ -37,8 +37,8 @@ auto mHotkey::sequence() const -> string {
return state.sequence;
}
auto mHotkey::setParent(sObject parent) -> type& {
state.parent = parent;
auto mHotkey::setOwner(sObject owner) -> type& {
state.owner = owner;
return *this;
}

View File

@ -48,9 +48,9 @@ auto Keyboard::poll() -> vector<bool> {
active = false;
break;
}
if(auto parent = hotkey->state.parent.acquire()) {
//todo: set active = false if parent no longer exists
active &= parent->focused();
if(auto owner = hotkey->state.owner.acquire()) {
//todo: set active = false if owner no longer exists
active &= owner->focused();
}
if(hotkey->state.active != active) {
hotkey->state.active = active;

View File

@ -13,7 +13,7 @@ auto mLayout::destruct() -> void {
auto mLayout::append(sSizable sizable) -> type& {
state.sizables.append(sizable);
sizable->setParent(this, sizables() - 1);
sizable->setParent(this, sizableCount() - 1);
setGeometry(geometry());
return *this;
}
@ -33,7 +33,7 @@ auto mLayout::remove(sSizable sizable) -> type& {
auto offset = sizable->offset();
sizable->setParent();
state.sizables.remove(offset);
for(auto n : range(offset, sizables())) {
for(auto n : range(offset, sizableCount())) {
state.sizables[n]->adjustOffset(-1);
}
setGeometry(geometry());
@ -53,12 +53,18 @@ auto mLayout::setParent(mObject* parent, signed offset) -> type& {
}
auto mLayout::sizable(unsigned position) const -> Sizable {
if(position < sizables()) return state.sizables[position];
if(position < sizableCount()) return state.sizables[position];
return {};
}
auto mLayout::sizables() const -> unsigned {
auto mLayout::sizableCount() const -> unsigned {
return state.sizables.size();
}
auto mLayout::sizables() const -> vector<Sizable> {
vector<Sizable> sizables;
for(auto& sizable : sizables) sizables.append(sizable);
return sizables;
}
#endif

View File

@ -13,20 +13,26 @@ auto mMenuBar::destruct() -> void {
auto mMenuBar::append(sMenu menu) -> type& {
state.menus.append(menu);
menu->setParent(this, menus() - 1);
menu->setParent(this, menuCount() - 1);
signal(append, menu);
return *this;
}
auto mMenuBar::menu(unsigned position) const -> Menu {
if(position < menus()) return state.menus[position];
if(position < menuCount()) return state.menus[position];
return {};
}
auto mMenuBar::menus() const -> unsigned {
auto mMenuBar::menuCount() const -> unsigned {
return state.menus.size();
}
auto mMenuBar::menus() const -> vector<Menu> {
vector<Menu> menus;
for(auto& menu : state.menus) menus.append(menu);
return menus;
}
auto mMenuBar::remove() -> type& {
if(auto window = parentWindow()) window->remove(window->menuBar());
return *this;
@ -36,7 +42,7 @@ auto mMenuBar::remove(sMenu menu) -> type& {
signed offset = menu->offset();
signal(remove, *menu);
state.menus.remove(offset);
for(auto n : range(offset, menus())) {
for(auto n : range(offset, menuCount())) {
state.menus[n]->adjustOffset(-1);
}
menu->setParent();

View File

@ -136,6 +136,16 @@ auto mObject::parentListView(bool recursive) const -> mListView* {
}
#endif
#if defined(Hiro_ListView)
auto mObject::parentListViewHeader(bool recursive) const -> mListViewHeader* {
if(auto listViewHeader = dynamic_cast<mListViewHeader*>(parent())) return listViewHeader;
if(recursive) {
if(auto object = parent()) return object->parentListViewHeader(true);
}
return nullptr;
}
#endif
#if defined(Hiro_ListView)
auto mObject::parentListViewItem(bool recursive) const -> mListViewItem* {
if(auto listViewItem = dynamic_cast<mListViewItem*>(parent())) return listViewItem;

View File

@ -12,17 +12,23 @@ auto mPopupMenu::destruct() -> void {
//
auto mPopupMenu::action(unsigned position) const -> Action {
if(position < actions()) return state.actions[position];
if(position < actionCount()) return state.actions[position];
return {};
}
auto mPopupMenu::actions() const -> unsigned {
auto mPopupMenu::actionCount() const -> unsigned {
return state.actions.size();
}
auto mPopupMenu::actions() const -> vector<Action> {
vector<Action> actions;
for(auto& action : state.actions) actions.append(action);
return actions;
}
auto mPopupMenu::append(sAction action) -> type& {
state.actions.append(action);
action->setParent(this, actions() - 1);
action->setParent(this, actionCount() - 1);
signal(append, action);
return *this;
}
@ -31,7 +37,7 @@ auto mPopupMenu::remove(sAction action) -> type& {
signed offset = action->offset();
signal(remove, action);
state.actions.remove(offset);
for(auto n : range(offset, actions())) {
for(auto n : range(offset, actionCount())) {
state.actions[n]->adjustOffset(-1);
}
action->setParent();
@ -43,6 +49,13 @@ auto mPopupMenu::reset() -> type& {
return *this;
}
auto mPopupMenu::setParent(mObject* parent, signed offset) -> type& {
for(auto& action : state.actions) action->destruct();
mObject::setParent(parent, offset);
for(auto& action : state.actions) action->construct();
return *this;
}
auto mPopupMenu::setVisible(bool visible) -> type& {
signal(setVisible, visible);
return *this;

View File

@ -18,7 +18,13 @@
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 offset() const { return self().offset(); } \
auto parent() const { \
if(auto object = self().parent()) { \
if(auto instance = object->instance.acquire()) return Object(instance); \
} \
return Object(); \
} \
auto remove() { return self().remove(), *this; } \
auto setEnabled(bool enabled = true) { return self().setEnabled(enabled), *this; } \
auto setFocused() { return self().setFocused(), *this; } \
@ -41,6 +47,7 @@
auto remove(sSizable sizable) { return self().remove(sizable), *this; } \
auto reset() { return self().reset(), *this; } \
auto sizable(unsigned position) { return self().sizable(position); } \
auto sizableCount() const { return self().sizableCount(); } \
auto sizables() const { return self().sizables(); } \
#define DeclareSharedWidget(Name) \
@ -61,6 +68,7 @@ struct Group : sGroup {
auto append(sObject object) -> type& { return self().append(object), *this; }
auto object(unsigned position) const { return self().object(position); }
auto objectCount() const { return self().objectCount(); }
auto objects() const { return self().objects(); }
auto remove(sObject object) -> type& { return self().remove(object), *this; }
@ -81,9 +89,9 @@ struct Hotkey : sHotkey {
auto doRelease() const { return self().doRelease(); }
auto onPress(const function<void ()>& callback = {}) { return self().onPress(callback), *this; }
auto onRelease(const function<void ()>& callback = {}) { return self().onRelease(callback), *this; }
auto parent() const { return self().parent(); }
auto owner() const { return self().owner(); }
auto sequence() const { return self().sequence(); }
auto setParent(sObject object) { return self().setParent(object), *this; }
auto setOwner(sObject owner) { return self().setOwner(owner), *this; }
auto setSequence(const string& sequence = "") { return self().setSequence(sequence), *this; }
};
#endif
@ -110,6 +118,7 @@ struct Menu : sMenu {
DeclareSharedAction(Menu)
auto action(unsigned position) const { return self().action(position); }
auto actionCount() const { return self().actionCount(); }
auto actions() const { return self().actions(); }
auto append(sAction action) { return self().append(action), *this; }
auto icon() const { return self().icon(); }
@ -285,6 +294,7 @@ struct ComboButton : sComboButton {
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 itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto remove(sComboButtonItem item) { return self().remove(item), *this; }
@ -328,21 +338,21 @@ struct Frame : sFrame {
struct HexEdit : sHexEdit {
DeclareSharedWidget(HexEdit)
auto address() const { return self().address(); }
auto backgroundColor() const { return self().backgroundColor(); }
auto columns() const { return self().columns(); }
auto doRead(unsigned offset) const { return self().doRead(offset); }
auto doWrite(unsigned offset, uint8_t data) const { return self().doWrite(offset, data); }
auto foregroundColor() const { return self().foregroundColor(); }
auto length() const { return self().length(); }
auto offset() const { return self().offset(); }
auto onRead(const function<uint8_t (unsigned)>& callback = {}) { return self().onRead(callback), *this; }
auto onWrite(const function<void (unsigned, uint8_t)>& callback = {}) { return self().onWrite(callback), *this; }
auto rows() const { return self().rows(); }
auto setAddress(unsigned address) { return self().setAddress(address), *this; }
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; }
};
@ -399,6 +409,7 @@ struct IconView : sIconView {
auto flow() const { return self().flow(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto item(unsigned position) const { return self().item(position); }
auto itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto multiSelect() const { return self().multiSelect(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
@ -422,12 +433,10 @@ struct IconView : sIconView {
struct Label : sLabel {
DeclareSharedWidget(Label)
auto horizontalAlignment() const { return self().horizontalAlignment(); }
auto setHorizontalAlignment(double alignment = 0.0) { return self().setHorizontalAlignment(alignment), *this; }
auto alignment() const { return self().alignment(); }
auto setAlignment(Alignment alignment = {}) { return self().setAlignment(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
@ -455,6 +464,7 @@ struct ListViewColumn : sListViewColumn {
DeclareSharedObject(ListViewColumn)
auto active() const { return self().active(); }
auto alignment() const { return self().alignment(); }
auto backgroundColor() const { return self().backgroundColor(); }
auto editable() const { return self().editable(); }
auto expandable() const { return self().expandable(); }
@ -463,6 +473,7 @@ struct ListViewColumn : sListViewColumn {
auto icon() const { return self().icon(); }
auto resizable() const { return self().resizable(); }
auto setActive() { return self().setActive(), *this; }
auto setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *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; }
@ -470,23 +481,43 @@ struct ListViewColumn : sListViewColumn {
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 setSortable(bool sortable = true) { return self().setSortable(sortable), *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 sortable() const { return self().sortable(); }
auto text() const { return self().text(); }
auto verticalAlignment() const { return self().verticalAlignment(); }
auto width() const { return self().width(); }
};
#endif
#if defined(Hiro_ListView)
struct ListViewHeader : sListViewHeader {
DeclareSharedObject(ListViewHeader)
auto append(sListViewColumn column) { return self().append(column), *this; }
auto column(unsigned position) const { return self().column(position); }
auto columnCount() const { return self().columnCount(); }
auto columns() const { return self().columns(); }
auto remove(sListViewColumn column) { return self().remove(column), *this; }
};
#endif
#if defined(Hiro_ListView)
struct ListViewCell : sListViewCell {
DeclareSharedObject(ListViewCell)
auto alignment() const { return self().alignment(); }
auto backgroundColor() const { return self().backgroundColor(); }
auto checkable() const { return self().checkable(); }
auto checked() const { return self().checked(); }
auto foregroundColor() const { return self().foregroundColor(); }
auto icon() const { return self().icon(); }
auto setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setCheckable(bool checkable = true) const { return self().setCheckable(checkable), *this; }
auto setChecked(bool checked = true) const { return self().setChecked(checked), *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; }
@ -498,18 +529,17 @@ struct ListViewCell : sListViewCell {
struct ListViewItem : sListViewItem {
DeclareSharedObject(ListViewItem)
auto alignment() const { return self().alignment(); }
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 cellCount() const { return self().cellCount(); }
auto cells() const { return self().cells(); }
auto checkable() const { return self().checkable(); }
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 setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *this; }
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
auto setCheckable(bool checkable = true) { return self().setCheckable(checkable), *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; }
};
@ -519,49 +549,40 @@ struct ListViewItem : sListViewItem {
struct ListView : sListView {
DeclareSharedWidget(ListView)
auto append(sListViewColumn column) { return self().append(column), *this; }
auto alignment() const { return self().alignment(); }
auto append(sListViewHeader header) { return self().append(header), *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 batched() const { return self().batched(); }
auto bordered() const { return self().bordered(); }
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 doToggle(sListViewCell cell) const { return self().doToggle(cell); }
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 header() const { return self().header(); }
auto item(unsigned position) const { return self().item(position); }
auto itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onContext(const function<void ()>& callback = {}) { return self().onContext(callback), *this; }
auto onEdit(const function<void (ListViewCell)>& callback = {}) { return self().onEdit(callback), *this; }
auto onSort(const function<void (ListViewColumn)>& callback = {}) { return self().onSort(callback), *this; }
auto onToggle(const function<void (ListViewItem)>& callback = {}) { return self().onToggle(callback), *this; }
auto remove(sListViewColumn column) { return self().remove(column), *this; }
auto onToggle(const function<void (ListViewCell)>& callback = {}) { return self().onToggle(callback), *this; }
auto remove(sListViewHeader header) { return self().remove(header), *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 setAlignment(Alignment alignment = {}) { return self().setAlignment(alignment), *this; }
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 setBordered(bool bordered = true) { return self().setBordered(bordered), *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
@ -655,6 +676,7 @@ struct TabFrame : sTabFrame {
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 itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
auto onClose(const function<void (sTabFrameItem)>& callback = {}) { return self().onClose(callback), *this; }
@ -697,6 +719,7 @@ struct TreeViewItem : sTreeViewItem {
auto checked() const { return self().checked(); }
auto icon() const { return self().icon(); }
auto item(const string& path) const { return self().item(path); }
auto itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto path() const { return self().path(); }
auto remove(sTreeViewItem item) { return self().remove(item), *this; }
@ -724,6 +747,7 @@ struct TreeView : sTreeView {
auto expand() { return self().expand(), *this; }
auto foregroundColor() const { return self().foregroundColor(); }
auto item(const string& path) const { return self().item(path); }
auto itemCount() const { return self().itemCount(); }
auto items() const { return self().items(); }
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
@ -798,6 +822,7 @@ struct PopupMenu : sPopupMenu {
DeclareSharedObject(PopupMenu)
auto action(unsigned position) const { return self().action(position); }
auto actionCount() const { return self().actionCount(); }
auto actions() const { return self().actions(); }
auto append(sAction action) { return self().append(action), *this; }
auto remove(sAction action) { return self().remove(action), *this; }
@ -811,6 +836,7 @@ struct MenuBar : sMenuBar {
auto append(sMenu menu) { return self().append(menu), *this; }
auto menu(unsigned position) const { return self().menu(position); }
auto menuCount() const { return self().menuCount(); }
auto menus() const { return self().menus(); }
auto remove(sMenu menu) { return self().remove(menu), *this; }
auto reset() { return self().reset(), *this; }
@ -849,6 +875,7 @@ struct Window : sWindow {
auto remove(sStatusBar statusBar) { return self().remove(statusBar), *this; }
auto reset() { return self().reset(), *this; }
auto resizable() const { return self().resizable(); }
auto setAlignment(Alignment alignment) { return self().setAlignment(alignment), *this; }
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; }
@ -858,7 +885,6 @@ struct Window : sWindow {
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; }

View File

@ -13,7 +13,7 @@ auto mComboButton::destruct() -> void {
auto mComboButton::append(sComboButtonItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -23,14 +23,20 @@ auto mComboButton::doChange() const -> void {
}
auto mComboButton::item(unsigned position) const -> ComboButtonItem {
if(position < items()) return state.items[position];
if(position < itemCount()) return state.items[position];
return {};
}
auto mComboButton::items() const -> unsigned {
auto mComboButton::itemCount() const -> unsigned {
return state.items.size();
}
auto mComboButton::items() const -> vector<ComboButtonItem> {
vector<ComboButtonItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mComboButton::onChange(const function<void ()>& callback) -> type& {
state.onChange = callback;
return *this;
@ -39,7 +45,7 @@ auto mComboButton::onChange(const function<void ()>& callback) -> type& {
auto mComboButton::remove(sComboButtonItem item) -> type& {
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) {
for(auto n : range(item->offset(), itemCount())) {
state.items[n]->adjustOffset(-1);
}
item->setParent();

View File

@ -6,6 +6,10 @@ auto mHexEdit::allocate() -> pObject* {
//
auto mHexEdit::address() const -> unsigned {
return state.address;
}
auto mHexEdit::backgroundColor() const -> Color {
return state.backgroundColor;
}
@ -31,10 +35,6 @@ auto mHexEdit::length() const -> unsigned {
return state.length;
}
auto mHexEdit::offset() const -> unsigned {
return state.offset;
}
auto mHexEdit::onRead(const function<uint8_t (unsigned)>& callback) -> type& {
state.onRead = callback;
return *this;
@ -49,6 +49,12 @@ auto mHexEdit::rows() const -> unsigned {
return state.rows;
}
auto mHexEdit::setAddress(unsigned address) -> type& {
state.address = address;
signal(setAddress, address);
return *this;
}
auto mHexEdit::setBackgroundColor(Color color) -> type& {
state.backgroundColor = color;
signal(setBackgroundColor, color);
@ -73,12 +79,6 @@ auto mHexEdit::setLength(unsigned length) -> type& {
return *this;
}
auto mHexEdit::setOffset(unsigned offset) -> type& {
state.offset = offset;
signal(setOffset, offset);
return *this;
}
auto mHexEdit::setRows(unsigned rows) -> type& {
state.rows = rows;
signal(setRows, rows);

View File

@ -13,7 +13,7 @@ auto mIconView::destruct() -> void {
auto mIconView::append(sIconViewItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -43,14 +43,20 @@ auto mIconView::foregroundColor() const -> Color {
}
auto mIconView::item(unsigned position) const -> IconViewItem {
if(position < items()) return state.items[position];
if(position < itemCount()) return state.items[position];
return {};
}
auto mIconView::items() const -> unsigned {
auto mIconView::itemCount() const -> unsigned {
return state.items.size();
}
auto mIconView::items() const -> vector<IconViewItem> {
vector<IconViewItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mIconView::multiSelect() const -> bool {
return state.multiSelect;
}
@ -77,7 +83,7 @@ auto mIconView::orientation() const -> Orientation {
auto mIconView::remove(sIconViewItem item) -> type& {
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) {
for(auto n : range(item->offset(), itemCount())) {
state.items[n]->adjustOffset(-1);
}
item->setParent();
@ -142,7 +148,7 @@ auto mIconView::setSelected(const vector<signed>& selections) -> type& {
if(selectAll) return signal(setItemSelectedAll), *this;
if(!selections) return signal(setItemSelectedNone), *this;
for(auto& position : selections) {
if(position >= items()) continue;
if(position >= itemCount()) continue;
state.items[position]->state.selected = true;
}
signal(setItemSelected, selections);

View File

@ -6,14 +6,13 @@ auto mLabel::allocate() -> pObject* {
//
auto mLabel::horizontalAlignment() const -> double {
return state.horizontalAlignment;
auto mLabel::alignment() const -> Alignment {
return state.alignment;
}
auto mLabel::setHorizontalAlignment(double alignment) -> type& {
alignment = max(0.0, min(1.0, alignment));
state.horizontalAlignment = alignment;
signal(setHorizontalAlignment, alignment);
auto mLabel::setAlignment(Alignment alignment) -> type& {
state.alignment = alignment;
signal(setAlignment, alignment);
return *this;
}
@ -23,19 +22,8 @@ auto mLabel::setText(const string& text) -> type& {
return *this;
}
auto mLabel::setVerticalAlignment(double alignment) -> type& {
alignment = max(0.0, min(1.0, alignment));
state.verticalAlignment = alignment;
signal(setVerticalAlignment, alignment);
return *this;
}
auto mLabel::text() const -> string {
return state.text;
}
auto mLabel::verticalAlignment() const -> double {
return state.verticalAlignment;
}
#endif

View File

@ -6,11 +6,91 @@ auto mListViewCell::allocate() -> pObject* {
//
auto mListViewCell::backgroundColor() const -> Color {
return state.backgroundColor;
auto mListViewCell::alignment(bool recursive) const -> Alignment {
if(auto alignment = state.alignment) return alignment;
if(recursive) {
if(auto parent = parentListViewItem()) {
if(auto alignment = parent->state.alignment) return alignment;
if(auto grandparent = parent->parentListView()) {
if(auto header = grandparent->state.header) {
if(offset() < header->columnCount()) {
if(auto column = header->state.columns[offset()]) {
if(auto alignment = column->state.alignment) return alignment;
}
}
}
if(auto alignment = grandparent->state.alignment) return alignment;
}
}
}
return {};
}
auto mListViewCell::foregroundColor() const -> Color {
auto mListViewCell::backgroundColor(bool recursive) const -> Color {
if(auto color = state.backgroundColor) return color;
if(recursive) {
if(auto parent = parentListViewItem()) {
if(auto color = parent->state.backgroundColor) return color;
if(auto grandparent = parent->parentListView()) {
if(auto header = grandparent->state.header) {
if(offset() < header->columnCount()) {
if(auto column = header->state.columns[offset()]) {
if(auto color = column->state.backgroundColor) return color;
}
}
}
if(auto color = grandparent->state.backgroundColor) return color;
}
}
}
return {};
}
auto mListViewCell::checkable() const -> bool {
return state.checkable;
}
auto mListViewCell::checked() const -> bool {
return state.checkable && state.checked;
}
auto mListViewCell::font(bool recursive) const -> string {
if(auto font = mObject::font()) return font;
if(recursive) {
if(auto parent = parentListViewItem()) {
if(auto font = parent->font()) return font;
if(auto grandparent = parent->parentListView()) {
if(auto header = grandparent->state.header) {
if(offset() < header->columnCount()) {
if(auto column = header->state.columns[offset()]) {
if(auto font = column->font()) return font;
}
}
}
if(auto font = grandparent->font(true)) return font;
}
}
}
return {};
}
auto mListViewCell::foregroundColor(bool recursive) const -> Color {
if(auto color = state.foregroundColor) return color;
if(recursive) {
if(auto parent = parentListViewItem()) {
if(auto color = parent->state.foregroundColor) return color;
if(auto grandparent = parent->parentListView()) {
if(auto header = grandparent->state.header) {
if(offset() < header->columnCount()) {
if(auto column = header->state.columns[offset()]) {
if(auto color = column->state.foregroundColor) return color;
}
}
}
if(auto color = grandparent->state.foregroundColor) return color;
}
}
}
return state.foregroundColor;
}
@ -18,12 +98,31 @@ auto mListViewCell::icon() const -> image {
return state.icon;
}
auto mListViewCell::setAlignment(Alignment alignment) -> type& {
state.alignment = alignment;
signal(setAlignment, alignment);
return *this;
}
auto mListViewCell::setBackgroundColor(Color color) -> type& {
state.backgroundColor = color;
signal(setBackgroundColor, color);
return *this;
}
auto mListViewCell::setCheckable(bool checkable) -> type& {
state.checkable = checkable;
signal(setCheckable, checkable);
return *this;
}
auto mListViewCell::setChecked(bool checked) -> type& {
setCheckable(true);
state.checked = checked;
signal(setChecked, checked);
return *this;
}
auto mListViewCell::setForegroundColor(Color color) -> type& {
state.foregroundColor = color;
signal(setForegroundColor, color);

View File

@ -11,6 +11,10 @@ auto mListViewColumn::active() const -> bool {
return false;
}
auto mListViewColumn::alignment() const -> Alignment {
return state.alignment;
}
auto mListViewColumn::backgroundColor() const -> Color {
return state.backgroundColor;
}
@ -36,7 +40,7 @@ auto mListViewColumn::icon() const -> image {
}
auto mListViewColumn::remove() -> type& {
if(auto listView = parentListView()) listView->remove(*this);
if(auto listView = parentListViewHeader()) listView->remove(*this);
return *this;
}
@ -50,6 +54,12 @@ auto mListViewColumn::setActive() -> type& {
return *this;
}
auto mListViewColumn::setAlignment(Alignment alignment) -> type& {
state.alignment = alignment;
signal(setAlignment, alignment);
return *this;
}
auto mListViewColumn::setBackgroundColor(Color color) -> type& {
state.backgroundColor = color;
signal(setBackgroundColor, color);
@ -68,12 +78,6 @@ auto mListViewColumn::setExpandable(bool expandable) -> type& {
return *this;
}
auto mListViewColumn::setFont(const string& font) -> type& {
state.font = font;
signal(setFont, this->font(true));
return *this;
}
auto mListViewColumn::setForegroundColor(Color color) -> type& {
state.foregroundColor = color;
signal(setForegroundColor, color);
@ -99,6 +103,12 @@ auto mListViewColumn::setResizable(bool resizable) -> type& {
return *this;
}
auto mListViewColumn::setSortable(bool sortable) -> type& {
state.sortable = sortable;
signal(setSortable, sortable);
return *this;
}
auto mListViewColumn::setText(const string& text) -> type& {
state.text = text;
signal(setText, text);
@ -124,6 +134,10 @@ auto mListViewColumn::setWidth(signed width) -> type& {
return *this;
}
auto mListViewColumn::sortable() const -> bool {
return state.sortable;
}
auto mListViewColumn::text() const -> string {
return state.text;
}

View File

@ -0,0 +1,53 @@
#if defined(Hiro_ListView)
auto mListViewHeader::allocate() -> pObject* {
return new pListViewHeader(*this);
}
//
auto mListViewHeader::append(sListViewColumn column) -> type& {
state.columns.append(column);
column->setParent(this, columnCount() - 1);
signal(append, column);
return *this;
}
auto mListViewHeader::column(unsigned position) const -> ListViewColumn {
if(position < columnCount()) return state.columns[position];
return {};
}
auto mListViewHeader::columnCount() const -> unsigned {
return state.columns.size();
}
auto mListViewHeader::columns() const -> vector<ListViewColumn> {
vector<ListViewColumn> columns;
for(auto& column : state.columns) columns.append(column);
return columns;
}
auto mListViewHeader::remove() -> type& {
if(auto listView = parentListView()) listView->remove(*this);
return *this;
}
auto mListViewHeader::remove(sListViewColumn column) -> type& {
signal(remove, column);
state.columns.remove(column->offset());
for(auto n : range(column->offset(), columnCount())) {
state.columns[n]->adjustOffset(-1);
}
column->setParent();
return *this;
}
auto mListViewHeader::setParent(mObject* parent, signed offset) -> type& {
for(auto& column : state.columns) column->destruct();
mObject::setParent(parent, offset);
for(auto& column : state.columns) column->setParent(this, column->offset());
return *this;
}
#endif

View File

@ -6,9 +6,13 @@ auto mListViewItem::allocate() -> pObject* {
//
auto mListViewItem::alignment() const -> Alignment {
return state.alignment;
}
auto mListViewItem::append(sListViewCell cell) -> type& {
state.cells.append(cell);
cell->setParent(this, cells() - 1);
cell->setParent(this, cellCount() - 1);
signal(append, cell);
return *this;
}
@ -18,20 +22,18 @@ auto mListViewItem::backgroundColor() const -> Color {
}
auto mListViewItem::cell(unsigned position) const -> ListViewCell {
if(position < cells()) return state.cells[position];
if(position < cellCount()) return state.cells[position];
return {};
}
auto mListViewItem::cells() const -> unsigned {
auto mListViewItem::cellCount() const -> unsigned {
return state.cells.size();
}
auto mListViewItem::checkable() const -> bool {
return state.checkable;
}
auto mListViewItem::checked() const -> bool {
return state.checkable && state.checked;
auto mListViewItem::cells() const -> vector<ListViewCell> {
vector<ListViewCell> cells;
for(auto& cell : state.cells) cells.append(cell);
return cells;
}
auto mListViewItem::foregroundColor() const -> Color {
@ -46,7 +48,7 @@ auto mListViewItem::remove() -> type& {
auto mListViewItem::remove(sListViewCell cell) -> type& {
signal(remove, cell);
state.cells.remove(cell->offset());
for(auto n : range(cell->offset(), cells())) {
for(auto n : range(cell->offset(), cellCount())) {
state.cells[n]->adjustOffset(-1);
}
cell->setParent();
@ -57,24 +59,18 @@ auto mListViewItem::selected() const -> bool {
return state.selected;
}
auto mListViewItem::setAlignment(Alignment alignment) -> type& {
state.alignment = alignment;
signal(setAlignment, alignment);
return *this;
}
auto mListViewItem::setBackgroundColor(Color color) -> type& {
state.backgroundColor = color;
signal(setBackgroundColor, color);
return *this;
}
auto mListViewItem::setCheckable(bool checkable) -> type& {
state.checkable = checkable;
signal(setCheckable, checkable);
return *this;
}
auto mListViewItem::setChecked(bool checked) -> type& {
state.checked = checked;
signal(setChecked, checked);
return *this;
}
auto mListViewItem::setFocused() -> type& {
signal(setFocused);
return *this;

View File

@ -6,22 +6,27 @@ auto mListView::allocate() -> pObject* {
auto mListView::destruct() -> void {
for(auto& item : state.items) item->destruct();
for(auto& column : state.columns) column->destruct();
if(auto& header = state.header) header->destruct();
mWidget::destruct();
}
//
auto mListView::append(sListViewColumn column) -> type& {
state.columns.append(column);
column->setParent(this, columns() - 1);
signal(append, column);
auto mListView::alignment() const -> Alignment {
return state.alignment;
}
auto mListView::append(sListViewHeader header) -> type& {
if(auto& header = state.header) remove(header);
state.header = header;
header->setParent(this, 0);
signal(append, header);
return *this;
}
auto mListView::append(sListViewItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -34,31 +39,16 @@ auto mListView::batchable() const -> bool {
return state.batchable;
}
auto mListView::checkable() const -> bool {
return state.checkable;
}
auto mListView::checkAll() -> type& {
for(auto& item : state.items) item->state.checked = true;
signal(checkAll);
return *this;
}
auto mListView::checked() const -> vector<ListViewItem> {
auto mListView::batched() const -> vector<ListViewItem> {
vector<ListViewItem> items;
for(auto& item : state.items) {
if(item->checked()) items.append(item);
if(item->selected()) items.append(item);
}
return items;
}
auto mListView::column(unsigned position) const -> ListViewColumn {
if(position < columns()) return state.columns[position];
return {};
}
auto mListView::columns() const -> unsigned {
return state.columns.size();
auto mListView::bordered() const -> bool {
return state.bordered;
}
auto mListView::doActivate() const -> void {
@ -81,31 +71,33 @@ auto mListView::doSort(sListViewColumn column) const -> void {
if(state.onSort) return state.onSort(column);
}
auto mListView::doToggle(sListViewItem item) const -> void {
if(state.onToggle) return state.onToggle(item);
auto mListView::doToggle(sListViewCell cell) const -> void {
if(state.onToggle) return state.onToggle(cell);
}
auto mListView::foregroundColor() const -> Color {
return state.foregroundColor;
}
auto mListView::gridVisible() const -> bool {
return state.gridVisible;
}
auto mListView::headerVisible() const -> bool {
return state.headerVisible;
auto mListView::header() const -> ListViewHeader {
return state.header;
}
auto mListView::item(unsigned position) const -> ListViewItem {
if(position < items()) return state.items[position];
if(position < itemCount()) return state.items[position];
return {};
}
auto mListView::items() const -> unsigned {
auto mListView::itemCount() const -> unsigned {
return state.items.size();
}
auto mListView::items() const -> vector<ListViewItem> {
vector<ListViewItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mListView::onActivate(const function<void ()>& callback) -> type& {
state.onActivate = callback;
return *this;
@ -131,27 +123,22 @@ auto mListView::onSort(const function<void (ListViewColumn)>& callback) -> type&
return *this;
}
auto mListView::onToggle(const function<void (ListViewItem)>& callback) -> type& {
auto mListView::onToggle(const function<void (ListViewCell)>& callback) -> type& {
state.onToggle = callback;
return *this;
}
auto mListView::remove(sListViewColumn column) -> type& {
signal(remove, column);
for(auto& item : state.items) item->setParent();
state.items.reset();
state.columns.remove(column->offset());
for(auto n : range(column->offset(), columns())) {
state.columns[n]->adjustOffset(-1);
}
column->setParent();
auto mListView::remove(sListViewHeader header) -> type& {
signal(remove, header);
header->setParent();
state.header.reset();
return *this;
}
auto mListView::remove(sListViewItem item) -> type& {
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) {
for(auto n : range(item->offset(), itemCount())) {
state.items[n]->adjustOffset(-1);
}
item->setParent();
@ -162,8 +149,8 @@ auto mListView::reset() -> type& {
signal(reset);
for(auto& item : state.items) item->setParent();
state.items.reset();
for(auto& column : state.columns) column->setParent();
state.columns.reset();
if(auto& header = state.header) header->setParent();
state.header.reset();
return *this;
}
@ -172,12 +159,6 @@ auto mListView::resizeColumns() -> type& {
return *this;
}
auto mListView::selectAll() -> type& {
for(auto& item : state.items) item->state.selected = true;
signal(selectAll);
return *this;
}
auto mListView::selected() const -> ListViewItem {
for(auto& item : state.items) {
if(item->selected()) return item;
@ -185,12 +166,10 @@ auto mListView::selected() const -> ListViewItem {
return {};
}
auto mListView::selectedItems() const -> vector<ListViewItem> {
vector<ListViewItem> items;
for(auto& item : state.items) {
if(item->selected()) items.append(item);
}
return items;
auto mListView::setAlignment(Alignment alignment) -> type& {
state.alignment = alignment;
signal(setAlignment, alignment);
return *this;
}
auto mListView::setBackgroundColor(Color color) -> type& {
@ -205,9 +184,9 @@ auto mListView::setBatchable(bool batchable) -> type& {
return *this;
}
auto mListView::setCheckable(bool checkable) -> type& {
state.checkable = checkable;
signal(setCheckable, checkable);
auto mListView::setBordered(bool bordered) -> type& {
state.bordered = bordered;
signal(setBordered, bordered);
return *this;
}
@ -217,47 +196,13 @@ auto mListView::setForegroundColor(Color color) -> type& {
return *this;
}
auto mListView::setGridVisible(bool visible) -> type& {
state.gridVisible = visible;
signal(setGridVisible, visible);
return *this;
}
auto mListView::setHeaderVisible(bool visible) -> type& {
state.headerVisible = visible;
signal(setHeaderVisible, visible);
return *this;
}
auto mListView::setParent(mObject* parent, signed offset) -> type& {
for(auto& item : state.items) item->destruct();
for(auto& column : state.columns) column->destruct();
if(auto& header = state.header) header->destruct();
mObject::setParent(parent, offset);
for(auto& column : state.columns) column->setParent(this, column->offset());
if(auto& header = state.header) header->setParent(this, 0);
for(auto& item : state.items) item->setParent(this, item->offset());
return *this;
}
auto mListView::setSortable(bool sortable) -> type& {
state.sortable = sortable;
signal(setSortable, sortable);
return *this;
}
auto mListView::sortable() const -> bool {
return state.sortable;
}
auto mListView::uncheckAll() -> type& {
for(auto& item : state.items) item->state.checked = false;
signal(uncheckAll);
return *this;
}
auto mListView::unselectAll() -> type& {
for(auto& item : state.items) item->state.selected = false;
signal(unselectAll);
return *this;
}
#endif

View File

@ -59,7 +59,7 @@ auto mRadioButton::setChecked() -> type& {
auto mRadioButton::setGroup(sGroup group) -> type& {
state.group = group;
signal(setGroup, group);
if(group && group->objects() == 1) setChecked();
if(group && group->objectCount() == 1) setChecked();
return *this;
}

View File

@ -41,7 +41,7 @@ auto mRadioLabel::setChecked() -> type& {
auto mRadioLabel::setGroup(sGroup group) -> type& {
state.group = group;
signal(setGroup, group);
if(group && group->objects() == 1) setChecked();
if(group && group->objectCount() == 1) setChecked();
return *this;
}

View File

@ -13,7 +13,7 @@ auto mTabFrame::destruct() -> void {
auto mTabFrame::append(sTabFrameItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -35,14 +35,20 @@ auto mTabFrame::edge() const -> Edge {
}
auto mTabFrame::item(unsigned position) const -> TabFrameItem {
if(position < items()) return state.items[position];
if(position < itemCount()) return state.items[position];
return {};
}
auto mTabFrame::items() const -> unsigned {
auto mTabFrame::itemCount() const -> unsigned {
return state.items.size();
}
auto mTabFrame::items() const -> vector<TabFrameItem> {
vector<TabFrameItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mTabFrame::onChange(const function<void ()>& callback) -> type& {
state.onChange = callback;
return *this;
@ -63,7 +69,7 @@ auto mTabFrame::remove(sTabFrameItem item) -> type& {
item->setParent();
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(offset, items())) {
for(auto n : range(offset, itemCount())) {
state.items[n]->adjustOffset(-1);
}
return *this;

View File

@ -13,7 +13,7 @@ auto mTreeViewItem::destruct() -> void {
auto mTreeViewItem::append(sTreeViewItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -30,15 +30,21 @@ auto mTreeViewItem::item(const string& path) const -> TreeViewItem {
if(path.empty()) return {};
auto paths = path.split("/");
unsigned position = decimal(paths.takeFirst());
if(position >= items()) return {};
if(position >= itemCount()) return {};
if(paths.empty()) return state.items[position];
return state.items[position]->item(paths.merge("/"));
}
auto mTreeViewItem::items() const -> unsigned {
auto mTreeViewItem::itemCount() const -> unsigned {
return state.items.size();
}
auto mTreeViewItem::items() const -> vector<TreeViewItem> {
vector<TreeViewItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mTreeViewItem::path() const -> string {
if(auto treeViewItem = parentTreeViewItem()) return {treeViewItem->path(), "/", offset()};
return {offset()};
@ -53,7 +59,7 @@ auto mTreeViewItem::remove() -> type& {
auto mTreeViewItem::remove(sTreeViewItem item) -> type& {
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) {
for(auto n : range(item->offset(), itemCount())) {
state.items[n]->adjustOffset(-1);
}
item->setParent();

View File

@ -13,7 +13,7 @@ auto mTreeView::destruct() -> void {
auto mTreeView::append(sTreeViewItem item) -> type& {
state.items.append(item);
item->setParent(this, items() - 1);
item->setParent(this, itemCount() - 1);
signal(append, item);
return *this;
}
@ -60,15 +60,21 @@ auto mTreeView::item(const string& path) const -> TreeViewItem {
if(path.empty()) return {};
auto paths = path.split("/");
unsigned position = decimal(paths.takeFirst());
if(position >= items()) return {};
if(position >= itemCount()) return {};
if(paths.empty()) return state.items[position];
return state.items[position]->item(paths.merge("/"));
}
auto mTreeView::items() const -> unsigned {
auto mTreeView::itemCount() const -> unsigned {
return state.items.size();
}
auto mTreeView::items() const -> vector<TreeViewItem> {
vector<TreeViewItem> items;
for(auto& item : state.items) items.append(item);
return items;
}
auto mTreeView::onActivate(const function<void ()>& callback) -> type& {
state.onActivate = callback;
return *this;
@ -92,7 +98,7 @@ auto mTreeView::onToggle(const function<void (sTreeViewItem)>& callback) -> type
auto mTreeView::remove(sTreeViewItem item) -> type& {
signal(remove, item);
state.items.remove(item->offset());
for(auto n : range(item->offset(), items())) {
for(auto n : range(item->offset(), itemCount())) {
state.items[n]->adjustOffset(-1);
}
item->setParent();

View File

@ -162,6 +162,16 @@ auto mWindow::resizable() const -> bool {
return state.resizable;
}
auto mWindow::setAlignment(Alignment alignment) -> type& {
if(!alignment) alignment = {0.0, 0.0};
auto workspace = Desktop::workspace();
auto geometry = frameGeometry();
signed left = alignment.horizontal() * (workspace.width() - geometry.width());
signed top = alignment.vertical() * (workspace.height() - geometry.height());
setFramePosition({left, top});
return *this;
}
auto mWindow::setBackgroundColor(Color color) -> type& {
state.backgroundColor = color;
signal(setBackgroundColor, color);
@ -229,17 +239,6 @@ auto mWindow::setModal(bool modal) -> type& {
return *this;
}
auto mWindow::setPlacement(double x, double y) -> type& {
x = max(0.0, min(1.0, x));
y = max(0.0, min(1.0, y));
auto workspace = Desktop::workspace();
auto geometry = frameGeometry();
signed left = x * (workspace.width() - geometry.width());
signed top = y * (workspace.height() - geometry.height());
setFramePosition({left, top});
return *this;
}
auto mWindow::setPosition(Position position) -> type& {
return setGeometry({
position.x(), position.y(),

View File

@ -32,30 +32,30 @@ private:
//accept button clicked, or enter pressed on file name line edit
//also called by list view activate after special case handling
auto BrowserDialogWindow::accept() -> void {
auto selectedItems = view.selectedItems();
auto batched = view.batched();
if(state.action == "openFile" && selectedItems) {
string name = selectedItems.first()->cell(0)->text();
if(state.action == "openFile" && batched) {
string name = batched.first()->cell(0)->text();
if(isFolder(name)) return setPath({state.path, name});
state.response.append(string{state.path, name});
}
if(state.action == "openFiles") {
for(auto selectedItem : selectedItems) {
string name = selectedItem->cell(0)->text();
for(auto item : batched) {
string name = item->cell(0)->text();
state.response.append(string{state.path, name, isFolder(name) ? "/" : ""});
}
}
if(state.action == "openFolder" && selectedItems) {
string name = selectedItems.first()->cell(0)->text();
if(state.action == "openFolder" && batched) {
string name = batched.first()->cell(0)->text();
if(!isMatch(name)) return setPath({state.path, name});
state.response.append(string{state.path, name, "/"});
}
if(state.action == "saveFile") {
string name = fileName.text();
if(!name && selectedItems) name = selectedItems.first()->cell(0)->text();
if(!name && batched) name = batched.first()->cell(0)->text();
if(!name || isFolder(name)) return;
if(file::exists({state.path, name})) {
if(MessageDialog("File already exists; overwrite it?").question() != "Yes") return;
@ -63,8 +63,8 @@ auto BrowserDialogWindow::accept() -> void {
state.response.append(string{state.path, name});
}
if(state.action == "selectFolder" && selectedItems) {
string name = selectedItems.first()->cell(0)->text();
if(state.action == "selectFolder" && batched) {
string name = batched.first()->cell(0)->text();
if(isFolder(name)) state.response.append(string{state.path, name, "/"});
}
@ -162,7 +162,9 @@ auto BrowserDialogWindow::setPath(string path) -> void {
pathName.setText(state.path = path);
view.reset();
view.append(ListViewColumn().setExpandable());
view.append(ListViewHeader().setVisible(false)
.append(ListViewColumn().setExpandable())
);
auto contents = directory::icontents(path);
bool folderMode = state.action == "openFolder";

View File

@ -9,7 +9,7 @@ auto mFixedLayout::append(sSizable sizable, Geometry geometry) -> type& {
auto mFixedLayout::minimumSize() const -> Size {
signed width = Size::Minimum, height = Size::Minimum;
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
width = max(width, sizable(n)->minimumSize().width());
height = max(height, sizable(n)->minimumSize().height());
}
@ -30,7 +30,7 @@ auto mFixedLayout::reset() -> type& {
auto mFixedLayout::setEnabled(bool enabled) -> type& {
mLayout::setEnabled(enabled);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setEnabled(sizable(n)->enabled());
}
return *this;
@ -38,7 +38,7 @@ auto mFixedLayout::setEnabled(bool enabled) -> type& {
auto mFixedLayout::setFont(const string& font) -> type& {
mLayout::setFont(font);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setFont(sizable(n)->font());
}
return *this;
@ -46,7 +46,7 @@ auto mFixedLayout::setFont(const string& font) -> type& {
auto mFixedLayout::setVisible(bool visible) -> type& {
mLayout::setVisible(visible);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setVisible(sizable(n)->visible());
}
return *this;

View File

@ -9,7 +9,7 @@ auto mHorizontalLayout::append(sSizable sizable, Size size, signed spacing) -> t
auto mHorizontalLayout::minimumSize() const -> Size {
signed width = 0, height = 0;
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.width == Size::Minimum || child.width == Size::Maximum) {
width += sizable(n)->minimumSize().width();
@ -19,7 +19,7 @@ auto mHorizontalLayout::minimumSize() const -> Size {
if(&child != &properties.last()) width += child.spacing;
}
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.height == Size::Minimum || child.height == Size::Maximum) {
height = max(height, sizable(n)->minimumSize().height());
@ -50,7 +50,7 @@ auto mHorizontalLayout::setAlignment(double alignment) -> type& {
auto mHorizontalLayout::setEnabled(bool enabled) -> type& {
mLayout::setEnabled(enabled);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setEnabled(sizable(n)->enabled());
}
return *this;
@ -58,7 +58,7 @@ auto mHorizontalLayout::setEnabled(bool enabled) -> type& {
auto mHorizontalLayout::setFont(const string& font) -> type& {
mLayout::setFont(font);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setFont(sizable(n)->font());
}
return *this;
@ -68,7 +68,7 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& {
mLayout::setGeometry(containerGeometry);
auto properties = this->properties;
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width();
if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height();
@ -95,7 +95,7 @@ auto mHorizontalLayout::setGeometry(Geometry containerGeometry) -> type& {
signed maximumHeight = 0;
for(auto& child : properties) maximumHeight = max(maximumHeight, child.height);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
signed pivot = (maximumHeight - child.height) * settings.alignment;
Geometry childGeometry = {geometry.x(), geometry.y() + pivot, child.width, child.height};
@ -120,7 +120,7 @@ auto mHorizontalLayout::setSpacing(signed spacing) -> type& {
auto mHorizontalLayout::setVisible(bool visible) -> type& {
mLayout::setVisible(visible);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setVisible(sizable(n)->visible());
}
return *this;

View File

@ -9,7 +9,7 @@ auto mVerticalLayout::append(sSizable sizable, Size size, signed spacing) -> typ
auto mVerticalLayout::minimumSize() const -> Size {
signed width = 0, height = 0;
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.width == Size::Minimum || child.width == Size::Maximum) {
width = max(width, sizable(n)->minimumSize().width());
@ -18,7 +18,7 @@ auto mVerticalLayout::minimumSize() const -> Size {
width = max(width, child.width);
}
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.height == Size::Minimum || child.height == Size::Maximum) {
height += sizable(n)->minimumSize().height();
@ -50,7 +50,7 @@ auto mVerticalLayout::setAlignment(double alignment) -> type& {
auto mVerticalLayout::setEnabled(bool enabled) -> type& {
mLayout::setEnabled(enabled);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setEnabled(sizable(n)->enabled());
}
return *this;
@ -58,7 +58,7 @@ auto mVerticalLayout::setEnabled(bool enabled) -> type& {
auto mVerticalLayout::setFont(const string& font) -> type& {
mLayout::setFont(font);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setFont(sizable(n)->font());
}
return *this;
@ -68,7 +68,7 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& {
mLayout::setGeometry(containerGeometry);
auto properties = this->properties;
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
if(child.width == Size::Minimum) child.width = sizable(n)->minimumSize().width();
if(child.height == Size::Minimum) child.height = sizable(n)->minimumSize().height();
@ -95,7 +95,7 @@ auto mVerticalLayout::setGeometry(Geometry containerGeometry) -> type& {
signed maximumWidth = 0;
for(auto& child : properties) maximumWidth = max(maximumWidth, child.width);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
auto& child = properties[sizable(n)->offset()];
signed pivot = (maximumWidth - child.width) * settings.alignment;
Geometry childGeometry = {geometry.x() + pivot, geometry.y(), child.width, child.height};
@ -122,7 +122,7 @@ auto mVerticalLayout::setSpacing(signed spacing) -> type& {
auto mVerticalLayout::setVisible(bool visible) -> type& {
mLayout::setVisible(visible);
for(auto n : range(sizables())) {
for(auto n : range(sizableCount())) {
sizable(n)->setVisible(sizable(n)->visible());
}
return *this;

View File

@ -8,7 +8,7 @@ auto pMenuBar::construct() -> void {
auto pMenuBar::destruct() -> void {
}
auto pMenuBar::append(shared_pointer<mMenu> menu) -> void {
auto pMenuBar::append(sMenu menu) -> void {
if(auto parent = _parent()) {
parent->_append(*menu);
if(menu->self()) {
@ -18,7 +18,7 @@ auto pMenuBar::append(shared_pointer<mMenu> menu) -> void {
}
}
auto pMenuBar::remove(shared_pointer<mMenu> menu) -> void {
auto pMenuBar::remove(sMenu menu) -> void {
}
auto pMenuBar::setEnabled(bool enabled) -> void {

View File

@ -5,8 +5,8 @@ namespace hiro {
struct pMenuBar : pObject {
Declare(MenuBar, Object)
auto append(shared_pointer<mMenu> menu) -> void;
auto remove(shared_pointer<mMenu> menu) -> void;
auto append(sMenu menu) -> void;
auto remove(sMenu menu) -> void;
auto setEnabled(bool enabled) -> void override;
auto setFont(const string& font) -> void override;
auto setVisible(bool visible) -> void override;

View File

@ -46,6 +46,7 @@
#include "widget/label.cpp"
#include "widget/line-edit.cpp"
#include "widget/list-view.cpp"
#include "widget/list-view-header.cpp"
#include "widget/list-view-column.cpp"
#include "widget/list-view-item.cpp"
#include "widget/list-view-cell.cpp"

View File

@ -57,6 +57,7 @@ namespace hiro {
#include "widget/label.hpp"
#include "widget/line-edit.hpp"
#include "widget/list-view.hpp"
#include "widget/list-view-header.hpp"
#include "widget/list-view-column.hpp"
#include "widget/list-view-item.hpp"
#include "widget/list-view-cell.hpp"

View File

@ -1,16 +1,5 @@
namespace hiro {
void Settings::load() {
string path = {configpath(), "hiro/"};
Configuration::Document::load({path, "gtk.bml"});
}
void Settings::save() {
string path = {configpath(), "hiro/"};
directory::create(path, 0755);
Configuration::Document::save({path, "gtk.bml"});
}
Settings::Settings() {
geometry.append(geometry.frameX = 4, "FrameX");
geometry.append(geometry.frameY = 24, "FrameY");
@ -23,4 +12,15 @@ Settings::Settings() {
append(window, "Window");
}
auto Settings::load() -> void {
string path = {configpath(), "hiro/"};
Configuration::Document::load({path, "gtk.bml"});
}
auto Settings::save() -> void {
string path = {configpath(), "hiro/"};
directory::create(path, 0755);
Configuration::Document::save({path, "gtk.bml"});
}
}

View File

@ -16,9 +16,9 @@ struct Settings : Configuration::Document {
unsigned backgroundColor;
} window;
void load();
void save();
Settings();
auto load() -> void;
auto save() -> void;
};
static Settings* settings = nullptr;

View File

@ -52,12 +52,12 @@ auto pHexEdit::construct() -> void {
gtk_widget_show(subWidget);
gtk_widget_show(container);
setAddress(state().address);
setBackgroundColor(state().backgroundColor);
setColumns(state().columns);
setForegroundColor(state().foregroundColor);
setRows(state().rows);
setLength(state().length);
setOffset(state().offset);
update();
g_signal_connect(G_OBJECT(subWidget), "key-press-event", G_CALLBACK(HexEdit_keyPress), (gpointer)this);
@ -80,6 +80,12 @@ auto pHexEdit::focused() const -> bool {
return GTK_WIDGET_HAS_FOCUS(subWidget) || GTK_WIDGET_HAS_FOCUS(scrollBar);
}
auto pHexEdit::setAddress(unsigned address) -> void {
setScroll();
updateScroll();
update();
}
auto pHexEdit::setBackgroundColor(Color color) -> void {
GdkColor gdkColor = CreateColor(color);
gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
@ -100,12 +106,6 @@ auto pHexEdit::setLength(unsigned length) -> void {
update();
}
auto pHexEdit::setOffset(unsigned offset) -> void {
setScroll();
updateScroll();
update();
}
auto pHexEdit::setRows(unsigned rows) -> void {
setScroll();
update();
@ -120,16 +120,16 @@ auto pHexEdit::update() -> void {
unsigned position = cursorPosition();
string output;
unsigned offset = state().offset;
unsigned address = state().address;
for(auto row : range(state().rows)) {
output.append(hex(offset, 8L));
output.append(hex(address, 8L));
output.append(" ");
string hexdata;
string ansidata = " ";
for(auto column : range(state().columns)) {
if(offset < state().length) {
uint8_t data = self().doRead(offset++);
if(address < state().length) {
uint8_t data = self().doRead(address++);
hexdata.append(hex(data, 2L));
hexdata.append(" ");
ansidata.append(data >= 0x20 && data <= 0x7e ? (char)data : '.');
@ -141,7 +141,7 @@ auto pHexEdit::update() -> void {
output.append(hexdata);
output.append(ansidata);
if(offset >= state().length) break;
if(address >= state().length) break;
if(row != state().rows - 1) output.append("\n");
}
@ -179,9 +179,9 @@ auto pHexEdit::keyPress(unsigned scancode, unsigned mask) -> bool {
if(scancode == GDK_Up) {
if(cursorY != 0) return false;
signed newOffset = state().offset - state().columns;
if(newOffset >= 0) {
self().setOffset(newOffset);
signed newAddress = state().address - state().columns;
if(newAddress >= 0) {
self().setAddress(newAddress);
update();
}
return true;
@ -191,34 +191,34 @@ auto pHexEdit::keyPress(unsigned scancode, unsigned mask) -> bool {
if(cursorY >= rows() - 1) return true;
if(cursorY != state().rows - 1) return false;
signed newOffset = state().offset + state().columns;
if(newOffset + state().columns * state().rows - (state().columns - 1) <= state().length) {
self().setOffset(newOffset);
signed newAddress = state().address + state().columns;
if(newAddress + state().columns * state().rows - (state().columns - 1) <= state().length) {
self().setAddress(newAddress);
update();
}
return true;
}
if(scancode == GDK_Page_Up) {
signed newOffset = state().offset - state().columns * state().rows;
if(newOffset >= 0) {
self().setOffset(newOffset);
signed newAddress = state().address - state().columns * state().rows;
if(newAddress >= 0) {
self().setAddress(newAddress);
} else {
self().setOffset(0);
self().setAddress(0);
}
update();
return true;
}
if(scancode == GDK_Page_Down) {
signed newOffset = state().offset + state().columns * state().rows;
signed newAddress = state().address + state().columns * state().rows;
for(auto n : range(state().rows)) {
if(newOffset + state().columns * state().rows - (state().columns - 1) <= state().length) {
self().setOffset(newOffset);
if(newAddress + state().columns * state().rows - (state().columns - 1) <= state().length) {
self().setAddress(newAddress);
update();
break;
}
newOffset -= state().columns;
newAddress -= state().columns;
}
return true;
}
@ -238,10 +238,10 @@ auto pHexEdit::keyPress(unsigned scancode, unsigned mask) -> bool {
cursorX /= 3;
if(cursorX < state().columns) {
//not in ANSI region
unsigned offset = state().offset + (cursorY * state().columns + cursorX);
unsigned address = state().address + (cursorY * state().columns + cursorX);
if(offset >= state().length) return false; //do not edit past end of data
uint8_t data = self().doRead(offset);
if(address >= state().length) return false; //do not edit past end of data
uint8_t data = self().doRead(address);
//write modified value
if(cursorNibble == 1) {
@ -249,7 +249,7 @@ auto pHexEdit::keyPress(unsigned scancode, unsigned mask) -> bool {
} else {
data = (data & 0x0f) | (scancode << 4);
}
self().doWrite(offset, data);
self().doWrite(address, data);
//auto-advance cursor to next nibble/byte
position++;
@ -278,7 +278,7 @@ auto pHexEdit::rowsScrollable() -> signed {
auto pHexEdit::scroll(signed position) -> void {
if(position > rowsScrollable()) position = rowsScrollable();
if(position < 0) position = 0;
self().setOffset(position * state().columns);
self().setAddress(position * state().columns);
}
auto pHexEdit::setCursorPosition(unsigned position) -> void {
@ -304,7 +304,7 @@ auto pHexEdit::setScroll() -> void {
}
auto pHexEdit::updateScroll() -> void {
unsigned row = state().offset / state().columns;
unsigned row = state().address / state().columns;
gtk_range_set_value(GTK_RANGE(scrollBar), row);
}

View File

@ -6,11 +6,11 @@ struct pHexEdit : pWidget {
Declare(HexEdit, Widget)
auto focused() const -> bool override;
auto setAddress(unsigned address) -> void;
auto setBackgroundColor(Color color) -> void;
auto setColumns(unsigned columns) -> void;
auto setForegroundColor(Color color) -> void;
auto setLength(unsigned length) -> void;
auto setOffset(unsigned offset) -> void;
auto setRows(unsigned rows) -> void;
auto update() -> void;

View File

@ -116,7 +116,7 @@ auto pIconView::setGeometry(Geometry geometry) -> void {
}
auto pIconView::setItemIcon(unsigned position, const image& icon) -> void {
if(position >= self().items()) return;
if(position >= self().itemCount()) return;
GtkTreeIter iter;
if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{position})) {
if(icon) {
@ -129,7 +129,7 @@ auto pIconView::setItemIcon(unsigned position, const image& icon) -> void {
}
auto pIconView::setItemSelected(unsigned position, bool selected) -> void {
if(position >= self().items()) return;
if(position >= self().itemCount()) return;
lock();
GtkTreePath* path = gtk_tree_path_new_from_string(string{position});
if(selected) {
@ -165,7 +165,7 @@ auto pIconView::setItemSelectedNone() -> void {
}
auto pIconView::setItemText(unsigned position, const string& text) -> void {
if(position >= self().items()) return;
if(position >= self().itemCount()) return;
GtkTreeIter iter;
if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{position})) {
gtk_list_store_set(store, &iter, 1, (const char*)text, -1);
@ -216,7 +216,7 @@ auto pIconView::_updateSelected() -> void {
currentSelection = selected;
for(auto& item : state().items) item->state.selected = false;
for(auto& position : currentSelection) {
if(position >= self().items()) continue;
if(position >= self().itemCount()) continue;
state().items[position]->state.selected = true;
}

View File

@ -5,7 +5,7 @@ namespace hiro {
auto pLabel::construct() -> void {
gtkWidget = gtk_label_new("");
_setAlignment();
setAlignment(state().alignment);
setText(state().text);
pWidget::construct();
@ -16,30 +16,23 @@ auto pLabel::destruct() -> void {
}
auto pLabel::minimumSize() const -> Size {
Size size = pFont::size(self().font(true), state().text);
auto size = pFont::size(self().font(true), state().text);
return {size.width(), size.height()};
}
auto pLabel::setHorizontalAlignment(double alignment) -> void {
_setAlignment();
auto pLabel::setAlignment(Alignment alignment) -> void {
if(!alignment) alignment = {0.0, 0.5};
gtk_misc_set_alignment(GTK_MISC(gtkWidget), alignment.horizontal(), alignment.vertical());
auto justify = GTK_JUSTIFY_CENTER;
if(alignment.horizontal() < 0.333) justify = GTK_JUSTIFY_LEFT;
if(alignment.horizontal() > 0.666) justify = GTK_JUSTIFY_RIGHT;
gtk_label_set_justify(GTK_LABEL(gtkWidget), justify);
}
auto pLabel::setText(const string& text) -> void {
gtk_label_set_text(GTK_LABEL(gtkWidget), text);
}
auto pLabel::setVerticalAlignment(double alignment) -> void {
_setAlignment();
}
auto pLabel::_setAlignment() -> void {
gtk_misc_set_alignment(GTK_MISC(gtkWidget), state().horizontalAlignment, state().verticalAlignment);
auto justify = GTK_JUSTIFY_CENTER;
if(state().horizontalAlignment < 0.333) justify = GTK_JUSTIFY_LEFT;
if(state().horizontalAlignment > 0.666) justify = GTK_JUSTIFY_RIGHT;
gtk_label_set_justify(GTK_LABEL(gtkWidget), justify);
}
}
#endif

View File

@ -6,11 +6,8 @@ struct pLabel : pWidget {
Declare(Label, Widget)
auto minimumSize() const -> Size override;
auto setHorizontalAlignment(double alignment) -> void;
auto setAlignment(Alignment alignment) -> void;
auto setText(const string& text) -> void;
auto setVerticalAlignment(double alignment) -> void;
auto _setAlignment() -> void;
};
}

View File

@ -3,36 +3,58 @@
namespace hiro {
auto pListViewCell::construct() -> void {
_setState();
}
auto pListViewCell::destruct() -> void {
}
auto pListViewCell::setAlignment(Alignment alignment) -> void {
}
auto pListViewCell::setBackgroundColor(Color color) -> void {
}
auto pListViewCell::setCheckable(bool checkable) -> void {
}
auto pListViewCell::setChecked(bool checked) -> void {
_setState();
}
auto pListViewCell::setForegroundColor(Color color) -> void {
}
auto pListViewCell::setIcon(const image& icon) -> void {
if(auto item = _parent()) {
if(auto view = item->_parent()) {
gtk_list_store_set(view->gtkListStore, &item->gtkIter, 1 + self().offset() * 2, CreatePixbuf(icon), -1);
}
}
_setState();
}
auto pListViewCell::setText(const string& text) -> void {
if(auto item = _parent()) {
if(auto view = item->_parent()) {
gtk_list_store_set(view->gtkListStore, &item->gtkIter, 1 + self().offset() * 2 + 1, text.data(), -1);
}
}
_setState();
}
auto pListViewCell::_parent() -> pListViewItem* {
if(auto parent = self().parentListViewItem()) return parent->self();
return nullptr;
auto pListViewCell::_grandparent() -> maybe<pListView&> {
if(auto parent = _parent()) return parent->_parent();
return nothing;
}
auto pListViewCell::_parent() -> maybe<pListViewItem&> {
if(auto parent = self().parentListViewItem()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pListViewCell::_setState() -> void {
if(auto parent = _parent()) {
if(auto grandparent = _grandparent()) {
grandparent->lock();
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 0, state().checked, -1);
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 1, CreatePixbuf(state().icon), -1);
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 2, state().text.data(), -1);
grandparent->unlock();
}
}
}
}

View File

@ -5,12 +5,17 @@ namespace hiro {
struct pListViewCell : pObject {
Declare(ListViewCell, Object)
auto setAlignment(Alignment alignment) -> void;
auto setBackgroundColor(Color color) -> void;
auto setCheckable(bool checkable) -> void;
auto setChecked(bool checked) -> void;
auto setForegroundColor(Color color) -> void;
auto setIcon(const image& icon) -> void;
auto setText(const string& text) -> void;
auto _parent() -> pListViewItem*;
auto _grandparent() -> maybe<pListView&>;
auto _parent() -> maybe<pListViewItem&>;
auto _setState() -> void;
};
}

View File

@ -3,91 +3,82 @@
namespace hiro {
auto pListViewColumn::construct() -> void {
unsigned offset = self().offset();
if(auto grandparent = _grandparent()) {
auto handle = grandparent.data();
unsigned offset = self().offset();
gtkHeader = gtk_hbox_new(false, 0);
gtkHeader = gtk_hbox_new(false, 0);
gtkHeaderIcon = gtk_image_new();
gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderIcon, false, false, 0);
gtkHeaderIcon = gtk_image_new();
gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderIcon, false, false, 0);
gtkHeaderText = gtk_label_new(state().text);
gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderText, true, false, 2);
gtkHeaderText = gtk_label_new(state().text);
gtk_box_pack_start(GTK_BOX(gtkHeader), gtkHeaderText, true, false, 2);
gtkColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_sizing(gtkColumn, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_title(gtkColumn, "");
gtk_tree_view_column_set_widget(gtkColumn, gtkHeader);
gtkColumn = gtk_tree_view_column_new();
gtk_tree_view_column_set_sizing(gtkColumn, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_title(gtkColumn, "");
gtk_tree_view_column_set_widget(gtkColumn, gtkHeader);
if(offset == 0) {
gtkCellToggle = gtk_cell_renderer_toggle_new();
gtk_tree_view_column_pack_start(gtkColumn, gtkCellToggle, false);
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellToggle, "active", 0, nullptr);
gtk_tree_view_column_set_cell_data_func(gtkColumn, GTK_CELL_RENDERER(gtkCellToggle), (GtkTreeCellDataFunc)ListView_cellRendererToggleDataFunc, (gpointer)_parent(), nullptr);
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellToggle, "active", 3 * offset + 0, nullptr);
gtk_tree_view_column_set_cell_data_func(gtkColumn, GTK_CELL_RENDERER(gtkCellToggle), (GtkTreeCellDataFunc)ListView_dataFunc, (gpointer)handle, nullptr);
gtkCellIcon = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(gtkColumn, gtkCellIcon, false);
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellIcon, "pixbuf", 3 * offset + 1, nullptr);
gtk_tree_view_column_set_cell_data_func(gtkColumn, GTK_CELL_RENDERER(gtkCellIcon), (GtkTreeCellDataFunc)ListView_dataFunc, (gpointer)handle, nullptr);
gtkCellText = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(gtkColumn, gtkCellText, true); //text must expand to cell width for horizontal alignment to work
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellText, "text", 3 * offset + 2, nullptr);
gtk_tree_view_column_set_cell_data_func(gtkColumn, GTK_CELL_RENDERER(gtkCellText), (GtkTreeCellDataFunc)ListView_dataFunc, (gpointer)handle, nullptr);
g_signal_connect(G_OBJECT(gtkColumn), "clicked", G_CALLBACK(ListView_headerActivate), (gpointer)handle);
g_signal_connect(G_OBJECT(gtkCellText), "edited", G_CALLBACK(ListView_edit), (gpointer)handle);
g_signal_connect(G_OBJECT(gtkCellToggle), "toggled", G_CALLBACK(ListView_toggle), (gpointer)handle);
gtk_tree_view_append_column(grandparent->gtkTreeView, gtkColumn);
gtk_widget_show_all(gtkHeader);
grandparent->_createModel();
_setState();
}
gtkCellIcon = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(gtkColumn, gtkCellIcon, false);
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellIcon, "pixbuf", 1 + offset * 2 + 0, nullptr);
gtkCellText = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start(gtkColumn, gtkCellText, false);
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellText, "text", 1 + offset * 2 + 1, nullptr);
g_signal_connect(G_OBJECT(gtkColumn), "clicked", G_CALLBACK(ListView_headerActivate), (gpointer)_parent());
g_signal_connect(G_OBJECT(gtkCellText), "edited", G_CALLBACK(ListView_edit), (gpointer)_parent());
if(gtkCellToggle) g_signal_connect(G_OBJECT(gtkCellToggle), "toggled", G_CALLBACK(ListView_toggle), (gpointer)_parent());
}
auto pListViewColumn::destruct() -> void {
if(auto grandparent = _grandparent()) {
gtk_tree_view_remove_column(grandparent->gtkTreeView, gtkColumn);
gtkColumn = nullptr;
grandparent->_createModel();
}
}
auto pListViewColumn::setActive() -> void {
if(auto parent = _parent()) {
gtk_tree_view_set_search_column(parent->gtkTreeView, 1 + self().offset() * 2 + 1);
}
_setState();
}
auto pListViewColumn::setAlignment(Alignment alignment) -> void {
}
auto pListViewColumn::setBackgroundColor(Color color) -> void {
if(color) {
GdkColor gdkColor = CreateColor(color);
if(gtkCellToggle) g_object_set(G_OBJECT(gtkCellToggle), "cell-background-gdk", &gdkColor, nullptr);
g_object_set(G_OBJECT(gtkCellIcon), "cell-background-gdk", &gdkColor, nullptr);
g_object_set(G_OBJECT(gtkCellText), "cell-background-gdk", &gdkColor, nullptr);
} else {
if(gtkCellToggle) g_object_set(G_OBJECT(gtkCellToggle), "cell-background-set", FALSE, nullptr);
g_object_set(G_OBJECT(gtkCellIcon), "cell-background-set", FALSE, nullptr);
g_object_set(G_OBJECT(gtkCellText), "cell-background-set", FALSE, nullptr);
}
}
auto pListViewColumn::setEditable(bool editable) -> void {
g_object_set(G_OBJECT(gtkCellText), "editable", editable ? TRUE : FALSE, nullptr);
g_object_set(G_OBJECT(gtkCellText), "editable", editable ? true : false, nullptr);
}
auto pListViewColumn::setExpandable(bool expandable) -> void {
if(auto parent = _parent()) {
parent->resizeColumns();
if(auto grandparent = _grandparent()) {
grandparent->resizeColumns();
}
}
auto pListViewColumn::setFont(const string& font) -> void {
pFont::setFont(gtkHeaderText, font);
auto fontDescription = pFont::create(font);
g_object_set(G_OBJECT(gtkCellText), "font-desc", fontDescription, nullptr);
pango_font_description_free(fontDescription);
}
auto pListViewColumn::setForegroundColor(Color color) -> void {
if(color) {
GdkColor gdkColor = CreateColor(color);
g_object_set(G_OBJECT(gtkCellText), "foreground-gdk", &gdkColor, nullptr);
} else {
g_object_set(G_OBJECT(gtkCellText), "foreground-set", FALSE, nullptr);
}
}
auto pListViewColumn::setHorizontalAlignment(double alignment) -> void {
_setAlignment();
}
auto pListViewColumn::setIcon(const image& icon) -> void {
@ -99,40 +90,47 @@ auto pListViewColumn::setIcon(const image& icon) -> void {
}
auto pListViewColumn::setResizable(bool resizable) -> void {
gtk_tree_view_column_set_resizable(gtkColumn, resizable);
_setState();
}
auto pListViewColumn::setSortable(bool sortable) -> void {
_setState();
}
auto pListViewColumn::setText(const string& text) -> void {
gtk_label_set_text(GTK_LABEL(gtkHeaderText), text);
}
auto pListViewColumn::setVerticalAlignment(double alignment) -> void {
_setAlignment();
_setState();
}
auto pListViewColumn::setVisible(bool visible) -> void {
gtk_tree_view_column_set_visible(gtkColumn, visible);
_setState();
}
auto pListViewColumn::setWidth(signed width) -> void {
if(auto parent = _parent()) {
parent->resizeColumns();
if(auto grandparent = _grandparent()) {
grandparent->resizeColumns();
}
}
auto pListViewColumn::_parent() -> pListView* {
if(auto parent = self().parentListView()) return parent->self();
return nullptr;
auto pListViewColumn::_grandparent() -> maybe<pListView&> {
if(auto parent = _parent()) return parent->_parent();
return nothing;
}
auto pListViewColumn::_setAlignment() -> void {
gtk_tree_view_column_set_alignment(gtkColumn, state().horizontalAlignment);
gtk_cell_renderer_set_alignment(GTK_CELL_RENDERER(gtkCellText), state().horizontalAlignment, state().verticalAlignment);
//set multi-line text alignment
auto pangoAlignment = PANGO_ALIGN_CENTER;
if(state().horizontalAlignment < 0.333) pangoAlignment = PANGO_ALIGN_LEFT;
if(state().horizontalAlignment > 0.666) pangoAlignment = PANGO_ALIGN_RIGHT;
g_object_set(G_OBJECT(gtkCellText), "alignment", pangoAlignment, nullptr);
auto pListViewColumn::_parent() -> maybe<pListViewHeader&> {
if(auto parent = self().parentListViewHeader()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pListViewColumn::_setState() -> void {
if(auto grandparent = _grandparent()) {
gtk_tree_view_set_search_column(grandparent->gtkTreeView, 3 * self().offset() + 2);
gtk_tree_view_column_set_resizable(gtkColumn, state().resizable);
gtk_tree_view_column_set_clickable(gtkColumn, state().sortable);
gtk_label_set_text(GTK_LABEL(gtkHeaderText), state().text);
gtk_tree_view_column_set_visible(gtkColumn, self().visible());
}
}
}

View File

@ -6,21 +6,24 @@ struct pListViewColumn : pObject {
Declare(ListViewColumn, Object)
auto setActive() -> void;
auto setAlignment(Alignment alignment) -> void;
auto setBackgroundColor(Color color) -> void;
auto setEditable(bool editable) -> void;
auto setExpandable(bool expandable) -> void;
auto setFont(const string& font) -> void override;
auto setForegroundColor(Color color) -> void;
auto setHorizontalAlignment(double alignment) -> void;
auto setHorizontalAlignment(double) -> void {}
auto setIcon(const image& icon) -> void;
auto setResizable(bool resizable) -> void;
auto setSortable(bool sortable) -> void;
auto setText(const string& text) -> void;
auto setVerticalAlignment(double alignment) -> void;
auto setVerticalAlignment(double) -> void {}
auto setVisible(bool visible) -> void override;
auto setWidth(signed width) -> void;
auto _parent() -> pListView*;
auto _setAlignment() -> void;
auto _grandparent() -> maybe<pListView&>;
auto _parent() -> maybe<pListViewHeader&>;
auto _setState() -> void;
GtkTreeViewColumn* gtkColumn = nullptr;
GtkWidget* gtkHeader = nullptr;

View File

@ -0,0 +1,41 @@
#if defined(Hiro_ListView)
namespace hiro {
auto pListViewHeader::construct() -> void {
_setState();
}
auto pListViewHeader::destruct() -> void {
}
auto pListViewHeader::append(sListViewColumn column) -> void {
_setState();
}
auto pListViewHeader::remove(sListViewColumn column) -> void {
}
auto pListViewHeader::setVisible(bool visible) -> void {
_setState();
}
auto pListViewHeader::_parent() -> maybe<pListView&> {
if(auto parent = self().parentListView()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pListViewHeader::_setState() -> void {
if(auto parent = _parent()) {
gtk_tree_view_set_headers_visible(parent->gtkTreeView, self().visible());
for(auto& column : state().columns) {
if(auto self = column->self()) self->_setState();
}
}
}
}
#endif

View File

@ -0,0 +1,18 @@
#if defined(Hiro_ListView)
namespace hiro {
struct pListViewHeader : pObject {
Declare(ListViewHeader, Object)
auto append(sListViewColumn column) -> void;
auto remove(sListViewColumn column) -> void;
auto setVisible(bool visible) -> void override;
auto _parent() -> maybe<pListView&>;
auto _setState() -> void;
};
}
#endif

View File

@ -3,9 +3,21 @@
namespace hiro {
auto pListViewItem::construct() -> void {
if(auto parent = _parent()) {
parent->lock();
gtk_list_store_append(parent->gtkListStore, &gtkIter);
_setState();
parent->unlock();
}
}
auto pListViewItem::destruct() -> void {
if(auto parent = _parent()) {
parent->lock();
gtk_list_store_remove(parent->gtkListStore, &gtkIter);
parent->_updateSelected();
parent->unlock();
}
}
auto pListViewItem::append(sListViewCell cell) -> void {
@ -14,18 +26,12 @@ auto pListViewItem::append(sListViewCell cell) -> void {
auto pListViewItem::remove(sListViewCell cell) -> void {
}
auto pListViewItem::setAlignment(Alignment alignment) -> void {
}
auto pListViewItem::setBackgroundColor(Color color) -> void {
}
auto pListViewItem::setCheckable(bool checkable) -> void {
}
auto pListViewItem::setChecked(bool checked) -> void {
if(auto parent = _parent()) {
gtk_list_store_set(parent->gtkListStore, &gtkIter, 0, checked, -1);
}
}
auto pListViewItem::setFocused() -> void {
if(auto parent = _parent()) {
GtkTreePath* path = gtk_tree_path_new_from_string(string{self().offset()});
@ -39,23 +45,32 @@ auto pListViewItem::setForegroundColor(Color color) -> void {
}
auto pListViewItem::setSelected(bool selected) -> void {
_setState();
}
auto pListViewItem::_parent() -> maybe<pListView&> {
if(auto parent = self().parentListView()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pListViewItem::_setState() -> void {
if(auto parent = _parent()) {
parent->lock();
if(selected) {
if(state().selected) {
gtk_tree_selection_select_iter(parent->gtkTreeSelection, &gtkIter);
} else {
gtk_tree_selection_unselect_iter(parent->gtkTreeSelection, &gtkIter);
}
parent->_updateSelected();
for(auto& cell : state().cells) {
if(auto self = cell->self()) self->_setState();
}
parent->unlock();
}
}
auto pListViewItem::_parent() -> pListView* {
if(auto parent = self().parentListView()) return parent->self();
return nullptr;
}
}
#endif

View File

@ -7,14 +7,14 @@ struct pListViewItem : pObject {
auto append(sListViewCell cell) -> void;
auto remove(sListViewCell cell) -> void;
auto setAlignment(Alignment alignment) -> void;
auto setBackgroundColor(Color color) -> void;
auto setCheckable(bool checkable) -> void;
auto setChecked(bool checked) -> void;
auto setFocused() -> void;
auto setForegroundColor(Color color) -> void;
auto setSelected(bool selected) -> void;
auto _parent() -> pListView*;
auto _parent() -> maybe<pListView&>;
auto _setState() -> void;
GtkTreeIter gtkIter;
};

View File

@ -10,8 +10,10 @@ static auto ListView_headerActivate(GtkTreeViewColumn* column, pListView* p) ->
static auto ListView_mouseMoveEvent(GtkWidget*, GdkEvent*, pListView* p) -> signed { return p->_doMouseMove(); }
static auto ListView_popup(GtkTreeView*, pListView* p) -> void { return p->_doContext(); }
static auto ListView_cellRendererToggleDataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, pListView* p) -> void { return p->_doCellRendererToggleDataFunc(renderer, iter); }
static auto ListView_toggle(GtkCellRendererToggle*, const char* path, pListView* p) -> void { return p->_doToggle(path); }
static auto ListView_dataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, pListView* p) -> void { return p->_doDataFunc(column, renderer, iter); }
static auto ListView_toggle(GtkCellRendererToggle* toggle, const char* path, pListView* p) -> void { return p->_doToggle(toggle, path); }
//gtk_tree_view_set_rules_hint(gtkTreeView, true);
auto pListView::construct() -> void {
gtkWidget = gtk_scrolled_window_new(0, 0);
@ -29,12 +31,9 @@ auto pListView::construct() -> void {
setBackgroundColor(state().backgroundColor);
setBatchable(state().batchable);
setCheckable(state().checkable);
setBordered(state().bordered);
setFont(self().font(true));
setForegroundColor(state().foregroundColor);
setGridVisible(state().gridVisible);
setHeaderVisible(state().headerVisible);
setSortable(state().sortable);
g_signal_connect(G_OBJECT(gtkTreeView), "button-press-event", G_CALLBACK(ListView_buttonEvent), (gpointer)this);
g_signal_connect(G_OBJECT(gtkTreeView), "button-release-event", G_CALLBACK(ListView_buttonEvent), (gpointer)this);
@ -51,68 +50,25 @@ auto pListView::destruct() -> void {
gtk_widget_destroy(gtkWidget);
}
auto pListView::append(sListViewColumn column) -> void {
gtk_tree_view_append_column(gtkTreeView, column->self()->gtkColumn);
gtk_widget_show_all(column->self()->gtkHeader);
column->setBackgroundColor(column->backgroundColor());
column->setEditable(column->editable());
column->setFont(column->font());
column->setForegroundColor(column->foregroundColor());
column->setHorizontalAlignment(column->horizontalAlignment());
column->setResizable(column->resizable());
column->setVerticalAlignment(column->verticalAlignment());
setCheckable(state().checkable);
setSortable(state().sortable);
_createModel();
resizeColumns();
gtk_tree_view_set_rules_hint(gtkTreeView, self().columns() >= 2); //two or more columns + checkbutton column
auto pListView::append(sListViewHeader header) -> void {
}
auto pListView::append(sListViewItem item) -> void {
gtk_list_store_append(gtkListStore, &item->self()->gtkIter);
item->setChecked(item->checked());
item->setSelected(item->selected());
for(auto column : range(self().columns())) {
if(auto cell = item->cell(column)) {
if(auto self = cell->self()) {
self->setIcon(cell->state.icon);
self->setText(cell->state.text);
}
}
}
}
auto pListView::checkAll() -> void {
for(auto& item : state().items) {
if(auto delegate = item->self()) delegate->setChecked(true);
}
}
auto pListView::focused() -> bool {
auto pListView::focused() const -> bool {
return GTK_WIDGET_HAS_FOCUS(gtkTreeView);
}
auto pListView::remove(sListViewColumn column) -> void {
if(auto delegate = column->self()) {
gtk_tree_view_remove_column(gtkTreeView, delegate->gtkColumn);
delegate->gtkColumn = nullptr;
}
_createModel();
gtk_tree_view_set_rules_hint(gtkTreeView, self().columns() >= 2); //two or more columns + checkbutton column
auto pListView::remove(sListViewHeader header) -> void {
}
auto pListView::remove(sListViewItem item) -> void {
lock();
if(auto delegate = item->self()) {
gtk_list_store_remove(gtkListStore, &delegate->gtkIter);
_updateSelected();
}
unlock();
}
auto pListView::reset() -> void {
GList* list = gtk_tree_view_get_columns(gtkTreeView), *p = list;
GList* list = gtk_tree_view_get_columns(gtkTreeView);
GList* p = list;
while(p && p->data) {
gtk_tree_view_remove_column(gtkTreeView, (GtkTreeViewColumn*)p->data);
p = p->next;
@ -125,41 +81,40 @@ auto pListView::reset() -> void {
auto pListView::resizeColumns() -> void {
lock();
vector<signed> widths;
signed minimumWidth = 0;
signed expandable = 0;
for(auto column : range(state().columns)) {
signed width = _width(column);
widths.append(width);
minimumWidth += width;
if(state().columns[column]->expandable()) expandable++;
}
if(auto& header = state().header) {
vector<signed> widths;
signed minimumWidth = 0;
signed expandable = 0;
for(auto column : range(header->columnCount())) {
signed width = _width(column);
widths.append(width);
minimumWidth += width;
if(header->column(column).expandable()) expandable++;
}
signed maximumWidth = self().geometry().width() - 6;
if(auto scrollBar = gtk_scrolled_window_get_vscrollbar(gtkScrolledWindow)) {
if(gtk_widget_get_visible(scrollBar)) maximumWidth -= scrollBar->allocation.width;
}
signed maximumWidth = self().geometry().width() - 6;
if(auto scrollBar = gtk_scrolled_window_get_vscrollbar(gtkScrolledWindow)) {
if(gtk_widget_get_visible(scrollBar)) maximumWidth -= scrollBar->allocation.width;
}
signed expandWidth = 0;
if(expandable && maximumWidth > minimumWidth) {
expandWidth = (maximumWidth - minimumWidth) / expandable;
}
signed expandWidth = 0;
if(expandable && maximumWidth > minimumWidth) {
expandWidth = (maximumWidth - minimumWidth) / expandable;
}
for(auto column : range(state().columns)) {
if(auto self = state().columns[column]->self()) {
signed width = widths[column];
if(self->state().expandable) width += expandWidth;
gtk_tree_view_column_set_fixed_width(self->gtkColumn, width);
for(auto column : range(header->columnCount())) {
if(auto self = header->state.columns[column]->self()) {
signed width = widths[column];
if(self->state().expandable) width += expandWidth;
gtk_tree_view_column_set_fixed_width(self->gtkColumn, width);
}
}
}
unlock();
}
auto pListView::selectAll() -> void {
for(auto& item : state().items) {
if(auto delegate = item->self()) delegate->setSelected(true);
}
auto pListView::setAlignment(Alignment alignment) -> void {
}
auto pListView::setBackgroundColor(Color color) -> void {
@ -171,10 +126,8 @@ auto pListView::setBatchable(bool batchable) -> void {
gtk_tree_selection_set_mode(gtkTreeSelection, batchable ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE);
}
auto pListView::setCheckable(bool checkable) -> void {
if(auto delegate = _column(0)) {
gtk_cell_renderer_set_visible(delegate->gtkCellToggle, checkable);
}
auto pListView::setBordered(bool bordered) -> void {
gtk_tree_view_set_grid_lines(gtkTreeView, bordered ? GTK_TREE_VIEW_GRID_LINES_BOTH : GTK_TREE_VIEW_GRID_LINES_NONE);
}
auto pListView::setFocused() -> void {
@ -182,8 +135,8 @@ auto pListView::setFocused() -> void {
}
auto pListView::setFont(const string& font) -> void {
for(auto& column : state().columns) {
if(auto delegate = column->self()) delegate->setFont(column->font(true));
if(auto& header = state().header) {
if(auto self = header->self()) self->_setState();
}
}
@ -192,39 +145,22 @@ auto pListView::setForegroundColor(Color color) -> void {
gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
}
auto pListView::setGridVisible(bool visible) -> void {
gtk_tree_view_set_grid_lines(gtkTreeView, visible ? GTK_TREE_VIEW_GRID_LINES_BOTH : GTK_TREE_VIEW_GRID_LINES_NONE);
}
auto pListView::setHeaderVisible(bool visible) -> void {
gtk_tree_view_set_headers_visible(gtkTreeView, visible);
}
auto pListView::setSortable(bool sortable) -> void {
for(auto& column : state().columns) {
if(auto delegate = column->self()) {
gtk_tree_view_column_set_clickable(delegate->gtkColumn, sortable);
auto pListView::setGeometry(Geometry geometry) -> void {
pWidget::setGeometry(geometry);
if(auto& header = state().header) {
for(auto& column : header->state.columns) {
if(column->state.expandable) return resizeColumns();
}
}
}
auto pListView::uncheckAll() -> void {
for(auto& item : state().items) {
if(auto delegate = item->self()) delegate->setChecked(false);
}
}
auto pListView::unselectAll() -> void {
for(auto& item : state().items) {
if(auto delegate = item->self()) delegate->setSelected(false);
}
}
auto pListView::_cellWidth(unsigned _row, unsigned _column) -> unsigned {
unsigned width = 8; //margin
if(state().checkable && _column == 0) width += 32; //checkbox
unsigned width = 8;
if(auto item = self().item(_row)) {
if(auto cell = item->cell(_column)) {
if(cell->state.checkable) {
width += 32;
}
if(auto& icon = cell->state.icon) {
width += icon.width() + 2;
}
@ -236,19 +172,16 @@ auto pListView::_cellWidth(unsigned _row, unsigned _column) -> unsigned {
return width;
}
auto pListView::_column(unsigned column) -> pListViewColumn* {
if(auto delegate = self().column(column)) return delegate->self();
return nullptr;
}
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;
}
if(auto& text = column->state.text) {
width += Font::size(column->font(true), text).width();
unsigned width = 8;
if(auto& header = state().header) {
if(auto column = header->column(_column)) {
if(auto& icon = column->state.icon) {
width += icon.width() + 2;
}
if(auto& text = column->state.text) {
width += Font::size(column->font(true), text).width();
}
}
}
return width;
@ -260,12 +193,15 @@ auto pListView::_createModel() -> void {
gtkTreeModel = nullptr;
vector<GType> types;
unsigned position = 0;
for(auto column : state().columns) {
if(!column->self()->gtkColumn) continue; //column is being removed
if(position++ == 0) types.append(G_TYPE_BOOLEAN);
types.append(GDK_TYPE_PIXBUF);
types.append(G_TYPE_STRING);
if(auto& header = state().header) {
for(auto column : header->state.columns) {
if(auto self = column->self()) {
if(!self->gtkColumn) continue; //may not have been created yet; or recently destroyed
types.append(G_TYPE_BOOLEAN);
types.append(GDK_TYPE_PIXBUF);
types.append(G_TYPE_STRING);
}
}
}
if(!types) return; //no columns available
@ -278,15 +214,6 @@ auto pListView::_doActivate() -> void {
if(!locked()) self().doActivate();
}
auto pListView::_doCellRendererToggleDataFunc(GtkCellRenderer* renderer, GtkTreeIter* iter) -> void {
auto path = gtk_tree_model_get_string_from_iter(gtkTreeModel, iter);
auto row = decimal(path);
if(auto item = self().item(row)) {
gtk_cell_renderer_set_visible(renderer, state().checkable && item->state.checkable);
}
g_free(path);
}
auto pListView::_doChange() -> void {
if(!locked()) _updateSelected();
}
@ -295,18 +222,70 @@ auto pListView::_doContext() -> void {
if(!locked()) self().doContext();
}
auto pListView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* path, const char* text) -> void {
for(auto& column : state().columns) {
if(auto delegate = column->self()) {
if(gtkCellRendererText == GTK_CELL_RENDERER_TEXT(delegate->gtkCellText)) {
auto row = decimal(path);
auto pListView::_doDataFunc(GtkTreeViewColumn* gtkColumn, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void {
auto path = gtk_tree_model_get_string_from_iter(gtkTreeModel, iter);
auto row = decimal(path);
g_free(path);
if(auto& header = state().header) {
for(auto& column : header->state.columns) {
if(auto p = column->self()) {
if(renderer != GTK_CELL_RENDERER(p->gtkCellToggle)
&& renderer != GTK_CELL_RENDERER(p->gtkCellIcon)
&& renderer != GTK_CELL_RENDERER(p->gtkCellText)
) continue;
if(auto item = self().item(row)) {
if(auto cell = item->cell(column->offset())) {
if(string{text} != cell->state.text) {
cell->setText(text);
if(!locked()) self().doEdit(cell);
if(renderer == GTK_CELL_RENDERER(p->gtkCellToggle)) {
gtk_cell_renderer_set_visible(renderer, cell->state.checkable);
} else if(renderer == GTK_CELL_RENDERER(p->gtkCellText)) {
auto alignment = cell->alignment(true);
if(!alignment) alignment = {0.0, 0.5};
//note: below line will center column header text; but causes strange glitches
//(specifically, windows fail to respond to the close button ... some kind of heap corruption inside GTK+)
//gtk_tree_view_column_set_alignment(gtkColumn, alignment.horizontal());
gtk_cell_renderer_set_alignment(renderer, alignment.horizontal(), alignment.vertical());
auto pangoAlignment = PANGO_ALIGN_CENTER;
if(alignment.horizontal() < 0.333) pangoAlignment = PANGO_ALIGN_LEFT;
if(alignment.horizontal() > 0.666) pangoAlignment = PANGO_ALIGN_RIGHT;
g_object_set(G_OBJECT(renderer), "alignment", pangoAlignment, nullptr);
auto font = pFont::create(cell->font(true));
g_object_set(G_OBJECT(renderer), "font-desc", font, nullptr);
pango_font_description_free(font);
if(auto color = cell->foregroundColor(true)) {
auto gdkColor = CreateColor(color);
g_object_set(G_OBJECT(renderer), "foreground-gdk", &gdkColor, nullptr);
} else {
g_object_set(G_OBJECT(renderer), "foreground-set", false, nullptr);
}
}
if(auto color = cell->backgroundColor(true)) {
auto gdkColor = CreateColor(color);
g_object_set(G_OBJECT(renderer), "cell-background-gdk", &gdkColor, nullptr);
} else {
g_object_set(G_OBJECT(renderer), "cell-background-set", false, nullptr);
}
}
}
}
}
}
}
auto pListView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* path, const char* text) -> void {
if(auto& header = state().header) {
for(auto& column : header->state.columns) {
if(auto delegate = column->self()) {
if(gtkCellRendererText == GTK_CELL_RENDERER_TEXT(delegate->gtkCellText)) {
auto row = decimal(path);
if(auto item = self().item(row)) {
if(auto cell = item->cell(column->offset())) {
if(string{text} != cell->state.text) {
cell->setText(text);
if(!locked()) self().doEdit(cell);
}
return;
}
return;
}
}
}
@ -322,7 +301,7 @@ auto pListView::_doEvent(GdkEventButton* event) -> signed {
//when clicking in empty space below the last list view item; GTK+ does not deselect all items;
//below code enables this functionality, to match behavior with all other UI toolkits (and because it's very convenient to have)
if(path == nullptr && gtk_tree_selection_count_selected_rows(gtkTreeSelection) > 0) {
self().unselectAll();
for(auto& item : state().items) item->setSelected(false);
self().doChange();
return true;
}
@ -344,11 +323,13 @@ auto pListView::_doEvent(GdkEventButton* event) -> signed {
}
auto pListView::_doHeaderActivate(GtkTreeViewColumn* gtkTreeViewColumn) -> void {
for(auto& column : state().columns) {
if(auto delegate = column->self()) {
if(gtkTreeViewColumn == delegate->gtkColumn) {
if(!locked()) self().doSort(column);
return;
if(auto& header = state().header) {
for(auto& column : header->state.columns) {
if(auto delegate = column->self()) {
if(gtkTreeViewColumn == delegate->gtkColumn) {
if(!locked()) self().doSort(column);
return;
}
}
}
}
@ -363,12 +344,21 @@ auto pListView::_doMouseMove() -> signed {
return false;
}
auto pListView::_doToggle(const char* path) -> void {
if(auto item = self().item(decimal(path))) {
if(auto delegate = item->self()) {
item->state.checked = !item->state.checked;
delegate->setChecked(item->state.checked);
if(!locked()) self().doToggle(item);
auto pListView::_doToggle(GtkCellRendererToggle* gtkCellRendererToggle, const char* path) -> void {
if(auto& header = state().header) {
for(auto& column : header->state.columns) {
if(auto delegate = column->self()) {
if(gtkCellRendererToggle == GTK_CELL_RENDERER_TOGGLE(delegate->gtkCellToggle)) {
auto row = decimal(path);
if(auto item = self().item(row)) {
if(auto cell = item->cell(column->offset())) {
cell->setChecked(!cell->checked());
if(!locked()) self().doToggle(cell);
return;
}
}
}
}
}
}
}
@ -411,7 +401,7 @@ auto pListView::_updateSelected() -> void {
currentSelection = selected;
for(auto& item : state().items) item->state.selected = false;
for(auto& position : currentSelection) {
if(position >= self().items()) continue;
if(position >= self().itemCount()) continue;
self().item(position)->state.selected = true;
}
@ -419,16 +409,17 @@ auto pListView::_updateSelected() -> void {
}
auto pListView::_width(unsigned column) -> unsigned {
if(auto width = state().columns[column]->width()) return width;
unsigned width = 1;
if(!state().columns[column]->visible()) return width;
if(state().headerVisible) {
width = max(width, _columnWidth(column));
if(auto& header = state().header) {
if(auto width = header->column(column).width()) return width;
unsigned width = 1;
if(!header->column(column).visible()) return width;
if(header->visible()) width = max(width, _columnWidth(column));
for(auto row : range(state().items)) {
width = max(width, _cellWidth(row, column));
}
return width;
}
for(auto row : range(state().items)) {
width = max(width, _cellWidth(row, column));
}
return width;
return 1;
}
}

View File

@ -5,40 +5,34 @@ namespace hiro {
struct pListView : pWidget {
Declare(ListView, Widget)
auto append(sListViewColumn column) -> void;
auto append(sListViewHeader column) -> void;
auto append(sListViewItem item) -> void;
auto checkAll() -> void;
auto focused() -> bool;
auto remove(sListViewColumn column) -> void;
auto focused() const -> bool override;
auto remove(sListViewHeader column) -> void;
auto remove(sListViewItem item) -> void;
auto reset() -> void;
auto resizeColumns() -> void;
auto selectAll() -> void;
auto setAlignment(Alignment alignment) -> void;
auto setBackgroundColor(Color color) -> void;
auto setBatchable(bool batchable) -> void;
auto setCheckable(bool checkable) -> void;
auto setBordered(bool bordered) -> void;
auto setFocused() -> void override;
auto setFont(const string& font) -> void override;
auto setForegroundColor(Color color) -> void;
auto setGridVisible(bool visible) -> void;
auto setHeaderVisible(bool visible) -> void;
auto setSortable(bool sortable) -> void;
auto uncheckAll() -> void;
auto unselectAll() -> void;
auto setGeometry(Geometry geometry) -> void override;
auto _cellWidth(unsigned row, unsigned column) -> unsigned;
auto _column(unsigned column) -> pListViewColumn*;
auto _columnWidth(unsigned column) -> unsigned;
auto _createModel() -> void;
auto _doActivate() -> void;
auto _doCellRendererToggleDataFunc(GtkCellRenderer* renderer, GtkTreeIter* iter) -> void;
auto _doChange() -> void;
auto _doContext() -> void;
auto _doEdit(GtkCellRendererText* renderer, const char* path, const char* text) -> void;
auto _doDataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void;
auto _doEdit(GtkCellRendererText* gtkCellRendererText, const char* path, const char* text) -> void;
auto _doEvent(GdkEventButton* event) -> signed;
auto _doHeaderActivate(GtkTreeViewColumn* column) -> void;
auto _doMouseMove() -> signed;
auto _doToggle(const char* path) -> void;
auto _doToggle(GtkCellRendererToggle* gtkCellRendererToggle, const char* path) -> void;
auto _updateSelected() -> void;
auto _width(unsigned column) -> unsigned;

View File

@ -125,9 +125,9 @@ auto pTabFrame::remove(sTabFrameItem item) -> void {
//the new tab will be the one after this one
unsigned displacement = 1;
//... unless it's the last tab, in which case it's the one before it
if(item->offset() == self().items() - 1) displacement = -1;
if(item->offset() == self().itemCount() - 1) displacement = -1;
//... unless there are no tabs left, in which case nothing is selected
if(self().items() > 1) {
if(self().itemCount() > 1) {
setItemSelected(item->offset() + displacement);
}
}

View File

@ -1,6 +1,15 @@
namespace phoenix {
#if defined(Hiro_Action)
void pAction::setEnabled(bool enabled) {
namespace hiro {
auto pAction::construct() -> void {
}
auto pAction::destruct() -> void {
}
auto pAction::setEnabled(bool enabled) -> void {
/*
if(dynamic_cast<Menu*>(&action)) {
((Menu&)action).p.qtMenu->setEnabled(enabled);
} else if(dynamic_cast<Separator*>(&action)) {
@ -12,9 +21,11 @@ void pAction::setEnabled(bool enabled) {
} else if(dynamic_cast<RadioItem*>(&action)) {
((RadioItem&)action).p.qtAction->setEnabled(enabled);
}
*/
}
void pAction::setFont(string font) {
auto pAction::setFont(const string& font) -> void {
/*
QFont qtFont = pFont::create(font);
if(dynamic_cast<Menu*>(&action)) {
@ -28,9 +39,11 @@ void pAction::setFont(string font) {
} else if(dynamic_cast<RadioItem*>(&action)) {
((RadioItem&)action).p.qtAction->setFont(qtFont);
}
*/
}
void pAction::setVisible(bool visible) {
auto pAction::setVisible(bool visible) -> void {
/*
if(dynamic_cast<Menu*>(&action)) {
((Menu&)action).p.qtMenu->menuAction()->setVisible(visible);
} else if(dynamic_cast<Separator*>(&action)) {
@ -42,12 +55,33 @@ void pAction::setVisible(bool visible) {
} else if(dynamic_cast<RadioItem*>(&action)) {
((RadioItem&)action).p.qtAction->setVisible(visible);
}
*/
}
void pAction::constructor() {
auto pAction::_parentMenu() -> maybe<pMenu&> {
if(auto parent = self().parentMenu()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
void pAction::destructor() {
auto pAction::_parentMenuBar() -> maybe<pMenuBar&> {
if(auto parent = self().parentMenuBar()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pAction::_parentPopupMenu() -> maybe<pPopupMenu&> {
if(auto parent = self().parentPopupMenu()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pAction::_setState() -> void {
}
}
#endif

20
hiro/qt/action/action.hpp Normal file
View File

@ -0,0 +1,20 @@
#if defined(Hiro_Action)
namespace hiro {
struct pAction : pObject {
Declare(Action, Object)
auto setEnabled(bool enabled) -> void override;
auto setFont(const string& font) -> void override;
auto setVisible(bool visible) -> void override;
auto _parentMenu() -> maybe<pMenu&>;
auto _parentMenuBar() -> maybe<pMenuBar&>;
auto _parentPopupMenu() -> maybe<pPopupMenu&>;
virtual auto _setState() -> void;
};
}
#endif

View File

@ -1,28 +0,0 @@
namespace phoenix {
void pCheckItem::setChecked(bool checked) {
qtAction->setChecked(checked);
}
void pCheckItem::setText(string text) {
qtAction->setText(QString::fromUtf8(text));
}
void pCheckItem::constructor() {
qtAction = new QAction(0);
qtAction->setCheckable(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onToggle()));
}
void pCheckItem::destructor() {
if(action.state.menu) action.state.menu->remove(checkItem);
delete qtAction;
qtAction = nullptr;
}
void pCheckItem::onToggle() {
checkItem.state.checked = qtAction->isChecked();
if(checkItem.onToggle) checkItem.onToggle();
}
}

View File

@ -1,26 +0,0 @@
namespace phoenix {
void pItem::setImage(const image& image) {
qtAction->setIcon(CreateIcon(image));
}
void pItem::setText(string text) {
qtAction->setText(QString::fromUtf8(text));
}
void pItem::constructor() {
qtAction = new QAction(0);
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
}
void pItem::destructor() {
if(action.state.menu) action.state.menu->remove(item);
delete qtAction;
qtAction = nullptr;
}
void pItem::onActivate() {
if(item.onActivate) item.onActivate();
}
}

View File

@ -0,0 +1,46 @@
#if defined(Hiro_MenuCheckItem)
namespace hiro {
auto pMenuCheckItem::construct() -> void {
qtMenuCheckItem = new QtMenuCheckItem(*this);
qtMenuCheckItem->setCheckable(true);
qtMenuCheckItem->connect(qtMenuCheckItem, SIGNAL(triggered()), SLOT(onToggle()));
if(auto parent = _parentMenu()) {
parent->qtMenu->addAction(qtMenuCheckItem);
}
if(auto parent = _parentPopupMenu()) {
parent->qtPopupMenu->addAction(qtMenuCheckItem);
}
_setState();
}
auto pMenuCheckItem::destruct() -> void {
delete qtMenuCheckItem;
qtMenuCheckItem = nullptr;
}
auto pMenuCheckItem::setChecked(bool checked) -> void {
_setState();
}
auto pMenuCheckItem::setText(const string& text) -> void {
_setState();
}
auto pMenuCheckItem::_setState() -> void {
qtMenuCheckItem->setChecked(state().checked);
qtMenuCheckItem->setText(QString::fromUtf8(state().text));
}
auto QtMenuCheckItem::onToggle() -> void {
p.state().checked = isChecked();
p.self().doToggle();
}
}
#endif

View File

@ -0,0 +1,18 @@
#if defined(Hiro_MenuCheckItem)
namespace hiro {
struct pMenuCheckItem : pAction {
Declare(MenuCheckItem, Action)
auto setChecked(bool checked) -> void;
auto setText(const string& text) -> void;
auto _setState() -> void override;
QtMenuCheckItem* qtMenuCheckItem = nullptr;
};
}
#endif

View File

@ -0,0 +1,44 @@
#if defined(Hiro_MenuItem)
namespace hiro {
auto pMenuItem::construct() -> void {
qtMenuItem = new QtMenuItem(*this);
qtMenuItem->connect(qtMenuItem, SIGNAL(triggered()), SLOT(onActivate()));
if(auto parent = _parentMenu()) {
parent->qtMenu->addAction(qtMenuItem);
}
if(auto parent = _parentPopupMenu()) {
parent->qtPopupMenu->addAction(qtMenuItem);
}
_setState();
}
auto pMenuItem::destruct() -> void {
delete qtMenuItem;
qtMenuItem = nullptr;
}
auto pMenuItem::setIcon(const image& icon) -> void {
_setState();
}
auto pMenuItem::setText(const string& text) -> void {
_setState();
}
auto pMenuItem::_setState() -> void {
qtMenuItem->setIcon(CreateIcon(state().icon));
qtMenuItem->setText(state().text);
}
auto QtMenuItem::onActivate() -> void {
p.self().doActivate();
}
}
#endif

View File

@ -0,0 +1,18 @@
#if defined(Hiro_MenuItem)
namespace hiro {
struct pMenuItem : pAction {
Declare(MenuItem, Action)
auto setIcon(const image& icon) -> void;
auto setText(const string& text) -> void;
auto _setState() -> void override;
QtMenuItem* qtMenuItem = nullptr;
};
}
#endif

View File

@ -0,0 +1,65 @@
#if defined(Hiro_MenuRadioItem)
namespace hiro {
auto pMenuRadioItem::construct() -> void {
qtMenuRadioItem = new QtMenuRadioItem(*this);
qtActionGroup = new QActionGroup(nullptr);
qtMenuRadioItem->setCheckable(true);
qtMenuRadioItem->setActionGroup(qtActionGroup);
qtMenuRadioItem->setChecked(true);
qtMenuRadioItem->connect(qtMenuRadioItem, SIGNAL(triggered()), SLOT(onActivate()));
if(auto parent = _parentMenu()) {
parent->qtMenu->addAction(qtMenuRadioItem);
}
if(auto parent = _parentPopupMenu()) {
parent->qtPopupMenu->addAction(qtMenuRadioItem);
}
_setState();
}
auto pMenuRadioItem::destruct() -> void {
delete qtMenuRadioItem;
delete qtActionGroup;
qtMenuRadioItem = nullptr;
qtActionGroup = nullptr;
}
auto pMenuRadioItem::setChecked() -> void {
_setState();
}
auto pMenuRadioItem::setGroup(sGroup group) -> void {
_setState();
}
auto pMenuRadioItem::setText(const string& text) -> void {
_setState();
}
auto pMenuRadioItem::_setState() -> void {
if(auto group = state().group) {
if(auto object = group->object(0)) {
if(auto menuRadioItem = dynamic_cast<mMenuRadioItem*>(object.data())) {
if(auto self = menuRadioItem->self()) {
qtMenuRadioItem->setActionGroup(self->qtActionGroup);
}
}
}
}
qtMenuRadioItem->setChecked(state().checked);
qtMenuRadioItem->setText(QString::fromUtf8(state().text));
}
auto QtMenuRadioItem::onActivate() -> void {
if(p.state().checked) return;
p.state().checked = true;
p.self().doActivate();
}
}
#endif

View File

@ -0,0 +1,20 @@
#if defined(Hiro_MenuRadioItem)
namespace hiro {
struct pMenuRadioItem : pAction {
Declare(MenuRadioItem, Action)
auto setChecked() -> void;
auto setGroup(sGroup group) -> void;
auto setText(const string& text) -> void;
auto _setState() -> void override;
QtMenuRadioItem* qtMenuRadioItem = nullptr;
QActionGroup* qtActionGroup = nullptr;
};
}
#endif

View File

@ -0,0 +1,25 @@
#if defined(Hiro_MenuSeparator)
namespace hiro {
auto pMenuSeparator::construct() -> void {
qtMenuSeparator = new QAction(nullptr);
qtMenuSeparator->setSeparator(true);
if(auto parent = _parentMenu()) {
parent->qtMenu->addAction(qtMenuSeparator);
}
if(auto parent = _parentPopupMenu()) {
parent->qtPopupMenu->addAction(qtMenuSeparator);
}
}
auto pMenuSeparator::destruct() -> void {
delete qtMenuSeparator;
qtMenuSeparator = nullptr;
}
}
#endif

View File

@ -0,0 +1,13 @@
#if defined(Hiro_MenuSeparator)
namespace hiro {
struct pMenuSeparator : pAction {
Declare(MenuSeparator, Action)
QAction* qtMenuSeparator = nullptr;
};
}
#endif

View File

@ -1,56 +1,60 @@
namespace phoenix {
#if defined(Hiro_Menu)
void pMenu::append(Action& action) {
if(dynamic_cast<Menu*>(&action)) {
qtMenu->addMenu(((Menu&)action).p.qtMenu);
} else if(dynamic_cast<Separator*>(&action)) {
qtMenu->addAction(((Separator&)action).p.qtAction);
} else if(dynamic_cast<Item*>(&action)) {
qtMenu->addAction(((Item&)action).p.qtAction);
} else if(dynamic_cast<CheckItem*>(&action)) {
qtMenu->addAction(((CheckItem&)action).p.qtAction);
} else if(dynamic_cast<RadioItem*>(&action)) {
qtMenu->addAction(((RadioItem&)action).p.qtAction);
}
}
namespace hiro {
void pMenu::remove(Action& action) {
if(dynamic_cast<Menu*>(&action)) {
//QMenu::removeMenu() does not exist
qtMenu->clear();
for(auto& action : menu.state.action) append(action);
} else if(dynamic_cast<Separator*>(&action)) {
qtMenu->removeAction(((Separator&)action).p.qtAction);
} else if(dynamic_cast<Item*>(&action)) {
qtMenu->removeAction(((Item&)action).p.qtAction);
} else if(dynamic_cast<CheckItem*>(&action)) {
qtMenu->removeAction(((CheckItem&)action).p.qtAction);
} else if(dynamic_cast<RadioItem*>(&action)) {
qtMenu->removeAction(((CheckItem&)action).p.qtAction);
}
}
void pMenu::setFont(string font) {
qtMenu->setFont(pFont::create(font));
for(auto &item : menu.state.action) item.p.setFont(font);
}
void pMenu::setImage(const image& image) {
qtMenu->setIcon(CreateIcon(image));
}
void pMenu::setText(string text) {
qtMenu->setTitle(QString::fromUtf8(text));
}
void pMenu::constructor() {
auto pMenu::construct() -> void {
qtMenu = new QMenu;
if(auto parent = _parentMenu()) {
parent->qtMenu->addMenu(qtMenu);
}
if(auto parent = _parentMenuBar()) {
if(auto window = parent->_parent()) {
window->qtMenuBar->addMenu(qtMenu);
}
}
if(auto parent = _parentPopupMenu()) {
parent->qtPopupMenu->addMenu(qtMenu);
}
_setState();
}
void pMenu::destructor() {
if(action.state.menu) action.state.menu->remove(menu);
auto pMenu::destruct() -> void {
delete qtMenu;
qtMenu = nullptr;
}
auto pMenu::append(sAction action) -> void {
}
auto pMenu::remove(sAction action) -> void {
}
auto pMenu::setFont(const string& font) -> void {
_setState();
}
auto pMenu::setIcon(const image& icon) -> void {
_setState();
}
auto pMenu::setText(const string& text) -> void {
_setState();
}
auto pMenu::_setState() -> void {
qtMenu->setFont(pFont::create(self().font(true)));
qtMenu->setIcon(CreateIcon(state().icon));
qtMenu->setTitle(QString::fromUtf8(state().text));
for(auto& action : state().actions) {
if(auto self = action->self()) self->setFont(action->font(true));
}
}
}
#endif

21
hiro/qt/action/menu.hpp Normal file
View File

@ -0,0 +1,21 @@
#if defined(Hiro_Menu)
namespace hiro {
struct pMenu : public pAction {
Declare(Menu, Action)
auto append(sAction action) -> void;
auto remove(sAction action) -> void;
auto setFont(const string& font) -> void override;
auto setIcon(const image& icon) -> void;
auto setText(const string& text) -> void;
auto _setState() -> void override;
QMenu* qtMenu = nullptr;
};
}
#endif

View File

@ -1,42 +0,0 @@
namespace phoenix {
void pRadioItem::setChecked() {
lock();
for(auto& item : radioItem.state.group) {
bool checkState = item.p.qtAction == qtAction;
item.state.checked = checkState;
item.p.qtAction->setChecked(checkState);
}
unlock();
}
void pRadioItem::setGroup(const group<RadioItem>& group) {
}
void pRadioItem::setText(string text) {
qtAction->setText(QString::fromUtf8(text));
}
void pRadioItem::constructor() {
qtAction = new QAction(0);
qtGroup = new QActionGroup(0);
qtAction->setCheckable(true);
qtAction->setActionGroup(qtGroup);
qtAction->setChecked(true);
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
}
void pRadioItem::destructor() {
if(action.state.menu) action.state.menu->remove(radioItem);
delete qtAction;
qtAction = nullptr;
}
void pRadioItem::onActivate() {
if(!radioItem.state.checked) {
setChecked();
if(!locked() && radioItem.onActivate) radioItem.onActivate();
}
}
}

View File

@ -1,14 +0,0 @@
namespace phoenix {
void pSeparator::constructor() {
qtAction = new QAction(0);
qtAction->setSeparator(true);
}
void pSeparator::destructor() {
if(action.state.menu) action.state.menu->remove(separator);
delete qtAction;
qtAction = nullptr;
}
}

View File

@ -1,41 +1,44 @@
namespace phoenix {
#if defined(Hiro_Application)
namespace hiro {
XlibDisplay* pApplication::display = nullptr;
void pApplication::run() {
if(Application::main) {
while(applicationState.quit == false) {
auto pApplication::run() -> void {
if(Application::state.onMain) {
while(!Application::state.quit) {
Application::doMain();
processEvents();
Application::main();
}
} else {
QApplication::exec();
}
}
bool pApplication::pendingEvents() {
auto pApplication::pendingEvents() -> bool {
return QApplication::hasPendingEvents();
}
void pApplication::processEvents() {
auto pApplication::processEvents() -> void {
while(pendingEvents()) QApplication::processEvents();
}
void pApplication::quit() {
auto pApplication::quit() -> void {
QApplication::quit();
//note: QApplication cannot be deleted; or libQtGui will crash
qtApplication = nullptr;
qtApplication = nullptr; //note: deleting QApplication will crash libQtGui
}
void pApplication::syncX() {
for(unsigned n = 0; n < 8; n++) {
//this is sadly necessary for things like determining window frame geometry
//obviously, it is used as sparingly as possible
auto pApplication::syncX() -> void {
for(auto n : range(8)) {
QApplication::syncX();
Application::processEvents();
usleep(2000);
}
}
void pApplication::initialize() {
auto pApplication::initialize() -> void {
display = XOpenDisplay(0);
settings = new Settings;
@ -43,7 +46,7 @@ void pApplication::initialize() {
static int argc = 1;
static char* argv[] = {new char[8], nullptr};
strcpy(argv[0], "phoenix");
strcpy(argv[0], "hiro");
char** argvp = argv;
qtApplication = new QApplication(argc, argvp);
@ -52,3 +55,5 @@ void pApplication::initialize() {
}
}
#endif

21
hiro/qt/application.hpp Normal file
View File

@ -0,0 +1,21 @@
#if defined(Hiro_Application)
namespace hiro {
struct pApplication {
static auto run() -> void;
static auto pendingEvents() -> bool;
static auto processEvents() -> void;
static auto quit() -> void;
static auto initialize() -> void;
static auto syncX() -> void;
static XlibDisplay* display;
};
static QApplication* qtApplication = nullptr;
}
#endif

View File

@ -1,6 +1,9 @@
namespace phoenix {
#if defined(Hiro_BrowserWindow)
string pBrowserWindow::directory(BrowserWindow::State& state) {
namespace hiro {
auto pBrowserWindow::directory(BrowserWindow::State& state) -> string {
/*
QString directory = QFileDialog::getExistingDirectory(
state.parent ? state.parent->p.qtWindow : nullptr,
state.title ? state.title : "Select Directory",
@ -9,9 +12,11 @@ string pBrowserWindow::directory(BrowserWindow::State& state) {
string name = directory.toUtf8().constData();
if(name && name.endsWith("/") == false) name.append("/");
return name;
*/
}
string pBrowserWindow::open(BrowserWindow::State& state) {
auto pBrowserWindow::open(BrowserWindow::State& state) -> string {
/*
string filters = state.filters.merge(";;");
//convert filter list from phoenix to Qt format, example:
@ -29,9 +34,11 @@ string pBrowserWindow::open(BrowserWindow::State& state) {
QString::fromUtf8(state.path), QString::fromUtf8(filters)
);
return filename.toUtf8().constData();
*/
}
string pBrowserWindow::save(BrowserWindow::State& state) {
auto pBrowserWindow::save(BrowserWindow::State& state) -> string {
/*
string filters = state.filters.merge(";;");
//convert filter list from phoenix to Qt format, example:
@ -49,6 +56,9 @@ string pBrowserWindow::save(BrowserWindow::State& state) {
QString::fromUtf8(state.path), QString::fromUtf8(filters)
);
return filename.toUtf8().constData();
*/
}
}
#endif

View File

@ -0,0 +1,13 @@
#if defined(Hiro_BrowserWindow)
namespace hiro {
struct pBrowserWindow {
static auto directory(BrowserWindow::State& state) -> string;
static auto open(BrowserWindow::State& state) -> string;
static auto save(BrowserWindow::State& state) -> string;
};
}
#endif

View File

@ -1,13 +1,17 @@
namespace phoenix {
#if defined(Hiro_Desktop)
Size pDesktop::size() {
namespace hiro {
auto pDesktop::size() -> Size {
QRect rect = QApplication::desktop()->screenGeometry();
return {rect.width(), rect.height()};
}
Geometry pDesktop::workspace() {
auto pDesktop::workspace() -> Geometry {
QRect rect = QApplication::desktop()->availableGeometry();
return {rect.x(), rect.y(), rect.width(), rect.height()};
}
}
#endif

12
hiro/qt/desktop.hpp Normal file
View File

@ -0,0 +1,12 @@
#if defined(Hiro_Desktop)
namespace hiro {
struct pDesktop {
static auto size() -> Size;
static auto workspace() -> Geometry;
};
}
#endif

View File

@ -1,28 +1,30 @@
namespace phoenix {
#if defined(Hiro_Font)
string pFont::serif(unsigned size, string style) {
namespace hiro {
auto pFont::serif(unsigned size, string style) -> string {
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Serif, ", size, ", ", style};
}
string pFont::sans(unsigned size, string style) {
auto pFont::sans(unsigned size, string style) -> string {
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Sans, ", size, ", ", style};
}
string pFont::monospace(unsigned size, string style) {
auto pFont::monospace(unsigned size, string style) -> string {
if(size == 0) size = 8;
if(style == "") style = "Normal";
return {"Liberation Mono, ", size, ", ", style};
}
Size pFont::size(string font, string text) {
auto pFont::size(string font, string text) -> Size {
return pFont::size(pFont::create(font), text);
}
QFont pFont::create(string description) {
auto pFont::create(string description) -> QFont {
lstring part = description.split(",", 2L).strip();
string family = "Sans";
@ -43,18 +45,20 @@ QFont pFont::create(string description) {
return qtFont;
}
Size pFont::size(const QFont& qtFont, string text) {
auto pFont::size(const QFont& qtFont, const string& text) -> Size {
QFontMetrics metrics(qtFont);
lstring lines;
lines.split("\n", text);
lines.split("\n", text ? text : " ");
unsigned maxWidth = 0;
for(auto& line : lines) {
maxWidth = max(maxWidth, metrics.width(line));
}
return {maxWidth, metrics.height() * lines.size()};
return Size().setWidth(maxWidth).setHeight(metrics.height() * lines.size());
}
}
#endif

17
hiro/qt/font.hpp Normal file
View File

@ -0,0 +1,17 @@
#if defined(Hiro_Font)
namespace hiro {
struct pFont {
static auto serif(unsigned size, string style) -> string;
static auto sans(unsigned size, string style) -> string;
static auto monospace(unsigned size, string style) -> string;
static auto size(string font, string text) -> Size;
static auto create(string description) -> QFont;
static auto size(const QFont& qtFont, const string& text) -> Size;
};
}
#endif

13
hiro/qt/group.cpp Normal file
View File

@ -0,0 +1,13 @@
#if defined(Hiro_Group)
namespace hiro {
auto pGroup::construct() -> void {
}
auto pGroup::destruct() -> void {
}
}
#endif

11
hiro/qt/group.hpp Normal file
View File

@ -0,0 +1,11 @@
#if defined(Hiro_Group)
namespace hiro {
struct pGroup : pObject {
Declare(Group, Object)
};
}
#endif

13
hiro/qt/hotkey.cpp Normal file
View File

@ -0,0 +1,13 @@
#if defined(Hiro_Hotkey)
namespace hiro {
auto pHotkey::construct() -> void {
}
auto pHotkey::destruct() -> void {
}
}
#endif

11
hiro/qt/hotkey.hpp Normal file
View File

@ -0,0 +1,11 @@
#if defined(Hiro_Hotkey)
namespace hiro {
struct pHotkey : pObject {
Declare(Hotkey, Object)
};
}
#endif

View File

@ -1,149 +1,47 @@
namespace phoenix {
#if defined(Hiro_Keyboard)
void pKeyboard::initialize() {
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
settings->keymap.insert(scancode, XKeysymToKeycode(pApplication::display, keysym));
};
namespace hiro {
append(Keyboard::Scancode::Escape, XK_Escape);
append(Keyboard::Scancode::F1, XK_F1);
append(Keyboard::Scancode::F2, XK_F2);
append(Keyboard::Scancode::F3, XK_F3);
append(Keyboard::Scancode::F4, XK_F4);
append(Keyboard::Scancode::F5, XK_F5);
append(Keyboard::Scancode::F6, XK_F6);
append(Keyboard::Scancode::F7, XK_F7);
append(Keyboard::Scancode::F8, XK_F8);
append(Keyboard::Scancode::F9, XK_F9);
append(Keyboard::Scancode::F10, XK_F10);
append(Keyboard::Scancode::F11, XK_F11);
append(Keyboard::Scancode::F12, XK_F12);
append(Keyboard::Scancode::PrintScreen, XK_Print);
append(Keyboard::Scancode::ScrollLock, XK_Scroll_Lock);
append(Keyboard::Scancode::Pause, XK_Pause);
append(Keyboard::Scancode::Insert, XK_Insert);
append(Keyboard::Scancode::Delete, XK_Delete);
append(Keyboard::Scancode::Home, XK_Home);
append(Keyboard::Scancode::End, XK_End);
append(Keyboard::Scancode::PageUp, XK_Prior);
append(Keyboard::Scancode::PageDown, XK_Next);
append(Keyboard::Scancode::Up, XK_Up);
append(Keyboard::Scancode::Down, XK_Down);
append(Keyboard::Scancode::Left, XK_Left);
append(Keyboard::Scancode::Right, XK_Right);
append(Keyboard::Scancode::Grave, XK_asciitilde);
append(Keyboard::Scancode::Number1, XK_1);
append(Keyboard::Scancode::Number2, XK_2);
append(Keyboard::Scancode::Number3, XK_3);
append(Keyboard::Scancode::Number4, XK_4);
append(Keyboard::Scancode::Number5, XK_5);
append(Keyboard::Scancode::Number6, XK_6);
append(Keyboard::Scancode::Number7, XK_7);
append(Keyboard::Scancode::Number8, XK_8);
append(Keyboard::Scancode::Number9, XK_9);
append(Keyboard::Scancode::Number0, XK_0);
append(Keyboard::Scancode::Minus, XK_minus);
append(Keyboard::Scancode::Equal, XK_equal);
append(Keyboard::Scancode::Backspace, XK_BackSpace);
append(Keyboard::Scancode::BracketLeft, XK_bracketleft);
append(Keyboard::Scancode::BracketRight, XK_bracketright);
append(Keyboard::Scancode::Backslash, XK_backslash);
append(Keyboard::Scancode::Semicolon, XK_semicolon);
append(Keyboard::Scancode::Apostrophe, XK_apostrophe);
append(Keyboard::Scancode::Comma, XK_comma);
append(Keyboard::Scancode::Period, XK_period);
append(Keyboard::Scancode::Slash, XK_slash);
append(Keyboard::Scancode::Tab, XK_Tab);
append(Keyboard::Scancode::CapsLock, XK_Caps_Lock);
append(Keyboard::Scancode::Return, XK_Return);
append(Keyboard::Scancode::ShiftLeft, XK_Shift_L);
append(Keyboard::Scancode::ShiftRight, XK_Shift_R);
append(Keyboard::Scancode::ControlLeft, XK_Control_L);
append(Keyboard::Scancode::ControlRight, XK_Control_R);
append(Keyboard::Scancode::SuperLeft, XK_Super_L);
append(Keyboard::Scancode::SuperRight, XK_Super_R);
append(Keyboard::Scancode::AltLeft, XK_Alt_L);
append(Keyboard::Scancode::AltRight, XK_Alt_R);
append(Keyboard::Scancode::Space, XK_space);
append(Keyboard::Scancode::Menu, XK_Menu);
append(Keyboard::Scancode::A, XK_A);
append(Keyboard::Scancode::B, XK_B);
append(Keyboard::Scancode::C, XK_C);
append(Keyboard::Scancode::D, XK_D);
append(Keyboard::Scancode::E, XK_E);
append(Keyboard::Scancode::F, XK_F);
append(Keyboard::Scancode::G, XK_G);
append(Keyboard::Scancode::H, XK_H);
append(Keyboard::Scancode::I, XK_I);
append(Keyboard::Scancode::J, XK_J);
append(Keyboard::Scancode::K, XK_K);
append(Keyboard::Scancode::L, XK_L);
append(Keyboard::Scancode::M, XK_M);
append(Keyboard::Scancode::N, XK_N);
append(Keyboard::Scancode::O, XK_O);
append(Keyboard::Scancode::P, XK_P);
append(Keyboard::Scancode::Q, XK_Q);
append(Keyboard::Scancode::R, XK_R);
append(Keyboard::Scancode::S, XK_S);
append(Keyboard::Scancode::T, XK_T);
append(Keyboard::Scancode::U, XK_U);
append(Keyboard::Scancode::V, XK_V);
append(Keyboard::Scancode::W, XK_W);
append(Keyboard::Scancode::X, XK_X);
append(Keyboard::Scancode::Y, XK_Y);
append(Keyboard::Scancode::Z, XK_Z);
append(Keyboard::Scancode::NumLock, XK_Num_Lock);
append(Keyboard::Scancode::Divide, XK_KP_Divide);
append(Keyboard::Scancode::Multiply, XK_KP_Multiply);
append(Keyboard::Scancode::Subtract, XK_KP_Subtract);
append(Keyboard::Scancode::Add, XK_KP_Add);
append(Keyboard::Scancode::Enter, XK_KP_Enter);
append(Keyboard::Scancode::Point, XK_KP_Decimal);
append(Keyboard::Scancode::Keypad1, XK_KP_1);
append(Keyboard::Scancode::Keypad2, XK_KP_2);
append(Keyboard::Scancode::Keypad3, XK_KP_3);
append(Keyboard::Scancode::Keypad4, XK_KP_4);
append(Keyboard::Scancode::Keypad5, XK_KP_5);
append(Keyboard::Scancode::Keypad6, XK_KP_6);
append(Keyboard::Scancode::Keypad7, XK_KP_7);
append(Keyboard::Scancode::Keypad8, XK_KP_8);
append(Keyboard::Scancode::Keypad9, XK_KP_9);
append(Keyboard::Scancode::Keypad0, XK_KP_0);
}
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
auto pKeyboard::poll() -> vector<bool> {
vector<bool> result;
char state[256];
XQueryKeymap(pApplication::display, state);
if(auto result = settings->keymap.find(scancode)) {
unsigned id = result();
return state[id >> 3] & (1 << (id & 7));
for(auto& code : settings->keycodes) {
result.append(_pressed(state, code));
}
return result;
}
auto pKeyboard::pressed(unsigned code) -> bool {
char state[256];
XQueryKeymap(pApplication::display, state);
return _pressed(state, code);
}
auto pKeyboard::_pressed(const char* state, uint16_t code) -> bool {
uint8_t lo = code >> 0;
uint8_t hi = code >> 8;
if(lo && state[lo >> 3] & (1 << (lo & 7))) return true;
if(hi && state[hi >> 3] & (1 << (hi & 7))) return true;
return false;
}
vector<bool> pKeyboard::state() {
vector<bool> output;
output.resize((unsigned)Keyboard::Scancode::Limit);
for(auto& n : output) n = false;
auto pKeyboard::initialize() -> void {
auto append = [](unsigned lo, unsigned hi = 0) {
lo = lo ? (uint8_t)XKeysymToKeycode(pApplication::display, lo) : 0;
hi = hi ? (uint8_t)XKeysymToKeycode(pApplication::display, hi) : 0;
settings->keycodes.append(lo << 0 | hi << 8);
};
char state[256];
XQueryKeymap(pApplication::display, state);
for(auto node : settings->keymap) {
if(state[node.value >> 3] & (1 << (node.value & 7))) {
output[(unsigned)node.key] = true;
}
#define map(name, ...) if(key == name) { append(__VA_ARGS__); continue; }
for(auto& key : Keyboard::keys) {
#include <hiro/platform/xorg/keyboard.hpp>
}
return output;
#undef map
}
}
#endif

16
hiro/qt/keyboard.hpp Normal file
View File

@ -0,0 +1,16 @@
#if defined(Hiro_Keyboard)
namespace hiro {
struct pKeyboard {
static auto poll() -> vector<bool>;
static auto pressed(unsigned code) -> bool;
static auto _pressed(const char* state, uint16_t code) -> bool;
static auto initialize() -> void;
};
}
#endif

19
hiro/qt/layout.cpp Normal file
View File

@ -0,0 +1,19 @@
#if defined(Hiro_Layout)
namespace hiro {
auto pLayout::construct() -> void {
}
auto pLayout::destruct() -> void {
}
auto pLayout::setVisible(bool visible) -> void {
for(auto& sizable : state().sizables) {
if(auto self = sizable->self()) self->setVisible(sizable->visible(true));
}
}
}
#endif

13
hiro/qt/layout.hpp Normal file
View File

@ -0,0 +1,13 @@
#if defined(Hiro_Layout)
namespace hiro {
struct pLayout : pSizable {
Declare(Layout, Sizable)
auto setVisible(bool visible) -> void override;
};
}
#endif

46
hiro/qt/menu-bar.cpp Normal file
View File

@ -0,0 +1,46 @@
#if defined(Hiro_MenuBar)
namespace hiro {
auto pMenuBar::construct() -> void {
_setState();
}
auto pMenuBar::destruct() -> void {
}
auto pMenuBar::append(sMenu menu) -> void {
}
auto pMenuBar::remove(sMenu menu) -> void {
}
auto pMenuBar::setEnabled(bool enabled) -> void {
_setState();
}
auto pMenuBar::setFont(const string& font) -> void {
_setState();
}
auto pMenuBar::setVisible(bool visible) -> void {
_setState();
}
auto pMenuBar::_parent() -> maybe<pWindow&> {
if(auto parent = self().parentWindow()) {
if(auto self = parent->self()) return *self;
}
return nothing;
}
auto pMenuBar::_setState() -> void {
if(auto parent = _parent()) {
parent->qtMenuBar->setFont(pFont::create(self().font(true)));
parent->qtMenuBar->setVisible(self().visible());
}
}
}
#endif

20
hiro/qt/menu-bar.hpp Normal file
View File

@ -0,0 +1,20 @@
#if defined(Hiro_MenuBar)
namespace hiro {
struct pMenuBar : pObject {
Declare(MenuBar, Object)
auto append(sMenu menu) -> void;
auto remove(sMenu menu) -> void;
auto setEnabled(bool enabled) -> void override;
auto setFont(const string& font) -> void override;
auto setVisible(bool visible) -> void override;
auto _parent() -> maybe<pWindow&>;
auto _setState() -> void;
};
}
#endif

View File

@ -1,6 +1,8 @@
namespace phoenix {
#if defined(Hiro_MessageWindow)
static QMessageBox::StandardButtons MessageWindow_buttons(MessageWindow::Buttons buttons) {
namespace hiro {
static auto MessageWindow_buttons(MessageWindow::Buttons buttons) -> QMessageBox::StandardButtons {
QMessageBox::StandardButtons standardButtons = QMessageBox::NoButton;
if(buttons == MessageWindow::Buttons::Ok) standardButtons = QMessageBox::Ok;
if(buttons == MessageWindow::Buttons::OkCancel) standardButtons = QMessageBox::Ok | QMessageBox::Cancel;
@ -9,7 +11,7 @@ static QMessageBox::StandardButtons MessageWindow_buttons(MessageWindow::Buttons
return standardButtons;
}
static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons buttons, QMessageBox::StandardButton response) {
static auto MessageWindow_response(MessageWindow::Buttons buttons, QMessageBox::StandardButton response) -> MessageWindow::Response {
if(response == QMessageBox::Ok) return MessageWindow::Response::Ok;
if(response == QMessageBox::Cancel) return MessageWindow::Response::Cancel;
if(response == QMessageBox::Yes) return MessageWindow::Response::Yes;
@ -24,32 +26,34 @@ static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons but
throw;
}
MessageWindow::Response pMessageWindow::error(MessageWindow::State& state) {
return MessageWindow_response(
state.buttons, QMessageBox::critical(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
);
auto pMessageWindow::error(MessageWindow::State& state) -> MessageWindow::Response {
// return MessageWindow_response(
// state.buttons, QMessageBox::critical(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
// QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
// );
}
MessageWindow::Response pMessageWindow::information(MessageWindow::State& state) {
return MessageWindow_response(
state.buttons, QMessageBox::information(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
);
auto pMessageWindow::information(MessageWindow::State& state) -> MessageWindow::Response {
// return MessageWindow_response(
// state.buttons, QMessageBox::information(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
// QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
// );
}
MessageWindow::Response pMessageWindow::question(MessageWindow::State& state) {
return MessageWindow_response(
state.buttons, QMessageBox::question(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
);
auto pMessageWindow::question(MessageWindow::State& state) -> MessageWindow::Response {
// return MessageWindow_response(
// state.buttons, QMessageBox::question(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
// QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
// );
}
MessageWindow::Response pMessageWindow::warning(MessageWindow::State& state) {
return MessageWindow_response(
state.buttons, QMessageBox::warning(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
);
auto pMessageWindow::warning(MessageWindow::State& state) -> MessageWindow::Response {
// return MessageWindow_response(
// state.buttons, QMessageBox::warning(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
// QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
// );
}
}
#endif

View File

@ -0,0 +1,14 @@
#if defined(Hiro_MessageWindow)
namespace hiro {
struct pMessageWindow {
static auto error(MessageWindow::State& state) -> MessageWindow::Response;
static auto information(MessageWindow::State& state) -> MessageWindow::Response;
static auto question(MessageWindow::State& state) -> MessageWindow::Response;
static auto warning(MessageWindow::State& state) -> MessageWindow::Response;
};
}
#endif

View File

@ -1,16 +1,20 @@
namespace phoenix {
#if defined(Hiro_Monitor)
unsigned pMonitor::count() {
namespace hiro {
auto pMonitor::count() -> unsigned {
return QApplication::desktop()->screenCount();
}
Geometry pMonitor::geometry(unsigned monitor) {
auto pMonitor::geometry(unsigned monitor) -> Geometry {
QRect rectangle = QApplication::desktop()->screenGeometry(monitor);
return {rectangle.x(), rectangle.y(), rectangle.width(), rectangle.height()};
}
unsigned pMonitor::primary() {
auto pMonitor::primary() -> unsigned {
return QApplication::desktop()->primaryScreen();
}
}
#endif

13
hiro/qt/monitor.hpp Normal file
View File

@ -0,0 +1,13 @@
#if defined(Hiro_Monitor)
namespace hiro {
struct pMonitor {
static auto count() -> unsigned;
static auto geometry(unsigned monitor) -> Geometry;
static auto primary() -> unsigned;
};
}
#endif

View File

@ -1,11 +1,13 @@
namespace phoenix {
#if defined(Hiro_Mouse)
Position pMouse::position() {
namespace hiro {
auto pMouse::position() -> Position {
QPoint point = QCursor::pos();
return {point.x(), point.y()};
}
bool pMouse::pressed(Mouse::Button button) {
auto pMouse::pressed(Mouse::Button button) -> bool {
Qt::MouseButtons buttons = QApplication::mouseButtons();
switch(button) {
case Mouse::Button::Left: return buttons & Qt::LeftButton;
@ -16,3 +18,5 @@ bool pMouse::pressed(Mouse::Button button) {
}
}
#endif

12
hiro/qt/mouse.hpp Normal file
View File

@ -0,0 +1,12 @@
#if defined(Hiro_Mouse)
namespace hiro {
struct pMouse {
static auto position() -> Position;
static auto pressed(Mouse::Button button) -> bool;
};
}
#endif

35
hiro/qt/object.cpp Normal file
View File

@ -0,0 +1,35 @@
#if defined(Hiro_Object)
namespace hiro {
auto pObject::construct() -> void {
}
auto pObject::destruct() -> void {
}
auto pObject::focused() const -> bool {
return false;
}
auto pObject::remove() -> void {
}
auto pObject::reset() -> void {
}
auto pObject::setEnabled(bool enabled) -> void {
}
auto pObject::setFocused() -> void {
}
auto pObject::setFont(const string& font) -> void {
}
auto pObject::setVisible(bool visible) -> void {
}
}
#endif

31
hiro/qt/object.hpp Normal file
View File

@ -0,0 +1,31 @@
#if defined(Hiro_Object)
namespace hiro {
struct pObject {
pObject(mObject& reference) : reference(reference) {}
virtual ~pObject() {}
auto self() const -> mObject& { return (mObject&)reference; }
auto state() const -> mObject::State& { return self().state; }
virtual auto construct() -> void;
virtual auto destruct() -> void;
virtual auto focused() const -> bool;
virtual auto remove() -> void;
virtual auto reset() -> void;
virtual auto setEnabled(bool enabled) -> void;
virtual auto setFocused() -> void;
virtual auto setFont(const string& font) -> void;
virtual auto setVisible(bool visible) -> void;
auto locked() const -> bool { return locks != 0; }
auto lock() -> void { locks++; }
auto unlock() -> void { locks--; }
mObject& reference;
signed locks = 0;
};
}
#endif

View File

@ -1,26 +1,37 @@
#include "platform.moc.hpp"
#include "platform.moc"
#include "qt.hpp"
#include "qt.moc"
#include "platform.hpp"
#include "utility.cpp"
#include "settings.cpp"
#include "font.cpp"
#include "desktop.cpp"
#include "monitor.cpp"
#include "keyboard.cpp"
#include "mouse.cpp"
#include "browser-window.cpp"
#include "message-window.cpp"
#include "font.cpp"
#include "object.cpp"
#include "group.cpp"
#include "hotkey.cpp"
#include "timer.cpp"
#include "window.cpp"
#include "status-bar.cpp"
#include "menu-bar.cpp"
#include "popup-menu.cpp"
#include "action/action.cpp"
#include "action/menu.cpp"
#include "action/separator.cpp"
#include "action/item.cpp"
#include "action/check-item.cpp"
#include "action/radio-item.cpp"
#include "action/menu-separator.cpp"
#include "action/menu-item.cpp"
#include "action/menu-check-item.cpp"
#include "action/menu-radio-item.cpp"
#include "sizable.cpp"
#include "layout.cpp"
#include "widget/widget.cpp"
#include "widget/button.cpp"
@ -28,6 +39,7 @@
#include "widget/check-button.cpp"
#include "widget/check-label.cpp"
#include "widget/combo-button.cpp"
#include "widget/combo-button-item.cpp"
#include "widget/console.cpp"
#include "widget/frame.cpp"
#include "widget/hex-edit.cpp"
@ -37,10 +49,15 @@
#include "widget/label.cpp"
#include "widget/line-edit.cpp"
#include "widget/list-view.cpp"
#include "widget/list-view-header.cpp"
#include "widget/list-view-column.cpp"
#include "widget/list-view-item.cpp"
#include "widget/list-view-cell.cpp"
#include "widget/progress-bar.cpp"
#include "widget/radio-button.cpp"
#include "widget/radio-label.cpp"
#include "widget/tab-frame.cpp"
#include "widget/tab-frame-item.cpp"
#include "widget/text-edit.cpp"
#include "widget/vertical-scroller.cpp"
#include "widget/vertical-slider.cpp"

137
hiro/qt/platform.hpp Normal file
View File

@ -0,0 +1,137 @@
#include "settings.hpp"
#define Declare(Name, Base) \
p##Name(m##Name& reference) : p##Base(reference) {} \
auto self() const -> m##Name& { return (m##Name&)reference; } \
auto state() const -> m##Name::State& { return self().state; } \
auto construct() -> void override; \
auto destruct() -> void override; \
#include "application.hpp"
#include "font.hpp"
#include "desktop.hpp"
#include "monitor.hpp"
#include "keyboard.hpp"
#include "mouse.hpp"
#include "browser-window.hpp"
#include "message-window.hpp"
#include "object.hpp"
#include "group.hpp"
#include "hotkey.hpp"
#include "timer.hpp"
#include "window.hpp"
#include "status-bar.hpp"
#include "menu-bar.hpp"
#include "popup-menu.hpp"
#include "action/action.hpp"
#include "action/menu.hpp"
#include "action/menu-separator.hpp"
#include "action/menu-item.hpp"
#include "action/menu-check-item.hpp"
#include "action/menu-radio-item.hpp"
#include "sizable.hpp"
#include "layout.hpp"
#include "widget/widget.hpp"
#include "widget/button.hpp"
#include "widget/canvas.hpp"
#include "widget/check-button.hpp"
#include "widget/check-label.hpp"
#include "widget/combo-button.hpp"
#include "widget/combo-button-item.hpp"
#include "widget/frame.hpp"
#include "widget/hex-edit.hpp"
#include "widget/horizontal-scroller.hpp"
#include "widget/horizontal-slider.hpp"
#include "widget/label.hpp"
#include "widget/line-edit.hpp"
#include "widget/list-view.hpp"
#include "widget/list-view-header.hpp"
#include "widget/list-view-column.hpp"
#include "widget/list-view-item.hpp"
#include "widget/list-view-cell.hpp"
#include "widget/progress-bar.hpp"
#include "widget/radio-button.hpp"
#include "widget/radio-label.hpp"
#include "widget/tab-frame.hpp"
#include "widget/tab-frame-item.hpp"
#include "widget/text-edit.hpp"
#include "widget/vertical-scroller.hpp"
#include "widget/vertical-slider.hpp"
#include "widget/viewport.hpp"
namespace hiro {
#if defined(Hiro_Console)
struct pConsole : public QObject, public pWidget {
Q_OBJECT
public:
Console& console;
struct QtConsole : public QTextEdit {
pConsole& self;
void keyPressEvent(QKeyEvent*);
void keyPressEventAcknowledge(QKeyEvent*);
QtConsole(pConsole& self) : self(self) {}
};
QtConsole* qtConsole;
void print(string text);
void reset();
void setBackgroundColor(Color color);
void setForegroundColor(Color color);
void setPrompt(string prompt);
pConsole(Console& console) : pWidget(console), console(console) {}
void constructor();
void destructor();
void orphan();
void keyPressEvent(QKeyEvent*);
};
#endif
#if defined(Hiro_IconView)
struct pIconView : public QObject, public pWidget {
Q_OBJECT
public:
IconView& iconView;
struct QtListWidget : public QListWidget {
void resizeEvent(QResizeEvent*);
};
QtListWidget* qtIconView;
void append();
void remove(unsigned selection);
void reset();
void setBackgroundColor(Color color);
void setFlow(Orientation flow);
void setForegroundColor(Color color);
void setImage(unsigned selection, const image& image);
void setOrientation(Orientation orientation);
void setSelected(unsigned selection, bool selected);
void setSelected(const vector<unsigned>& selections);
void setSelectedAll();
void setSelectedNone();
void setSingleSelection(bool singleSelection);
void setText(unsigned selection, const string& text);
pIconView(IconView& iconView) : pWidget(iconView), iconView(iconView) {}
void constructor();
void destructor();
void orphan();
public slots:
void onActivate();
void onChange();
void onContext();
};
#endif
#undef Declare
}

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