mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-05 04:56:31 +03:00
Merge branch 'dev-treeview' into develop
This commit is contained in:
@@ -736,6 +736,48 @@ Splitter::separator:hover {
|
||||
background-color: var(--primary);
|
||||
}
|
||||
|
||||
table::header {
|
||||
background-color: var(--back);
|
||||
}
|
||||
|
||||
table::header::column {
|
||||
background-color: var(--back);
|
||||
border-right-color: var(--tab-line);
|
||||
border-right-width: 1dp;
|
||||
border-bottom-color: var(--tab-line);
|
||||
border-bottom-width: 1dp;
|
||||
border-type: inside;
|
||||
color: var(--font);
|
||||
padding: 2dp 6dp 2dp 6dp;
|
||||
transition: all 0.125s;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table::header::column:hover {
|
||||
background-color: var(--tab-hover);
|
||||
}
|
||||
|
||||
table::row {
|
||||
background-color: var(--list-back);
|
||||
transition: all 0.125s;
|
||||
}
|
||||
|
||||
table::row:hover {
|
||||
background-color: var(--back);
|
||||
}
|
||||
|
||||
table::row:selected {
|
||||
background-color: var(--primary);
|
||||
}
|
||||
|
||||
TreeView {
|
||||
background-color: var(--list-back);
|
||||
}
|
||||
|
||||
TreeView > ScrollBar {
|
||||
background-color: var(--back);
|
||||
}
|
||||
|
||||
.appbackground {
|
||||
background-color: var(--back);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ class EE_API Event {
|
||||
OnSelectionChanged,
|
||||
OnNodeDropped,
|
||||
OnSave,
|
||||
OnModelEvent,
|
||||
UserEvent,
|
||||
NoEvent = eeINDEX_NOT_FOUND
|
||||
};
|
||||
|
||||
@@ -390,6 +390,10 @@ class EE_API Node : public Transformable {
|
||||
|
||||
void forEachNode( std::function<void( Node* )> func );
|
||||
|
||||
void forEachChild( std::function<void( Node* )> func );
|
||||
|
||||
virtual void nodeDraw();
|
||||
|
||||
protected:
|
||||
typedef std::map<Uint32, std::map<Uint32, EventCallback>> EventsMap;
|
||||
friend class EventDispatcher;
|
||||
@@ -488,8 +492,6 @@ class EE_API Node : public Transformable {
|
||||
|
||||
virtual Uint32 onFocusLoss();
|
||||
|
||||
virtual void internalDraw();
|
||||
|
||||
void clipEnd();
|
||||
|
||||
void updateScreenPos();
|
||||
|
||||
184
include/eepp/ui/abstract/model.hpp
Normal file
184
include/eepp/ui/abstract/model.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
#ifndef EE_UI_MODEL_MODEL_HPP
|
||||
#define EE_UI_MODEL_MODEL_HPP
|
||||
|
||||
#include <eepp/core/core.hpp>
|
||||
#include <eepp/graphics/drawable.hpp>
|
||||
#include <eepp/math/rect.hpp>
|
||||
#include <eepp/ui/abstract/modelindex.hpp>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
using namespace EE::Graphics;
|
||||
using namespace EE::Math;
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
enum class SortOrder { None, Ascending, Descending };
|
||||
|
||||
class UIAbstractView;
|
||||
|
||||
class Variant {
|
||||
public:
|
||||
enum class Type {
|
||||
Invalid,
|
||||
DataPtr,
|
||||
String,
|
||||
Bool,
|
||||
Float,
|
||||
Int,
|
||||
Int64,
|
||||
Drawable,
|
||||
Vector2f,
|
||||
Rectf,
|
||||
cstr
|
||||
};
|
||||
Variant() : mType( Type::Invalid ) {}
|
||||
explicit Variant( const std::string& string ) : mType( Type::String ) {
|
||||
mValue.asString = eeNew( std::string, ( string ) );
|
||||
}
|
||||
Variant( Drawable* drawable, bool ownDrawable = false ) : mType( Type::Drawable ) {
|
||||
mValue.asDrawable = drawable;
|
||||
mOwnsObject = ownDrawable;
|
||||
}
|
||||
Variant( const Vector2f& v ) : mType( Type::Vector2f ) {
|
||||
mValue.asVector2f = eeNew( Vector2f, ( v ) );
|
||||
}
|
||||
Variant( void* data ) : mType( Type::DataPtr ) { mValue.asDataPtr = data; }
|
||||
Variant( const Rectf& r ) : mType( Type::Rectf ) { mValue.asRectf = eeNew( Rectf, ( r ) ); }
|
||||
Variant( bool val ) : mType( Type::Bool ) { mValue.asBool = val; }
|
||||
Variant( const Float& val ) : mType( Type::Float ) { mValue.asFloat = val; }
|
||||
Variant( const int& val ) : mType( Type::Int ) { mValue.asInt = val; }
|
||||
Variant( const Int64& val ) : mType( Type::Int64 ) { mValue.asInt64 = val; }
|
||||
explicit Variant( const char* data ) : mType( Type::cstr ) { mValue.asCStr = data; }
|
||||
~Variant() { reset(); }
|
||||
const std::string& asString() const { return *mValue.asString; }
|
||||
Drawable* asDrawable() const { return mValue.asDrawable; }
|
||||
const bool& asBool() const { return mValue.asBool; }
|
||||
const Float& asFloat() const { return mValue.asFloat; }
|
||||
const int& asInt() const { return mValue.asInt; }
|
||||
const Int64& asInt64() const { return mValue.asInt64; }
|
||||
const Vector2f& asVector2f() const { return *mValue.asVector2f; }
|
||||
const Rectf& asRectf() const { return *mValue.asRectf; }
|
||||
const char* asCStr() const { return mValue.asCStr; }
|
||||
bool is( const Type& type ) const { return type == mType; }
|
||||
void reset() {
|
||||
switch ( mType ) {
|
||||
case Type::String:
|
||||
eeSAFE_DELETE( mValue.asString );
|
||||
break;
|
||||
case Type::Drawable:
|
||||
if ( mOwnsObject )
|
||||
eeSAFE_DELETE( mValue.asDrawable );
|
||||
break;
|
||||
case Type::Vector2f:
|
||||
eeSAFE_DELETE( mValue.asVector2f );
|
||||
break;
|
||||
case Type::Rectf:
|
||||
eeSAFE_DELETE( mValue.asRectf );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mType = Type::Invalid;
|
||||
}
|
||||
bool isValid() { return mType != Type::Invalid; }
|
||||
|
||||
private:
|
||||
union {
|
||||
void* asDataPtr;
|
||||
Drawable* asDrawable;
|
||||
std::string* asString;
|
||||
bool asBool;
|
||||
Float asFloat;
|
||||
int asInt;
|
||||
Int64 asInt64;
|
||||
Vector2f* asVector2f;
|
||||
Rectf* asRectf;
|
||||
const char* asCStr;
|
||||
} mValue;
|
||||
Type mType;
|
||||
bool mOwnsObject{false};
|
||||
};
|
||||
|
||||
class EE_API Model {
|
||||
public:
|
||||
enum UpdateFlag {
|
||||
DontInvalidateIndexes = 0,
|
||||
InvalidateAllIndexes = 1 << 0,
|
||||
};
|
||||
|
||||
enum class Role {
|
||||
Display,
|
||||
Icon,
|
||||
};
|
||||
|
||||
virtual ~Model(){};
|
||||
|
||||
virtual size_t rowCount( const ModelIndex& = ModelIndex() ) const = 0;
|
||||
|
||||
virtual size_t columnCount( const ModelIndex& = ModelIndex() ) const = 0;
|
||||
|
||||
virtual std::string columnName( const size_t& /*column*/ ) const { return {}; }
|
||||
|
||||
virtual Variant data( const ModelIndex&, Role = Role::Display ) const = 0;
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
virtual ModelIndex parentIndex( const ModelIndex& ) const { return {}; }
|
||||
|
||||
virtual ModelIndex index( int row, int column = 0, const ModelIndex& = ModelIndex() ) const {
|
||||
return createIndex( row, column );
|
||||
}
|
||||
|
||||
virtual ModelIndex sibling( int row, int column, const ModelIndex& parent ) const;
|
||||
|
||||
virtual void setData( const ModelIndex&, const Variant& ) {}
|
||||
|
||||
virtual size_t treeColumn() const { return 0; }
|
||||
|
||||
virtual bool acceptsDrag( const ModelIndex&, const std::string& dataType );
|
||||
|
||||
virtual bool isColumnSortable( const size_t& /*columnIndex*/ ) const { return true; }
|
||||
|
||||
virtual std::string dragDataType() const { return {}; }
|
||||
|
||||
bool isValid( const ModelIndex& index ) const {
|
||||
auto parentIndex = this->parentIndex( index );
|
||||
return index.row() >= 0 && index.row() < (Int64)rowCount( parentIndex ) &&
|
||||
index.column() >= 0 && index.column() < (Int64)columnCount( parentIndex );
|
||||
}
|
||||
|
||||
virtual int keyColumn() const { return -1; }
|
||||
|
||||
virtual SortOrder sortOrder() const { return SortOrder::None; }
|
||||
|
||||
virtual void setKeyColumnAndSortOrder( const size_t& /*column*/, const SortOrder& /*order*/ ) {}
|
||||
|
||||
void registerView( UIAbstractView* );
|
||||
|
||||
void unregisterView( UIAbstractView* );
|
||||
|
||||
void setOnUpdate( const std::function<void()>& onUpdate );
|
||||
|
||||
protected:
|
||||
Model(){};
|
||||
|
||||
void forEachView( std::function<void( UIAbstractView* )> );
|
||||
|
||||
void onModelUpdate( unsigned flags = UpdateFlag::InvalidateAllIndexes );
|
||||
|
||||
ModelIndex createIndex( int row, int column, const void* data = nullptr ) const;
|
||||
|
||||
private:
|
||||
std::unordered_set<UIAbstractView*> mViews;
|
||||
std::function<void()> mOnUpdate;
|
||||
};
|
||||
|
||||
inline ModelIndex ModelIndex::parent() const {
|
||||
return mModel ? mModel->parentIndex( *this ) : ModelIndex();
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_MODEL_MODEL_HPP
|
||||
48
include/eepp/ui/abstract/modeleditingdelegate.hpp
Normal file
48
include/eepp/ui/abstract/modeleditingdelegate.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef EE_UI_MODELEDITINGDELEGATE_HPP
|
||||
#define EE_UI_MODELEDITINGDELEGATE_HPP
|
||||
|
||||
#include <eepp/ui/abstract/model.hpp>
|
||||
#include <eepp/ui/uiwidget.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
class EE_API ModelEditingDelegate {
|
||||
public:
|
||||
virtual ~ModelEditingDelegate() {}
|
||||
|
||||
void bind( std::shared_ptr<Model> model, const ModelIndex& index ) {
|
||||
if ( mModel.get() == model.get() && mIndex == index )
|
||||
return;
|
||||
mModel = model;
|
||||
mIndex = index;
|
||||
mWidget = createWidget();
|
||||
}
|
||||
|
||||
UIWidget* getWidget() { return mWidget; }
|
||||
UIWidget* getWidget() const { return mWidget; }
|
||||
|
||||
std::function<void()> onCommit;
|
||||
|
||||
virtual Variant getValue() const = 0;
|
||||
virtual void setValue( const Variant& ) = 0;
|
||||
virtual void willBeginEditing() {}
|
||||
|
||||
protected:
|
||||
ModelEditingDelegate() {}
|
||||
|
||||
virtual UIWidget* createWidget() = 0;
|
||||
|
||||
void commit() {
|
||||
if ( onCommit )
|
||||
onCommit();
|
||||
}
|
||||
|
||||
std::shared_ptr<Model> mModel;
|
||||
ModelIndex mIndex;
|
||||
UIWidget* mWidget;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_MODELEDITINGDELEGATE_HPP
|
||||
50
include/eepp/ui/abstract/modelindex.hpp
Normal file
50
include/eepp/ui/abstract/modelindex.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#ifndef EE_UI_MODEL_MODELINDEX_HPP
|
||||
#define EE_UI_MODEL_MODELINDEX_HPP
|
||||
|
||||
#include <eepp/config.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
class Model;
|
||||
|
||||
class EE_API ModelIndex {
|
||||
public:
|
||||
ModelIndex() {}
|
||||
|
||||
bool isValid() const { return mRow != -1 && mColumn != -1; }
|
||||
|
||||
const Int64& row() const { return mRow; }
|
||||
|
||||
const Int64& column() const { return mColumn; }
|
||||
|
||||
void* data() const { return mData; }
|
||||
|
||||
ModelIndex parent() const;
|
||||
|
||||
bool hasParent() const { return parent().isValid(); }
|
||||
|
||||
bool operator<( const ModelIndex& other ) const {
|
||||
return mRow != other.mRow || mColumn != other.mColumn;
|
||||
}
|
||||
|
||||
bool operator==( const ModelIndex& other ) const {
|
||||
return mModel == other.mModel && mRow == other.mRow && mColumn == other.mColumn &&
|
||||
mData == other.mData;
|
||||
}
|
||||
|
||||
bool operator!=( const ModelIndex& other ) const { return !( *this == other ); }
|
||||
|
||||
protected:
|
||||
friend class Model;
|
||||
const Model* mModel{nullptr};
|
||||
Int64 mRow{-1};
|
||||
Int64 mColumn{-1};
|
||||
void* mData{nullptr};
|
||||
|
||||
ModelIndex( const Model& model, int row, int column, void* internalData ) :
|
||||
mModel( &model ), mRow( row ), mColumn( column ), mData( internalData ) {}
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_MODEL_MODELINDEX_HPP
|
||||
68
include/eepp/ui/abstract/modelselection.hpp
Normal file
68
include/eepp/ui/abstract/modelselection.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef EE_UI_MODEL_MODELSELECTION_HPP
|
||||
#define EE_UI_MODEL_MODELSELECTION_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <eepp/ui/abstract/modelindex.hpp>
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
class UIAbstractView;
|
||||
|
||||
class EE_API ModelSelection {
|
||||
public:
|
||||
ModelSelection( UIAbstractView* view ) : mView( view ) {}
|
||||
|
||||
int size() const { return mIndexes.size(); }
|
||||
bool isEmpty() const { return mIndexes.empty(); }
|
||||
bool contains( const ModelIndex& index ) const {
|
||||
return std::find( mIndexes.begin(), mIndexes.end(), index ) != mIndexes.end();
|
||||
}
|
||||
bool containsRow( int row ) const {
|
||||
for ( auto& index : mIndexes ) {
|
||||
if ( index.row() == row )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void set( const ModelIndex& );
|
||||
void add( const ModelIndex& );
|
||||
void toggle( const ModelIndex& );
|
||||
bool remove( const ModelIndex& );
|
||||
void clear();
|
||||
|
||||
template <typename Callback> void forEachIndex( Callback callback ) {
|
||||
for ( auto& index : indexes() )
|
||||
callback( index );
|
||||
}
|
||||
|
||||
template <typename Callback> void forEachIndex( Callback callback ) const {
|
||||
for ( auto& index : indexes() )
|
||||
callback( index );
|
||||
}
|
||||
|
||||
std::vector<ModelIndex> indexes() const {
|
||||
std::vector<ModelIndex> selectedIndexes;
|
||||
for ( auto& index : mIndexes )
|
||||
selectedIndexes.push_back( index );
|
||||
return selectedIndexes;
|
||||
}
|
||||
|
||||
ModelIndex first() const {
|
||||
if ( mIndexes.empty() )
|
||||
return {};
|
||||
return *mIndexes.begin();
|
||||
}
|
||||
|
||||
void removeMatching( std::function<bool( const ModelIndex& )> );
|
||||
|
||||
protected:
|
||||
UIAbstractView* mView;
|
||||
std::vector<ModelIndex> mIndexes;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_MODEL_MODELSELECTION_HPP
|
||||
82
include/eepp/ui/abstract/uiabstracttableview.hpp
Normal file
82
include/eepp/ui/abstract/uiabstracttableview.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef EE_UI_UIABSTRACTTABLEVIEW_HPP
|
||||
#define EE_UI_UIABSTRACTTABLEVIEW_HPP
|
||||
|
||||
#include <eepp/math/rect.hpp>
|
||||
#include <eepp/ui/abstract/uiabstractview.hpp>
|
||||
#include <eepp/ui/uitableheadercolumn.hpp>
|
||||
|
||||
using namespace EE::Math;
|
||||
|
||||
namespace EE { namespace UI {
|
||||
class UIPushButton;
|
||||
class UILinearLayout;
|
||||
}} // namespace EE::UI
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
public:
|
||||
Uint32 getType() const;
|
||||
|
||||
bool isType( const Uint32& type ) const;
|
||||
|
||||
virtual Float getRowHeight() const { return getHeaderHeight(); }
|
||||
|
||||
virtual Float getHeaderHeight() const;
|
||||
|
||||
virtual Sizef getContentSize() const;
|
||||
|
||||
bool areHeadersVisible() const;
|
||||
|
||||
void setHeadersVisible( bool visible );
|
||||
|
||||
bool isColumnHidden( const size_t& column ) const;
|
||||
|
||||
void setColumnHidden( const size_t& column, bool hidden );
|
||||
|
||||
virtual void selectAll();
|
||||
|
||||
const Float& getDragBorderDistance() const;
|
||||
|
||||
void setDragBorderDistance( const Float& dragBorderDistance );
|
||||
|
||||
Vector2f getColumnPosition( const size_t& index );
|
||||
|
||||
protected:
|
||||
friend class EE::UI::UITableHeaderColumn;
|
||||
|
||||
virtual ~UIAbstractTableView();
|
||||
|
||||
UIAbstractTableView( const std::string& tag );
|
||||
|
||||
struct ColumnData {
|
||||
Float width{0};
|
||||
bool visible{true};
|
||||
UIPushButton* widget{nullptr};
|
||||
};
|
||||
|
||||
ColumnData& columnData( const size_t& column ) const;
|
||||
|
||||
mutable std::vector<ColumnData> mColumn;
|
||||
|
||||
virtual size_t getItemCount() const;
|
||||
|
||||
virtual void onModelUpdate( unsigned flags );
|
||||
|
||||
virtual void createOrUpdateColumns();
|
||||
|
||||
virtual void onSizeChange();
|
||||
|
||||
virtual void onColumnSizeChange( const size_t& colIndex );
|
||||
|
||||
virtual void onColumnResizeToContent( const size_t& colIndex );
|
||||
|
||||
void updateHeaderSize();
|
||||
|
||||
UILinearLayout* mHeader;
|
||||
Float mDragBorderDistance{8};
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_UIABSTRACTTABLEVIEW_HPP
|
||||
80
include/eepp/ui/abstract/uiabstractview.hpp
Normal file
80
include/eepp/ui/abstract/uiabstractview.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef EE_UI_UIABSTRACTVIEW_HPP
|
||||
#define EE_UI_UIABSTRACTVIEW_HPP
|
||||
|
||||
#include <eepp/ui/abstract/model.hpp>
|
||||
#include <eepp/ui/abstract/modeleditingdelegate.hpp>
|
||||
#include <eepp/ui/abstract/modelselection.hpp>
|
||||
#include <eepp/ui/uiscrollablewidget.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
class ModelEvent : public Event {
|
||||
public:
|
||||
ModelEvent( Model* model, const ModelIndex& index, Node* node ) :
|
||||
Event( node, Event::OnModelEvent ), model( model ), index( index ) {}
|
||||
|
||||
const Model* getModel() const { return model; }
|
||||
|
||||
const ModelIndex& getModelIndex() const { return index; }
|
||||
|
||||
protected:
|
||||
const Model* model;
|
||||
ModelIndex index;
|
||||
};
|
||||
|
||||
class EE_API UIAbstractView : public UIScrollableWidget {
|
||||
public:
|
||||
Uint32 getType() const;
|
||||
|
||||
bool isType( const Uint32& type ) const;
|
||||
|
||||
void setModel( std::shared_ptr<Model> );
|
||||
|
||||
Model* getModel() { return mModel.get(); }
|
||||
|
||||
const Model* getModel() const { return mModel.get(); }
|
||||
|
||||
ModelSelection& getSelection() { return mSelection; }
|
||||
|
||||
const ModelSelection& getSelection() const { return mSelection; }
|
||||
|
||||
virtual void selectAll() = 0;
|
||||
|
||||
void notifySelectionChange();
|
||||
|
||||
std::function<void()> getOnSelectionChange() const;
|
||||
|
||||
void setOnSelectionChange( const std::function<void()>& onSelectionChange );
|
||||
|
||||
std::function<void( const ModelIndex& )> getOnSelection() const;
|
||||
|
||||
void setOnSelection( const std::function<void( const ModelIndex& )>& onSelection );
|
||||
|
||||
protected:
|
||||
friend class Model;
|
||||
|
||||
virtual void onModelUpdate( unsigned flags );
|
||||
|
||||
virtual void onModelSelectionChange();
|
||||
|
||||
UIAbstractView( const std::string& tag );
|
||||
|
||||
virtual ~UIAbstractView();
|
||||
|
||||
bool mEditable{false};
|
||||
ModelIndex mEditIndex;
|
||||
UIWidget* mEditWidget;
|
||||
Rect mEditWidgetContentRect;
|
||||
|
||||
std::shared_ptr<Model> mModel;
|
||||
std::unique_ptr<ModelEditingDelegate> mEditingDelegate;
|
||||
ModelSelection mSelection;
|
||||
|
||||
std::function<void()> mOnSelectionChange;
|
||||
std::function<void( const ModelIndex& )> mOnSelection;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
#endif // EE_UI_UIABSTRACTVIEW_HPP
|
||||
@@ -89,6 +89,10 @@ enum UINodeType {
|
||||
UI_TYPE_ITEMCONTAINER,
|
||||
UI_TYPE_CODEEDITOR,
|
||||
UI_TYPE_SPLITTER,
|
||||
UI_TYPE_ABSTRACTVIEW,
|
||||
UI_TYPE_ABSTRACTTABLEVIEW,
|
||||
UI_TYPE_TREEVIEW,
|
||||
UI_TYPE_SCROLLABLEWIDGET,
|
||||
UI_TYPE_USER = 10000
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ template <class TContainer> void UIItemContainer<TContainer>::drawChilds() {
|
||||
if ( tParent->mItems.size() ) {
|
||||
for ( Uint32 i = tParent->mVisibleFirst; i <= tParent->mVisibleLast; i++ )
|
||||
if ( NULL != tParent->mItems[i] )
|
||||
tParent->mItems[i]->internalDraw();
|
||||
tParent->mItems[i]->nodeDraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace EE { namespace UI {
|
||||
|
||||
class EE_API UILinearLayout : public UILayout {
|
||||
public:
|
||||
static UILinearLayout* NewWithTag( const std::string& tag, const UIOrientation& orientation );
|
||||
|
||||
static UILinearLayout* New();
|
||||
|
||||
static UILinearLayout* NewVertical();
|
||||
|
||||
@@ -36,7 +36,7 @@ class EE_API UIMenuItem : public UIPushButton {
|
||||
|
||||
virtual Uint32 onMouseClick( const Vector2i& pos, const Uint32& flags );
|
||||
|
||||
virtual UIWidget* getExtraInnerWidget();
|
||||
virtual UIWidget* getExtraInnerWidget() const;
|
||||
|
||||
void createShortcutView();
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ class EE_API UIMenuSubMenu : public UIMenuItem {
|
||||
|
||||
virtual void onAlphaChange();
|
||||
|
||||
virtual UIWidget* getExtraInnerWidget();
|
||||
virtual UIWidget* getExtraInnerWidget() const;
|
||||
|
||||
void onSubMenuFocusLoss( const Event* Event );
|
||||
|
||||
|
||||
@@ -257,6 +257,8 @@ class EE_API UINode : public Node {
|
||||
|
||||
Rectf getLocalDpBounds() const;
|
||||
|
||||
virtual void nodeDraw();
|
||||
|
||||
protected:
|
||||
Vector2f mDpPos;
|
||||
Sizef mDpSize;
|
||||
@@ -318,8 +320,6 @@ class EE_API UINode : public Node {
|
||||
|
||||
void checkClose();
|
||||
|
||||
virtual void internalDraw();
|
||||
|
||||
virtual void onWidgetFocusLoss();
|
||||
|
||||
void writeFlag( const Uint32& Flag, const Uint32& Val );
|
||||
|
||||
@@ -11,6 +11,8 @@ class EE_API UIPushButton : public UIWidget {
|
||||
public:
|
||||
static UIPushButton* New();
|
||||
|
||||
static UIPushButton* NewWithTag( const std::string& tag );
|
||||
|
||||
UIPushButton();
|
||||
|
||||
virtual ~UIPushButton();
|
||||
@@ -40,6 +42,10 @@ class EE_API UIPushButton : public UIWidget {
|
||||
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex = 0 );
|
||||
|
||||
void setTextAlign( const Uint32& align );
|
||||
|
||||
virtual Sizef getContentSize() const;
|
||||
|
||||
protected:
|
||||
UIImage* mIcon;
|
||||
UITextView* mTextBox;
|
||||
@@ -65,7 +71,7 @@ class EE_API UIPushButton : public UIWidget {
|
||||
|
||||
virtual Uint32 onKeyUp( const KeyEvent& Event );
|
||||
|
||||
virtual UIWidget* getExtraInnerWidget();
|
||||
virtual UIWidget* getExtraInnerWidget() const;
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
80
include/eepp/ui/uiscrollablewidget.hpp
Normal file
80
include/eepp/ui/uiscrollablewidget.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef EE_UI_UISCROLLABLEWIDGET_HPP
|
||||
#define EE_UI_UISCROLLABLEWIDGET_HPP
|
||||
|
||||
#include <eepp/ui/uitouchdraggablewidget.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
class UIScrollBar;
|
||||
|
||||
class EE_API UIScrollableWidget : public UIWidget {
|
||||
public:
|
||||
enum ScrollViewType { Inclusive, Exclusive };
|
||||
|
||||
virtual Uint32 getType() const;
|
||||
|
||||
virtual bool isType( const Uint32& type ) const;
|
||||
|
||||
void setVerticalScrollMode( const ScrollBarMode& Mode );
|
||||
|
||||
const ScrollBarMode& getVerticalScrollMode();
|
||||
|
||||
void setHorizontalScrollMode( const ScrollBarMode& Mode );
|
||||
|
||||
const ScrollBarMode& getHorizontalScrollMode();
|
||||
|
||||
const ScrollViewType& getViewType() const;
|
||||
|
||||
void setViewType( const ScrollViewType& viewType );
|
||||
|
||||
UIScrollBar* getVerticalScrollBar() const;
|
||||
|
||||
UIScrollBar* getHorizontalScrollBar() const;
|
||||
|
||||
virtual bool applyProperty( const StyleSheetProperty& attribute );
|
||||
|
||||
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex = 0 );
|
||||
|
||||
virtual Sizef getContentSize() const = 0;
|
||||
|
||||
void scrollToTop();
|
||||
|
||||
void scrollToBottom();
|
||||
|
||||
Sizef getScrollableArea() const;
|
||||
|
||||
Sizef getVisibleArea() const;
|
||||
|
||||
protected:
|
||||
ScrollViewType mViewType;
|
||||
ScrollBarMode mVScrollMode;
|
||||
ScrollBarMode mHScrollMode;
|
||||
UIScrollBar* mVScroll;
|
||||
UIScrollBar* mHScroll;
|
||||
Uint32 mSizeChangeCb;
|
||||
Uint32 mPosChangeCb;
|
||||
Vector2f mScrollOffset;
|
||||
|
||||
UIScrollableWidget( const std::string& tag );
|
||||
|
||||
virtual Uint32 onMessage( const NodeMessage* Msg );
|
||||
|
||||
virtual void onSizeChange();
|
||||
|
||||
virtual void onAlphaChange();
|
||||
|
||||
virtual void onPaddingChange();
|
||||
|
||||
void onValueChangeCb( const Event* Event );
|
||||
|
||||
virtual void onContentSizeChange();
|
||||
|
||||
virtual void updateScroll();
|
||||
|
||||
virtual void onScrollChange();
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif // EE_UI_UISCROLLABLEWIDGET_HPP
|
||||
@@ -62,7 +62,7 @@ class EE_API UITab : public UISelectButton {
|
||||
|
||||
virtual void onSizeChange();
|
||||
|
||||
virtual UIWidget* getExtraInnerWidget();
|
||||
virtual UIWidget* getExtraInnerWidget() const;
|
||||
|
||||
void setOwnedNode();
|
||||
|
||||
|
||||
38
include/eepp/ui/uitableheadercolumn.hpp
Normal file
38
include/eepp/ui/uitableheadercolumn.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef EE_UI_UITABLEHEADERCOLUMN_HPP
|
||||
#define EE_UI_UITABLEHEADERCOLUMN_HPP
|
||||
|
||||
#include <eepp/ui/uipushbutton.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
namespace Abstract {
|
||||
class UIAbstractTableView;
|
||||
}
|
||||
using namespace Abstract;
|
||||
|
||||
class UITableHeaderColumn : public UIPushButton {
|
||||
public:
|
||||
UITableHeaderColumn( UIAbstractTableView* view, const size_t& colIndex );
|
||||
|
||||
protected:
|
||||
UIAbstractTableView* mView;
|
||||
size_t mColIndex;
|
||||
|
||||
Uint32 onCalculateDrag( const Vector2f& position, const Uint32& flags );
|
||||
|
||||
Uint32 onMouseDown( const Vector2i& position, const Uint32& flags );
|
||||
|
||||
Uint32 onDrag( const Vector2f& position, const Uint32&, const Sizef& dragDiff );
|
||||
|
||||
Uint32 onMouseLeave( const Vector2i& position, const Uint32& flags );
|
||||
|
||||
Uint32 onMouseMove( const Vector2i& position, const Uint32& flags );
|
||||
|
||||
Uint32 onMouseDoubleClick( const Vector2i& position, const Uint32& flags );
|
||||
|
||||
Uint32 onDragStop( const Vector2i& pos, const Uint32& flags );
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // EE_UI_UITABLEHEADERCOLUMN_HPP
|
||||
@@ -86,6 +86,7 @@ class EE_API UITextView : public UIWidget {
|
||||
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex = 0 );
|
||||
|
||||
void setTextAlign( const Uint32& align );
|
||||
protected:
|
||||
Text* mTextCache;
|
||||
String mString;
|
||||
|
||||
95
include/eepp/ui/uitreeview.hpp
Normal file
95
include/eepp/ui/uitreeview.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef EE_UI_UITREEVIEW_HPP
|
||||
#define EE_UI_UITREEVIEW_HPP
|
||||
|
||||
#include <eepp/ui/abstract/uiabstracttableview.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace EE::UI::Abstract;
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
class UITableRow;
|
||||
|
||||
class EE_API UITreeView : public UIAbstractTableView {
|
||||
public:
|
||||
static UITreeView* New();
|
||||
|
||||
Uint32 getType() const;
|
||||
|
||||
bool isType( const Uint32& type ) const;
|
||||
|
||||
const Float& getIndentWidth() const;
|
||||
|
||||
void setIndentWidth( const Float& indentWidth );
|
||||
|
||||
virtual Sizef getContentSize() const;
|
||||
|
||||
virtual void drawChilds();
|
||||
|
||||
virtual Node* overFind( const Vector2f& point );
|
||||
|
||||
bool isExpanded( const ModelIndex& index ) const;
|
||||
|
||||
Drawable* getExpandIcon() const;
|
||||
|
||||
void setExpandedIcon( Drawable* expandIcon );
|
||||
|
||||
Drawable* getContractIcon() const;
|
||||
|
||||
void setContractedIcon( Drawable* contractIcon );
|
||||
|
||||
protected:
|
||||
enum class IterationDecision {
|
||||
Continue,
|
||||
Break,
|
||||
Stop,
|
||||
};
|
||||
|
||||
Float mIndentWidth;
|
||||
Sizef mContentSize;
|
||||
Drawable* mExpandIcon{nullptr};
|
||||
Drawable* mContractIcon{nullptr};
|
||||
|
||||
UITreeView();
|
||||
|
||||
virtual void createOrUpdateColumns();
|
||||
|
||||
struct MetadataForIndex;
|
||||
|
||||
template <typename Callback> void traverseTree( Callback ) const;
|
||||
|
||||
mutable std::map<void*, std::unique_ptr<MetadataForIndex>> mViewMetadata;
|
||||
mutable std::vector<std::map<int, UIWidget*>> mWidgets;
|
||||
mutable std::vector<UITableRow*> mRows;
|
||||
|
||||
virtual size_t getItemCount() const;
|
||||
|
||||
UITreeView::MetadataForIndex& getIndexMetadata( const ModelIndex& index ) const;
|
||||
|
||||
virtual void onColumnSizeChange( const size_t& colIndex );
|
||||
|
||||
virtual UIWidget* updateCell( const int& rowIndex, const ModelIndex& index, const size_t& col,
|
||||
const size_t& indentLevel, const Float& yOffset );
|
||||
|
||||
virtual UIWidget* updateRow( const int& rowIndex, const ModelIndex& index,
|
||||
const Float& yOffset );
|
||||
|
||||
virtual UIWidget* createCell( UIWidget* rowWidget, const ModelIndex& index, const size_t& col );
|
||||
|
||||
virtual void onScrollChange();
|
||||
|
||||
virtual void onColumnResizeToContent( const size_t& colIndex );
|
||||
|
||||
virtual void onModelSelectionChange();
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event );
|
||||
|
||||
virtual void onOpenModelIndex( const ModelIndex& index );
|
||||
|
||||
void updateContentSize();
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif // EE_UI_UITREEVIEW_HPP
|
||||
@@ -141,7 +141,7 @@ class EE_API UIWindow : public UIWidget {
|
||||
|
||||
virtual bool applyProperty( const StyleSheetProperty& attribute );
|
||||
|
||||
virtual void internalDraw();
|
||||
virtual void nodeDraw();
|
||||
|
||||
void invalidate( Node* invalidator );
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ function build_link_configuration( package_name, use_ee_icon )
|
||||
end
|
||||
|
||||
fix_shared_lib_linking_path( package_name, "libeepp-debug" )
|
||||
|
||||
|
||||
if not os.is_real("emscripten") then
|
||||
targetname ( package_name .. "-debug" .. extension )
|
||||
else
|
||||
@@ -748,7 +748,7 @@ function build_eepp( build_name )
|
||||
"src/eepp/scene/*.cpp",
|
||||
"src/eepp/scene/actions/*.cpp",
|
||||
"src/eepp/ui/*.cpp",
|
||||
"src/eepp/ui/actions/*.cpp",
|
||||
"src/eepp/ui/abstract/*.cpp",
|
||||
"src/eepp/ui/css/*.cpp",
|
||||
"src/eepp/ui/doc/*.cpp",
|
||||
"src/eepp/ui/tools/*.cpp",
|
||||
|
||||
1710
premake5.lua
1710
premake5.lua
File diff suppressed because it is too large
Load Diff
@@ -82,7 +82,7 @@ CODE_SRCS := \
|
||||
ui/*.cpp \
|
||||
ui/css/*.cpp \
|
||||
ui/doc/*.cpp \
|
||||
ui/actions/*.cpp \
|
||||
ui/model/*.cpp \
|
||||
ui/tools/*.cpp \
|
||||
maps/*.cpp \
|
||||
maps/mapeditor/*.cpp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 4.12.2, 2020-07-02T20:21:25. -->
|
||||
<!-- Written by QtCreator 4.12.2, 2020-07-04T20:24:45. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
|
||||
@@ -294,8 +294,14 @@
|
||||
../../include/eepp/thirdparty/chipmunk/cpSpatialIndex.h
|
||||
../../include/eepp/thirdparty/chipmunk/cpVect.h
|
||||
../../include/eepp/thirdparty/PlusCallback/callback.hpp
|
||||
../../include/eepp/ui/abstract/model.hpp
|
||||
../../include/eepp/ui/abstract/uiabstracttableview.hpp
|
||||
../../include/eepp/ui/abstract/uiabstractview.hpp
|
||||
../../include/eepp/ui/base.hpp
|
||||
../../include/eepp/ui.hpp
|
||||
../../include/eepp/ui/abstract/modeleditingdelegate.hpp
|
||||
../../include/eepp/ui/abstract/modelindex.hpp
|
||||
../../include/eepp/ui/abstract/modelselection.hpp
|
||||
../../include/eepp/ui/border.hpp
|
||||
../../include/eepp/ui/css/animationdefinition.hpp
|
||||
../../include/eepp/ui/css/drawableimageparser.hpp
|
||||
@@ -331,9 +337,13 @@
|
||||
../../include/eepp/ui/doc/undostack.hpp
|
||||
../../include/eepp/ui/keyboardshortcut.hpp
|
||||
../../include/eepp/ui/marginmove/scale.hpp
|
||||
../../include/eepp/ui/abstract/model.hpp
|
||||
../../include/eepp/ui/abstract/modelindex.hpp
|
||||
../../include/eepp/ui/abstract/modelselection.hpp
|
||||
../../include/eepp/ui/tools/textureatlaseditor.hpp
|
||||
../../include/eepp/ui/tools/uicodeeditorsplitter.hpp
|
||||
../../include/eepp/ui/tools/uicolorpicker.hpp
|
||||
../../include/eepp/ui/uiabstractview.hpp
|
||||
../../include/eepp/ui/uibackgrounddrawable.hpp
|
||||
../../include/eepp/ui/uiborderdrawable.hpp
|
||||
../../include/eepp/ui/uicheckbox.hpp
|
||||
@@ -371,6 +381,7 @@
|
||||
../../include/eepp/ui/uiradiobutton.hpp
|
||||
../../include/eepp/ui/uirelativelayout.hpp
|
||||
../../include/eepp/ui/uiscenenode.hpp
|
||||
../../include/eepp/ui/uiscrollablewidget.hpp
|
||||
../../include/eepp/ui/uiscrollbar.hpp
|
||||
../../include/eepp/ui/uiscrollview.hpp
|
||||
../../include/eepp/ui/uiselectbutton.hpp
|
||||
@@ -385,6 +396,7 @@
|
||||
../../include/eepp/ui/uitab.hpp
|
||||
../../include/eepp/ui/uitablecell.hpp
|
||||
../../include/eepp/ui/uitable.hpp
|
||||
../../include/eepp/ui/uitableheadercolumn.hpp
|
||||
../../include/eepp/ui/uitabwidget.hpp
|
||||
../../include/eepp/ui/uitextedit.hpp
|
||||
../../include/eepp/ui/uitextinput.hpp
|
||||
@@ -395,6 +407,7 @@
|
||||
../../include/eepp/ui/uithememanager.hpp
|
||||
../../include/eepp/ui/uitooltip.hpp
|
||||
../../include/eepp/ui/uitouchdraggablewidget.hpp
|
||||
../../include/eepp/ui/uitreeview.hpp
|
||||
../../include/eepp/ui/uiviewpager.hpp
|
||||
../../include/eepp/ui/uiwidgetcreator.hpp
|
||||
../../include/eepp/ui/uiwidget.hpp
|
||||
@@ -754,6 +767,10 @@
|
||||
../../src/eepp/system/translator.cpp
|
||||
../../src/eepp/system/virtualfilesystem.cpp
|
||||
../../src/eepp/system/zip.cpp
|
||||
../../src/eepp/ui/abstract/model.cpp
|
||||
../../src/eepp/ui/abstract/modelselection.cpp
|
||||
../../src/eepp/ui/abstract/uiabstracttableview.cpp
|
||||
../../src/eepp/ui/abstract/uiabstractview.cpp
|
||||
../../src/eepp/ui/border.cpp
|
||||
../../src/eepp/ui/css/animationdefinition.cpp
|
||||
../../src/eepp/ui/css/drawableimageparser.cpp
|
||||
@@ -784,6 +801,8 @@
|
||||
../../src/eepp/ui/doc/textdocument.cpp
|
||||
../../src/eepp/ui/doc/undostack.cpp
|
||||
../../src/eepp/ui/keyboardshortcut.cpp
|
||||
../../src/eepp/ui/abstract/model.cpp
|
||||
../../src/eepp/ui/abstract/modelselection.cpp
|
||||
../../src/eepp/ui/tools/textureatlaseditor.cpp
|
||||
../../src/eepp/ui/tools/textureatlasnew.cpp
|
||||
../../src/eepp/ui/tools/textureatlasnew.hpp
|
||||
@@ -791,6 +810,7 @@
|
||||
../../src/eepp/ui/tools/textureatlastextureregioneditor.hpp
|
||||
../../src/eepp/ui/tools/uicodeeditorsplitter.cpp
|
||||
../../src/eepp/ui/tools/uicolorpicker.cpp
|
||||
../../src/eepp/ui/uiabstractview.cpp
|
||||
../../src/eepp/ui/uibackgrounddrawable.cpp
|
||||
../../src/eepp/ui/uiborderdrawable.cpp
|
||||
../../src/eepp/ui/uicheckbox.cpp
|
||||
@@ -825,6 +845,7 @@
|
||||
../../src/eepp/ui/uiradiobutton.cpp
|
||||
../../src/eepp/ui/uirelativelayout.cpp
|
||||
../../src/eepp/ui/uiscenenode.cpp
|
||||
../../src/eepp/ui/uiscrollablewidget.cpp
|
||||
../../src/eepp/ui/uiscrollbar.cpp
|
||||
../../src/eepp/ui/uiscrollview.cpp
|
||||
../../src/eepp/ui/uiselectbutton.cpp
|
||||
@@ -839,6 +860,7 @@
|
||||
../../src/eepp/ui/uitab.cpp
|
||||
../../src/eepp/ui/uitablecell.cpp
|
||||
../../src/eepp/ui/uitable.cpp
|
||||
../../src/eepp/ui/uitableheadercolumn.cpp
|
||||
../../src/eepp/ui/uitabwidget.cpp
|
||||
../../src/eepp/ui/uitextedit.cpp
|
||||
../../src/eepp/ui/uitextinput.cpp
|
||||
@@ -849,6 +871,7 @@
|
||||
../../src/eepp/ui/uithememanager.cpp
|
||||
../../src/eepp/ui/uitooltip.cpp
|
||||
../../src/eepp/ui/uitouchdraggablewidget.cpp
|
||||
../../src/eepp/ui/uitreeview.cpp
|
||||
../../src/eepp/ui/uiviewpager.cpp
|
||||
../../src/eepp/ui/uiwidget.cpp
|
||||
../../src/eepp/ui/uiwidgetcreator.cpp
|
||||
|
||||
@@ -48,7 +48,7 @@ Node::~Node() {
|
||||
if ( NULL != mParentNode )
|
||||
mParentNode->childRemove( this );
|
||||
|
||||
EventDispatcher* eventDispatcher = NULL != mSceneNode ? mSceneNode->getEventDispatcher() : NULL;
|
||||
EventDispatcher* eventDispatcher = getEventDispatcher();
|
||||
|
||||
if ( NULL != eventDispatcher ) {
|
||||
if ( eventDispatcher->getFocusNode() == this && mSceneNode != this ) {
|
||||
@@ -489,7 +489,7 @@ void Node::drawChilds() {
|
||||
|
||||
while ( NULL != child ) {
|
||||
if ( child->mVisible ) {
|
||||
child->internalDraw();
|
||||
child->nodeDraw();
|
||||
}
|
||||
|
||||
child = child->mPrev;
|
||||
@@ -499,7 +499,7 @@ void Node::drawChilds() {
|
||||
|
||||
while ( NULL != child ) {
|
||||
if ( child->mVisible ) {
|
||||
child->internalDraw();
|
||||
child->nodeDraw();
|
||||
}
|
||||
|
||||
child = child->mNext;
|
||||
@@ -507,7 +507,7 @@ void Node::drawChilds() {
|
||||
}
|
||||
}
|
||||
|
||||
void Node::internalDraw() {
|
||||
void Node::nodeDraw() {
|
||||
if ( mVisible ) {
|
||||
if ( mNodeFlags & NODE_FLAG_POSITION_DIRTY )
|
||||
updateScreenPos();
|
||||
@@ -912,6 +912,14 @@ void Node::forEachNode( std::function<void( Node* )> func ) {
|
||||
}
|
||||
}
|
||||
|
||||
void Node::forEachChild( std::function<void( Node* )> func ) {
|
||||
Node* node = mChild;
|
||||
while ( node ) {
|
||||
func( node );
|
||||
node = node->getNextNode();
|
||||
}
|
||||
}
|
||||
|
||||
void Node::onSceneChange() {
|
||||
mSceneNode = findSceneNode();
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ std::string Color::toHexString( const bool& prependHashtag ) const {
|
||||
stream << std::setfill( '0' ) << std::setw( sizeof( Color ) * 2 ) << std::hex << getValue();
|
||||
std::string str = stream.str();
|
||||
if ( this->a == 255 )
|
||||
return str.substr( 0, 6 );
|
||||
return str.substr( 0, prependHashtag ? 7 : 6 );
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
46
src/eepp/ui/abstract/model.cpp
Normal file
46
src/eepp/ui/abstract/model.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <eepp/ui/abstract/model.hpp>
|
||||
#include <eepp/ui/abstract/uiabstractview.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
void Model::onModelUpdate( unsigned flags ) {
|
||||
if ( mOnUpdate )
|
||||
mOnUpdate();
|
||||
forEachView( [&]( UIAbstractView* view ) { view->onModelUpdate( flags ); } );
|
||||
}
|
||||
|
||||
void Model::forEachView( std::function<void( UIAbstractView* )> callback ) {
|
||||
for ( auto view : mViews )
|
||||
callback( view );
|
||||
}
|
||||
|
||||
void Model::unregisterView( UIAbstractView* view ) {
|
||||
mViews.erase( view );
|
||||
}
|
||||
|
||||
void Model::registerView( UIAbstractView* view ) {
|
||||
mViews.insert( view );
|
||||
}
|
||||
|
||||
ModelIndex Model::createIndex( int row, int column, const void* data ) const {
|
||||
return ModelIndex( *this, row, column, const_cast<void*>( data ) );
|
||||
}
|
||||
|
||||
void Model::setOnUpdate( const std::function<void()>& onUpdate ) {
|
||||
mOnUpdate = onUpdate;
|
||||
}
|
||||
|
||||
ModelIndex Model::sibling( int row, int column, const ModelIndex& parent ) const {
|
||||
if ( !parent.isValid() )
|
||||
return index( row, column, {} );
|
||||
int rowCount = this->rowCount( parent );
|
||||
if ( row < 0 || row > rowCount )
|
||||
return {};
|
||||
return index( row, column, parent );
|
||||
}
|
||||
|
||||
bool Model::acceptsDrag( const ModelIndex&, const std::string& ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
62
src/eepp/ui/abstract/modelselection.cpp
Normal file
62
src/eepp/ui/abstract/modelselection.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <eepp/core.hpp>
|
||||
#include <eepp/ui/abstract/modelselection.hpp>
|
||||
#include <eepp/ui/abstract/uiabstractview.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
void ModelSelection::removeMatching( std::function<bool( const ModelIndex& )> filter ) {
|
||||
std::vector<std::vector<ModelIndex>::iterator> toRemove;
|
||||
for ( auto it = mIndexes.begin(); it != mIndexes.end(); it++ ) {
|
||||
if ( filter( *it ) )
|
||||
toRemove.push_back( it );
|
||||
}
|
||||
for ( auto& index : toRemove )
|
||||
mIndexes.erase( index );
|
||||
}
|
||||
|
||||
void ModelSelection::set( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
if ( mIndexes.size() == 1 && contains( index ) )
|
||||
return;
|
||||
mIndexes.clear();
|
||||
mIndexes.push_back( index );
|
||||
mView->notifySelectionChange();
|
||||
}
|
||||
|
||||
void ModelSelection::add( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains == mIndexes.end() )
|
||||
return;
|
||||
mIndexes.push_back( index );
|
||||
mView->notifySelectionChange();
|
||||
}
|
||||
|
||||
void ModelSelection::toggle( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains != mIndexes.end() )
|
||||
mIndexes.erase( contains );
|
||||
else
|
||||
mIndexes.push_back( index );
|
||||
mView->notifySelectionChange();
|
||||
}
|
||||
|
||||
bool ModelSelection::remove( const ModelIndex& index ) {
|
||||
eeASSERT( index.isValid() );
|
||||
auto contains = std::find( mIndexes.begin(), mIndexes.end(), index );
|
||||
if ( contains == mIndexes.end() )
|
||||
return false;
|
||||
mIndexes.erase( contains );
|
||||
mView->notifySelectionChange();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelSelection::clear() {
|
||||
if ( mIndexes.empty() )
|
||||
return;
|
||||
mIndexes.clear();
|
||||
mView->notifySelectionChange();
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
165
src/eepp/ui/abstract/uiabstracttableview.cpp
Normal file
165
src/eepp/ui/abstract/uiabstracttableview.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#include <eepp/ui/abstract/uiabstracttableview.hpp>
|
||||
#include <eepp/ui/uilinearlayout.hpp>
|
||||
#include <eepp/ui/uipushbutton.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
UIAbstractTableView::UIAbstractTableView( const std::string& tag ) :
|
||||
UIAbstractView( tag ), mDragBorderDistance( PixelDensity::dpToPx( 4 ) ) {
|
||||
mHeader = UILinearLayout::NewWithTag( "table::header", UIOrientation::Horizontal );
|
||||
mHeader->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
mHeader->setParent( this );
|
||||
mHeader->setVisible( true );
|
||||
mHeader->setEnabled( true );
|
||||
}
|
||||
|
||||
UIAbstractTableView::~UIAbstractTableView() {}
|
||||
|
||||
Uint32 UIAbstractTableView::getType() const {
|
||||
return UI_TYPE_ABSTRACTTABLEVIEW;
|
||||
}
|
||||
|
||||
bool UIAbstractTableView::isType( const Uint32& type ) const {
|
||||
return UIAbstractTableView::getType() == type ? true : UIAbstractView::isType( type );
|
||||
}
|
||||
|
||||
void UIAbstractTableView::selectAll() {
|
||||
getSelection().clear();
|
||||
for ( size_t itemIndex = 0; itemIndex < getItemCount(); ++itemIndex ) {
|
||||
auto index = getModel()->index( itemIndex );
|
||||
getSelection().add( index );
|
||||
}
|
||||
}
|
||||
|
||||
size_t UIAbstractTableView::getItemCount() const {
|
||||
if ( !getModel() )
|
||||
return 0;
|
||||
return getModel()->rowCount();
|
||||
}
|
||||
|
||||
void UIAbstractTableView::onModelUpdate( unsigned flags ) {
|
||||
UIAbstractView::onModelUpdate( flags );
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
|
||||
void UIAbstractTableView::createOrUpdateColumns() {
|
||||
Model* model = getModel();
|
||||
if ( !model )
|
||||
return;
|
||||
|
||||
size_t count = model->columnCount();
|
||||
Float totalWidth = 0;
|
||||
|
||||
for ( size_t i = 0; i < count; i++ ) {
|
||||
ColumnData& col = columnData( i );
|
||||
if ( !col.widget ) {
|
||||
col.widget = eeNew( UITableHeaderColumn, ( this, i ) );
|
||||
col.widget->setParent( mHeader );
|
||||
col.widget->setEnabled( true );
|
||||
col.widget->setVisible( true );
|
||||
}
|
||||
col.visible = !isColumnHidden( i );
|
||||
col.widget->setVisible( col.visible );
|
||||
if ( !col.visible )
|
||||
continue;
|
||||
col.widget->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent );
|
||||
col.widget->setText( model->columnName( i ) );
|
||||
col.widget->reloadStyle( true, true, true );
|
||||
col.width = eeceil( eemax( col.width, col.widget->getPixelsSize().getWidth() ) );
|
||||
col.widget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
col.widget->setPixelsSize( col.width, getHeaderHeight() );
|
||||
totalWidth += col.width;
|
||||
}
|
||||
|
||||
if ( count < mColumn.size() ) {
|
||||
for ( size_t i = count; i < mColumn.size(); i++ ) {
|
||||
ColumnData& col = columnData( i );
|
||||
col.width = 0;
|
||||
col.visible = false;
|
||||
if ( col.widget ) {
|
||||
col.widget->close();
|
||||
col.widget = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mHeader->setPixelsSize( totalWidth, getHeaderHeight() );
|
||||
mHeader->updateLayout();
|
||||
}
|
||||
|
||||
Float UIAbstractTableView::getHeaderHeight() const {
|
||||
return areHeadersVisible() ? eeceil( columnData( 0 ).widget
|
||||
? columnData( 0 ).widget->getPixelsSize().getHeight()
|
||||
: 16 )
|
||||
: 0;
|
||||
}
|
||||
|
||||
Sizef UIAbstractTableView::getContentSize() const {
|
||||
size_t count = getModel()->columnCount();
|
||||
Sizef size;
|
||||
for ( size_t i = 0; i < count; i++ )
|
||||
if ( !isColumnHidden( i ) )
|
||||
size.x += columnData( i ).width;
|
||||
size.y = getHeaderHeight();
|
||||
size.y += getItemCount() * getRowHeight();
|
||||
return size;
|
||||
}
|
||||
|
||||
bool UIAbstractTableView::areHeadersVisible() const {
|
||||
return mHeader->isVisible();
|
||||
}
|
||||
|
||||
void UIAbstractTableView::setHeadersVisible( bool visible ) {
|
||||
mHeader->setVisible( visible );
|
||||
}
|
||||
|
||||
void UIAbstractTableView::onSizeChange() {
|
||||
UIAbstractView::onSizeChange();
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
|
||||
void UIAbstractTableView::onColumnSizeChange( const size_t& ) {}
|
||||
|
||||
void UIAbstractTableView::onColumnResizeToContent( const size_t& ) {}
|
||||
|
||||
void UIAbstractTableView::updateHeaderSize() {
|
||||
size_t count = getModel()->columnCount();
|
||||
Float totalWidth = 0;
|
||||
for ( size_t i = 0; i < count; i++ ) {
|
||||
ColumnData& col = columnData( i );
|
||||
totalWidth += col.width;
|
||||
}
|
||||
mHeader->setPixelsSize( totalWidth, getHeaderHeight() );
|
||||
}
|
||||
|
||||
const Float& UIAbstractTableView::getDragBorderDistance() const {
|
||||
return mDragBorderDistance;
|
||||
}
|
||||
|
||||
void UIAbstractTableView::setDragBorderDistance( const Float& dragBorderDistance ) {
|
||||
mDragBorderDistance = dragBorderDistance;
|
||||
}
|
||||
|
||||
Vector2f UIAbstractTableView::getColumnPosition( const size_t& index ) {
|
||||
return columnData( index ).widget->getPixelsPosition();
|
||||
}
|
||||
|
||||
UIAbstractTableView::ColumnData& UIAbstractTableView::columnData( const size_t& column ) const {
|
||||
if ( column >= mColumn.size() )
|
||||
mColumn.resize( column + 1 );
|
||||
return mColumn[column];
|
||||
}
|
||||
|
||||
bool UIAbstractTableView::isColumnHidden( const size_t& column ) const {
|
||||
return !columnData( column ).visible;
|
||||
}
|
||||
|
||||
void UIAbstractTableView::setColumnHidden( const size_t& column, bool hidden ) {
|
||||
if ( columnData( column ).visible != !hidden ) {
|
||||
columnData( column ).visible = !hidden;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
65
src/eepp/ui/abstract/uiabstractview.cpp
Normal file
65
src/eepp/ui/abstract/uiabstractview.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <eepp/ui/abstract/uiabstractview.hpp>
|
||||
|
||||
namespace EE { namespace UI { namespace Abstract {
|
||||
|
||||
UIAbstractView::UIAbstractView( const std::string& tag ) :
|
||||
UIScrollableWidget( tag ), mSelection( this ) {}
|
||||
|
||||
UIAbstractView::~UIAbstractView() {}
|
||||
|
||||
std::function<void( const ModelIndex& )> UIAbstractView::getOnSelection() const {
|
||||
return mOnSelection;
|
||||
}
|
||||
|
||||
void UIAbstractView::setOnSelection( const std::function<void( const ModelIndex& )>& onSelection ) {
|
||||
mOnSelection = onSelection;
|
||||
}
|
||||
|
||||
std::function<void()> UIAbstractView::getOnSelectionChange() const {
|
||||
return mOnSelectionChange;
|
||||
}
|
||||
|
||||
void UIAbstractView::setOnSelectionChange( const std::function<void()>& onSelectionChange ) {
|
||||
mOnSelectionChange = onSelectionChange;
|
||||
}
|
||||
|
||||
Uint32 UIAbstractView::getType() const {
|
||||
return UI_TYPE_ABSTRACTVIEW;
|
||||
}
|
||||
|
||||
bool UIAbstractView::isType( const Uint32& type ) const {
|
||||
return UIAbstractView::getType() == type ? true : UIScrollableWidget::isType( type );
|
||||
}
|
||||
|
||||
void UIAbstractView::setModel( std::shared_ptr<Model> model ) {
|
||||
if ( model.get() == mModel.get() )
|
||||
return;
|
||||
if ( mModel )
|
||||
mModel->unregisterView( this );
|
||||
mModel = model;
|
||||
if ( mModel )
|
||||
mModel->registerView( this );
|
||||
onModelUpdate( Model::InvalidateAllIndexes );
|
||||
}
|
||||
|
||||
void UIAbstractView::onModelUpdate( unsigned flags ) {
|
||||
if ( !getModel() || ( flags & Model::InvalidateAllIndexes ) ) {
|
||||
getSelection().clear();
|
||||
} else {
|
||||
getSelection().removeMatching(
|
||||
[this]( auto& index ) { return !getModel()->isValid( index ); } );
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractView::onModelSelectionChange() {
|
||||
if ( getModel() && mOnSelection && getSelection().first().isValid() )
|
||||
mOnSelection( getSelection().first() );
|
||||
}
|
||||
|
||||
void UIAbstractView::notifySelectionChange() {
|
||||
onModelSelectionChange();
|
||||
if ( mOnSelectionChange )
|
||||
mOnSelectionChange();
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
@@ -130,7 +130,7 @@ void StyleSheetPropertyAnimation::tweenProperty( UIWidget* widget, const Float&
|
||||
StyleSheetPropertyAnimation* StyleSheetPropertyAnimation::fromAnimationKeyframes(
|
||||
const AnimationDefinition& animation, const KeyframesDefinition& keyframes,
|
||||
const PropertyDefinition* propertyDef, UIWidget* widget, const Uint32& propertyIndex,
|
||||
const AnimationOrigin& animationOrigin ) {
|
||||
const AnimationOrigin& ) {
|
||||
std::vector<std::string> properties;
|
||||
std::vector<Float> times;
|
||||
|
||||
@@ -314,7 +314,7 @@ void StyleSheetPropertyAnimation::onStart() {
|
||||
}
|
||||
}
|
||||
|
||||
void StyleSheetPropertyAnimation::onUpdate( const Time& time ) {
|
||||
void StyleSheetPropertyAnimation::onUpdate( const Time& ) {
|
||||
if ( NULL != mNode && mNode->isWidget() ) {
|
||||
UIWidget* widget = mNode->asType<UIWidget>();
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ bool UIImage::isType( const Uint32& type ) const {
|
||||
}
|
||||
|
||||
UIImage* UIImage::setDrawable( Drawable* drawable, bool ownIt ) {
|
||||
if ( drawable == mDrawable )
|
||||
return this;
|
||||
|
||||
safeDeleteDrawable();
|
||||
|
||||
mDrawable = drawable;
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
UILinearLayout* UILinearLayout::NewWithTag( const std::string& tag,
|
||||
const UIOrientation& orientation ) {
|
||||
return eeNew( UILinearLayout, ( tag, orientation ) );
|
||||
}
|
||||
|
||||
UILinearLayout* UILinearLayout::New() {
|
||||
return eeNew( UILinearLayout, () );
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ Uint32 UIMenuItem::onMouseClick( const Vector2i&, const Uint32& flags ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
UIWidget* UIMenuItem::getExtraInnerWidget() {
|
||||
UIWidget* UIMenuItem::getExtraInnerWidget() const {
|
||||
return mShortcutView;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ void UIMenuSubMenu::onAlphaChange() {
|
||||
mArrow->setAlpha( mAlpha );
|
||||
}
|
||||
|
||||
UIWidget* UIMenuSubMenu::getExtraInnerWidget() {
|
||||
UIWidget* UIMenuSubMenu::getExtraInnerWidget() const {
|
||||
return mArrow;
|
||||
}
|
||||
|
||||
|
||||
@@ -726,7 +726,7 @@ void UINode::drawBorder() {
|
||||
}
|
||||
}
|
||||
|
||||
void UINode::internalDraw() {
|
||||
void UINode::nodeDraw() {
|
||||
if ( mVisible ) {
|
||||
if ( mNodeFlags & NODE_FLAG_POSITION_DIRTY )
|
||||
updateScreenPos();
|
||||
@@ -736,21 +736,21 @@ void UINode::internalDraw() {
|
||||
|
||||
matrixSet();
|
||||
|
||||
clipStart();
|
||||
|
||||
if ( mWorldBounds.intersect( mSceneNode->getWorldBounds() ) ) {
|
||||
clipStart();
|
||||
|
||||
draw();
|
||||
|
||||
drawChilds();
|
||||
|
||||
if ( 0.f != mAlpha )
|
||||
drawForeground();
|
||||
|
||||
clipEnd();
|
||||
} else if ( !isClipped() ) {
|
||||
drawChilds();
|
||||
}
|
||||
|
||||
clipEnd();
|
||||
|
||||
drawBorder();
|
||||
|
||||
drawHighlightFocus();
|
||||
|
||||
@@ -11,6 +11,10 @@ UIPushButton* UIPushButton::New() {
|
||||
return eeNew( UIPushButton, () );
|
||||
}
|
||||
|
||||
UIPushButton* UIPushButton::NewWithTag( const std::string& tag ) {
|
||||
return eeNew( UIPushButton, ( tag ) );
|
||||
}
|
||||
|
||||
UIPushButton::UIPushButton( const std::string& tag ) :
|
||||
UIWidget( tag ), mIcon( NULL ), mTextBox( NULL ) {
|
||||
mFlags |= ( UI_AUTO_SIZE | UI_VALIGN_CENTER | UI_HALIGN_CENTER );
|
||||
@@ -221,6 +225,8 @@ void UIPushButton::onSizeChange() {
|
||||
if ( NULL != eWidget && eWidget->isVisible() ) {
|
||||
eWidget->setPixelsPosition( ePos );
|
||||
}
|
||||
|
||||
UIWidget::onSizeChange();
|
||||
}
|
||||
|
||||
void UIPushButton::setTheme( UITheme* Theme ) {
|
||||
@@ -237,8 +243,10 @@ void UIPushButton::onThemeLoaded() {
|
||||
}
|
||||
|
||||
UIPushButton* UIPushButton::setIcon( Drawable* Icon ) {
|
||||
mIcon->setDrawable( Icon );
|
||||
onSizeChange();
|
||||
if ( mIcon->getDrawable() != Icon ) {
|
||||
mIcon->setDrawable( Icon );
|
||||
onSizeChange();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -318,10 +326,41 @@ const Sizei& UIPushButton::getIconMinimumSize() const {
|
||||
return mIconMinSize;
|
||||
}
|
||||
|
||||
UIWidget* UIPushButton::getExtraInnerWidget() {
|
||||
UIWidget* UIPushButton::getExtraInnerWidget() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UIPushButton::setTextAlign( const Uint32& align ) {
|
||||
mFlags &= ~( UI_HALIGN_CENTER | UI_HALIGN_RIGHT );
|
||||
mFlags |= align;
|
||||
onAlignChange();
|
||||
}
|
||||
|
||||
Sizef UIPushButton::getContentSize() const {
|
||||
Float sH = getSkinSize().getHeight();
|
||||
Float sHS = getSkinSize( UIState::StateFlagSelected ).getHeight();
|
||||
Float tH = mTextBox->getPixelsSize().getHeight();
|
||||
Float eH =
|
||||
NULL != getExtraInnerWidget() ? getExtraInnerWidget()->getPixelsSize().getHeight() : 0;
|
||||
Float minHeight = eeceil( eemax( eemax( PixelDensity::dpToPx( eemax( sH, sHS ) ), tH ), eH ) );
|
||||
Int32 txtW = mTextBox->getPixelsSize().getWidth();
|
||||
Int32 iconSize = mIcon->getPixelsSize().getWidth() > 0
|
||||
? mIcon->getPixelsSize().getWidth() +
|
||||
PixelDensity::dpToPxI( mIcon->getLayoutMargin().Left +
|
||||
mIcon->getLayoutMargin().Right )
|
||||
: 0;
|
||||
UIWidget* eWidget = getExtraInnerWidget();
|
||||
Int32 eWidgetSize = NULL != eWidget ? PixelDensity::dpToPxI( eWidget->getSize().getWidth() +
|
||||
eWidget->getLayoutMargin().Left +
|
||||
eWidget->getLayoutMargin().Right )
|
||||
: 0;
|
||||
Int32 minWidth = txtW + iconSize + eWidgetSize + mRealPadding.Left + mRealPadding.Right +
|
||||
( NULL != getSkin() ? PixelDensity::dpToPxI( getSkin()->getBorderSize().Left +
|
||||
getSkin()->getBorderSize().Right )
|
||||
: 0 );
|
||||
return Sizef( minWidth, minHeight );
|
||||
}
|
||||
|
||||
std::string UIPushButton::getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex ) {
|
||||
if ( NULL == propertyDef )
|
||||
@@ -336,6 +375,11 @@ std::string UIPushButton::getPropertyString( const PropertyDefinition* propertyD
|
||||
case PropertyId::MinIconSize:
|
||||
return String::format( "%ddp", mIconMinSize.getWidth() ) + " " +
|
||||
String::format( "%ddp", mIconMinSize.getHeight() );
|
||||
case PropertyId::TextAlign:
|
||||
return Font::getHorizontalAlign( getFlags() ) == UI_HALIGN_CENTER
|
||||
? "center"
|
||||
: ( Font::getHorizontalAlign( getFlags() ) == UI_HALIGN_RIGHT ? "right"
|
||||
: "left" );
|
||||
case PropertyId::Color:
|
||||
case PropertyId::ShadowColor:
|
||||
case PropertyId::SelectionColor:
|
||||
@@ -347,7 +391,6 @@ std::string UIPushButton::getPropertyString( const PropertyDefinition* propertyD
|
||||
case PropertyId::TextStrokeWidth:
|
||||
case PropertyId::TextStrokeColor:
|
||||
case PropertyId::TextSelection:
|
||||
case PropertyId::TextAlign:
|
||||
return mTextBox->getPropertyString( propertyDef, propertyIndex );
|
||||
default:
|
||||
return UIWidget::getPropertyString( propertyDef, propertyIndex );
|
||||
@@ -381,6 +424,16 @@ bool UIPushButton::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
case PropertyId::MinIconSize:
|
||||
setIconMinimumSize( attribute.asSizei() );
|
||||
break;
|
||||
case PropertyId::TextAlign: {
|
||||
std::string align = String::toLower( attribute.value() );
|
||||
if ( align == "center" )
|
||||
setTextAlign( UI_HALIGN_CENTER );
|
||||
else if ( align == "left" )
|
||||
setTextAlign( UI_HALIGN_LEFT );
|
||||
else if ( align == "right" )
|
||||
setTextAlign( UI_HALIGN_RIGHT );
|
||||
break;
|
||||
}
|
||||
case PropertyId::Color:
|
||||
case PropertyId::ShadowColor:
|
||||
case PropertyId::SelectionColor:
|
||||
@@ -392,7 +445,6 @@ bool UIPushButton::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
case PropertyId::TextStrokeWidth:
|
||||
case PropertyId::TextStrokeColor:
|
||||
case PropertyId::TextSelection:
|
||||
case PropertyId::TextAlign:
|
||||
attributeSet = mTextBox->applyProperty( attribute );
|
||||
break;
|
||||
default:
|
||||
|
||||
303
src/eepp/ui/uiscrollablewidget.cpp
Normal file
303
src/eepp/ui/uiscrollablewidget.cpp
Normal file
@@ -0,0 +1,303 @@
|
||||
#include <eepp/ui/css/propertydefinition.hpp>
|
||||
#include <eepp/ui/uiscrollablewidget.hpp>
|
||||
#include <eepp/ui/uiscrollbar.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
UIScrollableWidget::UIScrollableWidget( const std::string& tag ) :
|
||||
UIWidget( tag ),
|
||||
mViewType( Exclusive ),
|
||||
mVScrollMode( ScrollBarMode::Auto ),
|
||||
mHScrollMode( ScrollBarMode::Auto ),
|
||||
mVScroll( UIScrollBar::NewVertical() ),
|
||||
mHScroll( UIScrollBar::NewHorizontal() ),
|
||||
mSizeChangeCb( 0 ),
|
||||
mPosChangeCb( 0 ) {
|
||||
mFlags |= UI_OWNS_CHILDS_POSITION;
|
||||
|
||||
mVScroll->setParent( this );
|
||||
mHScroll->setParent( this );
|
||||
|
||||
mVScroll->addEventListener( Event::OnValueChange,
|
||||
cb::Make1( this, &UIScrollableWidget::onValueChangeCb ) );
|
||||
mHScroll->addEventListener( Event::OnValueChange,
|
||||
cb::Make1( this, &UIScrollableWidget::onValueChangeCb ) );
|
||||
|
||||
applyDefaultTheme();
|
||||
}
|
||||
|
||||
Uint32 UIScrollableWidget::getType() const {
|
||||
return UI_TYPE_SCROLLABLEWIDGET;
|
||||
}
|
||||
|
||||
bool UIScrollableWidget::isType( const Uint32& type ) const {
|
||||
return UIWidget::getType() == type ? true : UIWidget::isType( type );
|
||||
}
|
||||
|
||||
void UIScrollableWidget::onSizeChange() {
|
||||
onContentSizeChange();
|
||||
UIWidget::onSizeChange();
|
||||
}
|
||||
|
||||
void UIScrollableWidget::onAlphaChange() {
|
||||
UIWidget::onAlphaChange();
|
||||
mVScroll->setAlpha( mAlpha );
|
||||
mHScroll->setAlpha( mAlpha );
|
||||
}
|
||||
|
||||
void UIScrollableWidget::onPaddingChange() {
|
||||
onContentSizeChange();
|
||||
UIWidget::onPaddingChange();
|
||||
}
|
||||
|
||||
void UIScrollableWidget::setVerticalScrollMode( const ScrollBarMode& Mode ) {
|
||||
if ( Mode != mVScrollMode ) {
|
||||
mVScrollMode = Mode;
|
||||
onContentSizeChange();
|
||||
}
|
||||
}
|
||||
|
||||
const ScrollBarMode& UIScrollableWidget::getVerticalScrollMode() {
|
||||
return mVScrollMode;
|
||||
}
|
||||
|
||||
void UIScrollableWidget::setHorizontalScrollMode( const ScrollBarMode& Mode ) {
|
||||
if ( Mode != mHScrollMode ) {
|
||||
mHScrollMode = Mode;
|
||||
onContentSizeChange();
|
||||
}
|
||||
}
|
||||
|
||||
const ScrollBarMode& UIScrollableWidget::getHorizontalScrollMode() {
|
||||
return mHScrollMode;
|
||||
}
|
||||
|
||||
const UIScrollableWidget::ScrollViewType& UIScrollableWidget::getViewType() const {
|
||||
return mViewType;
|
||||
}
|
||||
|
||||
void UIScrollableWidget::setViewType( const ScrollViewType& viewType ) {
|
||||
if ( viewType != mViewType ) {
|
||||
mViewType = viewType;
|
||||
onContentSizeChange();
|
||||
}
|
||||
}
|
||||
|
||||
UIScrollBar* UIScrollableWidget::getVerticalScrollBar() const {
|
||||
return mVScroll;
|
||||
}
|
||||
|
||||
UIScrollBar* UIScrollableWidget::getHorizontalScrollBar() const {
|
||||
return mHScroll;
|
||||
}
|
||||
|
||||
void UIScrollableWidget::onContentSizeChange() {
|
||||
Sizef contentSize( getContentSize() );
|
||||
|
||||
if ( ScrollBarMode::AlwaysOn == mHScrollMode ) {
|
||||
mHScroll->setVisible( true );
|
||||
mHScroll->setEnabled( true );
|
||||
} else if ( ScrollBarMode::AlwaysOff == mHScrollMode ) {
|
||||
mHScroll->setVisible( false );
|
||||
mHScroll->setEnabled( false );
|
||||
} else {
|
||||
bool visible = contentSize.getWidth() >
|
||||
getPixelsSize().getWidth() - getPixelsPadding().Left -
|
||||
getPixelsPadding().Right - mVScroll->getPixelsSize().getWidth();
|
||||
|
||||
mHScroll->setVisible( visible );
|
||||
mHScroll->setEnabled( visible );
|
||||
}
|
||||
|
||||
if ( ScrollBarMode::AlwaysOn == mVScrollMode ) {
|
||||
mVScroll->setVisible( true );
|
||||
mVScroll->setEnabled( true );
|
||||
} else if ( ScrollBarMode::AlwaysOff == mVScrollMode ) {
|
||||
mVScroll->setVisible( false );
|
||||
mVScroll->setEnabled( false );
|
||||
} else {
|
||||
bool visible = contentSize.getHeight() >
|
||||
getPixelsSize().getHeight() - getPixelsPadding().Top -
|
||||
getPixelsPadding().Bottom - mHScroll->getPixelsSize().getHeight();
|
||||
|
||||
mVScroll->setVisible( visible );
|
||||
mVScroll->setEnabled( visible );
|
||||
}
|
||||
|
||||
Sizef size = getPixelsSize() - mRealPadding;
|
||||
|
||||
if ( Exclusive == mViewType ) {
|
||||
if ( mVScroll->isVisible() )
|
||||
size.x -= mVScroll->getPixelsSize().getWidth();
|
||||
|
||||
if ( mHScroll->isVisible() )
|
||||
size.y -= mHScroll->getPixelsSize().getHeight();
|
||||
}
|
||||
|
||||
mVScroll->setPixelsPosition( getPixelsSize().getWidth() - mVScroll->getPixelsSize().getWidth() -
|
||||
mRealPadding.Right,
|
||||
mRealPadding.Top );
|
||||
mHScroll->setPixelsPosition( mRealPadding.Left, getPixelsSize().getHeight() -
|
||||
mHScroll->getPixelsSize().getHeight() -
|
||||
mRealPadding.Bottom );
|
||||
|
||||
mVScroll->setPixelsSize( mVScroll->getPixelsSize().getWidth(),
|
||||
getPixelsSize().getHeight() - mRealPadding.Top - mRealPadding.Bottom );
|
||||
|
||||
mHScroll->setPixelsSize(
|
||||
getPixelsSize().getWidth() - mRealPadding.Left - mRealPadding.Right -
|
||||
( mVScroll->isVisible() ? mVScroll->getPixelsSize().getWidth() : 0 ),
|
||||
mHScroll->getPixelsSize().getHeight() );
|
||||
|
||||
if ( size.getWidth() > 0 )
|
||||
mHScroll->setPageStep( size.getWidth() / contentSize.getWidth() );
|
||||
if ( size.getHeight() > 0 )
|
||||
mVScroll->setPageStep( size.getHeight() / contentSize.getHeight() );
|
||||
|
||||
updateScroll();
|
||||
}
|
||||
|
||||
Sizef UIScrollableWidget::getScrollableArea() const {
|
||||
Sizef contentSize( getContentSize() );
|
||||
Sizef size = getVisibleArea();
|
||||
return contentSize - size;
|
||||
}
|
||||
|
||||
Sizef UIScrollableWidget::getVisibleArea() const {
|
||||
Sizef size = getPixelsSize() - mRealPadding;
|
||||
if ( mVScroll->isVisible() )
|
||||
size.x -= mVScroll->getPixelsSize().getWidth();
|
||||
if ( mHScroll->isVisible() )
|
||||
size.y -= mHScroll->getPixelsSize().getHeight();
|
||||
return size;
|
||||
}
|
||||
|
||||
void UIScrollableWidget::updateScroll() {
|
||||
Sizef totalScroll = getScrollableArea();
|
||||
Vector2f initScroll( mScrollOffset );
|
||||
mScrollOffset = Vector2f::Zero;
|
||||
|
||||
if ( mVScroll->isVisible() && totalScroll.y > 0 )
|
||||
mScrollOffset.y = totalScroll.y * mVScroll->getValue();
|
||||
|
||||
if ( mHScroll->isVisible() && totalScroll.x > 0 )
|
||||
mScrollOffset.x = totalScroll.x * mHScroll->getValue();
|
||||
|
||||
if ( initScroll != mScrollOffset )
|
||||
onScrollChange();
|
||||
}
|
||||
|
||||
void UIScrollableWidget::onScrollChange() {}
|
||||
|
||||
void UIScrollableWidget::onValueChangeCb( const Event* ) {
|
||||
updateScroll();
|
||||
}
|
||||
|
||||
std::string UIScrollableWidget::getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex ) {
|
||||
if ( NULL == propertyDef )
|
||||
return "";
|
||||
|
||||
switch ( propertyDef->getPropertyId() ) {
|
||||
case PropertyId::VScrollMode:
|
||||
return getVerticalScrollMode() == ScrollBarMode::Auto
|
||||
? "auto"
|
||||
: ( getVerticalScrollMode() == ScrollBarMode::AlwaysOn ? "on" : "off" );
|
||||
case PropertyId::HScrollMode:
|
||||
return getHorizontalScrollMode() == ScrollBarMode::Auto
|
||||
? "auto"
|
||||
: ( getHorizontalScrollMode() == ScrollBarMode::AlwaysOn ? "on" : "off" );
|
||||
case PropertyId::ScrollBarStyle:
|
||||
return mVScroll->getScrollBarType() == UIScrollBar::NoButtons ? "no-buttons"
|
||||
: "two-buttons";
|
||||
case PropertyId::ScrollBarMode:
|
||||
return getViewType() == Inclusive ? "inclusive" : "exclusive";
|
||||
default:
|
||||
return UIWidget::getPropertyString( propertyDef, propertyIndex );
|
||||
}
|
||||
}
|
||||
|
||||
void UIScrollableWidget::scrollToTop() {
|
||||
mVScroll->setValue( 0 );
|
||||
}
|
||||
|
||||
void UIScrollableWidget::scrollToBottom() {
|
||||
mVScroll->setValue( 1 );
|
||||
}
|
||||
|
||||
bool UIScrollableWidget::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
if ( !checkPropertyDefinition( attribute ) )
|
||||
return false;
|
||||
|
||||
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
|
||||
case PropertyId::ScrollBarMode: {
|
||||
std::string val( attribute.asString() );
|
||||
String::toLowerInPlace( val );
|
||||
if ( "inclusive" == val || "inside" == val )
|
||||
setViewType( Inclusive );
|
||||
else if ( "exclusive" == val || "outside" == val )
|
||||
setViewType( Exclusive );
|
||||
break;
|
||||
}
|
||||
case PropertyId::VScrollMode: {
|
||||
std::string val( attribute.asString() );
|
||||
String::toLowerInPlace( val );
|
||||
|
||||
if ( "on" == val )
|
||||
setVerticalScrollMode( ScrollBarMode::AlwaysOn );
|
||||
else if ( "off" == val )
|
||||
setVerticalScrollMode( ScrollBarMode::AlwaysOn );
|
||||
else if ( "auto" == val )
|
||||
setVerticalScrollMode( ScrollBarMode::Auto );
|
||||
break;
|
||||
}
|
||||
case PropertyId::HScrollMode: {
|
||||
std::string val( attribute.asString() );
|
||||
String::toLowerInPlace( val );
|
||||
|
||||
if ( "on" == val )
|
||||
setHorizontalScrollMode( ScrollBarMode::AlwaysOn );
|
||||
else if ( "off" == val )
|
||||
setHorizontalScrollMode( ScrollBarMode::AlwaysOn );
|
||||
else if ( "auto" == val )
|
||||
setHorizontalScrollMode( ScrollBarMode::Auto );
|
||||
break;
|
||||
}
|
||||
case PropertyId::ScrollBarStyle: {
|
||||
std::string val( attribute.asString() );
|
||||
String::toLowerInPlace( val );
|
||||
|
||||
if ( "no-buttons" == val || "nobuttons" == val ) {
|
||||
mVScroll->setScrollBarStyle( UIScrollBar::NoButtons );
|
||||
mHScroll->setScrollBarStyle( UIScrollBar::NoButtons );
|
||||
} else if ( "two-buttons" == val || "twobuttons" == val ) {
|
||||
mVScroll->setScrollBarStyle( UIScrollBar::TwoButtons );
|
||||
mHScroll->setScrollBarStyle( UIScrollBar::NoButtons );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return UIWidget::applyProperty( attribute );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Uint32 UIScrollableWidget::onMessage( const NodeMessage* Msg ) {
|
||||
switch ( Msg->getMsg() ) {
|
||||
case NodeMessage::MouseUp: {
|
||||
if ( mVScroll->isEnabled() ) {
|
||||
if ( Msg->getFlags() & EE_BUTTON_WUMASK ) {
|
||||
mVScroll->setValue( mVScroll->getValue() - mVScroll->getClickStep() );
|
||||
return 1;
|
||||
} else if ( Msg->getFlags() & EE_BUTTON_WDMASK ) {
|
||||
mVScroll->setValue( mVScroll->getValue() + mVScroll->getClickStep() );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return UIWidget::onMessage( Msg );
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
@@ -125,7 +125,7 @@ void UITab::onSizeChange() {
|
||||
UISelectButton::onSizeChange();
|
||||
}
|
||||
|
||||
UIWidget* UITab::getExtraInnerWidget() {
|
||||
UIWidget* UITab::getExtraInnerWidget() const {
|
||||
return mCloseButton;
|
||||
}
|
||||
|
||||
|
||||
90
src/eepp/ui/uitableheadercolumn.cpp
Normal file
90
src/eepp/ui/uitableheadercolumn.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include <eepp/ui/abstract/uiabstracttableview.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <eepp/ui/uitableheadercolumn.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
UITableHeaderColumn::UITableHeaderColumn( UIAbstractTableView* view, const size_t& colIndex ) :
|
||||
UIPushButton( "table::header::column" ), mView( view ), mColIndex( colIndex ) {
|
||||
setDragEnabled( true );
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onCalculateDrag( const Vector2f& position, const Uint32& flags ) {
|
||||
if ( isDragEnabled() && isDragging() && NULL != getEventDispatcher() ) {
|
||||
EventDispatcher* eventDispatcher = getEventDispatcher();
|
||||
if ( !( flags /*press trigger*/ & mDragButton ) ) {
|
||||
setDragging( false );
|
||||
eventDispatcher->setNodeDragging( NULL );
|
||||
return 1;
|
||||
}
|
||||
Vector2f pos( eefloor( position.x ), eefloor( position.y ) );
|
||||
if ( mDragPoint != pos && std::abs( mDragPoint.x - pos.x ) > 1.f ) {
|
||||
Sizef dragDiff( ( Float )( mDragPoint.x - pos.x ), 0 );
|
||||
if ( onDrag( pos, flags, dragDiff ) ) {
|
||||
mDragPoint = pos;
|
||||
eventDispatcher->setNodeDragging( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onMouseDown( const Vector2i& position, const Uint32& flags ) {
|
||||
Vector2f localPos( convertToNodeSpace( position.asFloat() ) );
|
||||
if ( NULL != getEventDispatcher() && !getEventDispatcher()->isNodeDragging() &&
|
||||
!( getEventDispatcher()->getLastPressTrigger() & mDragButton ) &&
|
||||
( flags & mDragButton ) && isDragEnabled() && !isDragging() &&
|
||||
localPos.x >= mSize.getWidth() - mView->getDragBorderDistance() ) {
|
||||
startDragging( position.asFloat() );
|
||||
}
|
||||
pushState( UIState::StatePressed );
|
||||
return Node::onMouseDown( position, flags );
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onDrag( const Vector2f& position, const Uint32&,
|
||||
const Sizef& dragDiff ) {
|
||||
Vector2f localPos( convertToNodeSpace( position ) );
|
||||
if ( isDragging() || localPos.x >= mSize.getWidth() - mView->getDragBorderDistance() ) {
|
||||
setPixelsSize( mSize.x - dragDiff.x, mSize.getHeight() );
|
||||
if ( mSize.getWidth() != mView->columnData( mColIndex ).width ) {
|
||||
mView->columnData( mColIndex ).width = mSize.getWidth();
|
||||
mView->updateHeaderSize();
|
||||
mView->onColumnSizeChange( mColIndex );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onMouseLeave( const Vector2i& position, const Uint32& flags ) {
|
||||
if ( !isDragging() )
|
||||
getUISceneNode()->setCursor( Cursor::Arrow );
|
||||
return UIPushButton::onMouseLeave( position, flags );
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onMouseMove( const Vector2i& position, const Uint32& flags ) {
|
||||
Vector2f localPos( convertToNodeSpace( position.asFloat() ) );
|
||||
if ( isDragging() || localPos.x >= mSize.getWidth() - mView->getDragBorderDistance() ) {
|
||||
getUISceneNode()->setCursor( Cursor::SizeWE );
|
||||
} else if ( !isDragging() ) {
|
||||
getUISceneNode()->setCursor( Cursor::Arrow );
|
||||
}
|
||||
return UIPushButton::onMouseMove( position, flags );
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onMouseDoubleClick( const Vector2i& position, const Uint32& flags ) {
|
||||
Vector2f localPos( convertToNodeSpace( position.asFloat() ) );
|
||||
if ( localPos.x >= mSize.getWidth() - mView->getDragBorderDistance() )
|
||||
mView->onColumnResizeToContent( mColIndex );
|
||||
return UIPushButton::onMouseDoubleClick( position, flags );
|
||||
}
|
||||
|
||||
Uint32 UITableHeaderColumn::onDragStop( const Vector2i& pos, const Uint32& flags ) {
|
||||
getUISceneNode()->setCursor( Cursor::Arrow );
|
||||
mView->columnData( mColIndex ).width = mSize.getWidth();
|
||||
mView->updateHeaderSize();
|
||||
mView->onColumnSizeChange( mColIndex );
|
||||
return UIPushButton::onDragStop( pos, flags );
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
@@ -649,11 +649,11 @@ bool UITextView::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
case PropertyId::TextAlign: {
|
||||
std::string align = String::toLower( attribute.value() );
|
||||
if ( align == "center" )
|
||||
setFlags( UI_HALIGN_CENTER );
|
||||
setTextAlign( UI_HALIGN_CENTER );
|
||||
else if ( align == "left" )
|
||||
setFlags( UI_HALIGN_LEFT );
|
||||
setTextAlign( UI_HALIGN_LEFT );
|
||||
else if ( align == "right" )
|
||||
setFlags( UI_HALIGN_RIGHT );
|
||||
setTextAlign( UI_HALIGN_RIGHT );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -703,4 +703,10 @@ std::string UITextView::getPropertyString( const PropertyDefinition* propertyDef
|
||||
}
|
||||
}
|
||||
|
||||
void UITextView::setTextAlign( const Uint32& align ) {
|
||||
mFlags &= ~(UI_HALIGN_CENTER|UI_HALIGN_RIGHT);
|
||||
mFlags |= align;
|
||||
onAlignChange();
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
500
src/eepp/ui/uitreeview.cpp
Normal file
500
src/eepp/ui/uitreeview.cpp
Normal file
@@ -0,0 +1,500 @@
|
||||
#include <eepp/graphics/renderer/renderer.hpp>
|
||||
#include <eepp/ui/uilinearlayout.hpp>
|
||||
#include <eepp/ui/uipushbutton.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <eepp/ui/uiscrollbar.hpp>
|
||||
#include <eepp/ui/uitreeview.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
struct UITreeView::MetadataForIndex {
|
||||
bool open{false};
|
||||
};
|
||||
|
||||
UITreeView* UITreeView::New() {
|
||||
return eeNew( UITreeView, () );
|
||||
}
|
||||
|
||||
UITreeView::UITreeView() : UIAbstractTableView( "treeview" ), mIndentWidth( 16 ) {
|
||||
mExpandIcon = getUISceneNode()->findIcon( "tree-expanded" );
|
||||
mContractIcon = getUISceneNode()->findIcon( "tree-contracted" );
|
||||
}
|
||||
|
||||
Uint32 UITreeView::getType() const {
|
||||
return UI_TYPE_TREEVIEW;
|
||||
}
|
||||
|
||||
bool UITreeView::isType( const Uint32& type ) const {
|
||||
return UITreeView::getType() == type ? true : UIAbstractTableView::isType( type );
|
||||
}
|
||||
|
||||
UITreeView::MetadataForIndex& UITreeView::getIndexMetadata( const ModelIndex& index ) const {
|
||||
eeASSERT( index.isValid() );
|
||||
auto it = mViewMetadata.find( index.data() );
|
||||
if ( it != mViewMetadata.end() )
|
||||
return *it->second;
|
||||
auto newMetadata = std::make_unique<MetadataForIndex>();
|
||||
auto* ref = newMetadata.get();
|
||||
mViewMetadata.insert( {index.data(), std::move( newMetadata )} );
|
||||
return *ref;
|
||||
}
|
||||
|
||||
template <typename Callback> void UITreeView::traverseTree( Callback callback ) const {
|
||||
eeASSERT( getModel() );
|
||||
auto& model = *getModel();
|
||||
int indentLevel = 1;
|
||||
Float yOffset = getHeaderHeight();
|
||||
int rowIndex = -1;
|
||||
std::function<IterationDecision( const ModelIndex& )> traverseIndex =
|
||||
[&]( const ModelIndex& index ) {
|
||||
if ( index.isValid() ) {
|
||||
auto& metadata = getIndexMetadata( index );
|
||||
rowIndex++;
|
||||
IterationDecision decision = callback( rowIndex, index, indentLevel, yOffset );
|
||||
if ( decision == IterationDecision::Break || decision == IterationDecision::Stop )
|
||||
return decision;
|
||||
yOffset += getRowHeight();
|
||||
if ( !metadata.open ) {
|
||||
return IterationDecision::Continue;
|
||||
}
|
||||
}
|
||||
if ( indentLevel > 0 && !index.isValid() )
|
||||
return IterationDecision::Continue;
|
||||
++indentLevel;
|
||||
int rowCount = model.rowCount( index );
|
||||
for ( int i = 0; i < rowCount; ++i ) {
|
||||
IterationDecision decision =
|
||||
traverseIndex( model.index( i, model.treeColumn(), index ) );
|
||||
if ( decision == IterationDecision::Break || decision == IterationDecision::Stop )
|
||||
return decision;
|
||||
}
|
||||
--indentLevel;
|
||||
return IterationDecision::Continue;
|
||||
};
|
||||
int rootCount = model.rowCount();
|
||||
for ( int rootIndex = 0; rootIndex < rootCount; ++rootIndex ) {
|
||||
IterationDecision decision =
|
||||
traverseIndex( model.index( rootIndex, model.treeColumn(), ModelIndex() ) );
|
||||
if ( decision == IterationDecision::Break || decision == IterationDecision::Stop )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UITreeView::createOrUpdateColumns() {
|
||||
if ( !getModel() )
|
||||
return;
|
||||
UIAbstractTableView::createOrUpdateColumns();
|
||||
updateContentSize();
|
||||
}
|
||||
|
||||
size_t UITreeView::getItemCount() const {
|
||||
size_t count = 0;
|
||||
traverseTree( [&]( const int&, const ModelIndex&, const size_t&, const Float& ) {
|
||||
count++;
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
return count;
|
||||
}
|
||||
|
||||
void UITreeView::onColumnSizeChange( const size_t& ) {
|
||||
updateContentSize();
|
||||
}
|
||||
|
||||
class UITableRow : public UIWidget {
|
||||
public:
|
||||
UITableRow( const std::string& tag ) : UIWidget( tag ) {}
|
||||
|
||||
ModelIndex getCurIndex() const { return mCurIndex; }
|
||||
|
||||
void setCurIndex( const ModelIndex& curIndex ) { mCurIndex = curIndex; }
|
||||
|
||||
protected:
|
||||
virtual Uint32 onMessage( const NodeMessage* msg ) {
|
||||
if ( msg->getMsg() == NodeMessage::MouseDown && ( msg->getFlags() & EE_BUTTON_LMASK ) &&
|
||||
( !getEventDispatcher()->getMouseDownNode() ||
|
||||
getEventDispatcher()->getMouseDownNode() == this ||
|
||||
isParentOf( getEventDispatcher()->getMouseDownNode() ) ) &&
|
||||
getEventDispatcher()->getNodeDragging() == nullptr ) {
|
||||
sendMouseEvent( Event::MouseDown, getEventDispatcher()->getMousePos(),
|
||||
msg->getFlags() );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ModelIndex mCurIndex;
|
||||
};
|
||||
|
||||
UIWidget* UITreeView::updateRow( const int& rowIndex, const ModelIndex& index,
|
||||
const Float& yOffset ) {
|
||||
if ( rowIndex >= (int)mRows.size() )
|
||||
mRows.resize( rowIndex + 1, nullptr );
|
||||
UITableRow* rowWidget = nullptr;
|
||||
if ( mRows[rowIndex] == nullptr ) {
|
||||
rowWidget = eeNew( UITableRow, ( "table::row" ) );
|
||||
rowWidget->clipEnable();
|
||||
rowWidget->setParent( this );
|
||||
rowWidget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
rowWidget->reloadStyle( true, true, true );
|
||||
rowWidget->addEventListener( Event::MouseDown, [&]( const Event* event ) {
|
||||
if ( ( !getEventDispatcher()->getMouseDownNode() ||
|
||||
getEventDispatcher()->getMouseDownNode() == this ||
|
||||
isParentOf( getEventDispatcher()->getMouseDownNode() ) ) &&
|
||||
getEventDispatcher()->getNodeDragging() == nullptr ) {
|
||||
getSelection().set( event->getNode()->asType<UITableRow>()->getCurIndex() );
|
||||
}
|
||||
} );
|
||||
mRows[rowIndex] = rowWidget;
|
||||
} else {
|
||||
rowWidget = mRows[rowIndex];
|
||||
}
|
||||
rowWidget->setCurIndex( index );
|
||||
rowWidget->setPixelsSize( getContentSize().getWidth(), getRowHeight() );
|
||||
rowWidget->setPixelsPosition( {-mScrollOffset.x, yOffset - mScrollOffset.y} );
|
||||
if ( getSelection().first() == index ) {
|
||||
rowWidget->pushState( UIState::StateSelected );
|
||||
} else {
|
||||
rowWidget->popState( UIState::StateSelected );
|
||||
}
|
||||
return rowWidget;
|
||||
}
|
||||
|
||||
UIWidget* UITreeView::createCell( UIWidget* rowWidget, const ModelIndex&, const size_t& col ) {
|
||||
UIPushButton* widget = UIPushButton::NewWithTag( "table::cell" );
|
||||
widget->setParent( rowWidget );
|
||||
widget->unsetFlags( UI_AUTO_SIZE );
|
||||
widget->clipEnable();
|
||||
widget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
widget->asType<UIPushButton>()->setTextAlign( UI_HALIGN_LEFT );
|
||||
if ( col == getModel()->treeColumn() ) {
|
||||
widget->addEventListener( Event::MouseDoubleClick, [&]( const Event* event ) {
|
||||
auto mouseEvent = static_cast<const MouseEvent*>( event );
|
||||
auto idx = mouseEvent->getNode()->getParent()->asType<UITableRow>()->getCurIndex();
|
||||
if ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) {
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
auto& data = getIndexMetadata( idx );
|
||||
data.open = !data.open;
|
||||
createOrUpdateColumns();
|
||||
} else {
|
||||
onOpenModelIndex( idx );
|
||||
}
|
||||
}
|
||||
} );
|
||||
widget->addEventListener( Event::MouseClick, [&]( const Event* event ) {
|
||||
auto mouseEvent = static_cast<const MouseEvent*>( event );
|
||||
UIImage* icon = mouseEvent->getNode()->asType<UIPushButton>()->getIcon();
|
||||
if ( icon ) {
|
||||
Vector2f pos( icon->convertToNodeSpace( mouseEvent->getPosition().asFloat() ) );
|
||||
if ( pos >= Vector2f::Zero && pos <= icon->getPixelsSize() ) {
|
||||
auto idx =
|
||||
mouseEvent->getNode()->getParent()->asType<UITableRow>()->getCurIndex();
|
||||
auto& data = getIndexMetadata( idx );
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
data.open = !data.open;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
|
||||
void UITreeView::onScrollChange() {
|
||||
mHeader->setPixelsPosition( -mScrollOffset.x, 0 );
|
||||
invalidateDraw();
|
||||
}
|
||||
|
||||
void UITreeView::updateContentSize() {
|
||||
Sizef oldSize( mContentSize );
|
||||
mContentSize = UIAbstractTableView::getContentSize();
|
||||
if ( oldSize != mContentSize )
|
||||
onContentSizeChange();
|
||||
}
|
||||
|
||||
UIWidget* UITreeView::updateCell( const int& rowIndex, const ModelIndex& index, const size_t& col,
|
||||
const size_t& indentLevel, const Float& yOffset ) {
|
||||
if ( rowIndex >= (int)mWidgets.size() )
|
||||
mWidgets.resize( rowIndex + 1 );
|
||||
auto* widget = mWidgets[rowIndex][col];
|
||||
if ( !widget ) {
|
||||
UIWidget* rowWidget = updateRow( rowIndex, index, yOffset );
|
||||
widget = createCell( rowWidget, index, col );
|
||||
mWidgets[rowIndex][col] = widget;
|
||||
}
|
||||
widget->setPixelsSize( columnData( col ).width, getRowHeight() );
|
||||
widget->setPixelsPosition( {getColumnPosition( col ).x, 0} );
|
||||
|
||||
if ( col == getModel()->treeColumn() )
|
||||
widget->setPaddingLeft( getIndentWidth() * indentLevel );
|
||||
|
||||
ModelIndex idx( getModel()->index( index.row(), col, index.parent() ) );
|
||||
|
||||
Variant txt( getModel()->data( idx, Model::Role::Display ) );
|
||||
|
||||
if ( widget->isType( UI_TYPE_PUSHBUTTON ) ) {
|
||||
UIPushButton* pushButton = widget->asType<UIPushButton>();
|
||||
if ( txt.isValid() ) {
|
||||
if ( txt.is( Variant::Type::String ) )
|
||||
pushButton->setText( txt.asString() );
|
||||
else if ( txt.is( Variant::Type::cstr ) )
|
||||
pushButton->setText( txt.asCStr() );
|
||||
}
|
||||
pushButton->setIcon( nullptr );
|
||||
if ( col == getModel()->treeColumn() )
|
||||
pushButton->setIcon( getIndexMetadata( index ).open ? mExpandIcon : mContractIcon );
|
||||
Variant icon( getModel()->data( idx, Model::Role::Icon ) );
|
||||
if ( icon.is( Variant::Type::Drawable ) )
|
||||
pushButton->setIcon( icon.asDrawable() );
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
const Float& UITreeView::getIndentWidth() const {
|
||||
return mIndentWidth;
|
||||
}
|
||||
|
||||
void UITreeView::setIndentWidth( const Float& indentWidth ) {
|
||||
if ( mIndentWidth != indentWidth ) {
|
||||
mIndentWidth = indentWidth;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
Sizef UITreeView::getContentSize() const {
|
||||
return mContentSize;
|
||||
}
|
||||
|
||||
void UITreeView::drawChilds() {
|
||||
traverseTree( [&]( const int& rowIndex, const ModelIndex& index, const size_t& indentLevel,
|
||||
const Float& yOffset ) {
|
||||
if ( yOffset - mScrollOffset.y > mSize.getHeight() )
|
||||
return IterationDecision::Stop;
|
||||
if ( yOffset - mScrollOffset.y + getRowHeight() < 0 )
|
||||
return IterationDecision::Continue;
|
||||
for ( size_t colIndex = 0; colIndex < getModel()->columnCount(); colIndex++ )
|
||||
updateCell( rowIndex, index, colIndex, indentLevel, yOffset );
|
||||
updateRow( rowIndex, index, yOffset )->nodeDraw();
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
if ( mHeader && mHeader->isVisible() )
|
||||
mHeader->nodeDraw();
|
||||
if ( mHScroll->isVisible() )
|
||||
mHScroll->nodeDraw();
|
||||
if ( mVScroll->isVisible() )
|
||||
mVScroll->nodeDraw();
|
||||
}
|
||||
|
||||
Node* UITreeView::overFind( const Vector2f& point ) {
|
||||
Node* pOver = NULL;
|
||||
if ( mEnabled && mVisible ) {
|
||||
updateWorldPolygon();
|
||||
if ( mWorldBounds.contains( point ) && mPoly.pointInside( point ) ) {
|
||||
writeNodeFlag( NODE_FLAG_MOUSEOVER_ME_OR_CHILD, 1 );
|
||||
mSceneNode->addMouseOverNode( this );
|
||||
if ( mHScroll->isVisible() && ( pOver = mHScroll->overFind( point ) ) )
|
||||
return pOver;
|
||||
if ( mVScroll->isVisible() && ( pOver = mVScroll->overFind( point ) ) )
|
||||
return pOver;
|
||||
if ( mHeader && ( pOver = mHeader->overFind( point ) ) )
|
||||
return pOver;
|
||||
traverseTree( [&, point]( int rowIndex, const ModelIndex& index, const size_t&,
|
||||
const Float& yOffset ) {
|
||||
if ( yOffset - mScrollOffset.y > mSize.getHeight() )
|
||||
return IterationDecision::Stop;
|
||||
if ( yOffset - mScrollOffset.y + getRowHeight() < 0 )
|
||||
return IterationDecision::Continue;
|
||||
pOver = updateRow( rowIndex, index, yOffset )->overFind( point );
|
||||
if ( pOver )
|
||||
return IterationDecision::Stop;
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
if ( !pOver )
|
||||
pOver = this;
|
||||
}
|
||||
}
|
||||
return pOver;
|
||||
}
|
||||
|
||||
bool UITreeView::isExpanded( const ModelIndex& index ) const {
|
||||
return getIndexMetadata( index ).open;
|
||||
}
|
||||
|
||||
Drawable* UITreeView::getExpandIcon() const {
|
||||
return mExpandIcon;
|
||||
}
|
||||
|
||||
void UITreeView::setExpandedIcon( Drawable* expandIcon ) {
|
||||
if ( mExpandIcon != expandIcon ) {
|
||||
mExpandIcon = expandIcon;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
Drawable* UITreeView::getContractIcon() const {
|
||||
return mContractIcon;
|
||||
}
|
||||
|
||||
void UITreeView::setContractedIcon( Drawable* contractIcon ) {
|
||||
if ( mContractIcon != contractIcon ) {
|
||||
mContractIcon = contractIcon;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
void UITreeView::onColumnResizeToContent( const size_t& colIndex ) {
|
||||
UIWidget* lWidget = nullptr;
|
||||
Float lWidth = 0;
|
||||
getUISceneNode()->setIsLoading( true );
|
||||
traverseTree( [&, colIndex]( const int& rowIndex, const ModelIndex& index,
|
||||
const size_t& indentLevel, const Float& yOffset ) {
|
||||
UIWidget* widget = updateCell( rowIndex, index, colIndex, indentLevel, yOffset );
|
||||
if ( widget->isType( UI_TYPE_PUSHBUTTON ) ) {
|
||||
Float w = widget->asType<UIPushButton>()->getContentSize().getWidth();
|
||||
if ( w > lWidth ) {
|
||||
lWidget = widget;
|
||||
lWidth = w;
|
||||
}
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
getUISceneNode()->setIsLoading( false );
|
||||
if ( lWidget ) {
|
||||
columnData( colIndex ).width = lWidth;
|
||||
createOrUpdateColumns();
|
||||
}
|
||||
}
|
||||
|
||||
void UITreeView::onModelSelectionChange() {
|
||||
UIAbstractTableView::onModelSelectionChange();
|
||||
invalidateDraw();
|
||||
}
|
||||
|
||||
Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
|
||||
if ( event.getMod() != 0 )
|
||||
return 0;
|
||||
|
||||
auto curIndex = getSelection().first();
|
||||
|
||||
switch ( event.getKeyCode() ) {
|
||||
case KEY_UP: {
|
||||
ModelIndex prevIndex;
|
||||
ModelIndex foundIndex;
|
||||
Float curY;
|
||||
traverseTree(
|
||||
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
|
||||
if ( index == curIndex ) {
|
||||
foundIndex = prevIndex;
|
||||
curY = offsetY;
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
prevIndex = index;
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
if ( foundIndex.isValid() ) {
|
||||
getSelection().set( foundIndex );
|
||||
if ( curY < mScrollOffset.y + getHeaderHeight() + getRowHeight() ||
|
||||
curY > mScrollOffset.y + getPixelsSize().getHeight() - mRealPadding.Top -
|
||||
mRealPadding.Bottom - getRowHeight() ) {
|
||||
curY -= getHeaderHeight() + getRowHeight();
|
||||
mVScroll->setValue( eemin<Float>(
|
||||
1.f, eemax<Float>( 0.f, curY / getScrollableArea().getHeight() ) ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_DOWN: {
|
||||
ModelIndex prevIndex;
|
||||
ModelIndex foundIndex;
|
||||
Float curY;
|
||||
traverseTree(
|
||||
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
|
||||
if ( prevIndex == curIndex ) {
|
||||
foundIndex = index;
|
||||
curY = offsetY;
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
prevIndex = index;
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
if ( foundIndex.isValid() ) {
|
||||
getSelection().set( foundIndex );
|
||||
if ( curY < mScrollOffset.y ||
|
||||
curY > mScrollOffset.y + getPixelsSize().getHeight() - mRealPadding.Top -
|
||||
mRealPadding.Bottom - getRowHeight() ) {
|
||||
curY -=
|
||||
eefloor( getVisibleArea().getHeight() / getRowHeight() ) * getRowHeight() -
|
||||
getRowHeight();
|
||||
mVScroll->setValue(
|
||||
eemin<Float>( 1.f, curY / getScrollableArea().getHeight() ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case KEY_END: {
|
||||
scrollToBottom();
|
||||
ModelIndex lastIndex;
|
||||
traverseTree( [&]( const int&, const ModelIndex& index, const size_t&, const Float& ) {
|
||||
lastIndex = index;
|
||||
return IterationDecision::Continue;
|
||||
} );
|
||||
getSelection().set( lastIndex );
|
||||
break;
|
||||
}
|
||||
case KEY_HOME: {
|
||||
scrollToTop();
|
||||
getSelection().set( getModel()->index( 0, 0 ) );
|
||||
break;
|
||||
}
|
||||
case KEY_RIGHT: {
|
||||
if ( curIndex.isValid() && getModel()->rowCount( curIndex ) ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
if ( !metadata.open ) {
|
||||
metadata.open = true;
|
||||
createOrUpdateColumns();
|
||||
return 0;
|
||||
}
|
||||
getSelection().set( getModel()->index( 0, getModel()->treeColumn(), curIndex ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_LEFT: {
|
||||
if ( curIndex.isValid() && getModel()->rowCount( curIndex ) ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
if ( metadata.open ) {
|
||||
metadata.open = false;
|
||||
createOrUpdateColumns();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ( curIndex.isValid() && curIndex.parent().isValid() ) {
|
||||
getSelection().set( curIndex.parent() );
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_RETURN:
|
||||
case KEY_SPACE: {
|
||||
if ( curIndex.isValid() ) {
|
||||
if ( getModel()->rowCount( curIndex ) ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
metadata.open = !metadata.open;
|
||||
createOrUpdateColumns();
|
||||
} else {
|
||||
onOpenModelIndex( curIndex );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UITreeView::onOpenModelIndex( const ModelIndex& index ) {
|
||||
ModelEvent event( getModel(), index, this );
|
||||
sendEvent( &event );
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <eepp/ui/uitextureregion.hpp>
|
||||
#include <eepp/ui/uitextview.hpp>
|
||||
#include <eepp/ui/uitouchdraggablewidget.hpp>
|
||||
#include <eepp/ui/uitreeview.hpp>
|
||||
#include <eepp/ui/uiviewpager.hpp>
|
||||
#include <eepp/ui/uiwidgetcreator.hpp>
|
||||
#include <eepp/ui/uiwindow.hpp>
|
||||
@@ -80,6 +81,7 @@ void UIWidgetCreator::createBaseWidgetList() {
|
||||
registeredWidget["viewpager"] = UIViewPager::New;
|
||||
registeredWidget["codeeditor"] = UICodeEditor::New;
|
||||
registeredWidget["splitter"] = UISplitter::New;
|
||||
registeredWidget["treeview"] = UITreeView::New;
|
||||
|
||||
registeredWidget["hbox"] = UILinearLayout::NewHorizontal;
|
||||
registeredWidget["vbox"] = UILinearLayout::NewVertical;
|
||||
|
||||
@@ -60,7 +60,7 @@ UIWindow::UIWindow( UIWindow::WindowBaseContainerType type, const StyleConfig& w
|
||||
|
||||
switch ( type ) {
|
||||
case LINEAR_LAYOUT:
|
||||
mContainer = UILinearLayout::NewWithTag( "window::container" );
|
||||
mContainer = UILinearLayout::NewWithTag( "window::container", UIOrientation::Vertical );
|
||||
break;
|
||||
case RELATIVE_LAYOUT:
|
||||
mContainer = UIRelativeLayout::NewWithTag( "window::container" );
|
||||
@@ -1212,7 +1212,7 @@ Uint32 UIWindow::onMouseDoubleClick( const Vector2i&, const Uint32& Flags ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UIWindow::internalDraw() {
|
||||
void UIWindow::nodeDraw() {
|
||||
if ( mVisible && 0 != mAlpha ) {
|
||||
updateScreenPos();
|
||||
|
||||
|
||||
@@ -1,4 +1,104 @@
|
||||
#include <eepp/ee.hpp>
|
||||
#include <eepp/ui/abstract/model.hpp>
|
||||
#include <eepp/ui/abstract/uiabstracttableview.hpp>
|
||||
#include <eepp/ui/uitreeview.hpp>
|
||||
|
||||
using namespace EE::UI::Abstract;
|
||||
|
||||
class TestModel : public Model {
|
||||
public:
|
||||
struct NodeT {
|
||||
std::vector<NodeT*> children;
|
||||
NodeT* parent{nullptr};
|
||||
|
||||
ModelIndex index( const TestModel& model, int column ) const {
|
||||
if ( !parent )
|
||||
return {};
|
||||
for ( size_t row = 0; row < parent->children.size(); ++row ) {
|
||||
if ( parent->children[row] == this )
|
||||
return model.createIndex( row, column, const_cast<NodeT*>( this ) );
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
size_t getRows() const { return 10000; }
|
||||
size_t getCols() const { return 4; }
|
||||
size_t getChilds() const { return 50; }
|
||||
|
||||
TestModel() : Model() {
|
||||
for ( size_t row = 0; row < getRows(); ++row ) {
|
||||
NodeT* n = new NodeT();
|
||||
n->parent = &mRoot;
|
||||
for ( size_t i = 0; i < getChilds(); i++ ) {
|
||||
NodeT* c = new NodeT();
|
||||
c->parent = n;
|
||||
n->children.push_back( c );
|
||||
}
|
||||
mRoot.children.push_back( n );
|
||||
}
|
||||
}
|
||||
|
||||
virtual ModelIndex parentIndex( const ModelIndex& index ) const {
|
||||
if ( !index.isValid() )
|
||||
return {};
|
||||
auto& node = this->node( index );
|
||||
if ( !node.parent ) {
|
||||
eeASSERT( &node == &mRoot );
|
||||
return {};
|
||||
}
|
||||
return node.parent->index( *this, index.column() );
|
||||
}
|
||||
|
||||
virtual size_t rowCount( const ModelIndex& index = ModelIndex() ) const {
|
||||
auto& node = this->node( index );
|
||||
return node.children.size();
|
||||
}
|
||||
|
||||
virtual size_t columnCount( const ModelIndex& = ModelIndex() ) const { return getCols(); }
|
||||
|
||||
NodeT mRoot;
|
||||
const NodeT& node( const ModelIndex& index ) const {
|
||||
if ( !index.isValid() )
|
||||
return mRoot;
|
||||
return *(NodeT*)index.data();
|
||||
}
|
||||
|
||||
ModelIndex index( int row, int column, const ModelIndex& parent ) const {
|
||||
if ( row < 0 || column < 0 )
|
||||
return {};
|
||||
auto& node = this->node( parent );
|
||||
if ( static_cast<size_t>( row ) >= node.children.size() )
|
||||
return {};
|
||||
return createIndex( row, column, node.children[row] );
|
||||
}
|
||||
|
||||
virtual std::string columnName( const size_t& column ) const {
|
||||
return String::format( "Column %ld", column );
|
||||
}
|
||||
|
||||
virtual Variant data( const ModelIndex& index, Role role = Role::Display ) const {
|
||||
switch ( role ) {
|
||||
case Role::Display: {
|
||||
return Variant( String::format( "Test %lld-%lld", index.row(), index.column() ) );
|
||||
}
|
||||
case Role::Icon: {
|
||||
if ( index.column() == 0 && rowCount( index ) == 0 ) {
|
||||
return Variant( SceneManager::instance()
|
||||
->getUISceneNode()
|
||||
->getUIIconThemeManager()
|
||||
->getCurrentTheme()
|
||||
->getIcon( "file" ) );
|
||||
}
|
||||
}
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return Variant();
|
||||
};
|
||||
|
||||
virtual void update() {}
|
||||
};
|
||||
|
||||
// This file is used to test some UI related stuffs.
|
||||
// It's not a benchmark or a real test suite.
|
||||
@@ -13,6 +113,21 @@ void mainLoop() {
|
||||
win->close();
|
||||
}
|
||||
|
||||
UISceneNode* uiSceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
if ( win->getInput()->isKeyUp( KEY_F6 ) ) {
|
||||
uiSceneNode->setHighlightFocus( !uiSceneNode->getHighlightFocus() );
|
||||
uiSceneNode->setHighlightOver( !uiSceneNode->getHighlightOver() );
|
||||
}
|
||||
|
||||
if ( win->getInput()->isKeyUp( KEY_F7 ) ) {
|
||||
uiSceneNode->setDrawBoxes( !uiSceneNode->getDrawBoxes() );
|
||||
}
|
||||
|
||||
if ( win->getInput()->isKeyUp( KEY_F8 ) ) {
|
||||
uiSceneNode->setDrawDebugData( !uiSceneNode->getDrawDebugData() );
|
||||
}
|
||||
|
||||
// Update the UI scene.
|
||||
SceneManager::instance()->update();
|
||||
|
||||
@@ -39,9 +154,23 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
Engine::instance()->getDisplayManager()->getDisplayIndex( 0 )->getPixelDensity() );
|
||||
FontTrueType* font =
|
||||
FontTrueType::New( "NotoSans-Regular", "assets/fonts/NotoSans-Regular.ttf" );
|
||||
FontTrueType* iconFont = FontTrueType::New( "icon", "assets/fonts/remixicon.ttf" );
|
||||
UIIconTheme* iconTheme = UIIconTheme::New( "remixicon" );
|
||||
auto addIcon = [iconTheme, iconFont]( const std::string& name, const Uint32& codePoint,
|
||||
const Uint32& size ) -> Drawable* {
|
||||
Drawable* ic = iconFont->getGlyphDrawable( codePoint, size );
|
||||
iconTheme->add( name, ic );
|
||||
return ic;
|
||||
};
|
||||
Drawable* closed = addIcon( "folder", 0xed6a, 16 );
|
||||
Drawable* open = addIcon( "folder-open", 0xed70, 16 );
|
||||
addIcon( "tree-expanded", 0xea50, 24 );
|
||||
addIcon( "tree-contracted", 0xea54, 24 );
|
||||
addIcon( "file", 0xecc3, 24 );
|
||||
UISceneNode* uiSceneNode = UISceneNode::New();
|
||||
SceneManager::instance()->add( uiSceneNode );
|
||||
uiSceneNode->getUIThemeManager()->setDefaultFont( font );
|
||||
uiSceneNode->getUIIconThemeManager()->setCurrentTheme( iconTheme );
|
||||
/*StyleSheetParser styleSheetParser;
|
||||
styleSheetParser.loadFromFile( "assets/ui/breeze.css" );
|
||||
uiSceneNode->setStyleSheet( styleSheetParser.getStyleSheet() );*/
|
||||
@@ -50,9 +179,10 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
pd = "1.5x";
|
||||
else if ( PixelDensity::getPixelDensity() >= 2.f )
|
||||
pd = "2x";
|
||||
UITheme* theme =
|
||||
/*UITheme* theme =
|
||||
UITheme::load( "uitheme" + pd, "uitheme" + pd, "assets/ui/uitheme" + pd + ".eta", font,
|
||||
"assets/ui/uitheme.css" );
|
||||
"assets/ui/uitheme.css" );*/
|
||||
UITheme* theme = UITheme::load( "breeze", "breeze", "", font, "assets/ui/breeze.css" );
|
||||
uiSceneNode->setStyleSheet( theme->getStyleSheet() );
|
||||
uiSceneNode->getUIThemeManager()
|
||||
->setDefaultEffectsEnabled( true )
|
||||
@@ -63,6 +193,17 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
auto* vlay = UILinearLayout::NewVertical();
|
||||
vlay->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
|
||||
Clock clock;
|
||||
auto model = std::make_shared<TestModel>();
|
||||
UITreeView* view = UITreeView::New();
|
||||
view->setId( "treeview" );
|
||||
view->setExpandedIcon( open );
|
||||
view->setContractedIcon( closed );
|
||||
view->setLayoutSizePolicy( SizePolicy::MatchParent, SizePolicy::MatchParent );
|
||||
view->setParent( vlay );
|
||||
view->setModel( model );
|
||||
eePRINTL( "Total time: %.2fms", clock.getElapsedTime().asMilliseconds() );
|
||||
|
||||
/* ListBox test */ /*
|
||||
std::vector<String> strings;
|
||||
for ( size_t i = 0; i < 10000; i++ )
|
||||
@@ -101,7 +242,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
uiSceneNode->getRoot()->childsCloseAll();
|
||||
SceneManager::instance()->update();*/
|
||||
|
||||
total.restart();
|
||||
/*total.restart();
|
||||
for ( size_t i = 0; i < 100000; i++ ) {
|
||||
auto* widget = UIWidget::New();
|
||||
widget->setParent( vlay );
|
||||
@@ -115,7 +256,7 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
widget->setBackgroundColor( Color::fromHsv( col ) );
|
||||
}
|
||||
std::cout << "Time UIWidget total: " << total.getElapsedTime().asMilliseconds() << " ms"
|
||||
<< std::endl;
|
||||
<< std::endl;*/
|
||||
|
||||
/*UIWindow* wind = UIWindow::New();
|
||||
wind->setSize( 500, 500 );
|
||||
|
||||
Reference in New Issue
Block a user