Merged in dfighter1985/ryzomcore/dfighter-tools (pull request #90)

GUI Editor improvements
Widget dragging, group selection, multiple selection, grouping, ungrouping.

--HG--
branch : develop
This commit is contained in:
Laszlo Kis-Adam 2014-10-11 02:18:33 +02:00
commit df82b02723
24 changed files with 834 additions and 168 deletions

View file

@ -126,6 +126,7 @@ namespace NLGUI
void onRemoved(); void onRemoved();
void onWidgetDeleted( CInterfaceElement *e ); void onWidgetDeleted( CInterfaceElement *e );
void moveBy( sint32 x, sint32 y );
protected: protected:

View file

@ -15,6 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <string> #include <string>
#include <vector>
namespace NLGUI namespace NLGUI
{ {
@ -24,7 +25,7 @@ namespace NLGUI
public: public:
/// Notifies the watcher about the change /// Notifies the watcher about the change
virtual void selectionChanged( std::string &newSelection ) = 0; virtual void selectionChanged() = 0;
}; };
} }

View file

@ -508,7 +508,24 @@ namespace NLGUI
/// Called when the widget is deleted, /// Called when the widget is deleted,
/// so other widgets in the group can check if it belongs to them /// so other widgets in the group can check if it belongs to them
virtual void onWidgetDeleted( CInterfaceElement *e ){} virtual void onWidgetDeleted( CInterfaceElement *e );
/// Move the element by x in the X direction and y in the Y direction
// Uses real coordinates
virtual void moveBy( sint32 x, sint32 y )
{
_XReal += x;
_YReal += y;
}
/// Retrieves the coordinates of the specified hotspot
void getHSCoords( const THotSpot &hs, sint32 &x, sint32 &y ) const;
/// Tells which hotspot is the closest to the specified element
void getClosestHotSpot( const CInterfaceElement *other, THotSpot &hs );
/// Aligns the element to the other element specified
void alignTo( CInterfaceElement *other );
protected: protected:

View file

@ -14,19 +14,22 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef WIDGET_ADD_WATCHER #ifndef IFACE_FACTORY
#define WIDGET_ADD_WATCHER #define IFACE_FACTORY
#include <string> #include <string>
namespace NLGUI namespace NLGUI
{ {
class IWidgetAdditionWatcher class CViewBase;
/// Simple interface element ( widget ) factory
class CInterfaceFactory
{ {
public: public:
virtual void widgetAdded( const std::string &name ) = 0; static CViewBase* createClass( const std::string &name );
}; };
} }
#endif
#endif

View file

@ -57,6 +57,7 @@ namespace NLGUI
CInterfaceElement* findFromShortId(const std::string &id); CInterfaceElement* findFromShortId(const std::string &id);
/// Dynamic creation /// Dynamic creation
virtual void addElement (CInterfaceElement *child, sint eltOrder = -1 );
virtual void addView (CViewBase *child , sint eltOrder = -1); virtual void addView (CViewBase *child , sint eltOrder = -1);
virtual void addCtrl (CCtrlBase *child, sint eltOrder = -1); virtual void addCtrl (CCtrlBase *child, sint eltOrder = -1);
virtual void addGroup (CInterfaceGroup *child, sint eltOrder = -1); virtual void addGroup (CInterfaceGroup *child, sint eltOrder = -1);
@ -327,6 +328,17 @@ namespace NLGUI
void onWidgetDeleted( CInterfaceElement *e ); void onWidgetDeleted( CInterfaceElement *e );
void moveBy( sint32 x, sint32 y );
// Blows up the group, moves it's children to it's parent
bool explode();
/// Adjusts the group's size so that all elements are fully inside the borders
void spanElements();
/// Aligns the elements - used for forming groups
void alignElements();
protected: protected:
void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH); void makeNewClip (sint32 &oldClipX, sint32 &oldClipY, sint32 &oldClipW, sint32 &oldClipH);

View file

@ -206,6 +206,10 @@ namespace NLGUI
virtual void serial(NLMISC::IStream &f); virtual void serial(NLMISC::IStream &f);
// Sets the parent element
// See the comment at the field
void setParentElm( CInterfaceElement *parent ){ _ParentElm = parent; }
protected: protected:
std::string _HardtextFormat; std::string _HardtextFormat;
/// Text to display. /// Text to display.
@ -382,6 +386,9 @@ namespace NLGUI
/// Dynamic tooltips /// Dynamic tooltips
std::vector<CCtrlToolTip*> _Tooltips; std::vector<CCtrlToolTip*> _Tooltips;
// Parent element is the element where this text belongs to
// For example: text button
CInterfaceElement *_ParentElm;
private: private:
void setup (); void setup ();

View file

@ -75,6 +75,16 @@ namespace NLGUI
virtual void process() = 0; virtual void process() = 0;
}; };
// Interface for event handlers that can be called when widgets are added or moved
class IWidgetWatcher
{
public:
IWidgetWatcher(){}
virtual ~IWidgetWatcher(){}
virtual void onWidgetAdded( const std::string &name ) = 0;
virtual void onWidgetMoved( const std::string &oldid, const std::string &newid ) = 0;
};
/// Frame render times /// Frame render times
struct SInterfaceTimes struct SInterfaceTimes
{ {
@ -493,18 +503,32 @@ namespace NLGUI
IParser* getParser() const{ return parser; } IParser* getParser() const{ return parser; }
std::string& getCurrentEditorSelection(){ return currentEditorSelection; } /// Retrieves the Id of the currently selected widgets
void setCurrentEditorSelection( const std::string &name ); void getEditorSelection( std::vector< std::string > &selection );
/// Adds the widget with the specified Id to the selected widgets
void selectWidget( const std::string &name );
/// Clears the selection
void clearEditorSelection();
void notifySelectionWatchers(); void notifySelectionWatchers();
void registerSelectionWatcher( IEditorSelectionWatcher *watcher ); void registerSelectionWatcher( IEditorSelectionWatcher *watcher );
void unregisterSelectionWatcher( IEditorSelectionWatcher *watcher ); void unregisterSelectionWatcher( IEditorSelectionWatcher *watcher );
void notifyAdditionWatchers( const std::string &widgetName );
void registerAdditionWatcher( IWidgetAdditionWatcher *watcher ); void onWidgetAdded( const std::string &id );
void unregisterAdditionWatcher( IWidgetAdditionWatcher *watcher ); void onWidgetMoved( const std::string &oldid, const std::string &newid );
void registerWidgetWatcher( IWidgetWatcher *watcher );
void unregisterWidgetWatcher( IWidgetWatcher *watcher );
CInterfaceElement* addWidgetToGroup( std::string &group, std::string &widgetClass, std::string &widgetName ); CInterfaceElement* addWidgetToGroup( std::string &group, std::string &widgetClass, std::string &widgetName );
void setGroupSelection( bool b ){ _GroupSelection = b; }
bool groupSelection();
bool unGroupSelection();
void setMultiSelection( bool b ){ multiSelection = b; }
private: private:
CWidgetManager(); CWidgetManager();
~CWidgetManager(); ~CWidgetManager();
@ -532,7 +556,7 @@ namespace NLGUI
NLMISC::CRefPtr< CViewBase > _CapturedView; NLMISC::CRefPtr< CViewBase > _CapturedView;
NLMISC::CRefPtr< CInterfaceElement > draggedElement; NLMISC::CRefPtr< CInterfaceElement > draggedElement; // the element that we're currently dragging
bool startDragging(); bool startDragging();
void stopDragging(); void stopDragging();
@ -594,10 +618,12 @@ namespace NLGUI
std::vector< INewScreenSizeHandler* > newScreenSizeHandlers; std::vector< INewScreenSizeHandler* > newScreenSizeHandlers;
std::vector< IOnWidgetsDrawnHandler* > onWidgetsDrawnHandlers; std::vector< IOnWidgetsDrawnHandler* > onWidgetsDrawnHandlers;
std::vector< IEditorSelectionWatcher* > selectionWatchers; std::vector< IEditorSelectionWatcher* > selectionWatchers;
std::vector< IWidgetAdditionWatcher* > additionWatchers; std::vector< IWidgetWatcher* > widgetWatchers;
std::vector< std::string > editorSelection;
std::string currentEditorSelection; bool _GroupSelection;
bool multiSelection;
uint32 _WidgetCount;
}; };
} }

View file

@ -23,6 +23,7 @@
#include "nel/gui/group_container_base.h" #include "nel/gui/group_container_base.h"
#include "nel/gui/lua_ihm.h" #include "nel/gui/lua_ihm.h"
#include "nel/gui/widget_manager.h" #include "nel/gui/widget_manager.h"
#include "nel/gui/interface_factory.h"
#include "nel/misc/i18n.h" #include "nel/misc/i18n.h"
using namespace std; using namespace std;
@ -66,8 +67,6 @@ namespace NLGUI
{ {
if( _ViewText != NULL ) if( _ViewText != NULL )
{ {
if( _Parent != NULL )
_Parent->delView( _ViewText, true );
delete _ViewText; delete _ViewText;
_ViewText = NULL; _ViewText = NULL;
} }
@ -569,6 +568,7 @@ namespace NLGUI
((CViewTextID*)_ViewText)->parseTextIdOptions(cur); ((CViewTextID*)_ViewText)->parseTextIdOptions(cur);
// Same RenderLayer as us. // Same RenderLayer as us.
_ViewText->setRenderLayer(getRenderLayer()); _ViewText->setRenderLayer(getRenderLayer());
_ViewText->setParentElm(this);
// Parse the hardText (if not text id) // Parse the hardText (if not text id)
if(!_IsViewTextId) if(!_IsViewTextId)
{ {
@ -863,6 +863,8 @@ namespace NLGUI
} }
if(getFrozen() && getFrozenHalfTone()) if(getFrozen() && getFrozenHalfTone())
_ViewText->setAlpha(_ViewText->getAlpha()>>2); _ViewText->setAlpha(_ViewText->getAlpha()>>2);
_ViewText->draw();
} }
} }
@ -873,6 +875,9 @@ namespace NLGUI
// Should have been setuped with addCtrl // Should have been setuped with addCtrl
nlassert(_Setuped); nlassert(_Setuped);
if( _Name == "==MARKED==" )
bool marked = true;
// Compute Size according to bitmap and Text. // Compute Size according to bitmap and Text.
if (!(_SizeRef & 1)) if (!(_SizeRef & 1))
{ {
@ -886,6 +891,8 @@ namespace NLGUI
} }
CViewBase::updateCoords(); CViewBase::updateCoords();
_ViewText->updateCoords();
} }
// *************************************************************************** // ***************************************************************************
@ -901,7 +908,7 @@ namespace NLGUI
if( _ViewText == NULL ) if( _ViewText == NULL )
{ {
CViewBase *v = CWidgetManager::getInstance()->getParser()->createClass( "text" ); CViewBase *v = CInterfaceFactory::createClass( "text" );
nlassert( v != NULL ); nlassert( v != NULL );
_ViewText = dynamic_cast< CViewText* >( v ); _ViewText = dynamic_cast< CViewText* >( v );
_ViewText->setId( _Id + "_text" ); _ViewText->setId( _Id + "_text" );
@ -910,15 +917,13 @@ namespace NLGUI
} }
// setup the viewText and add to parent // setup the viewText and add to parent
_ViewText->setParent (getParent()); _ViewText->setParentElm (this);
_ViewText->setParentPos (this); _ViewText->setParentPos (this);
_ViewText->setParentPosRef (_TextParentPosRef); _ViewText->setParentPosRef (_TextParentPosRef);
_ViewText->setPosRef (_TextPosRef); _ViewText->setPosRef (_TextPosRef);
_ViewText->setActive(_Active); _ViewText->setActive(_Active);
_ViewText->setX(_TextX); _ViewText->setX(_TextX);
_ViewText->setY(_TextY); _ViewText->setY(_TextY);
getParent()->addView(_ViewText);
} }
// *************************************************************************** // ***************************************************************************
@ -1007,17 +1012,18 @@ namespace NLGUI
// *************************************************************************** // ***************************************************************************
void CCtrlTextButton::onRemoved() void CCtrlTextButton::onRemoved()
{ {
if( _ViewText != NULL )
{
if( _Parent != NULL )
_Parent->delView( _ViewText, true );
}
} }
void CCtrlTextButton::onWidgetDeleted( CInterfaceElement *e ) void CCtrlTextButton::onWidgetDeleted( CInterfaceElement *e )
{ {
if( e == _ViewText ) }
_ViewText = NULL;
void CCtrlTextButton::moveBy( sint32 x, sint32 y )
{
CInterfaceElement::moveBy( x, y );
if( _ViewText != NULL )
_ViewText->updateCoords();
} }
} }

View file

@ -27,6 +27,7 @@
#include "nel/gui/widget_manager.h" #include "nel/gui/widget_manager.h"
#include "nel/gui/view_renderer.h" #include "nel/gui/view_renderer.h"
#include "nel/gui/db_manager.h" #include "nel/gui/db_manager.h"
#include "nel/gui/interface_factory.h"
#include <limits> #include <limits>
using namespace std; using namespace std;
@ -1543,7 +1544,7 @@ namespace NLGUI
if( editorMode ) if( editorMode )
{ {
nlwarning( "Trying to create a new 'edit_text' for %s", getId().c_str() ); nlwarning( "Trying to create a new 'edit_text' for %s", getId().c_str() );
_ViewText = dynamic_cast< CViewText* >( CWidgetManager::getInstance()->getParser()->createClass( "text" ) ); _ViewText = dynamic_cast< CViewText* >( CInterfaceFactory::createClass( "text" ) );
if( _ViewText != NULL ) if( _ViewText != NULL )
{ {
_ViewText->setParent( this ); _ViewText->setParent( this );

View file

@ -226,13 +226,13 @@ namespace NLGUI
else else
if( name == "posref" ) if( name == "posref" )
{ {
convertHotSpot( value.c_str() ); _PosRef = convertHotSpot( value.c_str() );
return; return;
} }
else else
if( name == "parentposref" ) if( name == "parentposref" )
{ {
convertHotSpot( value.c_str() ); _ParentPosRef = convertHotSpot( value.c_str() );
} }
else else
if( name == "sizeref" ) if( name == "sizeref" )
@ -1594,6 +1594,105 @@ namespace NLGUI
} }
} }
void CInterfaceElement::getHSCoords( const THotSpot &hs, sint32 &x, sint32 &y ) const
{
x = _XReal;
y = _YReal;
if( ( hs & Hotspot_Mx ) != 0 )
y += _HReal / 2;
else
if( ( hs & Hotspot_Tx ) != 0 )
y += _HReal;
if( ( hs & Hotspot_xM ) != 0 )
x += _WReal / 2;
else
if( ( hs & Hotspot_xR ) != 0 )
x += _WReal;
}
void CInterfaceElement::getClosestHotSpot( const CInterfaceElement *other, THotSpot &hs )
{
/// Iterate over the following hotspots, calculate the distance and store the closest
static THotSpot hslist[] =
{
Hotspot_BL,
Hotspot_BR,
Hotspot_MM,
Hotspot_TL,
Hotspot_TR
};
int c = sizeof( hslist ) / sizeof( THotSpot );
int x,y,ox,oy,vx,vy;
float d;
float closestd = 9999999.0f;
THotSpot closestHS = Hotspot_TR;
for( int i = 0; i < c; i++ )
{
other->getHSCoords( hslist[ i ], ox, oy );
getHSCoords( hslist[ i ], x, y );
// Make a vector between the two hotspots
vx = x - ox;
vy = y - oy;
// Calculate length
d = sqrt( pow( vx, 2.0f ) + pow( vy, 2.0f ) );
// If these hotspots are the closest, store the hotspot
if( d < closestd )
{
closestd = d;
closestHS = hslist[ i ];
}
}
hs = closestHS;
}
void CInterfaceElement::alignTo( CInterfaceElement *other )
{
if( other == this )
return;
// Check which hotspot is the closest
THotSpot hs;
other->getClosestHotSpot( this, hs );
// Get the hotspot coordinates
sint32 x, y, ox, oy;
getHSCoords( hs, x, y );
other->getHSCoords( hs, ox, oy );
// Calculate the difference between the hotspot we found and our current position,
sint32 dx = ox - x;
sint32 dy = oy - y;
// This difference is our offset, so we remain in the same position
setX( -1 * dx );
setY( -1 * dy );
setPosRef( hs );
setParentPosRef( hs );
invalidateCoords();
}
void CInterfaceElement::onWidgetDeleted( CInterfaceElement *e )
{
if( e == getParentPos() )
setParentPos( NULL );
if( e == getParentSize() )
setParentSize( NULL );
}
CStringMapper* CStringShared::_UIStringMapper = NULL; CStringMapper* CStringShared::_UIStringMapper = NULL;

View file

@ -0,0 +1,29 @@
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "nel/gui/interface_factory.h"
#include "nel/gui/view_base.h"
#include "nel/misc/factory.h"
namespace NLGUI
{
CViewBase* CInterfaceFactory::createClass( const std::string &name )
{
return NLMISC_GET_FACTORY( CViewBase, std::string ).createObject( std::string( name ) , CViewBase::TCtorParam() );
}
}

View file

@ -911,6 +911,31 @@ namespace NLGUI
} }
} }
// ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addElement (CInterfaceElement *child, sint eltOrder /*= -1*/)
{
if (!child)
{
nlwarning("<CInterfaceGroup::addView> : tried to add a NULL view");
return;
}
if( child->isGroup() )
{
addGroup( static_cast< CInterfaceGroup* >( child ), eltOrder );
}
else
if( child->isCtrl() )
{
addCtrl( static_cast< CCtrlBase* >( child ), eltOrder );
}
else
if( child->isView() )
{
addView( static_cast< CViewBase* >( child ), eltOrder );
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CInterfaceGroup::addView (CViewBase *child, sint eltOrder /*= -1*/) void CInterfaceGroup::addView (CViewBase *child, sint eltOrder /*= -1*/)
{ {
@ -1312,6 +1337,11 @@ namespace NLGUI
for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++) for (ite = _EltOrder.begin() ; ite != _EltOrder.end(); ite++)
{ {
CViewBase *pVB = *ite; CViewBase *pVB = *ite;
if( pVB->getName() == "=MARKED=" )
{
nlinfo( "=MARKED=" );
}
if (pVB->getActive()) if (pVB->getActive())
pVB->draw(); pVB->draw();
} }
@ -2514,5 +2544,101 @@ namespace NLGUI
for( std::vector< CInterfaceGroup* >::iterator itr = _ChildrenGroups.begin(); itr != _ChildrenGroups.end(); ++itr ) for( std::vector< CInterfaceGroup* >::iterator itr = _ChildrenGroups.begin(); itr != _ChildrenGroups.end(); ++itr )
(*itr)->onWidgetDeleted( e ); (*itr)->onWidgetDeleted( e );
} }
void CInterfaceGroup::moveBy( sint32 x, sint32 y )
{
CInterfaceElement::moveBy( x, y );
for( int i = 0; i < _EltOrder.size(); i++ )
{
CViewBase *v = _EltOrder[ i ];
v->updateCoords();
}
}
bool CInterfaceGroup::explode()
{
CInterfaceGroup *p = getParent();
if( p == NULL )
return false;
std::string oldId;
// Reparent children
for( sint32 i = 0; i < _EltOrder.size(); i++ )
{
CInterfaceElement *e = _EltOrder[ i ];
oldId = e->getId();
e->setW( e->getWReal() );
e->setH( e->getHReal() );
e->setSizeRef( "" );
e->setParent( p );
e->setParentPos( p );
e->setParentSize( p );
e->alignTo( p );
p->addElement( e );
e->setIdRecurse( e->getShortId() );
CWidgetManager::getInstance()->onWidgetMoved( oldId, e->getId() );
}
_EltOrder.clear();
_Views.clear();
_Controls.clear();
_ChildrenGroups.clear();
return true;
}
void CInterfaceGroup::spanElements()
{
sint32 minx = std::numeric_limits< sint32 >::max();
sint32 miny = std::numeric_limits< sint32 >::max();
sint32 maxx = std::numeric_limits< sint32 >::min();
sint32 maxy = std::numeric_limits< sint32 >::min();
sint32 tlx,tly,brx,bry;
// Find the min and max coordinates of the elements
for( int i = 0; i < _EltOrder.size(); i++ )
{
CViewBase *v = _EltOrder[ i ];
v->getHSCoords( Hotspot_TL, tlx, tly );
v->getHSCoords( Hotspot_BR, brx, bry );
if( tlx < minx )
minx = tlx;
if( brx > maxx )
maxx = brx;
if( bry < miny )
miny = bry;
if( tly > maxy )
maxy = tly;
}
// Set the position and the width and height based on these coords
setW( maxx - minx );
setH( maxy - miny );
_WReal = getW();
_HReal = getH();
_XReal = minx;
_YReal = miny;
}
void CInterfaceGroup::alignElements()
{
for( int i = 0; i < _EltOrder.size(); i++ )
{
CViewBase *v = _EltOrder[ i ];
v->alignTo( this );
}
}
} }

View file

@ -57,7 +57,7 @@ namespace NLGUI
{ {
if( editorMode ) if( editorMode )
{ {
CWidgetManager::getInstance()->setCurrentEditorSelection( getId() ); CWidgetManager::getInstance()->selectWidget( getId() );
return true; return true;
} }
} }

View file

@ -1847,9 +1847,18 @@ namespace NLGUI
if (_AutoClamp) if (_AutoClamp)
{ {
CViewBase::updateCoords (); CViewBase::updateCoords ();
if (_Parent)
{ // If there's no parent, try the parent of the parent element.
// Since we will be under the same group
CInterfaceGroup *parent = _Parent; CInterfaceGroup *parent = _Parent;
if( parent == NULL )
{
if( _ParentElm != NULL )
parent = _ParentElm->getParent();
}
if (parent)
{
// avoid resizing parents to compute the limiter // avoid resizing parents to compute the limiter
while (parent && (parent->getResizeFromChildW() || parent->isGroupList() )) while (parent && (parent->getResizeFromChildW() || parent->isGroupList() ))
{ {

View file

@ -34,7 +34,6 @@
#include "nel/gui/interface_expr.h" #include "nel/gui/interface_expr.h"
#include "nel/gui/reflect_register.h" #include "nel/gui/reflect_register.h"
#include "nel/gui/editor_selection_watcher.h" #include "nel/gui/editor_selection_watcher.h"
#include "nel/gui/widget_addition_watcher.h"
#include "nel/misc/events.h" #include "nel/misc/events.h"
namespace NLGUI namespace NLGUI
@ -2079,9 +2078,9 @@ namespace NLGUI
if( CInterfaceElement::getEditorMode() ) if( CInterfaceElement::getEditorMode() )
{ {
if( !currentEditorSelection.empty() ) for( int i = 0; i < editorSelection.size(); i++ )
{ {
CInterfaceElement *e = getElementFromId( currentEditorSelection ); CInterfaceElement *e = getElementFromId( editorSelection[ i ] );
if( e != NULL ) if( e != NULL )
e->drawHighlight(); e->drawHighlight();
} }
@ -2304,6 +2303,14 @@ namespace NLGUI
eventDesc.setX( _Pointer->getX() ); eventDesc.setX( _Pointer->getX() );
eventDesc.setY( _Pointer->getY() ); eventDesc.setY( _Pointer->getY() );
if( CInterfaceElement::getEditorMode() )
{
// Let's pretend we've handled the event... or actually we have!
if( ( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightdown ) ||
( eventDesc.getEventTypeExtended() == CEventDescriptorMouse::mouserightup ) )
return true;
}
if( isMouseHandlingEnabled() ) if( isMouseHandlingEnabled() )
{ {
// First thing to do : Capture handling // First thing to do : Capture handling
@ -2401,6 +2408,22 @@ namespace NLGUI
// must not capture a new element if a sheet is currentlty being dragged. // must not capture a new element if a sheet is currentlty being dragged.
// This may happen when alt-tab has been used => the sheet is dragged but the left button is up // This may happen when alt-tab has been used => the sheet is dragged but the left button is up
if (!CCtrlDraggable::getDraggedSheet()) if (!CCtrlDraggable::getDraggedSheet())
{
if( CInterfaceElement::getEditorMode() && _GroupSelection )
{
for( sint32 i = _GroupsUnderPointer.size() - 1; i >= 0; i-- )
{
CInterfaceGroup *g = _GroupsUnderPointer[ i ];
if( ( g != NULL ) && ( g->isInGroup( pNewCurrentWnd ) ) )
{
_CapturedView = g;
captured = true;
break;
}
}
}
if( !captured )
{ {
// Take the top most control. // Take the top most control.
uint nMaxDepth = 0; uint nMaxDepth = 0;
@ -2419,6 +2442,7 @@ namespace NLGUI
} }
} }
} }
}
if( CInterfaceElement::getEditorMode() && !captured ) if( CInterfaceElement::getEditorMode() && !captured )
{ {
@ -2452,6 +2476,11 @@ namespace NLGUI
// handle the capture // handle the capture
_CapturedView->handleEvent( evnt ); _CapturedView->handleEvent( evnt );
} }
else
{
if( CInterfaceElement::getEditorMode() )
clearEditorSelection();
}
} }
// Manage RightClick // Manage RightClick
@ -2631,9 +2660,10 @@ namespace NLGUI
else else
if( draggedElement != NULL ) if( draggedElement != NULL )
{ {
draggedElement->setXReal( newX ); sint32 dx = newX - oldX;
draggedElement->setYReal( newY ); sint32 dy = newY - oldY;
draggedElement->invalidateCoords();
draggedElement->moveBy( dx, dy );
} }
} }
@ -2666,7 +2696,30 @@ namespace NLGUI
void CWidgetManager::stopDragging() void CWidgetManager::stopDragging()
{ {
if( draggedElement != NULL )
{
CInterfaceGroup *g = getGroupUnder( draggedElement->getXReal(), draggedElement->getYReal() );
CInterfaceElement *e = draggedElement;
CInterfaceGroup *tw = getTopWindow();
if( g == NULL )
g = tw;
std::string oldid = e->getId();
e->setParent( g );
e->setIdRecurse( e->getShortId() );
e->setParentPos( g );
e->setParentSize( g );
g->addElement( e );
e->alignTo( g );
//e->setName( "==MARKED==" );
draggedElement = NULL; draggedElement = NULL;
onWidgetMoved( oldid, e->getId() );
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -3297,25 +3350,53 @@ namespace NLGUI
} }
} }
void CWidgetManager::getEditorSelection( std::vector< std::string > &selection )
void CWidgetManager::setCurrentEditorSelection( const std::string &name )
{ {
CInterfaceElement *e = getElementFromId( name ); selection.clear();
if( e != NULL ) for( int i = 0; i < editorSelection.size(); i++ )
{ selection.push_back( editorSelection[ i ] );
if( !currentEditorSelection.empty() ) }
{
CInterfaceElement *prev = getElementFromId( currentEditorSelection ); void CWidgetManager::selectWidget( const std::string &name )
if( prev != NULL ) {
prev->setEditorSelected( false ); std::vector< std::string >::iterator itr
= std::find( editorSelection.begin(), editorSelection.end(), name );
CInterfaceElement *e = getElementFromId( name );
if( itr != editorSelection.end() )
{
// If multiselection is on unselect if already selected
if( multiSelection )
{
editorSelection.erase( itr );
if( e != NULL )
e->setEditorSelected( false );
} }
e->setEditorSelected( true );
} }
else else
if( !name.empty() ) {
return; // Select if not yet selected
if( e != NULL )
{
// If multiselection is off, we can only have 1 widget selected
if( !multiSelection )
{
editorSelection.clear();
}
currentEditorSelection = name; e->setEditorSelected( true );
editorSelection.push_back( name );
}
}
notifySelectionWatchers();
}
void CWidgetManager::clearEditorSelection()
{
editorSelection.clear();
notifySelectionWatchers(); notifySelectionWatchers();
} }
@ -3324,7 +3405,7 @@ namespace NLGUI
std::vector< IEditorSelectionWatcher* >::iterator itr = selectionWatchers.begin(); std::vector< IEditorSelectionWatcher* >::iterator itr = selectionWatchers.begin();
while( itr != selectionWatchers.end() ) while( itr != selectionWatchers.end() )
{ {
(*itr)->selectionChanged( currentEditorSelection ); (*itr)->selectionChanged();
++itr; ++itr;
} }
} }
@ -3353,36 +3434,46 @@ namespace NLGUI
selectionWatchers.erase( itr ); selectionWatchers.erase( itr );
} }
void CWidgetManager::notifyAdditionWatchers( const std::string &widgetName ) void CWidgetManager::onWidgetAdded( const std::string &id )
{ {
std::vector< IWidgetAdditionWatcher* >::const_iterator itr = additionWatchers.begin(); std::vector< IWidgetWatcher* >::const_iterator itr = widgetWatchers.begin();
while( itr != additionWatchers.end() ) while( itr != widgetWatchers.end() )
{ {
(*itr)->widgetAdded( widgetName ); (*itr)->onWidgetAdded( id );
++itr; ++itr;
} }
} }
void CWidgetManager::registerAdditionWatcher( IWidgetAdditionWatcher *watcher ) void CWidgetManager::onWidgetMoved( const std::string &oldid, const std::string &newid )
{ {
std::vector< IWidgetAdditionWatcher* >::const_iterator itr std::vector< IWidgetWatcher* >::const_iterator itr = widgetWatchers.begin();
= std::find( additionWatchers.begin(), additionWatchers.end(), watcher ); while( itr != widgetWatchers.end() )
// already exists {
if( itr != additionWatchers.end() ) (*itr)->onWidgetMoved( oldid, newid );
return; ++itr;
}
additionWatchers.push_back( watcher );
} }
void CWidgetManager::unregisterAdditionWatcher( IWidgetAdditionWatcher *watcher ) void CWidgetManager::registerWidgetWatcher( IWidgetWatcher *watcher )
{ {
std::vector< IWidgetAdditionWatcher* >::iterator itr std::vector< IWidgetWatcher* >::const_iterator itr
= std::find( additionWatchers.begin(), additionWatchers.end(), watcher ); = std::find( widgetWatchers.begin(), widgetWatchers.end(), watcher );
// doesn't exist // already exists
if( itr == additionWatchers.end() ) if( itr != widgetWatchers.end() )
return; return;
additionWatchers.erase( itr ); widgetWatchers.push_back( watcher );
}
void CWidgetManager::unregisterWidgetWatcher( IWidgetWatcher *watcher )
{
std::vector< IWidgetWatcher* >::iterator itr
= std::find( widgetWatchers.begin(), widgetWatchers.end(), watcher );
// doesn't exist
if( itr == widgetWatchers.end() )
return;
widgetWatchers.erase( itr );
} }
CInterfaceElement* CWidgetManager::addWidgetToGroup( std::string &group, std::string &widgetClass, std::string &widgetName ) CInterfaceElement* CWidgetManager::addWidgetToGroup( std::string &group, std::string &widgetClass, std::string &widgetName )
@ -3415,11 +3506,103 @@ namespace NLGUI
else else
g->addView( v ); g->addView( v );
notifyAdditionWatchers( v->getId() ); onWidgetAdded( v->getId() );
return v; return v;
} }
bool CWidgetManager::groupSelection()
{
std::vector< CInterfaceElement* > elms;
// Resolve the widget names
for( int i = 0; i < editorSelection.size(); i++ )
{
CInterfaceElement *e = getElementFromId( editorSelection[ i ] );
if( e != NULL )
elms.push_back( e );
}
editorSelection.clear();
if( elms.empty() )
return false;
// Create the group as the subgroup of the top window
CInterfaceGroup *g = static_cast< CInterfaceGroup* >( getParser()->createClass( "interface_group" ) );
getTopWindow()->addGroup( g );
g->setParent( getTopWindow() );
g->setIdRecurse( std::string( "group" ) + NLMISC::toString( _WidgetCount ) );
_WidgetCount++;
onWidgetAdded( g->getId() );
std::string oldId;
// Reparent the widgets to the new group
for( int i = 0; i < elms.size(); i++ )
{
CInterfaceElement *e = elms[ i ];
oldId = e->getId();
CInterfaceGroup *p = e->getParent();
if( p != NULL )
p->takeElement( e );
g->addElement( e );
e->setParent( g );
e->setParentPos( g );
e->setParentSize( g );
e->setIdRecurse( e->getShortId() );
onWidgetMoved( oldId, e->getId() );
}
elms.clear();
// Make sure widgets aren't clipped because the group isn't big enough
g->spanElements();
// Make sure widgets are aligned
g->alignElements();
// Align the new group to the top window
g->alignTo( getTopWindow() );
g->setActive( true );
return true;
}
bool CWidgetManager::unGroupSelection()
{
if( editorSelection.size() != 1 )
return false;
// Does the element exist?
CInterfaceElement *e = getElementFromId( editorSelection[ 0 ] );
if( e == NULL )
return false;
// Is the element a group?
CInterfaceGroup *g = dynamic_cast< CInterfaceGroup* >( e );
if( g == NULL )
return false;
// Can't blow up a root group :(
CInterfaceGroup *p = g->getParent();
if( p == NULL )
return false;
// KABOOM!
bool ok = g->explode();
if( !ok )
return false;
p->delElement( g );
clearEditorSelection();
p->updateCoords();
return true;
}
CWidgetManager::CWidgetManager() CWidgetManager::CWidgetManager()
{ {
@ -3458,7 +3641,9 @@ namespace NLGUI
setScreenWH( 0, 0 ); setScreenWH( 0, 0 );
currentEditorSelection = ""; _GroupSelection = false;
multiSelection = false;
_WidgetCount = 0;
} }
CWidgetManager::~CWidgetManager() CWidgetManager::~CWidgetManager()
@ -3472,6 +3657,8 @@ namespace NLGUI
curContextHelp = NULL; curContextHelp = NULL;
CStringShared::deleteStringMapper(); CStringShared::deleteStringMapper();
editorSelection.clear();
} }
} }

View file

@ -25,35 +25,40 @@ namespace GUIEditor
{ {
void CEditorMessageProcessor::onDelete() void CEditorMessageProcessor::onDelete()
{ {
std::string selection = CWidgetManager::getInstance()->getCurrentEditorSelection(); std::vector< std::string > selection;
CWidgetManager::getInstance()->getEditorSelection( selection );
if( selection.empty() ) if( selection.empty() )
return; return;
QMessageBox::StandardButton r = QMessageBox::StandardButton r =
QMessageBox::question( NULL, QMessageBox::question( NULL,
tr( "Deleting widget" ), tr( "Deleting widget" ),
tr( "Are you sure you want to delete %1?" ).arg( selection.c_str() ), tr( "Are you sure you want to delete these?" ),
QMessageBox::Yes | QMessageBox::No ); QMessageBox::Yes | QMessageBox::No );
if( r != QMessageBox::Yes ) if( r != QMessageBox::Yes )
return; return;
CInterfaceElement *e = for( int i = 0; i < selection.size(); i++ )
CWidgetManager::getInstance()->getElementFromId( selection ); {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( selection[ i ] );
if( e == NULL ) if( e == NULL )
return; continue;
CInterfaceElement *p = e->getParent(); CInterfaceElement *p = e->getParent();
if( p == NULL ) if( p == NULL )
return; continue;
CInterfaceGroup *g = dynamic_cast< CInterfaceGroup* >( p ); CInterfaceGroup *g = dynamic_cast< CInterfaceGroup* >( p );
if( g == NULL ) if( g == NULL )
return; continue;
g->delElement( e );
if( g->delElement( e ) )
{
CWidgetManager::getInstance()->setCurrentEditorSelection( "" );
} }
CWidgetManager::getInstance()->clearEditorSelection();
} }
void CEditorMessageProcessor::onAdd( const QString &parentGroup, const QString &widgetType, const QString &name ) void CEditorMessageProcessor::onAdd( const QString &parentGroup, const QString &widgetType, const QString &name )
@ -130,5 +135,32 @@ namespace GUIEditor
e->setActive( false ); e->setActive( false );
e->setActive( true ); e->setActive( true );
} }
void CEditorMessageProcessor::onSetGroupSelection( bool b )
{
CWidgetManager::getInstance()->setGroupSelection( b );
}
void CEditorMessageProcessor::onGroup()
{
CWidgetManager::getInstance()->groupSelection();
}
void CEditorMessageProcessor::onUngroup()
{
bool ok = CWidgetManager::getInstance()->unGroupSelection();
if( !ok )
{
QMessageBox::critical( NULL,
tr( "Ungrouping widgets" ),
tr( "Couldn't ungroup widgets." ) );
}
}
void CEditorMessageProcessor::onSetMultiSelection( bool b )
{
CWidgetManager::getInstance()->setMultiSelection( b );
}
} }

View file

@ -38,6 +38,10 @@ namespace GUIEditor
public Q_SLOTS: public Q_SLOTS:
void onDelete(); void onDelete();
void onAdd( const QString &parentGroup, const QString &widgetType, const QString &name ); void onAdd( const QString &parentGroup, const QString &widgetType, const QString &name );
void onSetGroupSelection( bool b );
void onGroup();
void onUngroup();
void onSetMultiSelection( bool b );
private: private:
CWidgetInfoTree *tree; CWidgetInfoTree *tree;

View file

@ -18,9 +18,9 @@
namespace GUIEditor namespace GUIEditor
{ {
void CEditorSelectionWatcher::selectionChanged( std::string &newSelection ) void CEditorSelectionWatcher::selectionChanged()
{ {
Q_EMIT sgnSelectionChanged( newSelection ); Q_EMIT sgnSelectionChanged();
} }
} }

View file

@ -27,10 +27,10 @@ namespace GUIEditor
public: public:
CEditorSelectionWatcher() : QObject( NULL ){} CEditorSelectionWatcher() : QObject( NULL ){}
void selectionChanged( std::string &newSelection ); void selectionChanged();
Q_SIGNALS: Q_SIGNALS:
void sgnSelectionChanged( std::string &id ); void sgnSelectionChanged();
}; };
} }

View file

@ -283,8 +283,8 @@ namespace GUIEditor
CEditorSelectionWatcher *w = GUICtrl->getWatcher(); CEditorSelectionWatcher *w = GUICtrl->getWatcher();
disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); disconnect( w, SIGNAL( sgnSelectionChanged() ), hierarchyView, SLOT( onSelectionChanged() ) );
disconnect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); disconnect( w, SIGNAL( sgnSelectionChanged() ), &browserCtrl, SLOT( onSelectionChanged() ) );
projectFiles.clearAll(); projectFiles.clearAll();
projectWindow->clear(); projectWindow->clear();
@ -322,8 +322,8 @@ namespace GUIEditor
linkList->onGUILoaded(); linkList->onGUILoaded();
CEditorSelectionWatcher *w = GUICtrl->getWatcher(); CEditorSelectionWatcher *w = GUICtrl->getWatcher();
connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), hierarchyView, SLOT( onSelectionChanged( std::string& ) ) ); connect( w, SIGNAL( sgnSelectionChanged() ), hierarchyView, SLOT( onSelectionChanged() ) );
connect( w, SIGNAL( sgnSelectionChanged( std::string& ) ), &browserCtrl, SLOT( onSelectionChanged( std::string& ) ) ); connect( w, SIGNAL( sgnSelectionChanged() ), &browserCtrl, SLOT( onSelectionChanged() ) );
} }
void GUIEditorWindow::onAddWidgetClicked() void GUIEditorWindow::onAddWidgetClicked()
@ -399,6 +399,30 @@ namespace GUIEditor
connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) ); connect( a, SIGNAL( triggered( bool ) ), this, SLOT( onAddWidgetClicked() ) );
m->addAction( a ); m->addAction( a );
a = new QAction( "Group", this );
connect( a, SIGNAL( triggered() ), messageProcessor, SLOT( onGroup() ) );
m->addAction( a );
a = new QAction( "Ungroup", this );
connect( a, SIGNAL( triggered() ), messageProcessor, SLOT( onUngroup() ) );
m->addAction( a );
// ----------------------------------------------------------------------------------
m->addSeparator();
a = new QAction( "Select groups", this );
a->setCheckable( true );
a->setChecked( false );
connect( a, SIGNAL( triggered( bool ) ), messageProcessor, SLOT( onSetGroupSelection( bool ) ) );
m->addAction( a );
a = new QAction( "Multiselect", this );
a->setCheckable( true );
a->setChecked( false );
connect( a, SIGNAL( triggered( bool ) ), messageProcessor, SLOT( onSetMultiSelection( bool ) ) );
m->addAction( a );
menu = m; menu = m;
} }
} }

View file

@ -436,7 +436,7 @@ namespace GUIEditor
browser->clear(); browser->clear();
} }
void CPropBrowserCtrl::onSelectionChanged( std::string &id ) void CPropBrowserCtrl::onSelectionChanged()
{ {
if( browser == NULL ) if( browser == NULL )
return; return;
@ -444,14 +444,20 @@ namespace GUIEditor
disablePropertyWatchers(); disablePropertyWatchers();
browser->clear(); browser->clear();
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( id ); std::vector< std::string > selection;
CWidgetManager::getInstance()->getEditorSelection( selection );
if( selection.size() != 1 )
return;
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( selection[ 0 ] );
if( e == NULL ) if( e == NULL )
{ {
enablePropertyWatchers(); enablePropertyWatchers();
return; return;
} }
currentElement = id; currentElement = selection[ 0 ];
std::string n = e->getClassName(); std::string n = e->getClassName();
@ -494,6 +500,10 @@ namespace GUIEditor
return; return;
e->setProperty( propName.toUtf8().constData(), propValue.toUtf8().constData() ); e->setProperty( propName.toUtf8().constData(), propValue.toUtf8().constData() );
CInterfaceGroup *g = e->getParent();
if( g != NULL )
g->updateCoords();
// Make sure the changes are applied // Make sure the changes are applied
bool active = e->getActive(); bool active = e->getActive();
@ -514,13 +524,12 @@ namespace GUIEditor
return; return;
std::string type = itr->second; std::string type = itr->second;
if( type == "button_type" )
{
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement ); CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL ) if( e == NULL )
return; return;
if( type == "button_type" )
{
std::string v; std::string v;
v = NelButtonType::toString( value ); v = NelButtonType::toString( value );
if( v.empty() ) if( v.empty() )
@ -531,10 +540,6 @@ namespace GUIEditor
else else
if( type == "text_justification" ) if( type == "text_justification" )
{ {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL )
return;
std::string v; std::string v;
v = NelTxtJustification::toString( value ); v = NelTxtJustification::toString( value );
if( v.empty() ) if( v.empty() )
@ -545,10 +550,6 @@ namespace GUIEditor
else else
if( type == "posref" ) if( type == "posref" )
{ {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL )
return;
std::string v = NelPosRef::toString( value ); std::string v = NelPosRef::toString( value );
if( v.empty() ) if( v.empty() )
return; return;
@ -558,10 +559,6 @@ namespace GUIEditor
else else
if( type == "posreftt" ) if( type == "posreftt" )
{ {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL )
return;
std::string v = NelPosRefTT::toString( value ); std::string v = NelPosRefTT::toString( value );
if( v.empty() ) if( v.empty() )
return; return;
@ -608,10 +605,6 @@ namespace GUIEditor
else else
if( type == "tooltip_parent" ) if( type == "tooltip_parent" )
{ {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL )
return;
std::string v = NelTTParent::toString( value ); std::string v = NelTTParent::toString( value );
if( v.empty() ) if( v.empty() )
return; return;
@ -621,16 +614,18 @@ namespace GUIEditor
else else
if( type == "bitmap_align" ) if( type == "bitmap_align" )
{ {
CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( currentElement );
if( e == NULL )
return;
std::string v = NelBMAlign::toString( value ); std::string v = NelBMAlign::toString( value );
if( v.empty() ) if( v.empty() )
return; return;
e->setProperty( propName.toUtf8().constData(), v ); e->setProperty( propName.toUtf8().constData(), v );
} }
CInterfaceGroup *g = e->getParent();
if( g != NULL )
g->updateCoords();
} }
@ -643,6 +638,10 @@ namespace GUIEditor
return; return;
e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() );
CInterfaceGroup *g = e->getParent();
if( g != NULL )
g->updateCoords();
} }
void CPropBrowserCtrl::onTexturePropertyChanged( QtProperty *p, const QString &v ) void CPropBrowserCtrl::onTexturePropertyChanged( QtProperty *p, const QString &v )
@ -654,6 +653,10 @@ namespace GUIEditor
return; return;
e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() ); e->setProperty( propName.toUtf8().constData(), v.toUtf8().constData() );
CInterfaceGroup *g = e->getParent();
if( g != NULL )
g->updateCoords();
} }
void CPropBrowserCtrl::enablePropertyWatchers() void CPropBrowserCtrl::enablePropertyWatchers()

View file

@ -59,7 +59,7 @@ namespace GUIEditor
void clear(); void clear();
public Q_SLOTS: public Q_SLOTS:
void onSelectionChanged( std::string &id ); void onSelectionChanged();
private Q_SLOTS: private Q_SLOTS:
void onPropertyChanged( QtProperty *prop, const QVariant &v ); void onPropertyChanged( QtProperty *prop, const QVariant &v );

View file

@ -18,7 +18,6 @@
#include "widget_hierarchy.h" #include "widget_hierarchy.h"
#include "nel/gui/interface_group.h" #include "nel/gui/interface_group.h"
#include "nel/gui/widget_manager.h" #include "nel/gui/widget_manager.h"
#include "nel/gui/widget_addition_watcher.h"
namespace namespace
{ {
@ -76,18 +75,24 @@ namespace
GUIEditor::WidgetHierarchy *h; GUIEditor::WidgetHierarchy *h;
}; };
class CWidgetAdditionWatcher : public IWidgetAdditionWatcher class CWidgetWatcher : public CWidgetManager::IWidgetWatcher
{ {
public: public:
CWidgetAdditionWatcher(){ h = NULL; } CWidgetWatcher(){ h = NULL; }
~CWidgetAdditionWatcher(){} ~CWidgetWatcher(){}
void widgetAdded( const std::string &name ) void onWidgetAdded( const std::string &name )
{ {
if( h != NULL ) if( h != NULL )
h->onWidgetAdded( name ); h->onWidgetAdded( name );
} }
void onWidgetMoved( const std::string &oldid, const std::string &newid )
{
if( h != NULL )
h->onWidgetMoved( oldid, newid );
}
void setWidgetHierarchy( GUIEditor::WidgetHierarchy *h ){ this->h = h; } void setWidgetHierarchy( GUIEditor::WidgetHierarchy *h ){ this->h = h; }
private: private:
@ -95,7 +100,7 @@ namespace
}; };
CWidgetDeletionWatcher deletionWatcher; CWidgetDeletionWatcher deletionWatcher;
CWidgetAdditionWatcher additionWatcher; CWidgetWatcher widgetwatcher;
} }
namespace GUIEditor namespace GUIEditor
@ -107,7 +112,7 @@ namespace GUIEditor
connect( widgetHT, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ), connect( widgetHT, SIGNAL( itemDoubleClicked( QTreeWidgetItem*, int ) ),
this, SLOT( onItemDblClicked( QTreeWidgetItem* ) ) ); this, SLOT( onItemDblClicked( QTreeWidgetItem* ) ) );
deletionWatcher.setWidgetHierarchy( this ); deletionWatcher.setWidgetHierarchy( this );
additionWatcher.setWidgetHierarchy( this ); widgetwatcher.setWidgetHierarchy( this );
} }
WidgetHierarchy::~WidgetHierarchy() WidgetHierarchy::~WidgetHierarchy()
@ -117,7 +122,7 @@ namespace GUIEditor
void WidgetHierarchy::clearHierarchy() void WidgetHierarchy::clearHierarchy()
{ {
CInterfaceElement::unregisterDeletionWatcher( &deletionWatcher ); CInterfaceElement::unregisterDeletionWatcher( &deletionWatcher );
CWidgetManager::getInstance()->unregisterAdditionWatcher( &additionWatcher ); CWidgetManager::getInstance()->unregisterWidgetWatcher( &widgetwatcher );
widgetHT->clear(); widgetHT->clear();
widgetHierarchyMap.clear(); widgetHierarchyMap.clear();
} }
@ -126,7 +131,7 @@ namespace GUIEditor
{ {
clearHierarchy(); clearHierarchy();
CInterfaceElement::registerDeletionWatcher( &deletionWatcher ); CInterfaceElement::registerDeletionWatcher( &deletionWatcher );
CWidgetManager::getInstance()->registerAdditionWatcher( &additionWatcher ); CWidgetManager::getInstance()->registerWidgetWatcher( &widgetwatcher );
CInterfaceGroup *mg = CWidgetManager::getInstance()->getMasterGroupFromId( masterGroup ); CInterfaceGroup *mg = CWidgetManager::getInstance()->getMasterGroupFromId( masterGroup );
if( mg != NULL ) if( mg != NULL )
@ -177,6 +182,27 @@ namespace GUIEditor
} }
} }
QTreeWidgetItem* WidgetHierarchy::findItem( const std::string &id )
{
std::map< std::string, QTreeWidgetItem* >::iterator itr
= widgetHierarchyMap.find( id );
if( itr == widgetHierarchyMap.end() )
return NULL;
else
return itr->second;
}
QTreeWidgetItem* WidgetHierarchy::findParent( const std::string &id )
{
// Get the parent's name
std::string::size_type p = id.find_last_of( ':' );
if( p == std::string::npos )
return NULL;
std::string parentId = id.substr( 0, p );
return findItem( parentId );
}
void WidgetHierarchy::onWidgetDeleted( const std::string &id ) void WidgetHierarchy::onWidgetDeleted( const std::string &id )
{ {
std::map< std::string, QTreeWidgetItem* >::iterator itr std::map< std::string, QTreeWidgetItem* >::iterator itr
@ -231,16 +257,62 @@ namespace GUIEditor
widgetHierarchyMap[ id ] = item; widgetHierarchyMap[ id ] = item;
} }
void WidgetHierarchy::onWidgetMoved( const std::string &oldid, const std::string &newid )
{
QTreeWidgetItem *newParent = NULL;
QTreeWidgetItem *item = NULL;
QString id;
newParent = findParent( newid );
item = findItem( oldid );
if( ( newParent == NULL ) || ( item == NULL ) )
return;
// Remove item from old parent
QTreeWidgetItem *p = item->parent();
if( p != NULL )
p->setExpanded( false );
p->removeChild( item );
// Remove reference to old item
widgetHierarchyMap.erase( oldid );
// Add item to new parent
newParent->addChild( item );
// Add reference to new item
widgetHierarchyMap[ newid ] = item;
selectItem( item );
}
void WidgetHierarchy::selectItem( QTreeWidgetItem *item )
{
widgetHT->collapseAll();
QTreeWidgetItem *currItem = item;
while( currItem != NULL )
{
currItem->setExpanded( true );
currItem = currItem->parent();
}
widgetHT->setCurrentItem( item );
item->setSelected( true );
}
void WidgetHierarchy::getCurrentGroup( QString &g ) void WidgetHierarchy::getCurrentGroup( QString &g )
{ {
std::string s = CWidgetManager::getInstance()->getCurrentEditorSelection(); std::vector< std::string > selection;
if( s.empty() ) CWidgetManager::getInstance()->getEditorSelection( selection );
if( selection.size() != 1 )
{ {
g = ""; g = "";
return; return;
} }
NLGUI::CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( s ); NLGUI::CInterfaceElement *e = CWidgetManager::getInstance()->getElementFromId( selection[ 0 ] );
if( e == NULL ) if( e == NULL )
{ {
g = ""; g = "";
@ -271,8 +343,16 @@ namespace GUIEditor
currentSelection.clear(); currentSelection.clear();
} }
void WidgetHierarchy::onSelectionChanged( std::string &newSelection ) void WidgetHierarchy::onSelectionChanged()
{ {
std::vector< std::string > selection;
CWidgetManager::getInstance()->getEditorSelection( selection );
if( selection.size() != 1 )
return;
std::string newSelection = selection[ 0 ];
if( newSelection == currentSelection ) if( newSelection == currentSelection )
return; return;
@ -288,18 +368,11 @@ namespace GUIEditor
if( widgetHT->currentItem() != NULL ) if( widgetHT->currentItem() != NULL )
widgetHT->currentItem()->setSelected( false ); widgetHT->currentItem()->setSelected( false );
// expand the tree items, so that we can see the selected item widgetHT->collapseAll();
QTreeWidgetItem *item = itr->second;
QTreeWidgetItem *currItem = item;
while( currItem != NULL )
{
currItem->setExpanded( true );
currItem = currItem->parent();
}
// select the current item // select the current item
item->setSelected( true ); QTreeWidgetItem *item = itr->second;
widgetHT->setCurrentItem( item ); selectItem( item );
currentSelection = newSelection; currentSelection = newSelection;
} }
@ -308,8 +381,10 @@ namespace GUIEditor
if( item->parent() == NULL ) if( item->parent() == NULL )
return; return;
selectItem( item );
std::string n = item->text( 0 ).toUtf8().constData(); std::string n = item->text( 0 ).toUtf8().constData();
currentSelection = makeFullName( item, n ); currentSelection = makeFullName( item, n );
CWidgetManager::getInstance()->setCurrentEditorSelection( currentSelection ); CWidgetManager::getInstance()->selectWidget( currentSelection );
} }
} }

View file

@ -44,15 +44,19 @@ namespace GUIEditor
void onWidgetDeleted( const std::string &id ); void onWidgetDeleted( const std::string &id );
void onWidgetAdded( const std::string &id ); void onWidgetAdded( const std::string &id );
void onWidgetMoved( const std::string &oldid, const std::string &newid );
void getCurrentGroup( QString &g ); void getCurrentGroup( QString &g );
private: private:
void buildHierarchy( QTreeWidgetItem *parent, NLGUI::CInterfaceGroup *group ); void buildHierarchy( QTreeWidgetItem *parent, NLGUI::CInterfaceGroup *group );
QTreeWidgetItem* findItem( const std::string &id );
QTreeWidgetItem* findParent( const std::string &id );
void selectItem( QTreeWidgetItem *item );
public Q_SLOTS: public Q_SLOTS:
void onGUILoaded(); void onGUILoaded();
void onSelectionChanged( std::string &newSelection ); void onSelectionChanged();
private Q_SLOTS: private Q_SLOTS:
void onItemDblClicked( QTreeWidgetItem *item ); void onItemDblClicked( QTreeWidgetItem *item );