Minor improvements to UITreeView and related views.

Also improved UISplitter.
Improved side panel in ecode.
This commit is contained in:
Martín Lucas Golini
2020-07-19 21:12:23 -03:00
parent 08caa0070d
commit ad4e4b5367
25 changed files with 525 additions and 201 deletions

10
TODO.md
View File

@@ -25,20 +25,18 @@ Detect errors and log them.
* Add XML tags auto-close.
## UITreeView
Implement a simple tree view widget, to at least cover the most common use cases.
## Code Editor
* Support single instance (when a new file is opened while a previous instance exists, open it in the first instance).
* Once `UITreeView` is finished add a directory/project tree view.
* Add support for function listing.
* Display number of results in search and number of replacements.
* Add support for global/project search.
* Add support for find and open file.
## UI Editor
* Integrate the `UICodeEditor` into the editor in order to be able to edit the layouts and CSS in app.

View File

@@ -1508,6 +1508,27 @@ Sets the [skin](#skin) tint color.
---
### splitter-always-show
Sets if the splitter divisor is always visible. If false it will be shown only if two views are
attached to the splitter.
* Applicable to: EE::UI::UISplitter (Splitter)
* Data Type: [boolean](#boolean-data-type)
* Default value: `true`
---
### splitter-partition
Sets the space ocuppied by the first view contained by the splitter.
* Applicable to: EE::UI::UISplitter (Splitter)
* Data Type: [length-percentage](#length-percentage-data-type)
* Default value: `50%`
---
### src
Sets the source of a resource in an element that supports source.

View File

@@ -46,6 +46,14 @@ class EE_API UIAbstractTableView : public UIAbstractView {
int visibleColumnCount() const;
/** In pixels. */
void setRowHeight( const Float& rowHeight );
void columnResizeToContent( const size_t& colIndex );
/** In pixels. */
void setColumnWidth( const size_t& colIndex, const Float& width );
protected:
friend class EE::UI::UITableHeaderColumn;
@@ -53,6 +61,8 @@ class EE_API UIAbstractTableView : public UIAbstractView {
UIAbstractTableView( const std::string& tag );
Float mRowHeight{0};
struct ColumnData {
Float width{0};
bool visible{true};

View File

@@ -191,6 +191,8 @@ enum class PropertyId : Uint32 {
TabBarHideOnSingleTab = String::hash( "tabbar-hide-on-single-tab" ),
TabBarAllowRearrange = String::hash( "tabbar-allow-rearrange" ),
TabBarAllowDragAndDrop = String::hash( "tabbar-allow-drag-and-drop-tabs" ),
SplitterPartition = String::hash( "splitter-partition" ),
SplitterAlwaysShow = String::hash( "splitter-always-show" ),
};
enum class PropertyType : Uint32 {

View File

@@ -40,7 +40,7 @@ class EE_API StyleSheetLength {
StyleSheetLength( const Float& val, const Unit& unit );
StyleSheetLength( std::string val, const Float& defaultValue = 0 );
StyleSheetLength( const std::string& val, const Float& defaultValue = 0 );
StyleSheetLength( const StyleSheetLength& val );
@@ -56,7 +56,9 @@ class EE_API StyleSheetLength {
Float asDp( const Float& parentSize, const Sizef& viewSize, const Float& displayDpi,
const Float& elFontSize = 12, const Float& globalFontSize = 12 ) const;
bool operator==( const StyleSheetLength& val );
bool operator==( const StyleSheetLength& val ) const;
bool operator!=( const StyleSheetLength& val ) const;
StyleSheetLength& operator=( const StyleSheetLength& val );

View File

@@ -20,6 +20,7 @@ class EE_API FileSystemModel : public Model {
Permissions,
ModificationTime,
Inode,
Path,
SymlinkTarget,
Count,
};
@@ -32,10 +33,14 @@ class EE_API FileSystemModel : public Model {
Node* getParent() const { return mParent; }
const FileInfo& info() const { return mInfo; }
bool isSelected() const { return mSelected; }
void setSelected( bool selected );
void setSelected( bool selected ) { mSelected = selected; };
const std::string& fullPath() const;
const std::string& getMimeType() const { return mMimeType; }
size_t childCount() const { return mChildren.size(); }
const Node& getChild( const size_t& index ) {
eeASSERT( index < mChildren.size() );
return mChildren[index];
}
private:
friend class FileSystemModel;
@@ -49,7 +54,7 @@ class EE_API FileSystemModel : public Model {
bool mSelected{false};
ModelIndex index( const FileSystemModel& model, int column ) const;
void traverseIfNeeded( const FileSystemModel& );
void reifyIfNeeded( const FileSystemModel& );
void refreshIfNeeded( const FileSystemModel& );
bool fetchData( const String& fullPath );
};
@@ -62,6 +67,8 @@ class EE_API FileSystemModel : public Model {
void setRootPath( const std::string& rootPath );
void reload();
void update();
const Node& node( const ModelIndex& index ) const;
@@ -76,14 +83,24 @@ class EE_API FileSystemModel : public Model {
virtual Drawable* iconFor( const Node& node, const ModelIndex& index ) const;
FileSystemModel( const std::string& rootPath, const Mode& mode );
void setMode( const Mode& mode );
void updateNodeSelection( const ModelIndex& index, const bool selected );
ModelIndex getPreviouslySelectedIndex() const;
void setPreviouslySelectedIndex( const ModelIndex& previouslySelectedIndex );
protected:
std::string mRootPath;
std::unique_ptr<Node> mRoot{nullptr};
Mode mMode{Mode::FilesAndDirectories};
ModelIndex mPreviouslySelectedIndex{};
Node& nodeRef( const ModelIndex& index ) const;
FileSystemModel( const std::string& rootPath, const Mode& mode );
};
}}} // namespace EE::UI::Models

View File

@@ -80,6 +80,8 @@ class EE_API Model {
void unregisterView( UIAbstractView* );
void refreshView();
void setOnUpdate( const std::function<void()>& onUpdate );
protected:

View File

@@ -53,6 +53,8 @@ class EE_API UIPushButton : public UIWidget {
explicit UIPushButton( const std::string& tag );
virtual void updateLayout();
virtual void onSizeChange();
virtual void onAlphaChange();

View File

@@ -42,10 +42,15 @@ class EE_API UIScrollableWidget : public UIWidget {
void scrollToBottom();
void scrollToPosition( const Vector2f& pos, const bool& scrollVertically = true,
const bool& scrollHorizontally = false );
Sizef getScrollableArea() const;
Sizef getVisibleArea() const;
Rectf getVisibleRect() const;
protected:
ScrollViewType mViewType;
ScrollBarMode mVScrollMode;

View File

@@ -9,8 +9,6 @@ class EE_API UISplitter : public UILayout {
public:
static UISplitter* New();
UISplitter();
~UISplitter();
Uint32 getType() const;
@@ -25,9 +23,9 @@ class EE_API UISplitter : public UILayout {
void setAlwaysShowSplitter( bool alwaysShowSplitter );
const Float& getDivisionSplit() const;
const StyleSheetLength& getSplitPartition() const;
void setDivisionSplit( const Float& divisionSplit );
void setSplitPartition( const StyleSheetLength& divisionSplit );
void swap();
@@ -39,15 +37,21 @@ class EE_API UISplitter : public UILayout {
UIWidget* getLastWidget() const;
bool applyProperty( const StyleSheetProperty& attribute );
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
const Uint32& propertyIndex = 0 );
protected:
UIOrientation mOrientation;
bool mSplitOnlyWhenNeeded;
bool mAlwaysShowSplitter;
Float mDivisionSplit;
StyleSheetLength mSplitPartition;
UIWidget* mSplitter;
UIWidget* mFirstWidget;
UIWidget* mLastWidget;
UISplitter();
virtual void onChildCountChange( Node* child, const bool& removed );
virtual void updateLayout();

View File

@@ -10,7 +10,7 @@ class UIAbstractTableView;
}
using namespace Abstract;
class UITableHeaderColumn : public UIPushButton {
class EE_API UITableHeaderColumn : public UIPushButton {
public:
UITableHeaderColumn( UIAbstractTableView* view, const size_t& colIndex );

View File

@@ -0,0 +1,39 @@
#ifndef EE_UI_UITABLEROW_HPP
#define EE_UI_UITABLEROW_HPP
#include <eepp/ui/models/modelindex.hpp>
#include <eepp/ui/uiwidget.hpp>
using namespace EE::UI::Models;
namespace EE { namespace UI {
class EE_API UITableRow : public UIWidget {
public:
static UITableRow* New( const std::string& tag ) { return eeNew( UITableRow, ( tag ) ); }
ModelIndex getCurIndex() const { return mCurIndex; }
void setCurIndex( const ModelIndex& curIndex ) { mCurIndex = curIndex; }
protected:
UITableRow( const std::string& tag ) : UIWidget( tag ) {}
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;
};
}} // namespace EE::UI
#endif // EE_UI_UITABLEROW_HPP

View File

@@ -2,6 +2,7 @@
#define EE_UI_UITREEVIEW_HPP
#include <eepp/ui/abstract/uiabstracttableview.hpp>
#include <eepp/ui/uitablerow.hpp>
#include <memory>
#include <unordered_map>
@@ -71,12 +72,14 @@ class EE_API UITreeView : public UIAbstractTableView {
virtual void onColumnSizeChange( const size_t& colIndex );
virtual UITableRow* createRow();
virtual UITableRow* updateRow( const int& rowIndex, const ModelIndex& index,
const Float& yOffset );
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();

View File

@@ -399,6 +399,7 @@
../../include/eepp/ui/uitablecell.hpp
../../include/eepp/ui/uitable.hpp
../../include/eepp/ui/uitableheadercolumn.hpp
../../include/eepp/ui/uitablerow.hpp
../../include/eepp/ui/uitabwidget.hpp
../../include/eepp/ui/uitextedit.hpp
../../include/eepp/ui/uitextinput.hpp

View File

@@ -26,8 +26,29 @@ bool UIAbstractTableView::isType( const Uint32& type ) const {
}
Float UIAbstractTableView::getRowHeight() const {
return eeceil( columnData( 0 ).widget ? columnData( 0 ).widget->getPixelsSize().getHeight()
: 16 );
return mRowHeight != 0 ? mRowHeight
: ( eeceil( columnData( 0 ).widget
? columnData( 0 ).widget->getPixelsSize().getHeight()
: 16 ) );
}
void UIAbstractTableView::setRowHeight( const Float& rowHeight ) {
if ( mRowHeight != rowHeight ) {
mRowHeight = rowHeight;
createOrUpdateColumns();
}
}
void UIAbstractTableView::columnResizeToContent( const size_t& colIndex ) {
onColumnResizeToContent( colIndex );
}
void UIAbstractTableView::setColumnWidth( const size_t& colIndex, const Float& width ) {
if ( columnData( colIndex ).width != width ) {
columnData( colIndex ).width = width;
updateHeaderSize();
onColumnSizeChange( colIndex );
}
}
void UIAbstractTableView::selectAll() {

View File

@@ -91,7 +91,7 @@ StyleSheetLength::StyleSheetLength() : mUnit( Px ), mValue( 0 ) {}
StyleSheetLength::StyleSheetLength( const Float& val, const StyleSheetLength::Unit& unit ) :
mUnit( unit ), mValue( val ) {}
StyleSheetLength::StyleSheetLength( std::string val, const Float& defaultValue ) :
StyleSheetLength::StyleSheetLength( const std::string& val, const Float& defaultValue ) :
StyleSheetLength( fromString( val, defaultValue ) ) {}
StyleSheetLength::StyleSheetLength( const StyleSheetLength& val ) {
@@ -170,10 +170,14 @@ Float StyleSheetLength::asDp( const Float& parentSize, const Sizef& viewSize,
asPixels( parentSize, viewSize, displayDpi, elFontSize, globalFontSize ) );
}
bool StyleSheetLength::operator==( const StyleSheetLength& length ) {
bool StyleSheetLength::operator==( const StyleSheetLength& length ) const {
return mValue == length.mValue && mUnit == length.mUnit;
}
bool StyleSheetLength::operator!=( const StyleSheetLength& length ) const {
return !( *this == length );
}
StyleSheetLength& StyleSheetLength::operator=( const Float& val ) {
mValue = val;
mUnit = Unit::Px;

View File

@@ -364,6 +364,11 @@ void StyleSheetSpecification::registerDefaultProperties() {
registerProperty( "tabbar-allow-rearrange", "false" );
registerProperty( "tabbar-allow-drag-and-drop-tabs", "false" );
registerProperty( "splitter-partition", "50%" )
.setType( PropertyType::NumberLength )
.setRelativeTarget( PropertyRelativeTarget::LocalBlockWidth );
registerProperty( "splitter-always-show", "true" ).setType( PropertyType::Bool );
// Shorthands
registerShorthand( "margin", {"margin-top", "margin-right", "margin-bottom", "margin-left"},
"box" );

View File

@@ -59,7 +59,7 @@ void FileSystemModel::Node::traverseIfNeeded( const FileSystemModel& model ) {
}
}
void FileSystemModel::Node::reifyIfNeeded( const FileSystemModel& model ) {
void FileSystemModel::Node::refreshIfNeeded( const FileSystemModel& model ) {
traverseIfNeeded( model );
if ( mInfoDirty )
fetchData( fullPath() );
@@ -75,7 +75,7 @@ bool FileSystemModel::Node::fetchData( const String& fullPath ) {
std::shared_ptr<FileSystemModel> FileSystemModel::New( const std::string& rootPath,
const FileSystemModel::Mode& mode ) {
return std::make_shared<FileSystemModel>( rootPath, mode );
return std::shared_ptr<FileSystemModel>( new FileSystemModel( rootPath, mode ) );
}
FileSystemModel::FileSystemModel( const std::string& rootPath, const FileSystemModel::Mode& mode ) :
@@ -92,6 +92,10 @@ void FileSystemModel::setRootPath( const std::string& rootPath ) {
update();
}
void FileSystemModel::reload() {
setRootPath( mRootPath );
}
void FileSystemModel::update() {
mRoot = std::make_unique<Node>( mRootPath, *this );
onModelUpdate();
@@ -109,7 +113,7 @@ FileSystemModel::Node& FileSystemModel::nodeRef( const ModelIndex& index ) const
size_t FileSystemModel::rowCount( const ModelIndex& index ) const {
Node& node = const_cast<Node&>( this->node( index ) );
node.reifyIfNeeded( *this );
node.refreshIfNeeded( *this );
if ( node.info().isDirectory() )
return node.mChildren.size();
return 0;
@@ -139,6 +143,8 @@ std::string FileSystemModel::columnName( const size_t& column ) const {
return "Inode";
case Column::SymlinkTarget:
return "Symlink target";
case Column::Path:
return "Path";
default:
return "";
}
@@ -172,7 +178,7 @@ Variant FileSystemModel::data( const ModelIndex& index, Model::Role role ) const
if ( role == Role::Custom ) {
eeASSERT( index.column() == Column::Name );
return Variant( node.info().getFilepath() );
return Variant( node.info().getFilepath().c_str() );
}
if ( role == Role::Sort ) {
@@ -195,6 +201,8 @@ Variant FileSystemModel::data( const ModelIndex& index, Model::Role role ) const
return node.info().getInode();
case Column::SymlinkTarget:
return Variant( node.info().linksTo() );
case Column::Path:
return Variant( node.info().getFilepath().c_str() );
default:
eeASSERT( false );
}
@@ -220,6 +228,8 @@ Variant FileSystemModel::data( const ModelIndex& index, Model::Role role ) const
return Variant( String::toString( node.info().getInode() ) );
case Column::SymlinkTarget:
return node.info().isLink() ? Variant( node.info().linksTo() ) : Variant();
case Column::Path:
return Variant( node.info().getFilepath().c_str() );
}
}
@@ -244,7 +254,7 @@ ModelIndex FileSystemModel::index( int row, int column, const ModelIndex& parent
if ( row < 0 || column < 0 )
return {};
auto& node = this->node( parent );
const_cast<Node&>( node ).reifyIfNeeded( *this );
const_cast<Node&>( node ).refreshIfNeeded( *this );
if ( static_cast<size_t>( row ) >= node.mChildren.size() )
return {};
return createIndex( row, column, &node.mChildren[row] );
@@ -258,4 +268,25 @@ Drawable* FileSystemModel::iconFor( const Node& node, const ModelIndex& index )
return nullptr;
}
void FileSystemModel::setMode( const Mode& mode ) {
if ( mode != mMode ) {
mMode = mode;
reload();
}
}
void FileSystemModel::updateNodeSelection( const ModelIndex& index, const bool selected ) {
Node& node = const_cast<Node&>( this->node( index ) );
node.setSelected( selected );
setPreviouslySelectedIndex( index );
}
ModelIndex FileSystemModel::getPreviouslySelectedIndex() const {
return mPreviouslySelectedIndex;
}
void FileSystemModel::setPreviouslySelectedIndex( const ModelIndex& previouslySelectedIndex ) {
mPreviouslySelectedIndex = previouslySelectedIndex;
}
}}} // namespace EE::UI::Models

View File

@@ -18,6 +18,10 @@ void Model::unregisterView( UIAbstractView* view ) {
mViews.erase( view );
}
void Model::refreshView() {
forEachView( [&]( UIAbstractView* view ) { view->invalidateDraw(); } );
}
void Model::registerView( UIAbstractView* view ) {
mViews.insert( view );
}
@@ -43,4 +47,4 @@ bool Model::acceptsDrag( const ModelIndex&, const std::string& ) {
return false;
}
}}} // namespace EE::UI::Model
}}} // namespace EE::UI::Models

View File

@@ -108,15 +108,7 @@ void UIPushButton::onAutoSize() {
}
}
void UIPushButton::onPaddingChange() {
onSizeChange();
UIWidget::onPaddingChange();
}
void UIPushButton::onSizeChange() {
onAutoSize();
void UIPushButton::updateLayout() {
Rectf autoPadding;
if ( mFlags & UI_AUTO_PADDING ) {
@@ -225,6 +217,18 @@ void UIPushButton::onSizeChange() {
if ( NULL != eWidget && eWidget->isVisible() ) {
eWidget->setPixelsPosition( ePos );
}
}
void UIPushButton::onPaddingChange() {
onSizeChange();
UIWidget::onPaddingChange();
}
void UIPushButton::onSizeChange() {
onAutoSize();
updateLayout();
UIWidget::onSizeChange();
}
@@ -237,7 +241,7 @@ void UIPushButton::setTheme( UITheme* Theme ) {
}
void UIPushButton::onThemeLoaded() {
onSizeChange();
updateLayout();
UIWidget::onThemeLoaded();
}
@@ -245,7 +249,7 @@ void UIPushButton::onThemeLoaded() {
UIPushButton* UIPushButton::setIcon( Drawable* Icon ) {
if ( mIcon->getDrawable() != Icon ) {
mIcon->setDrawable( Icon );
onSizeChange();
updateLayout();
}
return this;
}
@@ -255,8 +259,10 @@ UIImage* UIPushButton::getIcon() const {
}
UIPushButton* UIPushButton::setText( const String& text ) {
mTextBox->setText( text );
onSizeChange();
if ( text != mTextBox->getText() ) {
mTextBox->setText( text );
updateLayout();
}
return this;
}

View File

@@ -172,7 +172,7 @@ void UIScrollableWidget::onContentSizeChange() {
Sizef UIScrollableWidget::getScrollableArea() const {
Sizef contentSize( getContentSize() );
Sizef size = getVisibleArea();
Sizef size( getVisibleArea() );
return contentSize - size;
}
@@ -185,6 +185,10 @@ Sizef UIScrollableWidget::getVisibleArea() const {
return size;
}
Rectf UIScrollableWidget::getVisibleRect() const {
return Rectf( mScrollOffset, getVisibleArea() );
}
void UIScrollableWidget::updateScroll() {
Sizef totalScroll = getScrollableArea();
Vector2f initScroll( mScrollOffset );
@@ -238,6 +242,25 @@ void UIScrollableWidget::scrollToBottom() {
mVScroll->setValue( 1 );
}
void UIScrollableWidget::scrollToPosition( const Vector2f& pos, const bool& scrollVertically,
const bool& scrollHorizontally ) {
Rectf visibleRect( getVisibleRect() );
if ( visibleRect.contains( pos ) )
return;
if ( scrollVertically ) {
if ( pos.y < visibleRect.Top || pos.y > visibleRect.Bottom ) {
mVScroll->setValue( pos.y / getContentSize().y );
}
}
if ( scrollHorizontally ) {
if ( pos.x < visibleRect.Left || pos.x > visibleRect.Right ) {
mHScroll->setValue( pos.x / getContentSize().x );
}
}
}
bool UIScrollableWidget::applyProperty( const StyleSheetProperty& attribute ) {
if ( !checkPropertyDefinition( attribute ) )
return false;

View File

@@ -11,9 +11,8 @@ UISplitter* UISplitter::New() {
UISplitter::UISplitter() :
UILayout( "splitter" ),
mOrientation( UIOrientation::Horizontal ),
mSplitOnlyWhenNeeded( true ),
mAlwaysShowSplitter( true ),
mDivisionSplit( 0.5f ),
mSplitPartition( StyleSheetLength( "50%" ) ),
mFirstWidget( NULL ),
mLastWidget( NULL ) {
mFlags |= UI_OWNS_CHILDS_POSITION;
@@ -77,13 +76,13 @@ void UISplitter::setAlwaysShowSplitter( bool alwaysShowSplitter ) {
}
}
const Float& UISplitter::getDivisionSplit() const {
return mDivisionSplit;
const StyleSheetLength& UISplitter::getSplitPartition() const {
return mSplitPartition;
}
void UISplitter::setDivisionSplit( const Float& divisionSplit ) {
if ( eeclamp( divisionSplit, 0.f, 1.f ) != mDivisionSplit ) {
mDivisionSplit = eeclamp( divisionSplit, 0.f, 1.f );
void UISplitter::setSplitPartition( const StyleSheetLength& divisionSplit ) {
if ( divisionSplit != mSplitPartition ) {
mSplitPartition = divisionSplit;
setLayoutDirty();
}
}
@@ -113,6 +112,35 @@ UIWidget* UISplitter::getLastWidget() const {
return mLastWidget;
}
bool UISplitter::applyProperty( const StyleSheetProperty& attribute ) {
if ( !checkPropertyDefinition( attribute ) )
return false;
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
case PropertyId::SplitterPartition:
setSplitPartition( StyleSheetLength( attribute.asString() ) );
case PropertyId::SplitterAlwaysShow:
setAlwaysShowSplitter( attribute.asBool() );
default:
return UILayout::applyProperty( attribute );
}
}
std::string UISplitter::getPropertyString( const PropertyDefinition* propertyDef,
const Uint32& propertyIndex ) {
if ( NULL == propertyDef )
return "";
switch ( propertyDef->getPropertyId() ) {
case PropertyId::SplitterPartition:
return getSplitPartition().toString();
case PropertyId::SplitterAlwaysShow:
return alwaysShowSplitter() ? "true" : "false";
default:
return UILayout::getPropertyString( propertyDef, propertyIndex );
}
}
void UISplitter::onChildCountChange( Node* child, const bool& removed ) {
if ( child != mSplitter ) {
if ( !removed ) {
@@ -131,6 +159,7 @@ void UISplitter::onChildCountChange( Node* child, const bool& removed ) {
} else {
mLastWidget = childWidget;
}
childWidget->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
mSplitter->toFront();
}
} else {
@@ -234,13 +263,19 @@ void UISplitter::updateFromDrag() {
}
if ( UIOrientation::Horizontal == mOrientation ) {
mDivisionSplit =
( mSplitter->getPixelsPosition().x + mSplitter->getPixelsSize().getWidth() ) /
( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right );
mSplitPartition = StyleSheetLength(
eeclamp<Float>(
( mSplitter->getPixelsPosition().x + mSplitter->getPixelsSize().getWidth() ) /
( mSize.getWidth() - mRealPadding.Left - mRealPadding.Right ) * 100,
0, 100 ),
StyleSheetLength::Percentage );
} else {
mDivisionSplit =
( mSplitter->getPixelsPosition().y + mSplitter->getPixelsSize().getHeight() ) /
( mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom );
mSplitPartition = StyleSheetLength(
eeclamp<Float>(
( mSplitter->getPixelsPosition().y + mSplitter->getPixelsSize().getHeight() ) /
( mSize.getHeight() - mRealPadding.Top - mRealPadding.Bottom ) * 100,
0, 100 ),
StyleSheetLength::Percentage );
}
mDirtyLayout = false;
@@ -286,7 +321,7 @@ void UISplitter::updateLayout() {
}
}
if ( mSplitOnlyWhenNeeded && !mLastWidget ) {
if ( !mLastWidget ) {
mSplitter->setVisible( false )->setEnabled( false );
if ( mFirstWidget ) {
@@ -311,7 +346,7 @@ void UISplitter::updateLayout() {
: mSplitter->getPixelsSize().getHeight();
}
Float firstSplit = ( totalSpace * mDivisionSplit );
Float firstSplit = convertLength( mSplitPartition, totalSpace );
Float secondSplit = totalSpace - firstSplit;
if ( mFirstWidget ) {

View File

@@ -1,3 +1,4 @@
#include <deque>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/ui/uilinearlayout.hpp>
#include <eepp/ui/uipushbutton.hpp>
@@ -96,49 +97,29 @@ 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() ||
UITableRow* UITreeView::createRow() {
UITableRow* rowWidget = UITableRow::New( "table::row" );
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 ) {
sendMouseEvent( Event::MouseDown, getEventDispatcher()->getMousePos(),
msg->getFlags() );
getSelection().set( event->getNode()->asType<UITableRow>()->getCurIndex() );
}
return 0;
}
} );
return rowWidget;
}
ModelIndex mCurIndex;
};
UIWidget* UITreeView::updateRow( const int& rowIndex, const ModelIndex& index,
const Float& yOffset ) {
UITableRow* 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() );
}
} );
rowWidget = createRow();
mRows[rowIndex] = rowWidget;
} else {
rowWidget = mRows[rowIndex];
@@ -375,10 +356,63 @@ Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
auto curIndex = getSelection().first();
switch ( event.getKeyCode() ) {
case KEY_PAGEUP: {
int pageSize = eefloor( getVisibleArea().getHeight() / getRowHeight() ) - 1;
std::deque<std::pair<ModelIndex, Float>> deque;
Float curY;
traverseTree(
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
deque.push_back( {index, offsetY} );
if ( (int)deque.size() > pageSize )
deque.pop_front();
if ( index == curIndex )
return IterationDecision::Break;
return IterationDecision::Continue;
} );
curY = deque.front().second - getHeaderHeight();
getSelection().set( deque.front().first );
scrollToPosition( {mScrollOffset.x, curY} );
break;
}
case KEY_PAGEDOWN: {
int pageSize = eefloor( getVisibleArea().getHeight() / getRowHeight() ) - 1;
int counted = 0;
bool foundStart = false;
bool resultFound = false;
ModelIndex foundIndex;
Float curY;
Float lastOffsetY;
ModelIndex lastIndex;
traverseTree(
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
if ( index == curIndex ) {
foundStart = true;
} else if ( foundStart ) {
counted++;
if ( counted == pageSize ) {
foundIndex = index;
curY = offsetY;
resultFound = true;
return IterationDecision::Break;
}
}
lastOffsetY = offsetY;
lastIndex = index;
return IterationDecision::Continue;
} );
if ( !resultFound ) {
foundIndex = lastIndex;
curY = lastOffsetY;
}
curY += getRowHeight();
getSelection().set( foundIndex );
scrollToPosition( {mScrollOffset.x, curY} );
break;
}
case KEY_UP: {
ModelIndex prevIndex;
ModelIndex foundIndex;
Float curY;
Float curY = 0;
traverseTree(
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
if ( index == curIndex ) {
@@ -404,7 +438,7 @@ Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
case KEY_DOWN: {
ModelIndex prevIndex;
ModelIndex foundIndex;
Float curY;
Float curY = 0;
traverseTree(
[&]( const int&, const ModelIndex& index, const size_t&, const Float& offsetY ) {
if ( prevIndex == curIndex ) {

View File

@@ -257,6 +257,7 @@ void App::loadConfig() {
mConfig.window.maximized = mIniState.getValueB( "window", "maximized", false );
mConfig.window.pixelDensity = mIniState.getValueF( "window", "pixeldensity" );
mConfig.window.winIcon = mIni.getValue( "window", "winicon", mResPath + "assets/icon/ee.png" );
mConfig.window.panelPartition = mIniState.getValue( "window", "panel_partition", "15%" );
mConfig.editor.showLineNumbers = mIni.getValueB( "editor", "show_line_numbers", true );
mConfig.editor.showWhiteSpaces = mIni.getValueB( "editor", "show_white_spaces", true );
mConfig.editor.highlightMatchingBracket =
@@ -265,6 +266,7 @@ void App::loadConfig() {
mIni.getValueB( "editor", "highlight_current_line", true );
mConfig.editor.horizontalScrollbar = mIni.getValueB( "editor", "horizontal_scrollbar", false );
mConfig.ui.fontSize = mIni.getValue( "ui", "font_size", "11dp" );
mConfig.ui.showSidePanel = mIni.getValueB( "ui", "show_side_panel", true );
mConfig.editor.trimTrailingWhitespaces =
mIni.getValueB( "editor", "trim_trailing_whitespaces", false );
mConfig.editor.forceNewLineAtEndOfFile =
@@ -296,6 +298,9 @@ void App::saveConfig() {
mIniState.setValueI( "window", "height", mConfig.window.size.getHeight() );
mIniState.setValueB( "window", "maximized", mConfig.window.maximized );
mIniState.setValueF( "window", "pixeldensity", mConfig.window.pixelDensity );
mIniState.setValue( "window", "panel_partition",
mProjectSplitter ? mProjectSplitter->getSplitPartition().toString()
: "15%" );
mIniState.setValue( "files", "recentfiles", String::join( mRecentFiles, ';' ) );
mIni.setValueB( "editor", "show_line_numbers", mConfig.editor.showLineNumbers );
mIni.setValueB( "editor", "show_white_spaces", mConfig.editor.showWhiteSpaces );
@@ -305,6 +310,7 @@ void App::saveConfig() {
mIni.setValueB( "editor", "horizontal_scrollbar", mConfig.editor.horizontalScrollbar );
mIni.setValue( "editor", "font_size", mConfig.editor.fontSize.toString() );
mIni.setValue( "ui", "font_size", mConfig.ui.fontSize.toString() );
mIni.setValueB( "ui", "show_side_panel", mConfig.ui.showSidePanel );
mIni.setValueB( "editor", "trim_trailing_whitespaces", mConfig.editor.trimTrailingWhitespaces );
mIni.setValueB( "editor", "force_new_line_at_end_of_file",
mConfig.editor.forceNewLineAtEndOfFile );
@@ -547,101 +553,46 @@ void App::updateRecentFiles() {
}
}
UIMenu* App::createViewMenu() {
mViewMenu = UIPopUpMenu::New();
mViewMenu->addCheckBox( "Show Line Numbers" )->setActive( mConfig.editor.showLineNumbers );
mViewMenu->addCheckBox( "Show White Space" )->setActive( mConfig.editor.showWhiteSpaces );
mViewMenu->addCheckBox( "Show Document Info" )->setActive( mConfig.editor.showDocInfo );
mViewMenu->addCheckBox( "Highlight Matching Bracket" )
->setActive( mConfig.editor.highlightMatchingBracket );
mViewMenu->addCheckBox( "Highlight Current Line" )
->setActive( mConfig.editor.highlightCurrentLine );
mViewMenu->addCheckBox( "Highlight Selection Match" )
->setActive( mConfig.editor.highlightSelectionMatch );
mViewMenu->addCheckBox( "Enable Horizontal ScrollBar" )
->setActive( mConfig.editor.horizontalScrollbar );
mViewMenu->addCheckBox( "Enable Color Preview" )
->setActive( mConfig.editor.colorPreview )
->setTooltipText( "Enables a quick preview of a color when the mouse\n"
"is hover a word that represents a color." );
mViewMenu->addCheckBox( "Enable Color Picker" )
->setActive( mConfig.editor.colorPickerSelection )
->setTooltipText( "Enables the color picker tool when a double click selection\n"
"is done over a word representing a color." );
mViewMenu->addCheckBox( "Enable Auto Complete" )
->setActive( mConfig.editor.autoComplete )
->setTooltipText( "Auto complete shows the completion popup as you type, so you can fill\n"
"in long words by typing only a few characters." );
mViewMenu->add( "Line Breaking Column" );
mViewMenu->addSeparator();
mViewMenu->add( "UI Scale Factor (Pixel Density)", findIcon( "pixel-density" ) );
mViewMenu->add( "UI Font Size", findIcon( "font-size" ) );
mViewMenu->add( "Editor Font Size", findIcon( "font-size" ) );
mViewMenu->addSeparator();
mViewMenu->addCheckBox( "Full Screen Mode" )
void App::showSidePanel( bool show ) {
if ( show == mSidePanel->isVisible() )
return;
if ( show ) {
mSidePanel->setVisible( true );
mSidePanel->setParent( mProjectSplitter );
mProjectSplitter->swap();
} else {
mSidePanel->setVisible( false );
mSidePanel->setParent( mUISceneNode->getRoot() );
}
}
UIMenu* App::createWindowMenu() {
mWindowMenu = UIPopUpMenu::New();
mWindowMenu->add( "UI Scale Factor (Pixel Density)", findIcon( "pixel-density" ) );
mWindowMenu->add( "UI Font Size", findIcon( "font-size" ) );
mWindowMenu->add( "Editor Font Size", findIcon( "font-size" ) );
mWindowMenu->addSeparator();
mWindowMenu->addCheckBox( "Full Screen Mode" )
->setShortcutText( getKeybind( "fullscreen-toggle" ) )
->setId( "fullscreen-mode" );
mViewMenu->addSeparator();
mViewMenu->add( "Split Left", findIcon( "split-horizontal" ), getKeybind( "split-left" ) );
mViewMenu->add( "Split Right", findIcon( "split-horizontal" ), getKeybind( "split-right" ) );
mViewMenu->add( "Split Top", findIcon( "split-vertical" ), getKeybind( "split-top" ) );
mViewMenu->add( "Split Bottom", findIcon( "split-vertical" ), getKeybind( "split-bottom" ) );
mViewMenu->addSeparator();
mViewMenu->add( "Zoom In", findIcon( "zoom-in" ), getKeybind( "font-size-grow" ) );
mViewMenu->add( "Zoom Out", findIcon( "zoom-out" ), getKeybind( "font-size-shrink" ) );
mViewMenu->add( "Zoom Reset", findIcon( "zoom-reset" ), getKeybind( "font-size-reset" ) );
mViewMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) {
mWindowMenu->addCheckBox( "Show Side Panel" )->setActive( mConfig.ui.showSidePanel );
mWindowMenu->addSeparator();
mWindowMenu->add( "Split Left", findIcon( "split-horizontal" ), getKeybind( "split-left" ) );
mWindowMenu->add( "Split Right", findIcon( "split-horizontal" ), getKeybind( "split-right" ) );
mWindowMenu->add( "Split Top", findIcon( "split-vertical" ), getKeybind( "split-top" ) );
mWindowMenu->add( "Split Bottom", findIcon( "split-vertical" ), getKeybind( "split-bottom" ) );
mWindowMenu->addSeparator();
mWindowMenu->add( "Zoom In", findIcon( "zoom-in" ), getKeybind( "font-size-grow" ) );
mWindowMenu->add( "Zoom Out", findIcon( "zoom-out" ), getKeybind( "font-size-shrink" ) );
mWindowMenu->add( "Zoom Reset", findIcon( "zoom-reset" ), getKeybind( "font-size-reset" ) );
mWindowMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) {
if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )
return;
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
if ( item->getText() == "Show Line Numbers" ) {
mConfig.editor.showLineNumbers = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setShowLineNumber( mConfig.editor.showLineNumbers );
} );
} else if ( item->getText() == "Show White Space" ) {
mConfig.editor.showWhiteSpaces = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setShowWhitespaces( mConfig.editor.showWhiteSpaces );
} );
} else if ( item->getText() == "Highlight Matching Bracket" ) {
mConfig.editor.highlightMatchingBracket = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightMatchingBracket( mConfig.editor.highlightMatchingBracket );
} );
} else if ( item->getText() == "Highlight Current Line" ) {
mConfig.editor.highlightCurrentLine = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightCurrentLine( mConfig.editor.highlightCurrentLine );
} );
} else if ( item->getText() == "Highlight Selection Match" ) {
mConfig.editor.highlightSelectionMatch = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightSelectionMatch( mConfig.editor.highlightSelectionMatch );
} );
} else if ( item->getText() == "Enable Horizontal ScrollBar" ) {
mConfig.editor.horizontalScrollbar = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHorizontalScrollBarEnabled( mConfig.editor.horizontalScrollbar );
} );
} else if ( item->getText() == "Enable Color Picker" ) {
mConfig.editor.colorPickerSelection = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setEnableColorPickerOnSelection( mConfig.editor.colorPickerSelection );
} );
} else if ( item->getText() == "Enable Auto Complete" ) {
setAutoComplete( item->asType<UIMenuCheckBox>()->isActive() );
} else if ( item->getText() == "Enable Color Preview" ) {
mConfig.editor.colorPreview = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setEnableColorPickerOnSelection( mConfig.editor.colorPreview );
} );
} else if ( item->getText() == "Show Document Info" ) {
mConfig.editor.showDocInfo = item->asType<UIMenuCheckBox>()->isActive();
if ( mDocInfo )
mDocInfo->setVisible( mConfig.editor.showDocInfo );
if ( mEditorSplitter->getCurEditor() )
updateDocInfo( mEditorSplitter->getCurEditor()->getDocument() );
if ( item->getText() == "Show Side Panel" ) {
mConfig.ui.showSidePanel = item->asType<UIMenuCheckBox>()->isActive();
showSidePanel( mConfig.ui.showSidePanel );
} else if ( item->getText() == "UI Scale Factor (Pixel Density)" ) {
UIMessageBox* msgBox = UIMessageBox::New(
UIMessageBox::INPUT, "Set the UI scale factor (pixel density):\nMinimum value is "
@@ -712,6 +663,104 @@ UIMenu* App::createViewMenu() {
msgBox->closeWindow();
} );
setFocusEditorOnClose( msgBox );
} else if ( "Zoom In" == item->getText() ) {
mEditorSplitter->zoomIn();
} else if ( "Zoom Out" == item->getText() ) {
mEditorSplitter->zoomOut();
} else if ( "Zoom Reset" == item->getText() ) {
mEditorSplitter->zoomReset();
} else if ( "Full Screen Mode" == item->getText() ) {
runCommand( "fullscreen-toggle" );
} else {
String text = String( event->getNode()->asType<UIMenuItem>()->getText() ).toLower();
String::replaceAll( text, " ", "-" );
String::replaceAll( text, "/", "-" );
runCommand( text );
}
} );
return mWindowMenu;
}
UIMenu* App::createViewMenu() {
mViewMenu = UIPopUpMenu::New();
mViewMenu->addCheckBox( "Show Line Numbers" )->setActive( mConfig.editor.showLineNumbers );
mViewMenu->addCheckBox( "Show White Space" )->setActive( mConfig.editor.showWhiteSpaces );
mViewMenu->addCheckBox( "Show Document Info" )->setActive( mConfig.editor.showDocInfo );
mViewMenu->addCheckBox( "Highlight Matching Bracket" )
->setActive( mConfig.editor.highlightMatchingBracket );
mViewMenu->addCheckBox( "Highlight Current Line" )
->setActive( mConfig.editor.highlightCurrentLine );
mViewMenu->addCheckBox( "Highlight Selection Match" )
->setActive( mConfig.editor.highlightSelectionMatch );
mViewMenu->addCheckBox( "Enable Horizontal ScrollBar" )
->setActive( mConfig.editor.horizontalScrollbar );
mViewMenu->addCheckBox( "Enable Color Preview" )
->setActive( mConfig.editor.colorPreview )
->setTooltipText( "Enables a quick preview of a color when the mouse\n"
"is hover a word that represents a color." );
mViewMenu->addCheckBox( "Enable Color Picker" )
->setActive( mConfig.editor.colorPickerSelection )
->setTooltipText( "Enables the color picker tool when a double click selection\n"
"is done over a word representing a color." );
mViewMenu->addCheckBox( "Enable Auto Complete" )
->setActive( mConfig.editor.autoComplete )
->setTooltipText( "Auto complete shows the completion popup as you type, so you can fill\n"
"in long words by typing only a few characters." );
mViewMenu->add( "Line Breaking Column" );
mViewMenu->addEventListener( Event::OnItemClicked, [&]( const Event* event ) {
if ( !event->getNode()->isType( UI_TYPE_MENUITEM ) )
return;
UIMenuItem* item = event->getNode()->asType<UIMenuItem>();
if ( item->getText() == "Show Line Numbers" ) {
mConfig.editor.showLineNumbers = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setShowLineNumber( mConfig.editor.showLineNumbers );
} );
} else if ( item->getText() == "Show White Space" ) {
mConfig.editor.showWhiteSpaces = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setShowWhitespaces( mConfig.editor.showWhiteSpaces );
} );
} else if ( item->getText() == "Highlight Matching Bracket" ) {
mConfig.editor.highlightMatchingBracket = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightMatchingBracket( mConfig.editor.highlightMatchingBracket );
} );
} else if ( item->getText() == "Highlight Current Line" ) {
mConfig.editor.highlightCurrentLine = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightCurrentLine( mConfig.editor.highlightCurrentLine );
} );
} else if ( item->getText() == "Highlight Selection Match" ) {
mConfig.editor.highlightSelectionMatch = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHighlightSelectionMatch( mConfig.editor.highlightSelectionMatch );
} );
} else if ( item->getText() == "Enable Horizontal ScrollBar" ) {
mConfig.editor.horizontalScrollbar = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setHorizontalScrollBarEnabled( mConfig.editor.horizontalScrollbar );
} );
} else if ( item->getText() == "Enable Color Picker" ) {
mConfig.editor.colorPickerSelection = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setEnableColorPickerOnSelection( mConfig.editor.colorPickerSelection );
} );
} else if ( item->getText() == "Enable Auto Complete" ) {
setAutoComplete( item->asType<UIMenuCheckBox>()->isActive() );
} else if ( item->getText() == "Enable Color Preview" ) {
mConfig.editor.colorPreview = item->asType<UIMenuCheckBox>()->isActive();
mEditorSplitter->forEachEditor( [&]( UICodeEditor* editor ) {
editor->setEnableColorPickerOnSelection( mConfig.editor.colorPreview );
} );
} else if ( item->getText() == "Show Document Info" ) {
mConfig.editor.showDocInfo = item->asType<UIMenuCheckBox>()->isActive();
if ( mDocInfo )
mDocInfo->setVisible( mConfig.editor.showDocInfo );
if ( mEditorSplitter->getCurEditor() )
updateDocInfo( mEditorSplitter->getCurEditor()->getDocument() );
} else if ( item->getText() == "Line Breaking Column" ) {
UIMessageBox* msgBox =
UIMessageBox::New( UIMessageBox::INPUT, "Set Line Breaking Column:\n"
@@ -732,14 +781,6 @@ UIMenu* App::createViewMenu() {
}
} );
setFocusEditorOnClose( msgBox );
} else if ( "Zoom In" == item->getText() ) {
mEditorSplitter->zoomIn();
} else if ( "Zoom Out" == item->getText() ) {
mEditorSplitter->zoomOut();
} else if ( "Zoom Reset" == item->getText() ) {
mEditorSplitter->zoomReset();
} else if ( "Full Screen Mode" == item->getText() ) {
runCommand( "fullscreen-toggle" );
} else {
String text = String( event->getNode()->asType<UIMenuItem>()->getText() ).toLower();
String::replaceAll( text, " ", "-" );
@@ -1009,7 +1050,7 @@ void App::updateDocInfo( TextDocument& doc ) {
if ( mConfig.editor.showDocInfo && mDocInfoText ) {
mDocInfoText->setText( String::format(
"line: %lld / %lu col: %lld %s", doc.getSelection().start().line() + 1,
doc.linesCount(), doc.getSelection().start().column() + 1,
doc.linesCount(), doc.getSelection().start().column(),
doc.getLineEnding() == TextDocument::LineEnding::LF ? "LF" : "CRLF" ) );
}
}
@@ -1115,7 +1156,7 @@ void App::onCodeEditorCreated( UICodeEditor* editor, TextDocument& doc ) {
doc.setCommand( "close-app", [&] { closeApp(); } );
doc.setCommand( "fullscreen-toggle", [&]() {
mWindow->toggleFullscreen();
mViewMenu->find( "fullscreen-mode" )
mWindowMenu->find( "fullscreen-mode" )
->asType<UIMenuCheckBox>()
->setActive( !mWindow->isWindowed() );
} );
@@ -1208,6 +1249,7 @@ void App::createSettingsMenu() {
mSettingsMenu->addSubMenu( "Document", nullptr, createDocumentMenu() );
mSettingsMenu->addSubMenu( "Edit", nullptr, createEditMenu() );
mSettingsMenu->addSubMenu( "View", nullptr, createViewMenu() );
mSettingsMenu->addSubMenu( "Window", nullptr, createWindowMenu() );
mSettingsMenu->addSeparator();
mSettingsMenu->add( "Close", findIcon( "document-close" ), getKeybind( "close-doc" ) );
mSettingsMenu->addSeparator();
@@ -1528,8 +1570,13 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
mUISceneNode->bind( "search_bar", mSearchBarLayout );
mUISceneNode->bind( "doc_info", mDocInfo );
mUISceneNode->bind( "doc_info_text", mDocInfoText );
mUISceneNode->bind( "panel", mSidePanel );
mUISceneNode->bind( "project_splitter", mProjectSplitter );
mDocInfo->setVisible( mConfig.editor.showDocInfo );
mSearchBarLayout->setVisible( false )->setEnabled( false );
mProjectSplitter->setSplitPartition( StyleSheetLength( mConfig.window.panelPartition ) );
if ( !mConfig.ui.showSidePanel )
showSidePanel( mConfig.ui.showSidePanel );
mEditorSplitter = UICodeEditorSplitter::New(
this, mUISceneNode,
@@ -1544,13 +1591,12 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
mConsole = eeNew( Console, ( fontMono, true, true, 1024 * 1000, 0, mWindow ) );
UISplitter* projectSplitter = mUISceneNode->find<UISplitter>( "project_splitter" );
projectSplitter->setDivisionSplit( 0.15f );
UITreeView* tree = mUISceneNode->find<UITreeView>( "project_view" );
tree->setColumnsHidden( {FileSystemModel::Icon, FileSystemModel::Size,
FileSystemModel::Group, FileSystemModel::Inode,
FileSystemModel::Owner, FileSystemModel::SymlinkTarget,
FileSystemModel::Permissions, FileSystemModel::ModificationTime},
FileSystemModel::Permissions, FileSystemModel::ModificationTime,
FileSystemModel::Path},
true );
tree->setHeadersVisible( false );
tree->addEventListener( Event::OnModelEvent, [&]( const Event* event ) {
@@ -1558,8 +1604,8 @@ void App::init( const std::string& file, const Float& pidelDensity ) {
if ( modelEvent->getModelEventType() == ModelEventType::Open ) {
Variant vPath( modelEvent->getModel()->data( modelEvent->getModelIndex(),
Model::Role::Custom ) );
if ( vPath.isValid() && vPath.is( Variant::Type::String ) ) {
std::string path ( vPath.asString() );
if ( vPath.isValid() && vPath.is( Variant::Type::cstr ) ) {
std::string path( vPath.asCStr() );
UITab* tab = mEditorSplitter->isDocumentOpen( path );
if ( !tab ) {
mEditorSplitter->loadFileFromPathInNewTab( path );

View File

@@ -37,6 +37,7 @@ class UISearchBar : public UILinearLayout {
struct UIConfig {
StyleSheetLength fontSize{12, StyleSheetLength::Dp};
bool showSidePanel{true};
};
struct WindowConfig {
@@ -44,6 +45,7 @@ struct WindowConfig {
Sizei size{1280, 720};
std::string winIcon;
bool maximized{false};
std::string panelPartition;
};
struct CodeEditorConfig {
@@ -148,6 +150,9 @@ class App : public UICodeEditorSplitter::Client {
AppConfig mConfig;
UIPopUpMenu* mDocMenu{nullptr};
UIPopUpMenu* mViewMenu{nullptr};
UIPopUpMenu* mWindowMenu{nullptr};
UISplitter* mProjectSplitter{nullptr};
UITabWidget* mSidePanel{nullptr};
UICodeEditorSplitter* mEditorSplitter{nullptr};
std::string mInitColorScheme;
std::map<std::string, std::string> mKeybindings;
@@ -159,6 +164,8 @@ class App : public UICodeEditorSplitter::Client {
std::string mResPath;
AutoCompleteModule* mAutoCompleteModule{nullptr};
void showSidePanel( bool show );
void onFileDropped( String file );
void onTextDropped( String text );
@@ -195,6 +202,8 @@ class App : public UICodeEditorSplitter::Client {
UIMenu* createEditMenu();
UIMenu* createWindowMenu();
Drawable* findIcon( const std::string& name );
UIMenu* createDocumentMenu();