mirror of https://github.com/bsnes-emu/bsnes.git
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:
parent
0271d6a12b
commit
4344b916b6
|
@ -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/";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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&;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
namespace hiro {
|
||||
|
||||
auto pListViewColumn::construct() -> void {
|
||||
if(auto grandparent = _grandparent()) {
|
||||
auto handle = grandparent.data();
|
||||
unsigned offset = self().offset();
|
||||
|
||||
gtkHeader = gtk_hbox_new(false, 0);
|
||||
|
@ -18,76 +20,65 @@ auto pListViewColumn::construct() -> void {
|
|||
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", 1 + offset * 2 + 0, nullptr);
|
||||
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, false);
|
||||
gtk_tree_view_column_set_attributes(gtkColumn, gtkCellText, "text", 1 + offset * 2 + 1, nullptr);
|
||||
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)_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());
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -3,9 +3,21 @@
|
|||
namespace hiro {
|
||||
|
||||
auto pListViewItem::construct() -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->lock();
|
||||
gtk_list_store_append(parent->gtkListStore, >kIter);
|
||||
_setState();
|
||||
parent->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewItem::destruct() -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->lock();
|
||||
gtk_list_store_remove(parent->gtkListStore, >kIter);
|
||||
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, >kIter, 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, >kIter);
|
||||
} else {
|
||||
gtk_tree_selection_unselect_iter(parent->gtkTreeSelection, >kIter);
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,14 +81,15 @@ auto pListView::reset() -> void {
|
|||
auto pListView::resizeColumns() -> void {
|
||||
lock();
|
||||
|
||||
if(auto& header = state().header) {
|
||||
vector<signed> widths;
|
||||
signed minimumWidth = 0;
|
||||
signed expandable = 0;
|
||||
for(auto column : range(state().columns)) {
|
||||
for(auto column : range(header->columnCount())) {
|
||||
signed width = _width(column);
|
||||
widths.append(width);
|
||||
minimumWidth += width;
|
||||
if(state().columns[column]->expandable()) expandable++;
|
||||
if(header->column(column).expandable()) expandable++;
|
||||
}
|
||||
|
||||
signed maximumWidth = self().geometry().width() - 6;
|
||||
|
@ -145,21 +102,19 @@ auto pListView::resizeColumns() -> void {
|
|||
expandWidth = (maximumWidth - minimumWidth) / expandable;
|
||||
}
|
||||
|
||||
for(auto column : range(state().columns)) {
|
||||
if(auto self = state().columns[column]->self()) {
|
||||
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,14 +172,10 @@ 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)) {
|
||||
unsigned width = 8;
|
||||
if(auto& header = state().header) {
|
||||
if(auto column = header->column(_column)) {
|
||||
if(auto& icon = column->state.icon) {
|
||||
width += icon.width() + 2;
|
||||
}
|
||||
|
@ -251,6 +183,7 @@ auto pListView::_columnWidth(unsigned _column) -> unsigned {
|
|||
width += Font::size(column->font(true), text).width();
|
||||
}
|
||||
}
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
|
@ -260,13 +193,16 @@ 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);
|
||||
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
|
||||
|
||||
gtkListStore = gtk_list_store_newv(types.size(), types.data());
|
||||
|
@ -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,8 +222,59 @@ auto pListView::_doContext() -> void {
|
|||
if(!locked()) self().doContext();
|
||||
}
|
||||
|
||||
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(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 {
|
||||
for(auto& column : state().columns) {
|
||||
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);
|
||||
|
@ -312,6 +290,7 @@ auto pListView::_doEdit(GtkCellRendererText* gtkCellRendererText, const char* pa
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pListView::_doEvent(GdkEventButton* event) -> signed {
|
||||
|
@ -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,7 +323,8 @@ auto pListView::_doEvent(GdkEventButton* event) -> signed {
|
|||
}
|
||||
|
||||
auto pListView::_doHeaderActivate(GtkTreeViewColumn* gtkTreeViewColumn) -> void {
|
||||
for(auto& column : state().columns) {
|
||||
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);
|
||||
|
@ -352,6 +332,7 @@ auto pListView::_doHeaderActivate(GtkTreeViewColumn* gtkTreeViewColumn) -> void
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//GtkTreeView::cursor-changed and GtkTreeSelection::changed do not send signals for changes during rubber-banding selection
|
||||
|
@ -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;
|
||||
if(auto& header = state().header) {
|
||||
if(auto width = header->column(column).width()) return width;
|
||||
unsigned width = 1;
|
||||
if(!state().columns[column]->visible()) return width;
|
||||
if(state().headerVisible) {
|
||||
width = max(width, _columnWidth(column));
|
||||
}
|
||||
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;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_MenuSeparator)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMenuSeparator : pAction {
|
||||
Declare(MenuSeparator, Action)
|
||||
|
||||
QAction* qtMenuSeparator = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#if defined(Hiro_Desktop)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pDesktop {
|
||||
static auto size() -> Size;
|
||||
static auto workspace() -> Geometry;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_Group)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pGroup::construct() -> void {
|
||||
}
|
||||
|
||||
auto pGroup::destruct() -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#if defined(Hiro_Group)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pGroup : pObject {
|
||||
Declare(Group, Object)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_Hotkey)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pHotkey::construct() -> void {
|
||||
}
|
||||
|
||||
auto pHotkey::destruct() -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
#if defined(Hiro_Hotkey)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pHotkey : pObject {
|
||||
Declare(Hotkey, Object)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,13 @@
|
|||
#if defined(Hiro_Layout)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pLayout : pSizable {
|
||||
Declare(Layout, Sizable)
|
||||
|
||||
auto setVisible(bool visible) -> void override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
#if defined(Hiro_Mouse)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pMouse {
|
||||
static auto position() -> Position;
|
||||
static auto pressed(Mouse::Button button) -> bool;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue