mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-11 17:17:42 +03:00
eepp: Several fixes on widgets.
ecode: Build Side Panel WIP.
This commit is contained in:
@@ -856,6 +856,26 @@ the load can't be determined.
|
||||
|
||||
---
|
||||
|
||||
### inner-widget-orientation
|
||||
|
||||
PushButton can contain 3 widgets: the text (textbox), the icon, and a custom extra
|
||||
item. And with these 3 items does its own layouting. This property allows configuring the order
|
||||
in which these items are displayed/sorted inside the button.
|
||||
|
||||
* Applicable to: EE::UI::UIPushButton (PushButton) and any element that extends it: UIMenuItem, UISelectButton (SelectButton), UITableCell , UITableHeaderColumn.
|
||||
* Data Type: [string-list](#string-list-data-type)
|
||||
* Value List (Widget is the custom widget):
|
||||
* `widgeticontextbox`: Widget | Icon | TextBox
|
||||
* `widgettextboxicon`: Widget | TextBox | Icon
|
||||
* `icontextboxwidget`: Icon | TextBox | Widget
|
||||
* `iconwidgettextbox`: Icon | Widget | TextBox
|
||||
* `textboxiconwidget`: TextBox | Icon | Widget
|
||||
* `textboxwidgeticon`: TextBox | Widget | Icon
|
||||
|
||||
* Default value: `widgeticontextbox`
|
||||
|
||||
---
|
||||
|
||||
### layout-gravity
|
||||
|
||||
The layout gravity defines how the element gravitates againts its parent (when possible). Gravity
|
||||
|
||||
@@ -211,6 +211,7 @@ enum class PropertyId : Uint32 {
|
||||
GravityOwner = String::hash( "gravity-owner" ),
|
||||
Href = String::hash( "href" ),
|
||||
Focusable = String::hash( "focusable" ),
|
||||
InnerWidgetOrientation = String::hash( "inner-widget-orientation" ),
|
||||
};
|
||||
|
||||
enum class PropertyType : Uint32 {
|
||||
|
||||
@@ -75,7 +75,9 @@ class EE_API UIListBox : public UITouchDraggableWidget {
|
||||
|
||||
const Uint32& getRowHeight() const;
|
||||
|
||||
Uint32 getCount();
|
||||
Uint32 getCount() const;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
void setSelected( Uint32 Index );
|
||||
|
||||
@@ -104,6 +106,8 @@ class EE_API UIListBox : public UITouchDraggableWidget {
|
||||
|
||||
virtual std::vector<PropertyId> getPropertiesImplemented() const;
|
||||
|
||||
Uint32 getMaxTextWidth() const;
|
||||
|
||||
protected:
|
||||
friend class UIListBoxItem;
|
||||
friend class UIItemContainer<UIListBox>;
|
||||
|
||||
@@ -7,10 +7,21 @@
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
enum class InnerWidgetOrientation { Left, Right, Center };
|
||||
enum class InnerWidgetOrientation {
|
||||
WidgetIconTextBox,
|
||||
WidgetTextBoxIcon,
|
||||
IconTextBoxWidget,
|
||||
IconWidgetTextBox,
|
||||
TextBoxIconWidget,
|
||||
TextBoxWidgetIcon,
|
||||
};
|
||||
|
||||
class EE_API UIPushButton : public UIWidget {
|
||||
public:
|
||||
static InnerWidgetOrientation innerWidgetOrientationFromString( std::string iwo );
|
||||
|
||||
static std::string innerWidgetOrientationToString( const InnerWidgetOrientation& orientation );
|
||||
|
||||
static UIPushButton* New();
|
||||
|
||||
static UIPushButton* NewWithTag( const std::string& tag );
|
||||
@@ -70,7 +81,7 @@ class EE_API UIPushButton : public UIWidget {
|
||||
UIImage* mIcon;
|
||||
UITextView* mTextBox;
|
||||
Sizei mIconMinSize;
|
||||
InnerWidgetOrientation mInnerWidgetOrientation{ InnerWidgetOrientation::Right };
|
||||
InnerWidgetOrientation mInnerWidgetOrientation{ InnerWidgetOrientation::IconTextBoxWidget };
|
||||
bool mTextAsFallback{ false };
|
||||
|
||||
UIPushButton();
|
||||
|
||||
@@ -129,6 +129,7 @@ class EE_API UITextInput : public UITextView, public TextDocument::Client {
|
||||
bool mMouseDown;
|
||||
bool mCreateDefaultContextMenuOptions{ true };
|
||||
bool mEscapePastedText{ false };
|
||||
bool mEnabledCreateContextMenu{ true };
|
||||
Uint32 mMaxLength{ 0 };
|
||||
KeyBindings mKeyBindings;
|
||||
Clock mLastDoubleClick;
|
||||
|
||||
@@ -62,7 +62,7 @@ class EE_API UITreeViewCell : public UITableCell {
|
||||
UITableCell( "treeview::cell", newTextViewCb ) {
|
||||
mTextBox->setElementTag( mTag + "::text" );
|
||||
mIcon->setElementTag( mTag + "::icon" );
|
||||
mInnerWidgetOrientation = InnerWidgetOrientation::Left;
|
||||
mInnerWidgetOrientation = InnerWidgetOrientation::WidgetIconTextBox;
|
||||
auto cb = [&]( const Event* ) { updateLayout(); };
|
||||
mImage = UIImage::NewWithTag( mTag + "::expander" );
|
||||
mImage->setScaleType( UIScaleType::FitInside )
|
||||
|
||||
@@ -182,7 +182,11 @@ bool Process::join( int* const returnCodeOut ) {
|
||||
|
||||
bool Process::kill() {
|
||||
eeASSERT( mProcess != nullptr );
|
||||
return PROCESS_PTR->alive ? 0 == subprocess_terminate( PROCESS_PTR ) : false;
|
||||
if ( PROCESS_PTR->alive ) {
|
||||
destroy();
|
||||
return 0 == subprocess_terminate( PROCESS_PTR );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Process::destroy() {
|
||||
|
||||
@@ -127,21 +127,25 @@ void StyleSheetSpecification::registerDefaultProperties() {
|
||||
registerProperty( "flags", "" );
|
||||
registerProperty( "margin-top", "0px" )
|
||||
.setType( PropertyType::NumberLength )
|
||||
.addAlias( "margin_top" )
|
||||
.addAlias( "layout-margin-top" )
|
||||
.addAlias( "layout_margintop" )
|
||||
.setRelativeTarget( PropertyRelativeTarget::ContainingBlockHeight );
|
||||
registerProperty( "margin-left", "0px" )
|
||||
.setType( PropertyType::NumberLength )
|
||||
.addAlias( "margin_left" )
|
||||
.addAlias( "layout-margin-left" )
|
||||
.addAlias( "layout_marginleft" )
|
||||
.setRelativeTarget( PropertyRelativeTarget::ContainingBlockWidth );
|
||||
registerProperty( "margin-right", "0px" )
|
||||
.setType( PropertyType::NumberLength )
|
||||
.addAlias( "margin_right" )
|
||||
.addAlias( "layout-margin-right" )
|
||||
.addAlias( "layout_marginright" )
|
||||
.setRelativeTarget( PropertyRelativeTarget::ContainingBlockWidth );
|
||||
registerProperty( "margin-bottom", "0px" )
|
||||
.setType( PropertyType::NumberLength )
|
||||
.addAlias( "margin_bottom" )
|
||||
.addAlias( "layout-margin-bottom" )
|
||||
.addAlias( "layout_marginbottom" )
|
||||
.setRelativeTarget( PropertyRelativeTarget::ContainingBlockHeight );
|
||||
@@ -393,6 +397,9 @@ void StyleSheetSpecification::registerDefaultProperties() {
|
||||
registerProperty( "href", "" ).setType( PropertyType::String );
|
||||
registerProperty( "focusable", "true" ).setType( PropertyType::Bool );
|
||||
|
||||
registerProperty( "inner-widget-orientation", "widgeticontextbox" )
|
||||
.setType( PropertyType::String );
|
||||
|
||||
// Shorthands
|
||||
registerShorthand( "margin", { "margin-top", "margin-right", "margin-bottom", "margin-left" },
|
||||
"box" );
|
||||
|
||||
@@ -20,6 +20,7 @@ UIDropDownList* UIDropDownList::New() {
|
||||
|
||||
UIDropDownList::UIDropDownList( const std::string& tag ) :
|
||||
UITextInput( tag ), mListBox( NULL ), mFriendNode( NULL ) {
|
||||
mEnabledCreateContextMenu = false;
|
||||
setClipType( ClipType::ContentBox );
|
||||
setFlags( UI_AUTO_SIZE | UI_AUTO_PADDING );
|
||||
unsetFlags( UI_TEXT_SELECTION_ENABLED );
|
||||
@@ -139,15 +140,18 @@ void UIDropDownList::showList() {
|
||||
|
||||
Float sliderValue = mListBox->getVerticalScrollBar()->getValue();
|
||||
|
||||
Float width =
|
||||
NULL != mFriendNode ? mFriendNode->getSize().getWidth() : getSize().getWidth();
|
||||
|
||||
mListBox->setSize(
|
||||
NULL != mFriendNode ? mFriendNode->getSize().getWidth() : getSize().getWidth(),
|
||||
(Int32)( std::min( mListBox->getCount(), mStyleConfig.MaxNumVisibleItems ) *
|
||||
mListBox->getRowHeight() ) +
|
||||
tPadding.Top + tPadding.Bottom +
|
||||
( mListBox->getHorizontalScrollBar() &&
|
||||
mListBox->getHorizontalScrollBar()->isVisible()
|
||||
? mListBox->getHorizontalScrollBar()->getSize().getHeight()
|
||||
: 0.f ) );
|
||||
width, (Int32)( eemin( mListBox->getCount(), mStyleConfig.MaxNumVisibleItems ) *
|
||||
mListBox->getRowHeight() ) +
|
||||
tPadding.Top + tPadding.Bottom +
|
||||
( mListBox->getHorizontalScrollBar() &&
|
||||
mListBox->getHorizontalScrollBar()->isVisible() &&
|
||||
PixelDensity::dpToPx( width ) < mListBox->getMaxTextWidth()
|
||||
? mListBox->getHorizontalScrollBar()->getSize().getHeight()
|
||||
: 0.f ) );
|
||||
|
||||
mListBox->getVerticalScrollBar()->setValue( sliderValue );
|
||||
|
||||
@@ -259,6 +263,7 @@ void UIDropDownList::onItemSelected( const Event* ) {
|
||||
messagePost( &Msg );
|
||||
|
||||
sendCommonEvent( Event::OnItemSelected );
|
||||
sendCommonEvent( Event::OnValueChange );
|
||||
}
|
||||
|
||||
void UIDropDownList::show() {
|
||||
|
||||
@@ -803,10 +803,14 @@ const Uint32& UIListBox::getRowHeight() const {
|
||||
return mRowHeight;
|
||||
}
|
||||
|
||||
Uint32 UIListBox::getCount() {
|
||||
Uint32 UIListBox::getCount() const {
|
||||
return (Uint32)mItems.size();
|
||||
}
|
||||
|
||||
bool UIListBox::isEmpty() const {
|
||||
return mItems.empty();
|
||||
}
|
||||
|
||||
void UIListBox::setSelected( const String& Text ) {
|
||||
setSelected( getItemIndex( Text ) );
|
||||
}
|
||||
@@ -1064,6 +1068,10 @@ std::vector<PropertyId> UIListBox::getPropertiesImplemented() const {
|
||||
return props;
|
||||
}
|
||||
|
||||
Uint32 UIListBox::getMaxTextWidth() const {
|
||||
return mMaxTextWidth;
|
||||
}
|
||||
|
||||
bool UIListBox::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
if ( !checkPropertyDefinition( attribute ) )
|
||||
return false;
|
||||
|
||||
@@ -8,6 +8,42 @@
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
InnerWidgetOrientation UIPushButton::innerWidgetOrientationFromString( std::string iwo ) {
|
||||
String::toLowerInPlace( iwo );
|
||||
if ( iwo == "widgeticontextbox" )
|
||||
return InnerWidgetOrientation::WidgetIconTextBox;
|
||||
if ( iwo == "widgettextboxicon" )
|
||||
return InnerWidgetOrientation::WidgetTextBoxIcon;
|
||||
if ( iwo == "icontextboxwidget" )
|
||||
return InnerWidgetOrientation::IconTextBoxWidget;
|
||||
if ( iwo == "iconwidgettextbox" )
|
||||
return InnerWidgetOrientation::IconWidgetTextBox;
|
||||
if ( iwo == "textboxiconwidget" )
|
||||
return InnerWidgetOrientation::TextBoxIconWidget;
|
||||
if ( iwo == "textboxwidgeticon" )
|
||||
return InnerWidgetOrientation::TextBoxWidgetIcon;
|
||||
return InnerWidgetOrientation::WidgetIconTextBox;
|
||||
}
|
||||
|
||||
std::string
|
||||
UIPushButton::innerWidgetOrientationToString( const InnerWidgetOrientation& orientation ) {
|
||||
switch ( orientation ) {
|
||||
case InnerWidgetOrientation::WidgetIconTextBox:
|
||||
return "widgeticontextbox";
|
||||
case InnerWidgetOrientation::WidgetTextBoxIcon:
|
||||
return "widgettextboxicon";
|
||||
case InnerWidgetOrientation::IconTextBoxWidget:
|
||||
return "icontextboxwidget";
|
||||
case InnerWidgetOrientation::IconWidgetTextBox:
|
||||
return "iconwidgettextbox";
|
||||
case InnerWidgetOrientation::TextBoxIconWidget:
|
||||
return "textboxiconwidget";
|
||||
case InnerWidgetOrientation::TextBoxWidgetIcon:
|
||||
return "textboxwidgeticon";
|
||||
}
|
||||
return "widgeticontextbox";
|
||||
}
|
||||
|
||||
UIPushButton* UIPushButton::New() {
|
||||
return eeNew( UIPushButton, () );
|
||||
}
|
||||
@@ -216,21 +252,35 @@ Vector2f UIPushButton::packLayout( const std::vector<UIWidget*>& widgets, const
|
||||
|
||||
UIWidget* UIPushButton::getFirstInnerItem() const {
|
||||
switch ( mInnerWidgetOrientation ) {
|
||||
case InnerWidgetOrientation::Left:
|
||||
case InnerWidgetOrientation::WidgetIconTextBox:
|
||||
return getExtraInnerWidget() && getExtraInnerWidget()->isVisible()
|
||||
? getExtraInnerWidget()
|
||||
: mIcon;
|
||||
case InnerWidgetOrientation::Center:
|
||||
case InnerWidgetOrientation::IconWidgetTextBox:
|
||||
return mIcon->isVisible()
|
||||
? mIcon
|
||||
: ( getExtraInnerWidget() && getExtraInnerWidget()->isVisible()
|
||||
? getExtraInnerWidget()
|
||||
: mTextBox );
|
||||
case InnerWidgetOrientation::Right:
|
||||
case InnerWidgetOrientation::IconTextBoxWidget:
|
||||
if ( mIcon->isVisible() )
|
||||
return mIcon;
|
||||
else
|
||||
return mTextBox;
|
||||
case InnerWidgetOrientation::WidgetTextBoxIcon:
|
||||
return ( getExtraInnerWidget() && getExtraInnerWidget()->isVisible() )
|
||||
? getExtraInnerWidget()
|
||||
: mTextBox;
|
||||
case InnerWidgetOrientation::TextBoxIconWidget:
|
||||
if ( mTextBox->isVisible() )
|
||||
return mTextBox;
|
||||
if ( mIcon->isVisible() )
|
||||
return mIcon;
|
||||
break;
|
||||
case InnerWidgetOrientation::TextBoxWidgetIcon:
|
||||
if ( mTextBox->isVisible() )
|
||||
return mTextBox;
|
||||
break;
|
||||
}
|
||||
return mChild->isWidget() ? mChild->asType<UIWidget>() : nullptr;
|
||||
}
|
||||
@@ -239,15 +289,24 @@ Sizef UIPushButton::updateLayout() {
|
||||
Sizef size;
|
||||
Rectf autoPadding = calculatePadding();
|
||||
switch ( mInnerWidgetOrientation ) {
|
||||
case InnerWidgetOrientation::Left:
|
||||
case InnerWidgetOrientation::WidgetIconTextBox:
|
||||
size = packLayout( { getExtraInnerWidget(), mIcon, mTextBox }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::Center:
|
||||
case InnerWidgetOrientation::IconWidgetTextBox:
|
||||
size = packLayout( { mIcon, getExtraInnerWidget(), mTextBox }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::Right:
|
||||
case InnerWidgetOrientation::IconTextBoxWidget:
|
||||
size = packLayout( { mIcon, mTextBox, getExtraInnerWidget() }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::WidgetTextBoxIcon:
|
||||
size = packLayout( { getExtraInnerWidget(), mTextBox, mIcon }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::TextBoxIconWidget:
|
||||
size = packLayout( { mTextBox, mIcon, getExtraInnerWidget() }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::TextBoxWidgetIcon:
|
||||
size = packLayout( { mTextBox, getExtraInnerWidget(), mIcon }, autoPadding );
|
||||
break;
|
||||
}
|
||||
return size.ceil();
|
||||
}
|
||||
@@ -401,15 +460,24 @@ Sizef UIPushButton::getContentSize() const {
|
||||
Sizef size;
|
||||
Rectf autoPadding = calculatePadding();
|
||||
switch ( mInnerWidgetOrientation ) {
|
||||
case InnerWidgetOrientation::Left:
|
||||
case InnerWidgetOrientation::WidgetIconTextBox:
|
||||
size = calcLayoutSize( { getExtraInnerWidget(), mIcon, mTextBox }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::Center:
|
||||
case InnerWidgetOrientation::IconWidgetTextBox:
|
||||
size = calcLayoutSize( { mIcon, getExtraInnerWidget(), mTextBox }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::Right:
|
||||
case InnerWidgetOrientation::IconTextBoxWidget:
|
||||
size = calcLayoutSize( { mIcon, mTextBox, getExtraInnerWidget() }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::TextBoxIconWidget:
|
||||
size = calcLayoutSize( { mIcon, mTextBox, getExtraInnerWidget() }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::TextBoxWidgetIcon:
|
||||
size = calcLayoutSize( { mTextBox, getExtraInnerWidget(), mIcon }, autoPadding );
|
||||
break;
|
||||
case InnerWidgetOrientation::WidgetTextBoxIcon:
|
||||
size = calcLayoutSize( { getExtraInnerWidget(), mTextBox, mIcon }, autoPadding );
|
||||
break;
|
||||
}
|
||||
if ( getSkin() )
|
||||
size.x += PixelDensity::dpToPxI( getSkin()->getBorderSize().Left +
|
||||
@@ -436,6 +504,8 @@ std::string UIPushButton::getPropertyString( const PropertyDefinition* propertyD
|
||||
return "";
|
||||
|
||||
switch ( propertyDef->getPropertyId() ) {
|
||||
case PropertyId::InnerWidgetOrientation:
|
||||
return innerWidgetOrientationToString( mInnerWidgetOrientation );
|
||||
case PropertyId::Text:
|
||||
return getText().toUtf8();
|
||||
case PropertyId::Icon:
|
||||
@@ -505,6 +575,9 @@ bool UIPushButton::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
}
|
||||
|
||||
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
|
||||
case PropertyId::InnerWidgetOrientation:
|
||||
setInnerWidgetOrientation( innerWidgetOrientationFromString( attribute.asString() ) );
|
||||
break;
|
||||
case PropertyId::Text:
|
||||
if ( NULL != mSceneNode && mSceneNode->isUISceneNode() )
|
||||
setText( getUISceneNode()->getTranslatorString( attribute.asString() ) );
|
||||
|
||||
@@ -81,21 +81,23 @@ Uint32 UITab::onDrag( const Vector2f& pos, const Uint32&, const Sizef& dragDiff
|
||||
}
|
||||
}
|
||||
|
||||
setEnabled( false );
|
||||
Node* overFind = getUISceneNode()->overFind( pos );
|
||||
setEnabled( true );
|
||||
if ( tabW->getAllowDragAndDropTabs() ) {
|
||||
setEnabled( false );
|
||||
Node* overFind = getUISceneNode()->overFind( pos );
|
||||
setEnabled( true );
|
||||
|
||||
if ( overFind && overFind->isType( UI_TYPE_WIDGET ) ) {
|
||||
UIWidget* widget = overFind->asType<UIWidget>()->acceptsDropOfWidgetInTree( this );
|
||||
if ( overFind && overFind->isType( UI_TYPE_WIDGET ) ) {
|
||||
UIWidget* widget = overFind->asType<UIWidget>()->acceptsDropOfWidgetInTree( this );
|
||||
|
||||
if ( mCurDropWidget ) {
|
||||
mCurDropWidget->writeNodeFlag( NODE_FLAG_DROPPABLE_HOVERING, 0 );
|
||||
mCurDropWidget = nullptr;
|
||||
}
|
||||
if ( mCurDropWidget ) {
|
||||
mCurDropWidget->writeNodeFlag( NODE_FLAG_DROPPABLE_HOVERING, 0 );
|
||||
mCurDropWidget = nullptr;
|
||||
}
|
||||
|
||||
if ( widget ) {
|
||||
mCurDropWidget = widget;
|
||||
mCurDropWidget->writeNodeFlag( NODE_FLAG_DROPPABLE_HOVERING, 1 );
|
||||
if ( widget ) {
|
||||
mCurDropWidget = widget;
|
||||
mCurDropWidget->writeNodeFlag( NODE_FLAG_DROPPABLE_HOVERING, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ UITableHeaderColumn::UITableHeaderColumn( const std::string& parentTag, UIAbstra
|
||||
const size_t& colIndex ) :
|
||||
UIPushButton( parentTag + "::header::column" ), mView( view ), mColIndex( colIndex ) {
|
||||
setDragEnabled( true );
|
||||
mInnerWidgetOrientation = InnerWidgetOrientation::Right;
|
||||
mInnerWidgetOrientation = InnerWidgetOrientation::IconTextBoxWidget;
|
||||
auto cb = [&]( const Event* ) { updateLayout(); };
|
||||
mImage = UIImage::NewWithTag( mTag + "::arrow" );
|
||||
mImage->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::WrapContent )
|
||||
|
||||
@@ -901,7 +901,7 @@ Uint32 UITabWidget::onMessage( const NodeMessage* msg ) {
|
||||
const NodeDropMessage* dropMsg = static_cast<const NodeDropMessage*>( msg );
|
||||
if ( dropMsg->getDroppedNode()->isType( UI_TYPE_TAB ) ) {
|
||||
UITab* tab = dropMsg->getDroppedNode()->asType<UITab>();
|
||||
if ( tab->getTabWidget() != this ) {
|
||||
if ( tab->getTabWidget() != this && tab->getTabWidget()->getAllowDragAndDropTabs() ) {
|
||||
tab->getTabWidget()->removeTab( tab, false, false, false );
|
||||
add( tab );
|
||||
setTabSelected( tab );
|
||||
|
||||
@@ -314,7 +314,7 @@ Uint32 UITextInput::onMouseUp( const Vector2i& position, const Uint32& flags ) {
|
||||
mMouseDown = false;
|
||||
getUISceneNode()->getWindow()->getInput()->captureMouse( false );
|
||||
}
|
||||
} else if ( ( flags & EE_BUTTON_RMASK ) ) {
|
||||
} else if ( ( flags & EE_BUTTON_RMASK ) && mEnabledCreateContextMenu ) {
|
||||
onCreateContextMenu( position, flags );
|
||||
}
|
||||
return UITextView::onMouseUp( position, flags );
|
||||
|
||||
@@ -137,6 +137,10 @@ Uint32 UITouchDraggableWidget::onMessage( const NodeMessage* msg ) {
|
||||
mTouchDragPoint = getEventDispatcher()->getMousePosf();
|
||||
mTouchDragAcceleration = Vector2f( 0, 0 );
|
||||
return 1;
|
||||
} else if ( msg->getMsg() == NodeMessage::MouseUp && ( msg->getFlags() & EE_BUTTON_LMASK ) && isTouchDragging() && isTouchOverAllowedChilds() ) {
|
||||
setTouchDragging( false );
|
||||
getEventDispatcher()->setNodeDragging( nullptr );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -348,8 +348,8 @@ json saveNode( Node* node ) {
|
||||
}
|
||||
|
||||
void AppConfig::saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
|
||||
const std::string& configPath,
|
||||
const ProjectDocumentConfig& docConfig ) {
|
||||
const std::string& configPath, const ProjectDocumentConfig& docConfig,
|
||||
const ProjectBuildConfiguration& buildConfig ) {
|
||||
FileSystem::dirAddSlashAtEnd( projectFolder );
|
||||
std::vector<UICodeEditor*> editors = editorSplitter->getAllEditors();
|
||||
std::vector<ProjectPath> paths;
|
||||
@@ -376,6 +376,8 @@ void AppConfig::saveProject( std::string projectFolder, UICodeEditorSplitter* ed
|
||||
TextDocument::lineEndingToString( docConfig.doc.lineEndings ) );
|
||||
ini.setValueI( "document", "tab_width", docConfig.doc.tabWidth );
|
||||
ini.setValueI( "document", "line_breaking_column", docConfig.doc.lineBreakingColumn );
|
||||
ini.setValue( "build", "build_name", buildConfig.buildName );
|
||||
ini.setValue( "build", "build_type", buildConfig.buildType );
|
||||
ini.setValue( "nodes", "documents",
|
||||
saveNode( editorSplitter->getBaseLayout()->getFirstChild() ).dump() );
|
||||
ini.deleteKey( "files" );
|
||||
@@ -510,6 +512,13 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed
|
||||
docConfig.doc.lineBreakingColumn =
|
||||
eemax( 0, ini.getValueI( "document", "line_breaking_column", 100 ) );
|
||||
|
||||
if ( app->getProjectBuildManager() ) {
|
||||
ProjectBuildConfiguration prjCfg;
|
||||
prjCfg.buildName = ini.getValue( "build", "build_name", "" );
|
||||
prjCfg.buildType = ini.getValue( "build", "build_type", "" );
|
||||
app->getProjectBuildManager()->setConfig( prjCfg );
|
||||
}
|
||||
|
||||
if ( ini.keyValueExists( "nodes", "documents" ) ) {
|
||||
json j;
|
||||
try {
|
||||
|
||||
@@ -109,6 +109,12 @@ struct ProjectDocumentConfig {
|
||||
ProjectDocumentConfig( const DocumentConfig& doc ) { this->doc = doc; }
|
||||
};
|
||||
|
||||
struct ProjectBuildConfiguration {
|
||||
ProjectBuildConfiguration() {}
|
||||
std::string buildName;
|
||||
std::string buildType;
|
||||
};
|
||||
|
||||
class NewTerminalOrientation {
|
||||
public:
|
||||
enum Orientation { Same, Vertical, Horizontal };
|
||||
@@ -175,7 +181,8 @@ class AppConfig {
|
||||
const GlobalSearchBarConfig& globalSearchBarConfig, PluginManager* pluginManager );
|
||||
|
||||
void saveProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
|
||||
const std::string& configPath, const ProjectDocumentConfig& docConfig );
|
||||
const std::string& configPath, const ProjectDocumentConfig& docConfig,
|
||||
const ProjectBuildConfiguration& buildConfig );
|
||||
|
||||
void loadProject( std::string projectFolder, UICodeEditorSplitter* editorSplitter,
|
||||
const std::string& configPath, ProjectDocumentConfig& docConfig,
|
||||
|
||||
@@ -81,7 +81,9 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) {
|
||||
.unescape() );
|
||||
msgBox->addEventListener( Event::OnConfirm, [&]( const Event* ) {
|
||||
if ( !mCurrentProject.empty() )
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig );
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
|
||||
mProjectBuildManager ? mProjectBuildManager->getConfig()
|
||||
: ProjectBuildConfiguration() );
|
||||
saveConfig();
|
||||
mWindow->close();
|
||||
} );
|
||||
@@ -92,7 +94,9 @@ bool App::onCloseRequestCallback( EE::Window::Window* ) {
|
||||
return false;
|
||||
} else {
|
||||
if ( !mCurrentProject.empty() )
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig );
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
|
||||
mProjectBuildManager ? mProjectBuildManager->getConfig()
|
||||
: ProjectBuildConfiguration() );
|
||||
saveConfig();
|
||||
return true;
|
||||
}
|
||||
@@ -752,6 +756,10 @@ ProjectBuildManager* App::getProjectBuildManager() const {
|
||||
return mProjectBuildManager.get();
|
||||
}
|
||||
|
||||
UITabWidget* App::getSidePanel() const {
|
||||
return mSidePanel;
|
||||
}
|
||||
|
||||
void App::switchSidePanel() {
|
||||
mConfig.ui.showSidePanel = !mConfig.ui.showSidePanel;
|
||||
mSettings->getWindowMenu()
|
||||
@@ -1788,7 +1796,9 @@ void App::closeEditors() {
|
||||
mSplitter->removeTabWithOwnedWidgetId( "welcome_ecode" );
|
||||
mStatusBar->setVisible( mConfig.ui.showStatusBar );
|
||||
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig );
|
||||
mConfig.saveProject( mCurrentProject, mSplitter, mConfigPath, mProjectDocConfig,
|
||||
mProjectBuildManager ? mProjectBuildManager->getConfig()
|
||||
: ProjectBuildConfiguration() );
|
||||
std::vector<UICodeEditor*> editors = mSplitter->getAllEditors();
|
||||
while ( !editors.empty() ) {
|
||||
UICodeEditor* editor = editors[0];
|
||||
@@ -2864,11 +2874,11 @@ void App::loadFolder( const std::string& path ) {
|
||||
mCurrentProject = rpath;
|
||||
mPluginManager->setWorkspaceFolder( rpath );
|
||||
|
||||
mProjectBuildManager = std::make_unique<ProjectBuildManager>( rpath, mThreadPool );
|
||||
|
||||
loadDirTree( rpath );
|
||||
|
||||
Clock projClock;
|
||||
mProjectBuildManager =
|
||||
std::make_unique<ProjectBuildManager>( rpath, mThreadPool, mSidePanel, this );
|
||||
mConfig.loadProject( rpath, mSplitter, mConfigPath, mProjectDocConfig, mThreadPool, this );
|
||||
Log::info( "Load project took: %.2f ms", projClock.getElapsedTime().asMilliseconds() );
|
||||
|
||||
@@ -3432,7 +3442,9 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
{ "cursor-pointer", 0xec09 },
|
||||
{ "drive", 0xedf8 },
|
||||
{ "refresh", 0xf064 },
|
||||
{ "hearth-pulse", 0xee10 } };
|
||||
{ "hearth-pulse", 0xee10 },
|
||||
{ "add", 0xea12 },
|
||||
{ "hammer", 0xedee } };
|
||||
for ( const auto& icon : icons )
|
||||
iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) );
|
||||
|
||||
@@ -3825,8 +3837,6 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
{ "convert-lang-output" }, "" );
|
||||
args::Flag disableFileLogs( parser, "disable-file-logs", "Disables writing logs to a log file",
|
||||
{ "disable-file-logs" } );
|
||||
args::ValueFlag<std::string> testBuild( parser, "test-build-path", "Test project build",
|
||||
{ "test-build-path" } );
|
||||
|
||||
std::vector<std::string> args;
|
||||
try {
|
||||
@@ -3848,23 +3858,6 @@ EE_MAIN_FUNC int main( int argc, char* argv[] ) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if ( !testBuild.Get().empty() ) {
|
||||
ProjectBuildManager bm( testBuild.Get(), {} );
|
||||
auto i18n = []( const std::string&, const String& def ) -> String { return def; };
|
||||
auto res = bm.generateBuildCommands( "ecode", i18n, "debug" );
|
||||
if ( res.isValid() ) {
|
||||
for ( const auto& cmd : res.cmds ) {
|
||||
for ( const auto& env : cmd.envs )
|
||||
std::cout << "export " << env.first << "=" << env.second << "\n";
|
||||
std::cout << cmd.workingDir << " " << cmd.cmd << " " << cmd.args << "\n";
|
||||
}
|
||||
} else {
|
||||
std::cout << res.errorMsg.toUtf8() << "\n";
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if ( convertLangPath && !convertLangPath.Get().empty() ) {
|
||||
Sys::windowAttachConsole();
|
||||
IOStreamFile sfile( convertLangPath.Get() );
|
||||
|
||||
@@ -235,22 +235,8 @@ class App : public UICodeEditorSplitter::Client {
|
||||
t.setCommand( "toggle-locatebar", [&] { mUniversalLocator->toggleLocateBar(); } );
|
||||
t.setCommand( "open-command-palette", [&] { mUniversalLocator->showCommandPalette(); } );
|
||||
t.setCommand( "project-build-start", [&] {
|
||||
if ( mProjectBuildManager && !mProjectBuildManager->isBuilding() &&
|
||||
!mProjectBuildManager->getBuilds().empty() ) {
|
||||
std::string os = String::toLower( Sys::getPlatform() );
|
||||
const ProjectBuild* build = nullptr;
|
||||
for ( const auto& buildIt : mProjectBuildManager->getBuilds() ) {
|
||||
if ( buildIt.second.isOSSupported( os ) ) {
|
||||
build = &buildIt.second;
|
||||
}
|
||||
}
|
||||
|
||||
if ( build ) {
|
||||
mStatusBuildOutputController->run(
|
||||
build->getName(),
|
||||
!build->buildTypes().empty() ? *build->buildTypes().begin() : "",
|
||||
mProjectBuildManager->getOutputParser( build->getName() ) );
|
||||
}
|
||||
if ( mProjectBuildManager && mStatusBuildOutputController ) {
|
||||
mProjectBuildManager->buildCurrentConfig( mStatusBuildOutputController.get() );
|
||||
}
|
||||
} );
|
||||
t.setCommand( "project-build-cancel", [&] {
|
||||
@@ -404,6 +390,8 @@ class App : public UICodeEditorSplitter::Client {
|
||||
|
||||
ProjectBuildManager* getProjectBuildManager() const;
|
||||
|
||||
UITabWidget* getSidePanel() const;
|
||||
|
||||
protected:
|
||||
std::vector<std::string> mArgs;
|
||||
EE::Window::Window* mWindow{ nullptr };
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
#include "projectbuild.hpp"
|
||||
#include "ecode.hpp"
|
||||
#include "scopedop.hpp"
|
||||
#include "statusbuildoutputcontroller.hpp"
|
||||
#include <eepp/core/string.hpp>
|
||||
#include <eepp/scene/scenemanager.hpp>
|
||||
#include <eepp/system/clock.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/system/process.hpp>
|
||||
#include <eepp/ui/uidropdownlist.hpp>
|
||||
#include <eepp/ui/uiiconthememanager.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::Scene;
|
||||
|
||||
/** @return The process environment variables */
|
||||
static std::unordered_map<std::string, std::string> getEnvironmentVariables() {
|
||||
@@ -73,8 +79,9 @@ bool ProjectBuild::isOSSupported( const std::string& os ) const {
|
||||
}
|
||||
|
||||
ProjectBuildManager::ProjectBuildManager( const std::string& projectRoot,
|
||||
std::shared_ptr<ThreadPool> pool ) :
|
||||
mProjectRoot( projectRoot ), mThreadPool( pool ) {
|
||||
std::shared_ptr<ThreadPool> pool, UITabWidget* sidePanel,
|
||||
App* app ) :
|
||||
mProjectRoot( projectRoot ), mThreadPool( pool ), mSidePanel( sidePanel ), mApp( app ) {
|
||||
FileSystem::dirAddSlashAtEnd( mProjectRoot );
|
||||
|
||||
if ( mThreadPool ) {
|
||||
@@ -85,6 +92,9 @@ ProjectBuildManager::ProjectBuildManager( const std::string& projectRoot,
|
||||
}
|
||||
|
||||
ProjectBuildManager::~ProjectBuildManager() {
|
||||
if ( mUISceneNode && !SceneManager::instance()->isShuttingDown() && mSidePanel && mTab ) {
|
||||
mSidePanel->removeTab( mTab );
|
||||
}
|
||||
mShuttingDown = true;
|
||||
mCancelBuild = true;
|
||||
while ( mLoading )
|
||||
@@ -250,6 +260,10 @@ bool ProjectBuildManager::load() {
|
||||
mBuilds.insert( { build.key(), std::move( b ) } );
|
||||
}
|
||||
|
||||
if ( mSidePanel ) {
|
||||
mSidePanel->runOnMainThread( [this]() { buildSidePanelTab(); } );
|
||||
}
|
||||
|
||||
mLoaded = true;
|
||||
return true;
|
||||
}
|
||||
@@ -301,6 +315,34 @@ ProjectBuildOutputParser ProjectBuildManager::getOutputParser( const std::string
|
||||
|
||||
void ProjectBuildManager::cancelBuild() {
|
||||
mCancelBuild = true;
|
||||
if ( mProcess ) {
|
||||
mProcess->destroy();
|
||||
mProcess->kill();
|
||||
}
|
||||
}
|
||||
|
||||
ProjectBuildConfiguration ProjectBuildManager::getConfig() const {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
void ProjectBuildManager::setConfig( const ProjectBuildConfiguration& config ) {
|
||||
mConfig = config;
|
||||
}
|
||||
|
||||
void ProjectBuildManager::buildCurrentConfig( StatusBuildOutputController* sboc ) {
|
||||
if ( sboc && !isBuilding() && !getBuilds().empty() ) {
|
||||
std::string os = String::toLower( Sys::getPlatform() );
|
||||
const ProjectBuild* build = nullptr;
|
||||
for ( const auto& buildIt : getBuilds() ) {
|
||||
if ( buildIt.second.getName() == mConfig.buildName ) {
|
||||
build = &buildIt.second;
|
||||
}
|
||||
}
|
||||
|
||||
if ( build ) {
|
||||
sboc->run( build->getName(), mConfig.buildType, getOutputParser( build->getName() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectBuildManager::runBuild( const std::string& buildName, const std::string& buildType,
|
||||
@@ -340,7 +382,7 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
|
||||
int c = 0;
|
||||
for ( const auto& cmd : res.cmds ) {
|
||||
int progress = c > 0 ? c / (Float)res.cmds.size() : 0;
|
||||
Process process;
|
||||
mProcess = std::make_unique<Process>();
|
||||
auto options = Process::SearchUserPath | Process::NoWindow | Process::CombinedStdoutStderr;
|
||||
std::unordered_map<std::string, std::string> env;
|
||||
if ( !cmd.config.clearSysEnv ) {
|
||||
@@ -353,7 +395,7 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
|
||||
} else {
|
||||
env = cmd.envs;
|
||||
}
|
||||
if ( process.create( cmd.cmd, cmd.args, options, env, cmd.workingDir ) ) {
|
||||
if ( mProcess->create( cmd.cmd, cmd.args, options, env, cmd.workingDir ) ) {
|
||||
if ( progressFn )
|
||||
progressFn( progress,
|
||||
Sys::getDateTimeStr() + ": " +
|
||||
@@ -365,14 +407,14 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
|
||||
unsigned bytesRead = 0;
|
||||
int returnCode;
|
||||
do {
|
||||
bytesRead = process.readStdOut( buffer );
|
||||
bytesRead = mProcess->readStdOut( buffer );
|
||||
std::string data( buffer.substr( 0, bytesRead ) );
|
||||
if ( progressFn )
|
||||
progressFn( progress, std::move( data ) );
|
||||
} while ( bytesRead != 0 && process.isAlive() && !mShuttingDown && !mCancelBuild );
|
||||
} while ( bytesRead != 0 && mProcess->isAlive() && !mShuttingDown && !mCancelBuild );
|
||||
|
||||
if ( mShuttingDown || mCancelBuild ) {
|
||||
process.kill();
|
||||
mProcess->kill();
|
||||
mCancelBuild = false;
|
||||
printElapsed();
|
||||
if ( doneFn )
|
||||
@@ -380,8 +422,8 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
|
||||
return;
|
||||
}
|
||||
|
||||
process.join( &returnCode );
|
||||
process.destroy();
|
||||
mProcess->join( &returnCode );
|
||||
mProcess->destroy();
|
||||
|
||||
if ( returnCode != EXIT_SUCCESS ) {
|
||||
if ( progressFn ) {
|
||||
@@ -421,4 +463,114 @@ void ProjectBuildManager::runBuild( const std::string& buildName, const std::str
|
||||
doneFn( EXIT_SUCCESS );
|
||||
}
|
||||
|
||||
void ProjectBuildManager::buildSidePanelTab() {
|
||||
mUISceneNode = mSidePanel->getUISceneNode();
|
||||
UIIcon* icon = mUISceneNode->findIcon( "symbol-property" );
|
||||
UIWidget* node = mUISceneNode->loadLayoutFromString(
|
||||
R"html(
|
||||
<style>
|
||||
#build_tab {
|
||||
background-color: var(--list-back);
|
||||
}
|
||||
</style>
|
||||
<ScrollView id="build_tab" lw="mp" lh="mp">
|
||||
<vbox lw="mp" lh="wc" padding="4dp">
|
||||
<TextView text="@string(build_settings, Build Settings)" font-size="15dp" />
|
||||
<TextView text="@string(build_configuration, Build Configuration)" />
|
||||
<DropDownList id="build_list" layout_width="mp" layout_height="wrap_content" margin-bottom="4dp" />
|
||||
<!--
|
||||
<hbox lw="mp" lh="wc">
|
||||
<PushButton lw="0" lw8="0.5" id="build_edit" text="@string(edit_build, Edit Build)" margin-right="2dp" />
|
||||
<PushButton lw="0" lw8="0.5" id="build_add" text="@string(add_build, Add Build)" margin-left="2dp" />
|
||||
</hbox>
|
||||
-->
|
||||
<TextView text="@string(build_target, Build Target)" margin-top="8dp" />
|
||||
<hbox lw="mp" lh="wc">
|
||||
<DropDownList id="build_type_list" layout_width="0" layout_weight="1" layout_height="wrap_content" />
|
||||
<!-- <PushButton id="build_type_add" text="@string(add_build, Add Build)" text-as-fallback="true" icon="icon(add, 12dp)" margin-left="2dp"/> -->
|
||||
</hbox>
|
||||
<PushButton id="build_button" lw="mp" lh="wc" text="@string(build, Build)" margin-top="8dp" icon="icon(hammer, 12dp)" />
|
||||
</vbox>
|
||||
</ScrollView>
|
||||
)html" );
|
||||
mTab = mSidePanel->add( mUISceneNode->getTranslatorStringFromKey( "build", "Build" ), node,
|
||||
icon ? icon->getSize( PixelDensity::dpToPx( 12 ) ) : nullptr );
|
||||
mTab->setTextAsFallback( true );
|
||||
|
||||
updateSidePanelTab();
|
||||
}
|
||||
|
||||
void ProjectBuildManager::updateSidePanelTab() {
|
||||
UIWidget* buildTab = mTab->getOwnedWidget()->find<UIWidget>( "build_tab" );
|
||||
UIDropDownList* buildList = buildTab->find<UIDropDownList>( "build_list" );
|
||||
UIPushButton* buildButton = buildTab->find<UIPushButton>( "build_button" );
|
||||
|
||||
buildList->getListBox()->clear();
|
||||
|
||||
String first = mConfig.buildName;
|
||||
std::vector<String> buildNamesItems;
|
||||
for ( const auto& build : mBuilds ) {
|
||||
buildNamesItems.push_back( build.first );
|
||||
if ( first.empty() )
|
||||
first = build.first;
|
||||
}
|
||||
|
||||
buildList->getListBox()->addListBoxItems( buildNamesItems );
|
||||
|
||||
if ( !first.empty() && buildList->getListBox()->getItemIndex( first ) != eeINDEX_NOT_FOUND ) {
|
||||
buildList->getListBox()->setSelected( first );
|
||||
mConfig.buildName = first;
|
||||
} else if ( !buildList->getListBox()->isEmpty() ) {
|
||||
buildList->getListBox()->setSelected( 0L );
|
||||
mConfig.buildName = buildList->getListBox()->getItemSelectedText();
|
||||
}
|
||||
|
||||
buildList->setEnabled( !buildList->getListBox()->isEmpty() );
|
||||
|
||||
UIDropDownList* buildTypeList = buildTab->find<UIDropDownList>( "build_type_list" );
|
||||
|
||||
buildTypeList->getListBox()->clear();
|
||||
|
||||
first = buildList->getListBox()->getItemSelectedText();
|
||||
if ( !first.empty() ) {
|
||||
auto foundIt = mBuilds.find( first );
|
||||
if ( foundIt != mBuilds.end() ) {
|
||||
const auto& buildTypes = foundIt->second.buildTypes();
|
||||
std::vector<String> buildTypesItems;
|
||||
for ( const auto& buildType : buildTypes )
|
||||
buildTypesItems.emplace_back( buildType );
|
||||
buildTypeList->getListBox()->addListBoxItems( buildTypesItems );
|
||||
if ( buildTypeList->getListBox()->getItemIndex( mConfig.buildType ) !=
|
||||
eeINDEX_NOT_FOUND ) {
|
||||
buildTypeList->getListBox()->setSelected( mConfig.buildType );
|
||||
mConfig.buildType = first;
|
||||
} else if ( !buildTypeList->getListBox()->isEmpty() ) {
|
||||
buildTypeList->getListBox()->setSelected( 0 );
|
||||
mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText();
|
||||
}
|
||||
}
|
||||
}
|
||||
buildTypeList->setEnabled( !buildTypeList->getListBox()->isEmpty() );
|
||||
|
||||
buildList->removeEventsOfType( Event::OnItemSelected );
|
||||
buildList->addEventListener( Event::OnItemSelected, [this, buildList]( const Event* ) {
|
||||
mConfig.buildName = buildList->getListBox()->getItemSelectedText();
|
||||
} );
|
||||
|
||||
buildTypeList->removeEventsOfType( Event::OnItemSelected );
|
||||
buildTypeList->addEventListener( Event::OnItemSelected, [this, buildTypeList]( const Event* ) {
|
||||
mConfig.buildType = buildTypeList->getListBox()->getItemSelectedText();
|
||||
} );
|
||||
|
||||
buildButton->addMouseClickListener(
|
||||
[this]( const Event* ) {
|
||||
if ( isBuilding() ) {
|
||||
cancelBuild();
|
||||
} else {
|
||||
buildCurrentConfig( mApp->getStatusBuildOutputController() );
|
||||
}
|
||||
},
|
||||
MouseButton::EE_BUTTON_LEFT );
|
||||
}
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#ifndef ECODE_PROJECTBUILD_HPP
|
||||
#define ECODE_PROJECTBUILD_HPP
|
||||
|
||||
#include "appconfig.hpp"
|
||||
#include <eepp/system/process.hpp>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
#include <eepp/ui/uitabwidget.hpp>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -11,9 +14,13 @@
|
||||
|
||||
using namespace EE;
|
||||
using namespace EE::System;
|
||||
using namespace EE::UI;
|
||||
|
||||
namespace ecode {
|
||||
|
||||
class App;
|
||||
class StatusBuildOutputController;
|
||||
|
||||
/** reference:
|
||||
{
|
||||
"ecode": {
|
||||
@@ -133,7 +140,7 @@ class ProjectBuild {
|
||||
|
||||
std::string mName;
|
||||
std::string mProjectRoot;
|
||||
std::unordered_set<std::string> mOS;
|
||||
std::set<std::string> mOS;
|
||||
std::set<std::string> mBuildTypes;
|
||||
ProjectBuildSteps mBuild;
|
||||
ProjectBuildSteps mClean;
|
||||
@@ -177,7 +184,8 @@ using ProjectBuildi18nFn =
|
||||
|
||||
class ProjectBuildManager {
|
||||
public:
|
||||
ProjectBuildManager( const std::string& projectRoot, std::shared_ptr<ThreadPool> pool );
|
||||
ProjectBuildManager( const std::string& projectRoot, std::shared_ptr<ThreadPool> pool,
|
||||
UITabWidget* sidePanel, App* app );
|
||||
|
||||
~ProjectBuildManager();
|
||||
|
||||
@@ -206,11 +214,23 @@ class ProjectBuildManager {
|
||||
|
||||
void cancelBuild();
|
||||
|
||||
ProjectBuildConfiguration getConfig() const;
|
||||
|
||||
void setConfig( const ProjectBuildConfiguration& config );
|
||||
|
||||
void buildCurrentConfig( StatusBuildOutputController* sboc );
|
||||
|
||||
protected:
|
||||
std::string mProjectRoot;
|
||||
std::string mProjectFile;
|
||||
ProjectBuildMap mBuilds;
|
||||
ProjectBuildConfiguration mConfig;
|
||||
std::shared_ptr<ThreadPool> mThreadPool;
|
||||
UITabWidget* mSidePanel{ nullptr };
|
||||
UISceneNode* mUISceneNode{ nullptr };
|
||||
UITab* mTab{ nullptr };
|
||||
App* mApp{ nullptr };
|
||||
std::unique_ptr<Process> mProcess;
|
||||
bool mLoaded{ false };
|
||||
bool mLoading{ false };
|
||||
bool mBuilding{ false };
|
||||
@@ -223,6 +243,10 @@ class ProjectBuildManager {
|
||||
const ProjectBuildDoneFn& doneFn = {} );
|
||||
|
||||
bool load();
|
||||
|
||||
void buildSidePanelTab();
|
||||
|
||||
void updateSidePanelTab();
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
@@ -72,6 +72,15 @@ static std::string getProjectOutputParserTypeToString( const ProjectOutputParser
|
||||
return "notice";
|
||||
}
|
||||
|
||||
UIPushButton* StatusBuildOutputController::getBuildButton( App* app ) {
|
||||
if ( app->getSidePanel() ) {
|
||||
UIWidget* tab = app->getSidePanel()->find<UIWidget>( "build_tab" );
|
||||
if ( tab )
|
||||
return tab->find<UIPushButton>( "build_button" );
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void StatusBuildOutputController::run( const std::string& buildName, const std::string& buildType,
|
||||
const ProjectBuildOutputParser& outputParser ) {
|
||||
if ( !mApp->getProjectBuildManager() )
|
||||
@@ -103,6 +112,10 @@ void StatusBuildOutputController::run( const std::string& buildName, const std::
|
||||
mContainer->getDocument().setSyntaxDefinition( synDef );
|
||||
mContainer->getVScrollBar()->setValue( 1.f );
|
||||
|
||||
UIPushButton* buildButton = getBuildButton( mApp );
|
||||
if ( buildButton )
|
||||
buildButton->setText( mApp->i18n( "cancel_build", "Cancel Build" ) );
|
||||
|
||||
auto res = pbm->run(
|
||||
buildName, [this]( const auto& key, const auto& def ) { return mApp->i18n( key, def ); },
|
||||
buildType,
|
||||
@@ -131,6 +144,10 @@ void StatusBuildOutputController::run( const std::string& buildName, const std::
|
||||
if ( scrollToBottom )
|
||||
mContainer->setScrollY( mContainer->getMaxScroll().y );
|
||||
} );
|
||||
|
||||
UIPushButton* buildButton = nullptr;
|
||||
if ( ( buildButton = getBuildButton( mApp ) ) )
|
||||
buildButton->setText( mApp->i18n( "build", "Build" ) );
|
||||
} );
|
||||
|
||||
if ( !res.isValid() ) {
|
||||
|
||||
@@ -38,6 +38,8 @@ class StatusBuildOutputController {
|
||||
UICodeEditor* mContainer{ nullptr };
|
||||
|
||||
UICodeEditor* createContainer();
|
||||
|
||||
UIPushButton* getBuildButton( App* app );
|
||||
};
|
||||
|
||||
} // namespace ecode
|
||||
|
||||
Reference in New Issue
Block a user