Added documentation. Moved some functions from .h to .cpp files.

This commit is contained in:
Maciej Suminski 2014-03-07 10:26:33 +01:00
parent 88a0311afe
commit 3927c667cc
4 changed files with 321 additions and 113 deletions

View File

@ -29,6 +29,17 @@
#include <class_drawsegment.h> #include <class_drawsegment.h>
bool EDIT_POINT::WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const
{
// Corners of the square
VECTOR2I topLeft = GetPosition() - aSize;
VECTOR2I bottomRight = GetPosition() + aSize;
return ( aPoint.x > topLeft.x && aPoint.y > topLeft.y &&
aPoint.x < bottomRight.x && aPoint.y < bottomRight.y );
}
EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) : EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) :
EDA_ITEM( NOT_USED ), m_parent( aParent ) EDA_ITEM( NOT_USED ), m_parent( aParent )
{ {
@ -61,6 +72,62 @@ EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation )
} }
EDIT_POINT* EDIT_POINTS::Previous( const EDIT_POINT& aPoint )
{
for( unsigned int i = 0; i < m_points.size(); ++i )
{
if( m_points[i] == aPoint )
{
if( i == 0 )
return &m_points[m_points.size() - 1];
else
return &m_points[i - 1];
}
}
for( unsigned int i = 0; i < m_lines.size(); ++i )
{
if( m_lines[i] == aPoint )
{
if( i == 0 )
return &m_lines[m_lines.size() - 1];
else
return &m_lines[i - 1];
}
}
return NULL;
}
EDIT_POINT* EDIT_POINTS::Next( const EDIT_POINT& aPoint )
{
for( unsigned int i = 0; i < m_points.size(); ++i )
{
if( m_points[i] == aPoint )
{
if( i == m_points.size() - 1 )
return &m_points[0];
else
return &m_points[i + 1];
}
}
for( unsigned int i = 0; i < m_lines.size(); ++i )
{
if( m_lines[i] == aPoint )
{
if( i == m_lines.size() - 1 )
return &m_lines[0];
else
return &m_lines[i + 1];
}
}
return NULL;
}
void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
{ {
aGal->SetFillColor( KIGFX::COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); aGal->SetFillColor( KIGFX::COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
@ -79,3 +146,32 @@ void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
aGal->PopDepth(); aGal->PopDepth();
} }
void EPC_45DEGREE::Apply()
{
// Current line vector
VECTOR2I lineVector( m_constrained.GetPosition() - m_constrainer.GetPosition() );
double angle = lineVector.Angle();
// Find the closest angle, which is a multiple of 45 degrees
double newAngle = round( angle / ( M_PI / 4.0 ) ) * M_PI / 4.0;
VECTOR2I newLineVector = lineVector.Rotate( newAngle - angle );
m_constrained.SetPosition( m_constrainer.GetPosition() + newLineVector );
}
void EPC_CIRCLE::Apply()
{
VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition();
VECTOR2I centerToPoint = m_constrained.GetPosition() - m_center.GetPosition();
int radius = centerToEnd.EuclideanNorm();
double angle = centerToPoint.Angle();
VECTOR2I newLine( radius, 0 );
newLine = newLine.Rotate( angle );
m_constrained.SetPosition( m_center.GetPosition() + newLine );
}

View File

@ -34,23 +34,50 @@
class EDIT_POINT; class EDIT_POINT;
/**
* Class EDIT_POINT_CONSTRAINT
*
* Allows to describe constraints between two points. After the constrained point is changed,
* Apply() has to be called to fix its coordinates according to the implemented constraint.
*/
class EDIT_POINT_CONSTRAINT class EDIT_POINT_CONSTRAINT
{ {
public: public:
/**
* Constructor
*
* @param aConstrained is EDIT_POINT to which the constraint is applied.
*/
EDIT_POINT_CONSTRAINT( EDIT_POINT& aConstrained ) : m_constrained( aConstrained ) {}; EDIT_POINT_CONSTRAINT( EDIT_POINT& aConstrained ) : m_constrained( aConstrained ) {};
virtual ~EDIT_POINT_CONSTRAINT() {}; virtual ~EDIT_POINT_CONSTRAINT() {};
/**
* Function Apply()
*
* Corrects coordinates of the constrained point.
*/
virtual void Apply() = 0; virtual void Apply() = 0;
protected: protected:
EDIT_POINT& m_constrained; EDIT_POINT& m_constrained; ///< Point that is constrained by rules implemented by Apply()
}; };
// TODO docs /**
* Class EDIT_POINT
*
* Represents a single point that can be used for modifying items. It is directly related to one
* of points in a graphical item (e.g. vertex of a zone or center of a circle).
*/
class EDIT_POINT class EDIT_POINT
{ {
public: public:
/**
* Constructor
*
* @param aPoint stores coordinates for EDIT_POINT.
*/
EDIT_POINT( const VECTOR2I& aPoint ) : EDIT_POINT( const VECTOR2I& aPoint ) :
m_position( aPoint ), m_constraint( NULL ) {}; m_position( aPoint ), m_constraint( NULL ) {};
@ -59,25 +86,44 @@ public:
delete m_constraint; delete m_constraint;
} }
/**
* Function GetPosition()
*
* Returns coordinates of an EDIT_POINT. Note that it may be different than coordinates of
* a graphical item that is bound to the EDIT_POINT.
*/
virtual VECTOR2I GetPosition() const virtual VECTOR2I GetPosition() const
{ {
return m_position; return m_position;
} }
/**
* Function SetPosition()
*
* Sets new coordinates for an EDIT_POINT. It does not change the coordinates of a graphical
* item.
* @param aPosition are new coordinates.
*/
virtual void SetPosition( const VECTOR2I& aPosition ) virtual void SetPosition( const VECTOR2I& aPosition )
{ {
m_position = aPosition; m_position = aPosition;
} }
bool WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const /**
{ * Function WithinPoint()
VECTOR2I topLeft = GetPosition() - aSize; *
VECTOR2I bottomRight = GetPosition() + aSize; * Checks if given point is within a square centered in the EDIT_POINT position.
* @param aPoint is point to be checked.
return ( aPoint.x > topLeft.x && aPoint.y > topLeft.y && * @param aSize is length of the square side.
aPoint.x < bottomRight.x && aPoint.y < bottomRight.y ); */
} bool WithinPoint( const VECTOR2I& aPoint, unsigned int aSize ) const;
/**
* Function SetConstraint()
*
* Sets a constraint for and EDIT_POINT.
* @param aConstraint is the constraint to be set.
*/
void SetConstraint( EDIT_POINT_CONSTRAINT* aConstraint ) void SetConstraint( EDIT_POINT_CONSTRAINT* aConstraint )
{ {
if( m_constraint ) if( m_constraint )
@ -86,22 +132,33 @@ public:
m_constraint = aConstraint; m_constraint = aConstraint;
} }
/**
* Function ClearConstraint()
*
* Removes previously set constraint.
*/
void ClearConstraint() void ClearConstraint()
{ {
delete m_constraint; delete m_constraint;
m_constraint = NULL; m_constraint = NULL;
} }
EDIT_POINT_CONSTRAINT* GetConstraint() const /**
{ * Function IsConstrained()
return m_constraint; *
} * Checks if point is constrained.
* @return True is point is constrained, false otherwise.
*/
bool IsConstrained() const bool IsConstrained() const
{ {
return m_constraint != NULL; return m_constraint != NULL;
} }
/**
* Function ApplyConstraint()
*
* Corrects coordinates of an EDIT_POINT by applying previously set constraint.
*/
void ApplyConstraint() void ApplyConstraint()
{ {
if( m_constraint ) if( m_constraint )
@ -117,25 +174,40 @@ public:
static const int POINT_SIZE = 10; static const int POINT_SIZE = 10;
protected: protected:
VECTOR2I m_position; VECTOR2I m_position; ///< Position of EDIT_POINT
EDIT_POINT_CONSTRAINT* m_constraint; EDIT_POINT_CONSTRAINT* m_constraint; ///< Constraint for the point, NULL if none
}; };
/**
* Class EDIT_LINE
*
* Represents a line connecting two EDIT_POINTs. That allows to move them both by dragging the
* EDIT_POINT in the middle. As it uses references to EDIT_POINTs, all coordinates are
* automatically synchronized.
*/
class EDIT_LINE : public EDIT_POINT class EDIT_LINE : public EDIT_POINT
{ {
public: public:
/**
* Constructor
*
* @param aOrigin is the origin of EDIT_LINE.
* @param aEnd is the end of EDIT_LINE.
*/
EDIT_LINE( EDIT_POINT& aOrigin, EDIT_POINT& aEnd ) : EDIT_LINE( EDIT_POINT& aOrigin, EDIT_POINT& aEnd ) :
EDIT_POINT( aOrigin.GetPosition() + ( aEnd.GetPosition() - aOrigin.GetPosition() ) / 2 ), EDIT_POINT( aOrigin.GetPosition() + ( aEnd.GetPosition() - aOrigin.GetPosition() ) / 2 ),
m_origin( aOrigin ), m_end( aEnd ) m_origin( aOrigin ), m_end( aEnd )
{ {
} }
///> @copydoc EDIT_POINT::GetPosition()
virtual VECTOR2I GetPosition() const virtual VECTOR2I GetPosition() const
{ {
return m_origin.GetPosition() + ( m_end.GetPosition() - m_origin.GetPosition() ) / 2; return m_origin.GetPosition() + ( m_end.GetPosition() - m_origin.GetPosition() ) / 2;
} }
///> @copydoc EDIT_POINT::GetPosition()
virtual void SetPosition( const VECTOR2I& aPosition ) virtual void SetPosition( const VECTOR2I& aPosition )
{ {
VECTOR2I difference = aPosition - GetPosition(); VECTOR2I difference = aPosition - GetPosition();
@ -155,101 +227,110 @@ public:
} }
private: private:
EDIT_POINT& m_origin; EDIT_POINT& m_origin; ///< Origin point for a line
EDIT_POINT& m_end; EDIT_POINT& m_end; ///< End point for a line
}; };
/**
* Class EDIT_POINTS
*
* EDIT_POINTS is a VIEW_ITEM that manages EDIT_POINTs and EDIT_LINEs and draws them.
*/
class EDIT_POINTS : public EDA_ITEM class EDIT_POINTS : public EDA_ITEM
{ {
public: public:
/**
* Constructor.
*
* @param aParent is the item to which EDIT_POINTs are related.
*/
EDIT_POINTS( EDA_ITEM* aParent ); EDIT_POINTS( EDA_ITEM* aParent );
/** /**
* Function FindPoint * Function FindPoint()
*
* Returns a point that is at given coordinates or NULL if there is no such point. * Returns a point that is at given coordinates or NULL if there is no such point.
* @param aLocation is the location for searched point. * @param aLocation is the location for searched point.
*/ */
EDIT_POINT* FindPoint( const VECTOR2I& aLocation ); EDIT_POINT* FindPoint( const VECTOR2I& aLocation );
/**
* Function GetParent()
*
* Returns parent of the EDIT_POINTS.
*/
EDA_ITEM* GetParent() const EDA_ITEM* GetParent() const
{ {
return m_parent; return m_parent;
} }
/**
* Function AddPoint()
*
* Adds an EDIT_POINT.
* @param aPoint is the new point.
*/
void AddPoint( const EDIT_POINT& aPoint ) void AddPoint( const EDIT_POINT& aPoint )
{ {
m_points.push_back( aPoint ); m_points.push_back( aPoint );
} }
/**
* Function AddPoint()
*
* Adds an EDIT_POINT.
* @param aPoint are coordinates of the new point.
*/
void AddPoint( const VECTOR2I& aPoint ) void AddPoint( const VECTOR2I& aPoint )
{ {
AddPoint( EDIT_POINT( aPoint ) ); AddPoint( EDIT_POINT( aPoint ) );
} }
/**
* Function AddLine()
*
* Adds an EDIT_LINE.
* @param aLine is the new line.
*/
void AddLine( const EDIT_LINE& aLine ) void AddLine( const EDIT_LINE& aLine )
{ {
m_lines.push_back( aLine ); m_lines.push_back( aLine );
} }
/**
* Function AddLine()
*
* Adds an EDIT_LINE.
* @param aOrigin is the origin for a new line.
* @param aEnd is the end for a new line.
*/
void AddLine( EDIT_POINT& aOrigin, EDIT_POINT& aEnd ) void AddLine( EDIT_POINT& aOrigin, EDIT_POINT& aEnd )
{ {
m_lines.push_back( EDIT_LINE( aOrigin, aEnd ) ); m_lines.push_back( EDIT_LINE( aOrigin, aEnd ) );
} }
EDIT_POINT* Previous( const EDIT_POINT& aPoint ) /**
{ * Function Previous()
for( unsigned int i = 0; i < m_points.size(); ++i ) *
{ * Returns the point that is after the given point in the list.
if( m_points[i] == aPoint ) * @param aPoint is the point that is supposed to be preceding the searched point.
{ * @return The point following aPoint in the list. If aPoint is the first in
if( i == 0 ) * the list, the last from the list will be returned. If there are no points at all, NULL
return &m_points[m_points.size() - 1]; * is returned.
else */
return &m_points[i - 1]; EDIT_POINT* Previous( const EDIT_POINT& aPoint );
}
}
for( unsigned int i = 0; i < m_lines.size(); ++i ) /**
{ * Function Next()
if( m_lines[i] == aPoint ) *
{ * Returns the point that is before the given point in the list.
if( i == 0 ) * @param aPoint is the point that is supposed to be following the searched point.
return &m_lines[m_lines.size() - 1]; * @return The point preceding aPoint in the list. If aPoint is the last in
else * the list, the first point from the list will be returned. If there are no points at all,
return &m_lines[i - 1]; * NULL is returned.
} */
} EDIT_POINT* Next( const EDIT_POINT& aPoint );
return NULL;
}
EDIT_POINT* Next( const EDIT_POINT& aPoint )
{
for( unsigned int i = 0; i < m_points.size(); ++i )
{
if( m_points[i] == aPoint )
{
if( i == m_points.size() - 1 )
return &m_points[0];
else
return &m_points[i + 1];
}
}
for( unsigned int i = 0; i < m_lines.size(); ++i )
{
if( m_lines[i] == aPoint )
{
if( i == m_lines.size() - 1 )
return &m_lines[0];
else
return &m_lines[i + 1];
}
}
return NULL;
}
EDIT_POINT& operator[]( unsigned int aIndex ) EDIT_POINT& operator[]( unsigned int aIndex )
{ {
@ -261,18 +342,26 @@ public:
return m_points[aIndex]; return m_points[aIndex];
} }
/**
* Function Size()
*
* Returns number of stored points.
*/
unsigned int Size() const unsigned int Size() const
{ {
return m_points.size(); return m_points.size();
} }
///> @copydoc VIEW_ITEM::ViewBBox()
virtual const BOX2I ViewBBox() const virtual const BOX2I ViewBBox() const
{ {
return m_parent->ViewBBox(); return m_parent->ViewBBox();
} }
///> @copydoc VIEW_ITEM::ViewDraw()
virtual void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const; virtual void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const;
///> @copydoc VIEW_ITEM::ViewGetLayers()
virtual void ViewGetLayers( int aLayers[], int& aCount ) const virtual void ViewGetLayers( int aLayers[], int& aCount ) const
{ {
aCount = 1; aCount = 1;
@ -284,19 +373,31 @@ public:
} }
private: private:
EDA_ITEM* m_parent; EDA_ITEM* m_parent; ///< Parent of the EDIT_POINTs
std::deque<EDIT_POINT> m_points; std::deque<EDIT_POINT> m_points; ///< EDIT_POINTs for modifying m_parent
std::deque<EDIT_LINE> m_lines; std::deque<EDIT_LINE> m_lines; ///< EDIT_LINEs for modifying m_parent
}; };
/**
* Class EPC_VERTICAL.
*
* EDIT_POINT_CONSTRAINT that imposes a constraint that two points have to have the same X coordinate.
*/
class EPC_VERTICAL : public EDIT_POINT_CONSTRAINT class EPC_VERTICAL : public EDIT_POINT_CONSTRAINT
{ {
public: public:
EPC_VERTICAL( EDIT_POINT& aConstrained, EDIT_POINT& aConstrainer ) : /**
* Constructor.
*
* @param aConstrained is the point that is put under constrain.
* @param aConstrainer is the point that is the source of the constrain.
*/
EPC_VERTICAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer ) EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer )
{} {}
///> @copydoc EDIT_POINT_CONSTRAINT::Apply()
virtual void Apply() virtual void Apply()
{ {
VECTOR2I point = m_constrained.GetPosition(); VECTOR2I point = m_constrained.GetPosition();
@ -304,23 +405,30 @@ public:
m_constrained.SetPosition( point ); m_constrained.SetPosition( point );
} }
virtual std::list<EDIT_POINT*> GetConstrainers() const
{
return std::list<EDIT_POINT*>( 1, &m_constrainer );
}
private: private:
EDIT_POINT& m_constrainer; const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
}; };
/**
* Class EPC_HORIZONTAL.
*
* EDIT_POINT_CONSTRAINT that imposes a constraint that two points have to have the same Y coordinate.
*/
class EPC_HORIZONTAL : public EDIT_POINT_CONSTRAINT class EPC_HORIZONTAL : public EDIT_POINT_CONSTRAINT
{ {
public: public:
/**
* Constructor.
*
* @param aConstrained is the point that is put under constrain.
* @param aConstrainer is the point that is the source of the constrain.
*/
EPC_HORIZONTAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) : EPC_HORIZONTAL( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer ) EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer )
{} {}
///> @copydoc EDIT_POINT_CONSTRAINT::Apply()
virtual void Apply() virtual void Apply()
{ {
VECTOR2I point = m_constrained.GetPosition(); VECTOR2I point = m_constrained.GetPosition();
@ -329,60 +437,64 @@ public:
} }
private: private:
const EDIT_POINT& m_constrainer; const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
}; };
/**
* Class EPC_45DEGREE
*
* EDIT_POINT_CONSTRAINT that imposes a constraint that two to be located at angle of 45 degree
* multiplicity.
*/
class EPC_45DEGREE : public EDIT_POINT_CONSTRAINT class EPC_45DEGREE : public EDIT_POINT_CONSTRAINT
{ {
public: public:
/**
* Constructor.
*
* @param aConstrained is the point that is put under constrain.
* @param aConstrainer is the point that is the source of the constrain.
*/
EPC_45DEGREE ( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) : EPC_45DEGREE ( EDIT_POINT& aConstrained, const EDIT_POINT& aConstrainer ) :
EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer ) EDIT_POINT_CONSTRAINT( aConstrained ), m_constrainer( aConstrainer )
{} {}
virtual void Apply() ///> @copydoc EDIT_POINT_CONSTRAINT::Apply()
{ virtual void Apply();
// Current line vector
VECTOR2I lineVector( m_constrained.GetPosition() - m_constrainer.GetPosition() );
double angle = lineVector.Angle();
// Find the closest angle, which is a multiple of 45 degrees
double newAngle = round( angle / ( M_PI / 4.0 ) ) * M_PI / 4.0;
VECTOR2I newLineVector = lineVector.Rotate( newAngle - angle );
m_constrained.SetPosition( m_constrainer.GetPosition() + newLineVector );
}
private: private:
const EDIT_POINT& m_constrainer; const EDIT_POINT& m_constrainer; ///< Point that imposes the constraint.
}; };
/**
* Class EPC_CIRCLE.
*
* EDIT_POINT_CONSTRAINT that imposes a constraint that a point has to lie on a circle.
*/
class EPC_CIRCLE : public EDIT_POINT_CONSTRAINT class EPC_CIRCLE : public EDIT_POINT_CONSTRAINT
{ {
public: public:
/**
* Constructor.
*
* @param aConstrained is the point that is put under constrain.
* @parama aCenter is the point that is the center of the circle.
* @parama aEnd is the point that decides on the radius of the circle.
*/
EPC_CIRCLE( EDIT_POINT& aConstrained, const EDIT_POINT& aCenter, const EDIT_POINT& aEnd ) : EPC_CIRCLE( EDIT_POINT& aConstrained, const EDIT_POINT& aCenter, const EDIT_POINT& aEnd ) :
EDIT_POINT_CONSTRAINT( aConstrained ), m_center( aCenter ), m_end( aEnd ) EDIT_POINT_CONSTRAINT( aConstrained ), m_center( aCenter ), m_end( aEnd )
{} {}
virtual ~EPC_CIRCLE() {}; ///> @copydoc EDIT_POINT_CONSTRAINT::Apply()
virtual void Apply();
virtual void Apply()
{
VECTOR2I centerToEnd = m_end.GetPosition() - m_center.GetPosition();
VECTOR2I centerToPoint = m_constrained.GetPosition() - m_center.GetPosition();
int radius = centerToEnd.EuclideanNorm();
double angle = centerToPoint.Angle();
VECTOR2I newLine( radius, 0 );
newLine = newLine.Rotate( angle );
m_constrained.SetPosition( m_center.GetPosition() + newLine );
}
private: private:
///> Point that imposes the constraint (center of the circle).
const EDIT_POINT& m_center; const EDIT_POINT& m_center;
///> Point that imposes the constraint (decides on the radius of the circle).
const EDIT_POINT& m_end; const EDIT_POINT& m_end;
}; };

View File

@ -159,6 +159,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent )
KIGFX::VIEW* view = getView(); KIGFX::VIEW* view = getView();
PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>(); PCB_EDIT_FRAME* editFrame = getEditFrame<PCB_EDIT_FRAME>();
EDA_ITEM* item = selection.items.GetPickedItem( 0 ); EDA_ITEM* item = selection.items.GetPickedItem( 0 );
EDIT_POINT constrainer( VECTOR2I( 0, 0 ) );
m_editPoints = EDIT_POINTS_FACTORY::Make( item ); m_editPoints = EDIT_POINTS_FACTORY::Make( item );
if( !m_editPoints ) if( !m_editPoints )
@ -220,7 +221,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent )
if( !m_dragPoint->IsConstrained() ) if( !m_dragPoint->IsConstrained() )
{ {
// Find a proper constraining point for 45 degrees mode // Find a proper constraining point for 45 degrees mode
EDIT_POINT constrainer = get45DegConstrainer(); constrainer = get45DegConstrainer();
m_dragPoint->SetConstraint( new EPC_45DEGREE( *m_dragPoint, constrainer ) ); m_dragPoint->SetConstraint( new EPC_45DEGREE( *m_dragPoint, constrainer ) );
} }
} }

View File

@ -37,7 +37,6 @@ class SELECTION_TOOL;
* *
* Tool that displays edit points allowing to modify items by dragging the points. * Tool that displays edit points allowing to modify items by dragging the points.
*/ */
class POINT_EDITOR : public TOOL_INTERACTIVE class POINT_EDITOR : public TOOL_INTERACTIVE
{ {
public: public: