Commit 46020e20 authored by Maciej Sumiński's avatar Maciej Sumiński

Merged the new Interactive Push and Shove router.

Do not pay attention to add/remove files - it seems there may be a bug in git-bzr-ng plugin. I have checked them, they stayed exactly the same as before.
parents 41e41b95 51ee6916
......@@ -203,6 +203,7 @@ set( COMMON_SRCS
wildcards_and_files_ext.cpp
worksheet.cpp
wxwineda.cpp
wxunittext.cpp
xnode.cpp
zoom.cpp
)
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2014 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
......@@ -67,7 +67,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this );
Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this );
/* Generic events for the Tool Dispatcher */
......@@ -125,7 +124,7 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
m_view->UpdateItems();
m_gal->BeginDrawing();
m_gal->ClearScreen();
m_gal->ClearScreen( m_painter->GetSettings()->GetBackgroundColor() );
if( m_view->IsDirty() )
{
......@@ -184,10 +183,21 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
}
void EDA_DRAW_PANEL_GAL::StartDrawing()
{
m_pendingRefresh = false;
Connect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
wxPaintEvent redrawEvent;
wxPostEvent( this, redrawEvent );
}
void EDA_DRAW_PANEL_GAL::StopDrawing()
{
Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
m_pendingRefresh = true;
m_refreshTimer.Stop();
Disconnect( wxEVT_PAINT, wxPaintEventHandler( EDA_DRAW_PANEL_GAL::onPaint ), NULL, this );
}
......@@ -198,8 +208,7 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
return;
// Prevent refreshing canvas during backend switch
m_pendingRefresh = true;
m_refreshTimer.Stop();
StopDrawing();
delete m_gal;
......@@ -219,7 +228,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
wxSize size = GetClientSize();
m_gal->ResizeScreen( size.GetX(), size.GetY() );
m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
if( m_painter )
m_painter->SetGAL( m_gal );
......@@ -228,7 +236,6 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
m_view->SetGAL( m_gal );
m_currentGal = aGalType;
m_pendingRefresh = false;
}
......
......@@ -315,10 +315,10 @@ void CAIRO_GAL::Flush()
}
void CAIRO_GAL::ClearScreen()
void CAIRO_GAL::ClearScreen( const COLOR4D& aColor )
{
cairo_set_source_rgb( currentContext,
backgroundColor.r, backgroundColor.g, backgroundColor.b );
backgroundColor = aColor;
cairo_set_source_rgb( currentContext, aColor.r, aColor.g, aColor.b );
cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y );
cairo_fill( currentContext );
}
......@@ -973,7 +973,7 @@ void CAIRO_GAL::initSurface()
cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
// Clear the screen
ClearScreen();
ClearScreen( backgroundColor );
// Compute the world <-> screen transformations
ComputeWorldScreenMatrix();
......
......@@ -589,10 +589,10 @@ void OPENGL_GAL::Flush()
}
void OPENGL_GAL::ClearScreen()
void OPENGL_GAL::ClearScreen( const COLOR4D& aColor )
{
// Clear screen
glClearColor( backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a );
glClearColor( aColor.r, aColor.g, aColor.b, aColor.a );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
......
......@@ -23,11 +23,13 @@
*/
#include <math/vector2d.h>
#include <math.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_circle.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_segment.h>
typedef VECTOR2I::extended_type ecoord;
......@@ -45,7 +47,7 @@ static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int
return false;
if( aNeedMTV )
aMTV = delta.Resize( sqrt( abs( min_dist_sq - dist_sq ) ) + 1 );
aMTV = delta.Resize( min_dist - sqrt( dist_sq ) + 3 ); // fixme: apparent rounding error
return true;
}
......@@ -57,12 +59,8 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int a
const VECTOR2I c = aB.GetCenter();
const VECTOR2I p0 = aA.GetPosition();
const VECTOR2I size = aA.GetSize();
const ecoord r = aB.GetRadius();
const ecoord min_dist = aClearance + r;
const ecoord min_dist_sq = min_dist * min_dist;
if( aA.BBox( 0 ).Contains( c ) )
return true;
const int r = aB.GetRadius();
const int min_dist = aClearance + r;
const VECTOR2I vts[] =
{
......@@ -73,33 +71,35 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int a
VECTOR2I( p0.x, p0.y )
};
ecoord nearest_seg_dist_sq = VECTOR2I::ECOORD_MAX;
int nearest_seg_dist = INT_MAX;
VECTOR2I nearest;
bool inside = c.x >= p0.x && c.x <= ( p0.x + size.x )
&& c.y >= p0.y && c.y <= ( p0.y + size.y );
if( !inside )
{
if( !aNeedMTV && inside )
return true;
for( int i = 0; i < 4; i++ )
{
const SEG seg( vts[i], vts[i + 1] );
ecoord dist_sq = seg.SquaredDistance( c );
if( dist_sq < min_dist_sq )
{
if( !aNeedMTV )
VECTOR2I pn = seg.NearestPoint( c );
int d = ( pn - c ).EuclideanNorm();
if( ( d < min_dist ) && !aNeedMTV )
return true;
else
if( d < nearest_seg_dist )
{
nearest = seg.NearestPoint( c );
nearest_seg_dist_sq = dist_sq;
}
}
nearest = pn;
nearest_seg_dist = d;
}
}
if( nearest_seg_dist_sq >= min_dist_sq && !inside )
if( nearest_seg_dist >= min_dist && !inside )
return false;
VECTOR2I delta = c - nearest;
......@@ -107,25 +107,77 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int a
if( !aNeedMTV )
return true;
if( inside )
aMTV = -delta.Resize( sqrt( abs( r * r + nearest_seg_dist_sq ) + 1 ) );
aMTV = -delta.Resize( abs( min_dist + 1 + nearest_seg_dist ) + 1 );
else
aMTV = delta.Resize( sqrt( abs( r * r - nearest_seg_dist_sq ) + 1 ) );
aMTV = delta.Resize( abs( min_dist + 1 - nearest_seg_dist ) + 1 );
return true;
}
static VECTOR2I pushoutForce( const SHAPE_CIRCLE& aA, const SEG& aB, int aClearance )
{
VECTOR2I nearest = aB.NearestPoint( aA.GetCenter() );
VECTOR2I f (0, 0);
int dist = ( nearest - aA.GetCenter() ).EuclideanNorm();
int min_dist = aClearance + aA.GetRadius();
if( dist < min_dist )
f = ( aA.GetCenter() - nearest ).Resize ( min_dist - dist + 10 );
return f;
}
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
bool found = false;
VECTOR2I::extended_type clSq = (VECTOR2I::extended_type) aClearance * aClearance;
for( int s = 0; s < aB.SegmentCount(); s++ )
{
if( aA.Collide( aB.CSegment( s ), aClearance ) )
return true;
{
found = true;
break;
}
}
return false;
if( !aNeedMTV || !found )
return found;
SHAPE_CIRCLE cmoved( aA );
VECTOR2I f_total( 0, 0 );
for( int s = 0; s < aB.SegmentCount(); s++ )
{
VECTOR2I f = pushoutForce( cmoved, aB.CSegment( s ), aClearance );
cmoved.SetCenter( cmoved.GetCenter() + f );
f_total += f;
}
aMTV = f_total;
return found;
}
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
bool col = aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2);
if( col && aNeedMTV )
{
aMTV = pushoutForce( aA, aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2);
}
return col;
}
......@@ -155,8 +207,39 @@ static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, in
}
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance,
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
return aA.Collide( aSeg.GetSeg(), aClearance + aSeg.GetWidth() / 2 );
}
static inline bool Collide( const SHAPE_SEGMENT& aA, const SHAPE_SEGMENT& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
return aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 );
}
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_SEGMENT& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
if( aA.Collide( aB.GetSeg(), aClearance + aB.GetWidth() / 2 ) )
return true;
return false;
}
template<class ShapeAType, class ShapeBType> bool
CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
return Collide (*static_cast<const ShapeAType*>( aA ),
*static_cast<const ShapeBType*>( aB ),
aClearance, aNeedMTV, aMTV);
}
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
switch( aA->Type() )
{
......@@ -164,63 +247,81 @@ bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance,
switch( aB->Type() )
{
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
break;
case SH_CIRCLE:
switch( aB->Type() )
{
case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_CIRCLE*>( aA ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_CIRCLE, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN *>( aB ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_CIRCLE, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
break;
case SH_LINE_CHAIN:
switch( aB->Type() )
{
case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_RECT, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_CIRCLE, SHAPE_LINE_CHAIN>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
return CollCase<SHAPE_LINE_CHAIN, SHAPE_LINE_CHAIN>( aA, aB, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
case SH_SEGMENT:
switch( aB->Type() )
{
case SH_RECT:
return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return CollCase<SHAPE_CIRCLE, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
case SH_SEGMENT:
return CollCase<SHAPE_SEGMENT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
default:
break;
}
default:
break;
}
assert( 0 ); // unsupported_collision
bool unsupported_collision = true;
assert( unsupported_collision == false );
return false;
}
......
......@@ -135,6 +135,9 @@ int SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const
{
int d = INT_MAX;
if( IsClosed() && PointInside( aP ) )
return 0;
for( int s = 0; s < SegmentCount(); s++ )
d = std::min( d, CSegment( s ).Distance( aP ) );
......@@ -179,7 +182,7 @@ int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
{
for( int s = 0; s< PointCount(); s++ )
for( int s = 0; s < PointCount(); s++ )
if( CPoint( s ) == aP )
return s;
......@@ -187,6 +190,16 @@ int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
}
int SHAPE_LINE_CHAIN::FindSegment( const VECTOR2I& aP ) const
{
for( int s = 0; s < SegmentCount(); s++ )
if( CSegment( s ).Distance( aP ) <= 1 )
return s;
return -1;
}
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
{
SHAPE_LINE_CHAIN rv;
......@@ -261,6 +274,9 @@ int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS&
if( a.Collinear( b ) )
{
is.our = a;
is.their = b;
if( a.Contains( b.A ) ) { is.p = b.A; aIp.push_back( is ); }
if( a.Contains( b.B ) ) { is.p = b.B; aIp.push_back( is ); }
if( b.Contains( a.A ) ) { is.p = a.A; aIp.push_back( is ); }
......@@ -282,44 +298,6 @@ int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS&
}
return aIp.size();
for( int s1 = 0; s1 < SegmentCount(); s1++ )
{
for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
{
const SEG& a = CSegment( s1 );
const SEG& b = aChain.CSegment( s2 );
OPT_VECTOR2I p = a.Intersect( b );
INTERSECTION is;
if( p )
{
is.p = *p;
is.our = a;
is.their = b;
aIp.push_back( is );
}
else if( a.Collinear( b ) )
{
if( a.A != b.A && a.A != b.B && b.Contains( a.A ) )
{
is.p = a.A;
is.our = a;
is.their = b;
aIp.push_back( is );
}
else if( a.B != b.A && a.B != b.B && b.Contains( a.B ) )
{
is.p = a.B;
is.our = a;
is.their = b;
aIp.push_back( is );
}
}
}
}
return aIp.size();
}
......@@ -372,10 +350,13 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
{
if( SegmentCount() < 1 )
if( !PointCount() )
return false;
else if( PointCount() == 1 )
return m_points[0] == aP;
for( int i = 1; i < SegmentCount(); i++ )
for( int i = 0; i < SegmentCount(); i++ )
{
const SEG s = CSegment( i );
......@@ -534,3 +515,30 @@ const std::string SHAPE_LINE_CHAIN::Format() const
return ss.str();
}
bool SHAPE_LINE_CHAIN::CompareGeometry ( const SHAPE_LINE_CHAIN & aOther ) const
{
SHAPE_LINE_CHAIN a(*this), b(aOther);
a.Simplify();
b.Simplify();
if(a.m_points.size() != b.m_points.size())
return false;
for(int i = 0; i < a.PointCount(); i++)
if(a.CPoint(i) != b.CPoint(i))
return false;
return true;
}
bool SHAPE_LINE_CHAIN::Intersects( const SHAPE_LINE_CHAIN& aChain ) const
{
INTERSECTIONS dummy;
return Intersect(aChain, dummy) != 0;
}
SHAPE* SHAPE_LINE_CHAIN::Clone() const
{
return new SHAPE_LINE_CHAIN( *this );
}
......@@ -50,6 +50,7 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
// action name without specifying at least toolName is not valid
assert( aAction->GetName().find( '.', 0 ) != std::string::npos );
// TOOL_ACTIONs must have unique names & ids
assert( m_actionNameIndex.find( aAction->m_name ) == m_actionNameIndex.end() );
assert( m_actionIdIndex.find( aAction->m_id ) == m_actionIdIndex.end() );
......@@ -60,6 +61,8 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
if( aAction->HasHotKey() )
m_actionHotKeys[aAction->m_currentHotKey].push_back( aAction );
aAction->setActionMgr( this );
}
......@@ -69,6 +72,7 @@ void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction )
m_actionIdIndex.erase( aAction->m_id );
// Indicate that the ACTION_MANAGER no longer care about the object
aAction->setActionMgr( NULL );
aAction->setId( -1 );
if( aAction->HasHotKey() )
......
......@@ -26,44 +26,55 @@
#include <tool/tool_manager.h>
#include <tool/tool_interactive.h>
#include <tool/context_menu.h>
#include <boost/bind.hpp>
#include <cassert>
CONTEXT_MENU::CONTEXT_MENU() :
m_titleSet( false ), m_selected( -1 ), m_handler( this ), m_tool( NULL )
m_titleSet( false ), m_selected( -1 ), m_tool( NULL )
{
m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler );
m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler );
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu );
m_menu.AddPendingEvent( menuEvent );
setCustomEventHandler( boost::bind( &CONTEXT_MENU::handleCustomEvent, this, _1 ) );
setupEvents();
}
CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_handler( this ), m_tool( aMenu.m_tool )
m_titleSet( aMenu.m_titleSet ), m_selected( -1 ), m_tool( aMenu.m_tool ),
m_toolActions( aMenu.m_toolActions ), m_customHandler( aMenu.m_customHandler )
{
m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler );
m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler );
// Copy all the menu entries
for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i )
{
wxMenuItem* item = aMenu.FindItemByPosition( i );
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu );
m_menu.AddPendingEvent( menuEvent );
if( item->IsSubMenu() )
{
#ifdef DEBUG
// Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well
assert( dynamic_cast<CONTEXT_MENU*>( item->GetSubMenu() ) );
#endif
// Copy all the menu entries
for( unsigned i = 0; i < aMenu.m_menu.GetMenuItemCount(); ++i )
CONTEXT_MENU* menu = new CONTEXT_MENU( static_cast<const CONTEXT_MENU&>( *item->GetSubMenu() ) );
AppendSubMenu( menu, item->GetItemLabel(), wxEmptyString );
}
else
{
wxMenuItem* item = aMenu.m_menu.FindItemByPosition( i );
m_menu.Append( new wxMenuItem( &m_menu, item->GetId(), item->GetItemLabel(),
wxEmptyString, wxITEM_NORMAL ) );
wxMenuItem* newItem = new wxMenuItem( this, item->GetId(), item->GetItemLabel(),
wxEmptyString, item->GetKind() );
Append( newItem );
copyItem( item, newItem );
}
}
// Copy tool actions that are available to choose from context menu
m_toolActions = aMenu.m_toolActions;
setupEvents();
}
void CONTEXT_MENU::setupEvents()
{
Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this );
Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this );
}
......@@ -71,15 +82,16 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle )
{
// TODO handle an empty string (remove title and separator)
// Unfortunately wxMenu::SetTitle() does nothing..
// Unfortunately wxMenu::SetTitle() does nothing.. (at least wxGTK)
if( m_titleSet )
{
m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle );
FindItemByPosition( 0 )->SetItemLabel( aTitle );
}
else
{
m_menu.InsertSeparator( 0 );
m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) );
InsertSeparator( 0 );
Insert( 0, new wxMenuItem( this, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) );
m_titleSet = true;
}
}
......@@ -89,11 +101,11 @@ void CONTEXT_MENU::Add( const wxString& aLabel, int aId )
{
#ifdef DEBUG
if( m_menu.FindItem( aId ) != NULL )
if( FindItem( aId ) != NULL )
wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in"
"undefined behaviour" ) );
#endif
m_menu.Append( new wxMenuItem( &m_menu, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) );
Append( new wxMenuItem( this, aId, aLabel, wxEmptyString, wxITEM_NORMAL ) );
}
......@@ -101,17 +113,29 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
{
/// ID numbers for tool actions need to have a value higher than m_actionId
int id = m_actionId + aAction.GetId();
wxString menuEntry;
wxMenuItem* item = new wxMenuItem( this, id,
wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 ),
wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL );
if( aAction.HasHotKey() )
menuEntry = wxString( ( aAction.GetMenuItem() + '\t' +
getHotKeyDescription( aAction ) ).c_str(), wxConvUTF8 );
else
menuEntry = wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 );
{
int key = aAction.GetHotKey() & ~MD_MODIFIER_MASK;
int mod = aAction.GetHotKey() & MD_MODIFIER_MASK;
int flags = wxACCEL_NORMAL;
m_menu.Append( new wxMenuItem( &m_menu, id, menuEntry,
wxString( aAction.GetDescription().c_str(), wxConvUTF8 ), wxITEM_NORMAL ) );
switch( mod )
{
case MD_ALT: flags = wxACCEL_ALT; break;
case MD_CTRL: flags = wxACCEL_CTRL; break;
case MD_SHIFT: flags = wxACCEL_SHIFT; break;
}
wxAcceleratorEntry accel( flags, key, id, item );
item->SetAccel( &accel );
}
Append( item );
m_toolActions[id] = &aAction;
}
......@@ -121,38 +145,17 @@ void CONTEXT_MENU::Clear()
m_titleSet = false;
// Remove all the entries from context menu
for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i )
m_menu.Destroy( m_menu.FindItemByPosition( 0 ) );
for( unsigned i = 0; i < GetMenuItemCount(); ++i )
Destroy( FindItemByPosition( 0 ) );
m_toolActions.clear();
}
std::string CONTEXT_MENU::getHotKeyDescription( const TOOL_ACTION& aAction ) const
void CONTEXT_MENU::onMenuEvent( wxEvent& aEvent )
{
int hotkey = aAction.GetHotKey();
std::string description = "";
if( hotkey & MD_ALT )
description += "ALT+";
if( hotkey & MD_CTRL )
description += "CTRL+";
if( hotkey & MD_SHIFT )
description += "SHIFT+";
// TODO dispatch keys such as Fx, TAB, PG_UP/DN, HOME, END, etc.
description += char( hotkey & ~MD_MODIFIER_MASK );
return description;
}
OPT_TOOL_EVENT evt;
void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
{
TOOL_EVENT evt;
wxEventType type = aEvent.GetEventType();
// When the currently chosen item in the menu is changed, an update event is issued.
......@@ -165,21 +168,42 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
else if( type == wxEVT_COMMAND_MENU_SELECTED )
{
// Store the selected position
m_menu->m_selected = aEvent.GetId();
m_selected = aEvent.GetId();
// Check if there is a TOOL_ACTION for the given ID
if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 )
if( m_toolActions.count( aEvent.GetId() ) == 1 )
{
evt = m_menu->m_toolActions[aEvent.GetId()]->MakeEvent();
evt = m_toolActions[aEvent.GetId()]->MakeEvent();
}
else
{
evt = m_customHandler( aEvent );
// Handling non-action menu entries (e.g. items in clarification list)
if( !evt )
evt = TOOL_EVENT( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, aEvent.GetId() );
}
}
assert( m_tool ); // without tool & tool manager we cannot handle events
// forward the action/update event to the TOOL_MANAGER
if( m_menu->m_tool )
m_menu->m_tool->GetManager()->ProcessEvent( evt );
if( evt && m_tool )
m_tool->GetManager()->ProcessEvent( *evt );
}
void CONTEXT_MENU::copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const
{
assert( !aSource->IsSubMenu() ); // it does not transfer submenus
aDest->SetKind( aSource->GetKind() );
aDest->SetHelp( aSource->GetHelp() );
aDest->Enable( aSource->IsEnabled() );
if( aSource->IsCheckable() )
aDest->Check( aSource->IsChecked() );
if( aSource->GetKind() == wxITEM_NORMAL )
aDest->SetBitmap( aSource->GetBitmap() );
}
......@@ -240,6 +240,13 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
evt->SetMousePosition( pos );
}
#ifdef __APPLE__
// TODO That's a big ugly workaround, somehow DRAWPANEL_GAL loses focus
// after second LMB click and currently I have no means to do better debugging
if( type == wxEVT_LEFT_UP )
m_editFrame->GetGalCanvas()->SetFocus();
#endif /* __APPLE__ */
}
// Keyboard handling
......
......@@ -103,14 +103,6 @@ TOOL_MANAGER::TOOL_MANAGER() :
TOOL_MANAGER::~TOOL_MANAGER()
{
DeleteAll();
delete m_actionMgr;
}
void TOOL_MANAGER::DeleteAll()
{
std::map<TOOL_BASE*, TOOL_STATE*>::iterator it, it_end;
......@@ -122,6 +114,7 @@ void TOOL_MANAGER::DeleteAll()
}
m_toolState.clear();
delete m_actionMgr;
}
......@@ -308,8 +301,6 @@ int TOOL_MANAGER::GetPriority( int aToolId ) const
for( std::deque<int>::const_iterator it = m_activeTools.begin(),
itEnd = m_activeTools.end(); it != itEnd; ++it )
{
std::cout << FindTool( *it )->GetName() << std::endl;
if( *it == aToolId )
return priority;
......@@ -497,7 +488,7 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
st->contextMenuTrigger = CMENU_OFF;
boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
GetEditFrame()->PopupMenu( menu->GetMenu() );
GetEditFrame()->PopupMenu( menu.get() );
// If nothing was chosen from the context menu, we must notify the tool as well
if( menu->GetSelected() < 0 )
......@@ -513,7 +504,6 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
if( m_view->IsDirty() )
{
PCB_EDIT_FRAME* f = static_cast<PCB_EDIT_FRAME*>( GetEditFrame() );
if( f->IsGalCanvasActive() )
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
}
......
......@@ -1019,3 +1019,38 @@ void VIEW::UpdateItems()
m_needsUpdate.clear();
}
struct VIEW::extentsVisitor {
BOX2I extents;
bool first;
extentsVisitor()
{
first = true;
}
bool operator()( VIEW_ITEM* aItem )
{
if(first)
extents = aItem->ViewBBox();
else
extents.Merge ( aItem->ViewBBox() );
return false;
}
};
const BOX2I VIEW::CalculateExtents()
{
extentsVisitor v;
BOX2I fullScene;
fullScene.SetMaximum();
BOOST_FOREACH( VIEW_LAYER* l, m_orderedLayers )
{
l->items->Query( fullScene, v );
}
return v.extents;
}
......@@ -160,12 +160,12 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
// Set scaling speed depending on scroll wheel event interval
if( timeDiff < 500 && timeDiff > 0 )
{
zoomScale = ( aEvent.GetWheelRotation() > 0.0 ) ? 2.05 - timeDiff / 500 :
zoomScale = ( aEvent.GetWheelRotation() > 0 ) ? 2.05 - timeDiff / 500 :
1.0 / ( 2.05 - timeDiff / 500 );
}
else
{
zoomScale = ( aEvent.GetWheelRotation() > 0.0 ) ? 1.05 : 0.95;
zoomScale = ( aEvent.GetWheelRotation() > 0 ) ? 1.05 : 0.95;
}
VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
......@@ -217,6 +217,11 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
{
case AUTO_PANNING:
{
#if wxCHECK_VERSION( 3, 0, 0 )
if( !m_parentPanel->HasFocus() )
break;
#endif
double borderSize = std::min( m_autoPanMargin * m_view->GetScreenPixelSize().x,
m_autoPanMargin * m_view->GetScreenPixelSize().y );
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "wxunittext.h"
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
#include <limits>
#include <base_units.h>
#if wxCHECK_VERSION( 2, 9, 0 )
#include <wx/valnum.h>
#endif
#include <boost/optional.hpp>
WX_UNIT_TEXT::WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel, double aValue, double aStep ) :
wxPanel( aParent, wxID_ANY ),
m_step( aStep )
{
// Use the currently selected units
m_units = g_UserUnit;
wxBoxSizer* sizer;
sizer = new wxBoxSizer( wxHORIZONTAL );
// Helper label
m_inputLabel = new wxStaticText( this, wxID_ANY, aLabel,
wxDefaultPosition, wxDefaultSize, 0 );
wxSize size = m_inputLabel->GetMinSize();
size.SetWidth( 150 );
m_inputLabel->SetMinSize( size );
sizer->Add( m_inputLabel, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
// Main input control
m_inputValue = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER );
SetValue( aValue );
sizer->Add( m_inputValue, 0, wxALIGN_CENTER_VERTICAL | wxALL );
#if wxCHECK_VERSION( 2, 9, 0 ) // Sorry guys, I am tired of dealing with 2.8 compatibility
wxFloatingPointValidator<double> validator( 4, NULL, wxNUM_VAL_NO_TRAILING_ZEROES );
validator.SetRange( 0.0, std::numeric_limits<double>::max() );
m_inputValue->SetValidator( validator );
// Spin buttons for modifying values using the mouse
m_spinButton = new wxSpinButton( this, wxID_ANY );
m_spinButton->SetRange( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
m_spinButton->SetCanFocus( false );
sizer->Add( m_spinButton, 0, wxALIGN_CENTER_VERTICAL | wxALL );
Connect( wxEVT_SPIN_UP, wxSpinEventHandler( WX_UNIT_TEXT::onSpinUpEvent ), NULL, this );
Connect( wxEVT_SPIN_DOWN, wxSpinEventHandler( WX_UNIT_TEXT::onSpinDownEvent ), NULL, this );
#endif
sizer->AddSpacer( 5 );
// Create units label
m_unitLabel = new wxStaticText( this, wxID_ANY, GetUnitsLabel( g_UserUnit ),
wxDefaultPosition, wxDefaultSize, 0 );
sizer->Add( m_unitLabel, 0, wxALIGN_CENTER_VERTICAL | wxALL );
SetSizer( sizer );
Layout();
}
WX_UNIT_TEXT::~WX_UNIT_TEXT()
{
}
void WX_UNIT_TEXT::SetUnits( EDA_UNITS_T aUnits, bool aConvert )
{
assert( !aConvert ); // TODO conversion does not work yet
m_unitLabel->SetLabel( GetUnitsLabel( g_UserUnit ) );
}
void WX_UNIT_TEXT::SetValue( double aValue )
{
if( aValue >= 0.0 )
{
m_inputValue->SetValue( wxString( Double2Str( aValue ).c_str(), wxConvUTF8 ) );
m_inputValue->MarkDirty();
}
else
{
m_inputValue->SetValue( DEFAULT_VALUE );
}
}
/*boost::optional<double> WX_UNIT_TEXT::GetValue( EDA_UNITS_T aUnit ) const
{
if( aUnit == m_units )
return GetValue(); // no conversion needed
switch( m_units )
{
case MILLIMETRES:
switch( aUnit )
{
case INCHES:
iu = Mils2iu( GetValue() * 1000.0 );
break;
case UNSCALED_UNITS:
iu = GetValue();
break;
}
break;
case INCHES:
switch( aUnit )
{
case MILLIMETRES:
return Mils2mm( GetValue() * 1000.0 );
break;
case UNSCALED_UNITS:
return Mils2iu( GetValue() * 1000.0 );
break;
}
break;
case UNSCALED_UNITS:
switch( aUnit )
{
case MILLIMETRES:
return Iu2Mils( GetValue() ) / 1000.0;
break;
// case INCHES:
// return
// break;
}
break;
}
assert( false ); // seems that there are some conversions missing
return 0.0;
}*/
boost::optional<double> WX_UNIT_TEXT::GetValue() const
{
wxString text = m_inputValue->GetValue();
double value;
if( text == DEFAULT_VALUE )
return boost::optional<double>( -1.0 );
if( !text.ToDouble( &value ) )
return boost::optional<double>();
return boost::optional<double>( value );
}
void WX_UNIT_TEXT::onSpinUpEvent( wxSpinEvent& aEvent )
{
SetValue( *GetValue() + m_step );
}
void WX_UNIT_TEXT::onSpinDownEvent( wxSpinEvent& aEvent )
{
double newValue = *GetValue() - m_step;
if( newValue >= 0.0 )
SetValue( newValue );
}
const wxString WX_UNIT_TEXT::DEFAULT_VALUE = _( "default ");
This diff is collapsed.
This diff is collapsed.
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* Copyright (C) 2013-2014 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
......@@ -111,9 +111,16 @@ public:
m_eventDispatcher = aEventDispatcher;
}
/**
* Function StartDrawing()
* Begins drawing if it was stopped previously.
*/
void StartDrawing();
/**
* Function StopDrawing()
* Prevents the GAL canvas from further drawing till it is recreated.
* Prevents the GAL canvas from further drawing till it is recreated
* or StartDrawing() is called.
*/
void StopDrawing();
......
......@@ -135,7 +135,7 @@ public:
virtual void Flush();
/// @copydoc GAL::ClearScreen()
virtual void ClearScreen();
virtual void ClearScreen( const COLOR4D& aColor );
// -----------------
// Attribute setting
......@@ -333,6 +333,7 @@ private:
unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image
int stride; ///< Stride value for Cairo
bool isInitialized; ///< Are Cairo image & surface ready to use
COLOR4D backgroundColor; ///< Background color
// Methods
void storePath(); ///< Store the actual path
......
......@@ -168,8 +168,11 @@ public:
/// @brief Force all remaining objects to be drawn.
virtual void Flush() = 0;
/// @brief Clear the screen.
virtual void ClearScreen() = 0;
/**
* @brief Clear the screen.
* @param aColor is the color used for clearing.
*/
virtual void ClearScreen( const COLOR4D& aColor ) = 0;
// -----------------
// Attribute setting
......@@ -225,16 +228,6 @@ public:
return strokeColor;
}
/**
* @brief Set the background color.
*
* @param aColor is the color for background filling.
*/
inline virtual void SetBackgroundColor( const COLOR4D& aColor )
{
backgroundColor = aColor;
}
/**
* @brief Set the line width.
*
......@@ -849,7 +842,6 @@ protected:
bool isFillEnabled; ///< Is filling of graphic objects enabled ?
bool isStrokeEnabled; ///< Are the outlines stroked ?
COLOR4D backgroundColor; ///< The background color
COLOR4D fillColor; ///< The fill color
COLOR4D strokeColor; ///< The color of the outlines
......
......@@ -143,7 +143,7 @@ public:
virtual void Flush();
/// @copydoc GAL::ClearScreen()
virtual void ClearScreen();
virtual void ClearScreen( const COLOR4D& aColor );
// --------------
// Transformation
......
......@@ -46,17 +46,14 @@ public:
* to an object the segment belongs to (e.g. a line chain) or references to locally stored
* points (m_a, m_b).
*/
VECTOR2I& A;
VECTOR2I& B;
VECTOR2I A;
VECTOR2I B;
/** Default constructor
* Creates an empty (0, 0) segment, locally-referenced
*/
SEG() : A( m_a ), B( m_b )
SEG()
{
A = m_a;
B = m_b;
m_is_local = true;
m_index = -1;
}
......@@ -64,13 +61,10 @@ public:
* Constructor
* Creates a segment between (aX1, aY1) and (aX2, aY2), locally referenced
*/
SEG( int aX1, int aY1, int aX2, int aY2 ) : A( m_a ), B( m_b )
SEG( int aX1, int aY1, int aX2, int aY2 ) :
A ( VECTOR2I( aX1, aY1 ) ),
B ( VECTOR2I( aX2, aY2 ) )
{
m_a = VECTOR2I( aX1, aY1 );
m_b = VECTOR2I( aX2, aY2 );
A = m_a;
B = m_b;
m_is_local = true;
m_index = -1;
}
......@@ -78,11 +72,8 @@ public:
* Constructor
* Creates a segment between (aA) and (aB), locally referenced
*/
SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : A( m_a ), B( m_b ), m_a( aA ), m_b( aB )
SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : A( aA ), B( aB )
{
A = m_a;
B = m_b;
m_is_local = true;
m_index = -1;
}
......@@ -93,43 +84,23 @@ public:
* @param aB reference to the end point in the parent shape
* @param aIndex index of the segment within the parent shape
*/
SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ) : A( aA ), B( aB )
SEG ( const VECTOR2I& aA, const VECTOR2I& aB, int aIndex ) : A( aA ), B( aB )
{
m_is_local = false;
m_index = aIndex;
}
/**
* Copy constructor
*/
SEG ( const SEG& aSeg ) : A( m_a ), B( m_b )
SEG ( const SEG& aSeg ) : A( aSeg.A ), B( aSeg.B ), m_index ( aSeg.m_index )
{
if( aSeg.m_is_local )
{
m_a = aSeg.m_a;
m_b = aSeg.m_b;
A = m_a;
B = m_b;
m_is_local = true;
m_index = -1;
}
else
{
A = aSeg.A;
B = aSeg.B;
m_index = aSeg.m_index;
m_is_local = false;
}
}
SEG& operator=( const SEG& aSeg )
{
A = aSeg.A;
B = aSeg.B;
m_a = aSeg.m_a;
m_b = aSeg.m_b;
m_index = aSeg.m_index;
m_is_local = aSeg.m_is_local;
return *this;
}
......@@ -244,14 +215,14 @@ public:
*/
bool Collinear( const SEG& aSeg ) const
{
ecoord qa = A.y - B.y;
ecoord qb = B.x - A.x;
ecoord qc = -qa * A.x - qb * A.y;
ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc );
ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc );
return ( d1 <= 1 && d2 <= 1 );
ecoord qa1 = A.y - B.y;
ecoord qb1 = B.x - A.x;
ecoord qc1 = -qa1 * A.x - qb1 * A.y;
ecoord qa2 = aSeg.A.y - aSeg.B.y;
ecoord qb2 = aSeg.B.x - aSeg.A.x;
ecoord qc2 = -qa2 * aSeg.A.x - qb2 * aSeg.A.y;
return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 );
}
/**
......@@ -289,14 +260,8 @@ public:
private:
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
///> locally stored start/end coordinates (used when m_is_local == true)
VECTOR2I m_a, m_b;
///> index withing the parent shape (used when m_is_local == false)
int m_index;
///> locality flag
bool m_is_local;
};
......@@ -344,8 +309,7 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg )
{
if( aSeg.m_is_local )
aStream << "[ local " << aSeg.A << " - " << aSeg.B << " ]";
aStream << "[ " << aSeg.A << " - " << aSeg.B << " ]";
return aStream;
}
......
......@@ -38,9 +38,20 @@ public:
SHAPE( SH_CIRCLE ), m_radius( aRadius ), m_center( aCenter )
{}
SHAPE_CIRCLE ( const SHAPE_CIRCLE& aOther ) :
SHAPE( SH_CIRCLE ),
m_radius( aOther.m_radius ),
m_center( aOther.m_center )
{};
~SHAPE_CIRCLE()
{}
SHAPE* Clone() const
{
return new SHAPE_CIRCLE( *this );
}
const BOX2I BBox( int aClearance = 0 ) const
{
const VECTOR2I rc( m_radius + aClearance, m_radius + aClearance );
......
......@@ -43,7 +43,7 @@
template <class T>
static const SHAPE* shapeFunctor( T aItem )
{
return aItem->GetShape();
return aItem->Shape();
}
......
......@@ -30,7 +30,7 @@
template <class T>
const SHAPE* defaultShapeFunctor( const T aItem )
{
return aItem->GetShape();
return aItem->Shape();
}
template <class T, const SHAPE* (ShapeFunctor) (const T) = defaultShapeFunctor<T> >
......
......@@ -116,6 +116,8 @@ public:
~SHAPE_LINE_CHAIN()
{}
SHAPE* Clone() const;
/**
* Function Clear()
* Removes all points from the line chain.
......@@ -366,6 +368,11 @@ public:
}
}
void Insert( int aVertex, const VECTOR2I& aP )
{
m_points.insert( m_points.begin() + aVertex, aP );
}
/**
* Function Replace()
*
......@@ -417,6 +424,15 @@ public:
*/
int Find( const VECTOR2I& aP ) const;
/**
* Function FindSegment()
*
* Searches for segment containing point aP.
* @param aP the point to be looked for
* @return index of the correspoinding segment in the line chain or negative when not found.
*/
int FindSegment( const VECTOR2I& aP ) const;
/**
* Function Slice()
*
......@@ -429,7 +445,7 @@ public:
struct compareOriginDistance
{
compareOriginDistance( VECTOR2I& aOrigin ):
compareOriginDistance( const VECTOR2I& aOrigin ):
m_origin( aOrigin )
{}
......@@ -441,6 +457,8 @@ public:
VECTOR2I m_origin;
};
bool Intersects( const SHAPE_LINE_CHAIN& aChain ) const;
/**
* Function Intersect()
*
......@@ -533,6 +551,8 @@ public:
return false;
}
bool CompareGeometry( const SHAPE_LINE_CHAIN & aOther ) const;
private:
/// array of vertices
std::vector<VECTOR2I> m_points;
......
......@@ -57,6 +57,18 @@ public:
SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH )
{}
SHAPE_RECT ( const SHAPE_RECT& aOther ) :
SHAPE( SH_RECT ),
m_p0( aOther.m_p0 ),
m_w( aOther.m_w ),
m_h( aOther.m_h )
{};
SHAPE* Clone() const
{
return new SHAPE_RECT( *this );
}
/// @copydoc SHAPE::BBox()
const BOX2I BBox( int aClearance = 0 ) const
{
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_SEGMENT_H
#define __SHAPE_SEGMENT_H
#include <geometry/shape.h>
#include <geometry/seg.h>
class SHAPE_SEGMENT : public SHAPE {
public:
SHAPE_SEGMENT():
SHAPE( SH_SEGMENT ), m_width( 0 ) {};
SHAPE_SEGMENT( const VECTOR2I& aA, const VECTOR2I& aB, int aWidth = 0 ):
SHAPE( SH_SEGMENT ), m_seg( aA, aB ), m_width( aWidth ) {};
SHAPE_SEGMENT( const SEG& aSeg, int aWidth = 0 ):
SHAPE( SH_SEGMENT ), m_seg( aSeg ), m_width( aWidth ) {};
~SHAPE_SEGMENT() {};
SHAPE* Clone() const
{
return new SHAPE_SEGMENT( m_seg, m_width );
}
const BOX2I BBox( int aClearance = 0 ) const
{
return BOX2I( m_seg.A, m_seg.B - m_seg.A ).Inflate( aClearance + m_width / 2 );
}
bool Collide( const SEG& aSeg, int aClearance = 0 ) const
{
return m_seg.Distance( aSeg ) <= m_width / 2 + aClearance;
}
bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const
{
return m_seg.Distance( aP ) <= m_width / 2 + aClearance;
}
void SetSeg ( const SEG& aSeg )
{
m_seg = aSeg;
}
const SEG& GetSeg () const
{
return m_seg;
}
void SetWidth ( int aWidth )
{
m_width = aWidth;
}
int GetWidth() const
{
return m_width;
}
private:
SEG m_seg;
int m_width;
};
#endif
......@@ -40,6 +40,11 @@ T rescale( T aNumerator, T aValue, T aDenominator )
return aNumerator * aValue / aDenominator;
}
template <typename T>
int sign( T val )
{
return ( T( 0 ) < val) - ( val < T( 0 ) );
}
// explicit specializations for integer types, taking care of overflow.
template <>
......
......@@ -28,6 +28,7 @@
#ifndef VECTOR2D_H_
#define VECTOR2D_H_
#include <cmath>
#include <climits>
#include <iostream>
#include <sstream>
......@@ -376,7 +377,7 @@ VECTOR2<T> VECTOR2<T>::Resize( T aNewLength ) const
return VECTOR2<T> (
( x < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) x * x, l_sq_current ) ),
( y < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) y * y, l_sq_current ) ) );
( y < 0 ? -1 : 1 ) * sqrt( rescale( l_sq_new, (extended_type) y * y, l_sq_current ) ) ) * sign( aNewLength );
}
......
......@@ -177,6 +177,36 @@ public:
return m_worksheetLineWidth;
}
/**
* Function TranslateColor
* Returns the color responding to the one of EDA_COLOR_T enum values.
* @param EDA_COLOR_T color equivalent.
*/
const COLOR4D& TranslateColor( EDA_COLOR_T aColor )
{
return m_legacyColorMap[aColor];
}
/**
* Function GetBackgroundColor
* Returns current background color settings.
* @return Background color.
*/
const COLOR4D& GetBackgroundColor() const
{
return m_backgroundColor;
}
/**
* Function SetBackgroundColor
* Sets new color for background.
* @param aColor is the new background color.
*/
void SetBackgroundColor( const COLOR4D& aColor )
{
m_backgroundColor = aColor;
}
protected:
/**
* Function update
......@@ -203,6 +233,8 @@ protected:
float m_outlineWidth; ///< Line width used when drawing outlines
float m_worksheetLineWidth; ///< Line width used when drawing worksheet
COLOR4D m_backgroundColor; ///< The background color
/// Map of colors that were usually used for display
std::map<EDA_COLOR_T, COLOR4D> m_legacyColorMap;
};
......
......@@ -28,6 +28,7 @@
#include <wx/menu.h>
#include <tool/tool_action.h>
#include <map>
#include <boost/function.hpp>
class TOOL_INTERACTIVE;
......@@ -37,7 +38,7 @@ class TOOL_INTERACTIVE;
* Defines the structure of a context (usually right-click) popup menu
* for a given tool.
*/
class CONTEXT_MENU
class CONTEXT_MENU : public wxMenu
{
public:
///> Default constructor
......@@ -71,6 +72,7 @@ public:
*/
void Add( const TOOL_ACTION& aAction );
/**
* Function Clear()
* Removes all the entries from the menu (as well as its title). It leaves the menu in the
......@@ -89,32 +91,29 @@ public:
return m_selected;
}
/**
* Function GetMenu()
* Returns the instance of wxMenu object used to display the menu.
*/
wxMenu* GetMenu() const
protected:
void setCustomEventHandler( boost::function<OPT_TOOL_EVENT(const wxEvent&)> aHandler )
{
return const_cast<wxMenu*>( &m_menu );
m_customHandler = aHandler;
}
private:
///> Class CMEventHandler takes care of handling menu events. After reception of particular
///> events, it translates them to TOOL_EVENTs that may control tools.
class CMEventHandler : public wxEvtHandler
virtual OPT_TOOL_EVENT handleCustomEvent(const wxEvent& aEvent )
{
public:
///> Default constructor
///> aMenu is the CONTEXT_MENU instance for which it handles events.
CMEventHandler( CONTEXT_MENU* aMenu ) : m_menu( aMenu ) {};
return OPT_TOOL_EVENT();
}
///> Handler for menu events.
void onEvent( wxEvent& aEvent );
private:
/**
* Function copyItem
* Copies all properties of a menu entry to another.
*/
void copyItem( const wxMenuItem* aSource, wxMenuItem* aDest ) const;
///> Initializes handlers for events.
void setupEvents();
private:
///> CONTEXT_MENU instance for which it handles events.
CONTEXT_MENU* m_menu;
};
///> Event handler.
void onMenuEvent( wxEvent& aEvent );
friend class TOOL_INTERACTIVE;
......@@ -128,25 +127,14 @@ private:
m_tool = aTool;
}
/**
* Function getHotKeyDescription()
* Returns a hot key in the string format accepted by wxMenu.
* @param aAction is the action with hot key to be translated..
* @return Hot key in the string format compatible with wxMenu.
*/
std::string getHotKeyDescription( const TOOL_ACTION& aAction ) const;
///> Flag indicating that the menu title was set up.
bool m_titleSet;
///> Instance of wxMenu used for display of the context menu.
wxMenu m_menu;
///> Stores the id number of selected item.
int m_selected;
///> Instance of menu event handler.
CMEventHandler m_handler;
//CMEventHandler m_handler;
///> Creator of the menu
TOOL_INTERACTIVE* m_tool;
......@@ -156,6 +144,9 @@ private:
/// Associates tool actions with menu item IDs. Non-owning.
std::map<int, const TOOL_ACTION*> m_toolActions;
/// Custom events handler, allows to translate wxEvents to TOOL_EVENTs.
boost::function<OPT_TOOL_EVENT(const wxEvent& aEvent)> m_customHandler;
};
#endif
......@@ -52,12 +52,12 @@ public:
m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ),
m_menuDescription( aMenuDesc ), m_id( -1 )
{
TOOL_MANAGER::Instance().RegisterAction( this );
TOOL_MANAGER::GetActionList().push_back( this );
}
~TOOL_ACTION()
{
TOOL_MANAGER::Instance().UnregisterAction( this );
TOOL_MANAGER::GetActionList().remove( this );
}
bool operator==( const TOOL_ACTION& aRhs ) const
......@@ -195,6 +195,12 @@ private:
m_id = aId;
}
/// Assigns ACTION_MANAGER object that handles the TOOL_ACTION.
void setActionMgr( ACTION_MANAGER* aManager )
{
m_actionMgr = aManager;
}
/// Name of the action (convention is: app.[tool.]action.name)
std::string m_name;
......@@ -219,11 +225,14 @@ private:
/// Unique ID for fast matching. Assigned by ACTION_MANAGER.
int m_id;
/// Action manager that handles this TOOL_ACTION.
ACTION_MANAGER* m_actionMgr;
/// Origin of the action
// const TOOL_BASE* m_origin;
// const TOOL_BASE* m_origin;
/// Originating UI object
// wxWindow* m_uiOrigin;
// wxWindow* m_uiOrigin;
};
#endif
......@@ -48,20 +48,10 @@ class wxWindow;
class TOOL_MANAGER
{
public:
static TOOL_MANAGER& Instance()
{
static TOOL_MANAGER manager;
return manager;
}
TOOL_MANAGER();
~TOOL_MANAGER();
/**
* Deletes all the tools that were registered in the TOOL_MANAGER.
*/
void DeleteAll();
/**
* Generates an unique ID from for a tool with given name.
*/
......@@ -251,9 +241,20 @@ public:
m_passEvent = true;
}
private:
TOOL_MANAGER();
/**
* Returns list of TOOL_ACTIONs. TOOL_ACTIONs add themselves to the list upon their
* creation.
* @return List of TOOL_ACTIONs.
*/
static std::list<TOOL_ACTION*>& GetActionList()
{
// TODO I am afraid this approach won't work when we reach multitab version of kicad.
static std::list<TOOL_ACTION*> actionList;
return actionList;
}
private:
struct TOOL_STATE;
typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;
......
......@@ -507,6 +507,8 @@ public:
*/
void UpdateItems();
const BOX2I CalculateExtents() ;
static const int VIEW_MAX_LAYERS = 128; ///< maximum number of layers that may be shown
private:
......@@ -534,6 +536,8 @@ private:
struct unlinkItem;
struct updateItemsColor;
struct changeItemsDepth;
struct extentsVisitor;
///* Redraws contents within rect aRect
void redrawRect( const BOX2I& aRect );
......
......@@ -90,7 +90,7 @@ protected:
/// main window.
wxAuiToolBar* m_auxiliaryToolBar;
TOOL_MANAGER& m_toolManager;
TOOL_MANAGER* m_toolManager;
TOOL_DISPATCHER* m_toolDispatcher;
void updateGridSelectBox();
......
......@@ -248,6 +248,7 @@ public:
void OnUpdateZoneDisplayStyle( wxUpdateUIEvent& aEvent );
void OnUpdateSelectTrackWidth( wxUpdateUIEvent& aEvent );
void OnUpdateSelectAutoTrackWidth( wxUpdateUIEvent& aEvent );
void OnUpdateSelectCustomTrackWidth( wxUpdateUIEvent& aEvent );
void OnUpdateAutoPlaceModulesMode( wxUpdateUIEvent& aEvent );
void OnUpdateAutoPlaceTracksMode( wxUpdateUIEvent& aEvent );
void OnUpdateMuWaveToolbar( wxUpdateUIEvent& aEvent );
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef WXUNITTEXT_H_
#define WXUNITTEXT_H_
#include <common.h>
#include <wx/spinbutt.h>
namespace boost
{
template <class T>
class optional;
}
class wxTextCtrl;
class wxSpinButton;
class wxStaticText;
class WX_UNIT_TEXT : public wxPanel
{
public:
/**
* Constructor.
* @param aParent is the parent window.
* @param aLabel is the label displayed next to the text input control.
* @param aValue is the initial value for the control.
* @param aStep is the step size when using spin buttons.
*/
WX_UNIT_TEXT( wxWindow* aParent, const wxString& aLabel = _( "Size:" ),
double aValue = 0.0, double aStep = 0.1 );
virtual ~WX_UNIT_TEXT();
/**
* Function SetUnits
* Changes the units used by the control.
* @param aUnits is the new unit to be used.
* @param aConvert decides if the current value should be converted to the value in new units
* or should it stay the same.
*/
void SetUnits( EDA_UNITS_T aUnits, bool aConvert = false );
/**
* Function SetValue
* Sets new value for the control.
* @param aValue is the new value.
*/
virtual void SetValue( double aValue );
/**
* Function GetValue
* Returns the current value using specified units (if currently used units are different, then
* they are converted first).
* @param aUnits is the wanted unit.
*/
//virtual double GetValue( EDA_UNITS_T aUnits ) const;
/**
* Function GetValue
* Returns the current value in currently used units.
*/
virtual boost::optional<double> GetValue() const;
/**
* Function GetUnits
* Returns currently used units.
*/
EDA_UNITS_T GetUnits() const
{
return m_units;
}
/**
* Function SetStep
* Sets the difference introduced by a single spin button click.
* @param aStep is new step size.
*/
void SetStep( double aStep )
{
assert( aStep > 0.0 );
m_step = aStep;
}
/**
* Function GetStep
* Returns the difference introduced by a single spin button click.
*/
double GetStep() const
{
return m_step;
}
protected:
///> Spin up button click event handler.
void onSpinUpEvent( wxSpinEvent& aEvent );
///> Spin down button click event handler.
void onSpinDownEvent( wxSpinEvent& aEvent );
///> Label for the input (e.g. "Size:")
wxStaticText* m_inputLabel;
///> Text input control.
wxTextCtrl* m_inputValue;
///> Spin buttons for changing the value using mouse.
wxSpinButton* m_spinButton;
///> Label showing currently used units.
wxStaticText* m_unitLabel;
///> Currently used units.
EDA_UNITS_T m_units;
///> Step size (added/subtracted difference if spin buttons are used).
double m_step;
///> Default value (or non-specified)
static const wxString DEFAULT_VALUE;
};
#endif /* WXUNITTEXT_H_ */
......@@ -97,6 +97,8 @@ set( PCBNEW_DIALOGS
dialogs/dialog_netlist_fbp.cpp
dialogs/dialog_pcb_text_properties.cpp
dialogs/dialog_pcb_text_properties_base.cpp
dialogs/dialog_pns_settings.cpp
dialogs/dialog_pns_settings_base.cpp
dialogs/dialog_non_copper_zones_properties_base.cpp
dialogs/dialog_pad_properties.cpp
dialogs/dialog_pad_properties_base.cpp
......@@ -115,6 +117,8 @@ set( PCBNEW_DIALOGS
dialogs/dialog_set_grid.cpp
dialogs/dialog_set_grid_base.cpp
dialogs/dialog_target_properties_base.cpp
dialogs/dialog_track_via_size.cpp
dialogs/dialog_track_via_size_base.cpp
footprint_wizard.cpp
footprint_wizard_frame.cpp
dialogs/dialog_footprint_wizard_list_base.cpp
......
......@@ -201,7 +201,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag )
LAYER_MSK layerMask;
// use the default NETCLASS?
NETCLASS* nc = aPcb->m_NetClasses.GetDefault();
NETCLASS* nc = aPcb->GetDesignSettings().GetDefault();
int trackWidth = nc->GetTrackWidth();
int clearance = nc->GetClearance();
......
......@@ -280,7 +280,7 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int aLayersCount )
m_canvas->SetAbortRequest( false );
s_Clearance = GetBoard()->m_NetClasses.GetDefault()->GetClearance();
s_Clearance = GetBoard()->GetDesignSettings().GetDefault()->GetClearance();
// Prepare the undo command info
s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but...
......@@ -428,7 +428,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe,
result = NOSUCCESS;
marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 );
marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );
/* clear direction flags */
i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL);
......@@ -1174,7 +1174,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row,
( RoutingMatrix.m_GridRouting * col )));
g_CurrentTrackSegment->SetEnd( g_CurrentTrackSegment->GetStart() );
g_CurrentTrackSegment->SetWidth( pcb->GetCurrentViaSize() );
g_CurrentTrackSegment->SetWidth( pcb->GetDesignSettings().GetCurrentViaSize() );
newVia->SetViaType( pcb->GetDesignSettings().m_CurrentViaType );
g_CurrentTrackSegment->SetNetCode( current_net_code );
......@@ -1233,7 +1233,7 @@ static void OrCell_Trace( BOARD* pcb, int col, int row,
}
}
g_CurrentTrackSegment->SetWidth( pcb->GetCurrentTrackWidth() );
g_CurrentTrackSegment->SetWidth( pcb->GetDesignSettings().GetCurrentTrackWidth() );
if( g_CurrentTrackSegment->GetStart() != g_CurrentTrackSegment->GetEnd() )
{
......@@ -1275,8 +1275,8 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
EDA_DRAW_PANEL* panel = pcbframe->GetCanvas();
PCB_SCREEN* screen = pcbframe->GetScreen();
marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 );
via_marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentViaSize() / 2 );
marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentTrackWidth() / 2 );
via_marge = s_Clearance + ( pcbframe->GetDesignSettings().GetCurrentViaSize() / 2 );
dx1 = g_CurrentTrackSegment->GetEnd().x - g_CurrentTrackSegment->GetStart().x;
dy1 = g_CurrentTrackSegment->GetEnd().y - g_CurrentTrackSegment->GetStart().y;
......
......@@ -133,10 +133,10 @@ END_EVENT_TABLE()
PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
long aStyle, const wxString & aFrameName ) :
EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ),
m_toolManager( TOOL_MANAGER::Instance() )
EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName )
{
m_Pcb = NULL;
m_toolManager = NULL;
m_toolDispatcher = NULL;
m_DisplayPadFill = true; // How to draw pads
......@@ -159,6 +159,9 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
this, -1, wxPoint( 0, 0 ), m_FrameSize,
EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) );
// GAL should not be active yet
GetGalCanvas()->StopDrawing();
// Hide by default, it has to be explicitly shown
GetGalCanvas()->Hide();
......@@ -832,7 +835,7 @@ void PCB_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
}
// Some more required layers settings
view->SetRequired( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( VIAS_VISIBLE ) );
view->SetRequired( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ) );
view->SetRequired( ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) );
view->SetRequired( NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) );
......
......@@ -637,7 +637,7 @@ void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& aEvent )
// Inform tools that undo command was issued
TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL );
m_toolManager.ProcessEvent( event );
m_toolManager->ProcessEvent( event );
/* Get the old list */
PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromUndoList();
......@@ -660,7 +660,7 @@ void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& aEvent )
// Inform tools that redo command was issued
TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL );
m_toolManager.ProcessEvent( event );
m_toolManager->ProcessEvent( event );
/* Get the old list */
PICKED_ITEMS_LIST* List = GetScreen()->PopCommandFromRedoList();
......
......@@ -66,8 +66,7 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD::BOARD() :
BOARD_ITEM( (BOARD_ITEM*) NULL, PCB_T ),
m_NetInfo( this ),
m_paper( PAGE_INFO::A4 ),
m_NetClasses( this )
m_paper( PAGE_INFO::A4 )
{
// we have not loaded a board yet, assume latest until then.
m_fileFormatVersionAtLoad = LEGACY_BOARD_FILE_VERSION;
......@@ -92,19 +91,18 @@ BOARD::BOARD() :
m_Layer[layer].m_Type = LT_UNDEFINED;
}
m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) );
NETCLASS* defaultClass = m_designSettings.GetDefault();
defaultClass->SetDescription( _( "This is the default net class." ) );
m_viaSizeIndex = 0;
m_trackWidthIndex = 0;
/* Dick 5-Feb-2012: this seems unnecessary. I don't believe the comment
near line 70 of class_netclass.cpp. I stepped through with debugger.
Perhaps something else is at work, it is not a constructor race.
// Initialize default values in default netclass.
*/
m_NetClasses.GetDefault()->SetParams();
defaultClass->SetParams( m_designSettings );
m_designSettings.SetCurrentNetClass( defaultClass->GetName() );
SetCurrentNetClass( m_NetClasses.GetDefault()->GetName() );
// Set sensible initial values for custom track width & via size
m_designSettings.UseCustomTrackViaSize( false );
m_designSettings.SetCustomTrackWidth( m_designSettings.GetCurrentTrackWidth() );
m_designSettings.SetCustomViaSize( m_designSettings.GetCurrentViaSize() );
m_designSettings.SetCustomViaDrill( m_designSettings.GetCurrentViaDrill() );
// Initialize ratsnest
m_ratsnest = new RN_DATA( this );
......@@ -313,100 +311,6 @@ void BOARD::PopHighLight()
}
bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
{
NETCLASS* netClass = m_NetClasses.Find( aNetClassName );
bool lists_sizes_modified = false;
// if not found (should not happen) use the default
if( netClass == NULL )
netClass = m_NetClasses.GetDefault();
m_currentNetClassName = netClass->GetName();
// Initialize others values:
if( m_ViasDimensionsList.size() == 0 )
{
VIA_DIMENSION viadim;
lists_sizes_modified = true;
m_ViasDimensionsList.push_back( viadim );
}
if( m_TrackWidthList.size() == 0 )
{
lists_sizes_modified = true;
m_TrackWidthList.push_back( 0 );
}
/* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values
* are always the Netclass values
*/
if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() )
lists_sizes_modified = true;
m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter();
if( m_TrackWidthList[0] != netClass->GetTrackWidth() )
lists_sizes_modified = true;
m_TrackWidthList[0] = netClass->GetTrackWidth();
if( m_viaSizeIndex >= m_ViasDimensionsList.size() )
m_viaSizeIndex = m_ViasDimensionsList.size();
if( m_trackWidthIndex >= m_TrackWidthList.size() )
m_trackWidthIndex = m_TrackWidthList.size();
return lists_sizes_modified;
}
int BOARD::GetBiggestClearanceValue()
{
int clearance = m_NetClasses.GetDefault()->GetClearance();
//Read list of Net Classes
for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
{
NETCLASS* netclass = nc->second;
clearance = std::max( clearance, netclass->GetClearance() );
}
return clearance;
}
int BOARD::GetSmallestClearanceValue()
{
int clearance = m_NetClasses.GetDefault()->GetClearance();
//Read list of Net Classes
for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
{
NETCLASS* netclass = nc->second;
clearance = std::min( clearance, netclass->GetClearance() );
}
return clearance;
}
int BOARD::GetCurrentMicroViaSize()
{
NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
return netclass->GetuViaDiameter();
}
int BOARD::GetCurrentMicroViaDrill()
{
NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
return netclass->GetuViaDrill();
}
bool BOARD::SetLayer( LAYER_NUM aIndex, const LAYER& aLayer )
{
if( aIndex < NB_COPPER_LAYERS )
......@@ -2194,24 +2098,6 @@ TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment, PICKED_ITEMS
}
void BOARD::SetViaSizeIndex( unsigned aIndex )
{
if( aIndex >= m_ViasDimensionsList.size() )
m_viaSizeIndex = m_ViasDimensionsList.size();
else
m_viaSizeIndex = aIndex;
}
void BOARD::SetTrackWidthIndex( unsigned aIndex )
{
if( aIndex >= m_TrackWidthList.size() )
m_trackWidthIndex = m_TrackWidthList.size();
else
m_trackWidthIndex = aIndex;
}
ZONE_CONTAINER* BOARD::AddArea( PICKED_ITEMS_LIST* aNewZonesList, int aNetcode,
LAYER_NUM aLayer, wxPoint aStartPointPosition, int aHatch )
{
......
......@@ -111,8 +111,6 @@ public:
/** The type of the layer */
LAYER_T m_Type;
// int m_Color;
/**
* Function ShowType
* converts a LAYER_T enum to a const char*
......@@ -136,52 +134,15 @@ private:
};
/**
* Struct VIA_DIMENSION
* is a small helper container to handle a stock of specific vias each with
* unique diameter and drill sizes in the BOARD class.
*/
struct VIA_DIMENSION
{
int m_Diameter; // <= 0 means use Netclass via diameter
int m_Drill; // <= 0 means use Netclass via drill
VIA_DIMENSION()
{
m_Diameter = 0;
m_Drill = 0;
}
VIA_DIMENSION( int aDiameter, int aDrill )
{
m_Diameter = aDiameter;
m_Drill = aDrill;
}
bool operator == ( const VIA_DIMENSION& other ) const
{
return (m_Diameter == other.m_Diameter) && (m_Drill == other.m_Drill);
}
bool operator < ( const VIA_DIMENSION& other ) const
{
if( m_Diameter != other.m_Diameter )
return m_Diameter < other.m_Diameter;
return m_Drill < other.m_Drill;
}
};
// Helper class to handle high light nets
class HIGH_LIGHT_INFO
{
friend class BOARD;
protected:
int m_netCode; // net selected for highlight (-1 when no net selected )
bool m_highLightOn; // highlight active
protected:
void Clear()
{
m_netCode = -1;
......@@ -247,17 +208,6 @@ private:
/// Number of unconnected nets in the current rats nest.
int m_unconnectedNetCount;
/// Current net class name used to display netclass info.
/// This is also the last used netclass after starting a track.
wxString m_currentNetClassName;
/// Index for #m_ViasDimensionsList to select the current via size.
/// 0 is the index selection of the default value Netclass
unsigned m_viaSizeIndex;
// Index for m_TrackWidthList to select the value.
unsigned m_trackWidthIndex;
/**
* Function chainMarkedSegments
* is used by MarkTrace() to set the BUSY flag of connected segments of the trace
......@@ -269,10 +219,6 @@ private:
*/
void chainMarkedSegments( wxPoint aPosition, LAYER_MSK aLayerMask, TRACK_PTRS* aList );
void formatNetClass( NETCLASS* aNetClass, OUTPUTFORMATTER* aFormatter, int aNestLevel,
int aControlBits ) const
throw( IO_ERROR );
public:
void SetFileName( const wxString& aFileName ) { m_fileName = aFileName; }
......@@ -296,22 +242,6 @@ public:
/// zone contour currently in progress
ZONE_CONTAINER* m_CurrentZoneContour;
/// List of current netclasses. There is always the default netclass.
NETCLASSES m_NetClasses;
// handling of vias and tracks size:
// the first value is always the value of the current NetClass
// The others values are extra values
// The first value is the current netclass via size // TODO verify
/// Vias size and drill list
std::vector<VIA_DIMENSION> m_ViasDimensionsList;
// The first value is the current netclass track width // TODO verify
/// Track width list
std::vector<int> m_TrackWidthList;
BOARD();
~BOARD();
......@@ -639,7 +569,10 @@ public:
* Function SetDesignSettings
* @param aDesignSettings the new BOARD_DESIGN_SETTINGS to use
*/
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aDesignSettings ) { m_designSettings = aDesignSettings; }
void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aDesignSettings )
{
m_designSettings = aDesignSettings;
}
const PAGE_INFO& GetPageSettings() const { return m_paper; }
void SetPageSettings( const PAGE_INFO& aPageSettings ) { m_paper = aPageSettings; }
......@@ -685,6 +618,19 @@ public:
CPOLYGONS_LIST& aHoles,
wxString* aErrorText = NULL );
/**
* Function ConvertBrdLayerToPolygonalContours
* Build a set of polygons which are the outlines of copper items
* (pads, tracks, vias, texts, zones)
* Holes in vias or pads are ignored
* Usefull to export the shape of copper layers to dxf polygons
* or 3D viewer
* the polygons are not merged.
* @param aLayer = A copper layer, like LAYER_N_BACK, etc.
* @param aOutlines The CPOLYGONS_LIST to fill in with items outline.
*/
void ConvertBrdLayerToPolygonalContours( LAYER_NUM aLayer, CPOLYGONS_LIST& aOutlines );
/**
* Function GetLayerName
* returns the name of a layer given by aLayer. Copper layers may
......@@ -770,7 +716,6 @@ public:
return m_FullRatsnest.size();
}
/**
* Function GetNodesCount
* @return the number of pads members of nets (i.e. with netcode > 0)
......@@ -799,20 +744,6 @@ public:
*/
void SetUnconnectedNetCount( unsigned aCount ) { m_unconnectedNetCount = aCount; }
/**
* Function SetCurrentNetClassName
* sets the current net class name to \a aName.
*
* @param aName is a reference to a wxString object containing the current net class name.
*/
void SetCurrentNetClassName( const wxString& aName ) { m_currentNetClassName = aName; }
/**
* Function GetCurrentNetClassName
* @return the current net class name.
*/
const wxString& GetCurrentNetClassName() const { return m_currentNetClassName; }
/**
* Function GetPadCount
* @return the number of pads in board
......@@ -1021,11 +952,6 @@ public:
*/
int SortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount );
/**************************************/
/**
* Function relative to NetClasses: **/
/**************************************/
/**
* Function SynchronizeNetsAndNetClasses
* copies NETCLASS info to each NET, based on NET membership in a NETCLASS.
......@@ -1035,104 +961,6 @@ public:
*/
void SynchronizeNetsAndNetClasses();
/**
* Function SetCurrentNetClass
* Must be called after a netclass selection (or after a netclass parameter change
* Initialize vias and tracks values displayed in comb boxes of the auxiliary toolbar
* and some others parameters (netclass name ....)
* @param aNetClassName = the new netclass name
* @return true if lists of tracks and vias sizes are modified
*/
bool SetCurrentNetClass( const wxString& aNetClassName );
/**
* Function GetBiggestClearanceValue
* @return the biggest clearance value found in NetClasses list
*/
int GetBiggestClearanceValue();
/**
* Function GetSmallestClearanceValue
* @return the smallest clearance value found in NetClasses list
*/
int GetSmallestClearanceValue();
/**
* Function GetTrackWidthIndex
* @return the current track width list index.
*/
unsigned GetTrackWidthIndex() const { return m_trackWidthIndex; }
/**
* Function SetTrackWidthIndex
* sets the current track width list index to \a aIndex.
*
* @param aIndex is the track width list index.
*/
void SetTrackWidthIndex( unsigned aIndex );
/**
* Function GetCurrentTrackWidth
* @return the current track width, according to the selected options
* ( using the default netclass value or a preset value )
* the default netclass is always in m_TrackWidthList[0]
*/
int GetCurrentTrackWidth() const
{
return m_TrackWidthList[m_trackWidthIndex];
}
/**
* Function GetViaSizeIndex
* @return the current via size list index.
*/
unsigned GetViaSizeIndex() const { return m_viaSizeIndex; }
/**
* Function SetViaSizeIndex
* sets the current via size list index to \a aIndex.
*
* @param aIndex is the via size list index.
*/
void SetViaSizeIndex( unsigned aIndex );
/**
* Function GetCurrentViaSize
* @return the current via size, according to the selected options
* ( using the default netclass value or a preset value )
* the default netclass is always in m_TrackWidthList[0]
*/
int GetCurrentViaSize()
{
return m_ViasDimensionsList[m_viaSizeIndex].m_Diameter;
}
/**
* Function GetCurrentViaDrill
* @return the current via size, according to the selected options
* ( using the default netclass value or a preset value )
* the default netclass is always in m_TrackWidthList[0]
*/
int GetCurrentViaDrill()
{
return m_ViasDimensionsList[m_viaSizeIndex].m_Drill > 0 ?
m_ViasDimensionsList[m_viaSizeIndex].m_Drill : -1;
}
/**
* Function GetCurrentMicroViaSize
* @return the current micro via size,
* that is the current netclass value
*/
int GetCurrentMicroViaSize();
/**
* Function GetCurrentMicroViaDrill
* @return the current micro via drill,
* that is the current netclass value
*/
int GetCurrentMicroViaDrill();
/***************************************************************************/
wxString GetClass() const
......
......@@ -144,7 +144,7 @@ NETCLASS* BOARD_CONNECTED_ITEM::GetNetClass() const
if( netclass )
return netclass;
else
return board->m_NetClasses.GetDefault();
return board->GetDesignSettings().GetDefault();
}
......@@ -158,7 +158,7 @@ wxString BOARD_CONNECTED_ITEM::GetNetClassName() const
else
{
BOARD* board = GetBoard();
name = board->m_NetClasses.GetDefault()->GetName();
name = NETCLASS::Default;
}
return name;
......
......@@ -54,13 +54,13 @@
BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
m_Pad_Master( NULL )
{
m_EnabledLayers = ALL_LAYERS; // All layers enabled at first.
m_enabledLayers = ALL_LAYERS; // All layers enabled at first.
// SetCopperLayerCount() will adjust this.
SetVisibleLayers( FULL_LAYERS );
// set all but hidden text as visible.
m_VisibleElements = ~( 1 << MOD_TEXT_INVISIBLE );
m_visibleElements = ~( 1 << MOD_TEXT_INVISIBLE );
SetCopperLayerCount( 2 ); // Default design is a double sided board
......@@ -81,7 +81,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
m_PcbTextSize = wxSize( DEFAULT_TEXT_PCB_SIZE,
DEFAULT_TEXT_PCB_SIZE ); // current Pcb (not module) Text size
m_TrackMinWidth = DMils2iu( 100 ); // track min value for width ((min copper size value
m_TrackMinWidth = DMils2iu( 100 ); // track min value for width (min copper size value)
m_ViasMinSize = DMils2iu( 350 ); // vias (not micro vias) min diameter
m_ViasMinDrill = DMils2iu( 200 ); // vias (not micro vias) min drill diameter
m_MicroViasMinSize = DMils2iu( 200 ); // micro vias (not vias) min diameter
......@@ -102,6 +102,9 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
// Layer thickness for 3D viewer
m_boardThickness = Millimeter2iu( DEFAULT_BOARD_THICKNESS_MM );
m_viaSizeIndex = 0;
m_trackWidthIndex = 0;
}
// Add parameters to save in project config.
......@@ -171,32 +174,144 @@ void BOARD_DESIGN_SETTINGS::AppendConfigs( PARAM_CFG_ARRAY* aResult )
}
// see pcbstruct.h
LAYER_MSK BOARD_DESIGN_SETTINGS::GetVisibleLayers() const
bool BOARD_DESIGN_SETTINGS::SetCurrentNetClass( const wxString& aNetClassName )
{
NETCLASS* netClass = m_NetClasses.Find( aNetClassName );
bool lists_sizes_modified = false;
// if not found (should not happen) use the default
if( netClass == NULL )
netClass = m_NetClasses.GetDefault();
m_currentNetClassName = netClass->GetName();
// Initialize others values:
if( m_ViasDimensionsList.size() == 0 )
{
VIA_DIMENSION viadim;
lists_sizes_modified = true;
m_ViasDimensionsList.push_back( viadim );
}
if( m_TrackWidthList.size() == 0 )
{
lists_sizes_modified = true;
m_TrackWidthList.push_back( 0 );
}
/* note the m_ViasDimensionsList[0] and m_TrackWidthList[0] values
* are always the Netclass values
*/
if( m_ViasDimensionsList[0].m_Diameter != netClass->GetViaDiameter() )
lists_sizes_modified = true;
m_ViasDimensionsList[0].m_Diameter = netClass->GetViaDiameter();
if( m_TrackWidthList[0] != netClass->GetTrackWidth() )
lists_sizes_modified = true;
m_TrackWidthList[0] = netClass->GetTrackWidth();
if( GetViaSizeIndex() >= m_ViasDimensionsList.size() )
SetViaSizeIndex( m_ViasDimensionsList.size() );
if( GetTrackWidthIndex() >= m_TrackWidthList.size() )
SetTrackWidthIndex( m_TrackWidthList.size() );
return lists_sizes_modified;
}
int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue()
{
return m_VisibleLayers;
int clearance = m_NetClasses.GetDefault()->GetClearance();
//Read list of Net Classes
for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
{
NETCLASS* netclass = nc->second;
clearance = std::max( clearance, netclass->GetClearance() );
}
return clearance;
}
void BOARD_DESIGN_SETTINGS::SetVisibleAlls()
int BOARD_DESIGN_SETTINGS::GetSmallestClearanceValue()
{
SetVisibleLayers( FULL_LAYERS );
m_VisibleElements = -1;
int clearance = m_NetClasses.GetDefault()->GetClearance();
//Read list of Net Classes
for( NETCLASSES::const_iterator nc = m_NetClasses.begin(); nc != m_NetClasses.end(); nc++ )
{
NETCLASS* netclass = nc->second;
clearance = std::min( clearance, netclass->GetClearance() );
}
return clearance;
}
int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaSize()
{
NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
return netclass->GetuViaDiameter();
}
int BOARD_DESIGN_SETTINGS::GetCurrentMicroViaDrill()
{
NETCLASS* netclass = m_NetClasses.Find( m_currentNetClassName );
return netclass->GetuViaDrill();
}
void BOARD_DESIGN_SETTINGS::SetViaSizeIndex( unsigned aIndex )
{
if( aIndex >= m_ViasDimensionsList.size() )
m_viaSizeIndex = m_ViasDimensionsList.size();
else
m_viaSizeIndex = aIndex;
}
void BOARD_DESIGN_SETTINGS::SetVisibleLayers( LAYER_MSK aMask )
int BOARD_DESIGN_SETTINGS::GetCurrentViaDrill() const
{
m_VisibleLayers = aMask & m_EnabledLayers & FULL_LAYERS;
int drill;
if( m_useCustomTrackVia )
drill = m_customViaSize.m_Drill;
else
drill = m_ViasDimensionsList[m_viaSizeIndex].m_Drill;
return drill > 0 ? drill : -1;
}
void BOARD_DESIGN_SETTINGS::SetTrackWidthIndex( unsigned aIndex )
{
if( aIndex >= m_TrackWidthList.size() )
m_trackWidthIndex = m_TrackWidthList.size();
else
m_trackWidthIndex = aIndex;
}
void BOARD_DESIGN_SETTINGS::SetVisibleAlls()
{
SetVisibleLayers( FULL_LAYERS );
m_visibleElements = -1;
}
void BOARD_DESIGN_SETTINGS::SetLayerVisibility( LAYER_NUM aLayer, bool aNewState )
{
if( aNewState && IsLayerEnabled( aLayer ) )
m_VisibleLayers |= GetLayerMask( aLayer );
m_visibleLayers |= GetLayerMask( aLayer );
else
m_VisibleLayers &= ~GetLayerMask( aLayer );
m_visibleLayers &= ~GetLayerMask( aLayer );
}
......@@ -206,9 +321,9 @@ void BOARD_DESIGN_SETTINGS::SetElementVisibility( int aElementCategory, bool aNe
return;
if( aNewState )
m_VisibleElements |= 1 << aElementCategory;
m_visibleElements |= 1 << aElementCategory;
else
m_VisibleElements &= ~( 1 << aElementCategory );
m_visibleElements &= ~( 1 << aElementCategory );
}
......@@ -216,17 +331,17 @@ void BOARD_DESIGN_SETTINGS::SetCopperLayerCount( int aNewLayerCount )
{
// if( aNewLayerCount < 2 ) aNewLayerCount = 2;
m_CopperLayerCount = aNewLayerCount;
m_copperLayerCount = aNewLayerCount;
// ensure consistency with the m_EnabledLayers member
m_EnabledLayers &= ~ALL_CU_LAYERS;
m_EnabledLayers |= LAYER_BACK;
m_enabledLayers &= ~ALL_CU_LAYERS;
m_enabledLayers |= LAYER_BACK;
if( m_CopperLayerCount > 1 )
m_EnabledLayers |= LAYER_FRONT;
if( m_copperLayerCount > 1 )
m_enabledLayers |= LAYER_FRONT;
for( LAYER_NUM ii = LAYER_N_2; ii < aNewLayerCount - 1; ++ii )
m_EnabledLayers |= GetLayerMask( ii );
m_enabledLayers |= GetLayerMask( ii );
}
......@@ -235,13 +350,13 @@ void BOARD_DESIGN_SETTINGS::SetEnabledLayers( LAYER_MSK aMask )
// Back and front layers are always enabled.
aMask |= LAYER_BACK | LAYER_FRONT;
m_EnabledLayers = aMask;
m_enabledLayers = aMask;
// A disabled layer cannot be visible
m_VisibleLayers &= aMask;
m_visibleLayers &= aMask;
// update m_CopperLayerCount to ensure its consistency with m_EnabledLayers
m_CopperLayerCount = LayerMaskCountSet( aMask & ALL_CU_LAYERS);
m_copperLayerCount = LayerMaskCountSet( aMask & ALL_CU_LAYERS);
}
......
......@@ -447,7 +447,7 @@ const EDA_RECT MODULE::GetBoundingBox() const
// Add the Clearance shape size: (shape around the pads when the
// clearance is shown. Not optimized, but the draw cost is small
// (perhaps smaller than optimization).
int biggest_clearance = GetBoard()->GetBiggestClearanceValue();
int biggest_clearance = GetBoard()->GetDesignSettings().GetBiggestClearanceValue();
area.Inflate( biggest_clearance );
return area;
......
......@@ -39,59 +39,43 @@
const wxChar NETCLASS::Default[] = wxT( "Default" );
// Initial values for netclass initialization
int NETCLASS::DEFAULT_CLEARANCE = DMils2iu( 100 ); // track to track and track to pads clearance
int NETCLASS::DEFAULT_VIA_DRILL = DMils2iu( 250 ); // default via drill
int NETCLASS::DEFAULT_UVIA_DRILL = DMils2iu( 50 ); // micro via drill
const int NETCLASS::DEFAULT_CLEARANCE = DMils2iu( 100 ); // track to track and track to pads clearance
const int NETCLASS::DEFAULT_VIA_DRILL = DMils2iu( 250 ); // default via drill
const int NETCLASS::DEFAULT_UVIA_DRILL = DMils2iu( 50 ); // micro via drill
NETCLASS::NETCLASS( BOARD* aParent, const wxString& aName, const NETCLASS* initialParameters ) :
m_Parent( aParent ),
NETCLASS::NETCLASS( const wxString& aName ) :
m_Name( aName )
{
// use initialParameters if not NULL, else set the initial
// parameters from boardDesignSettings (try to change this)
SetParams( initialParameters );
// Default settings
SetClearance( DEFAULT_CLEARANCE );
SetViaDrill( DEFAULT_VIA_DRILL );
SetuViaDrill( DEFAULT_UVIA_DRILL );
}
void NETCLASS::SetParams( const NETCLASS* defaults )
void NETCLASS::SetParams( const NETCLASS& aDefaults )
{
if( defaults )
{
SetClearance( defaults->GetClearance() );
SetTrackWidth( defaults->GetTrackWidth() );
SetViaDiameter( defaults->GetViaDiameter() );
SetViaDrill( defaults->GetViaDrill() );
SetuViaDiameter( defaults->GetuViaDiameter() );
SetuViaDrill( defaults->GetuViaDrill() );
}
else
{
/* Dick 5-Feb-2012: I do not believe this comment to be true with current code.
It is certainly not a constructor race. Normally items are initialized
within a class according to the order of their appearance.
// Note:
// We use m_Parent->GetDesignSettings() to get some default values
// But when this function is called when instantiating a BOARD class,
// by the NETCLASSES constructor that calls NETCLASS constructor,
// the BOARD constructor (see BOARD::BOARD) is not yet run,
// and BOARD::m_designSettings contains not yet initialized values.
// So inside the BOARD constructor itself, you SHOULD recall SetParams
*/
SetClearance( aDefaults.GetClearance() );
SetTrackWidth( aDefaults.GetTrackWidth() );
SetViaDiameter( aDefaults.GetViaDiameter() );
SetViaDrill( aDefaults.GetViaDrill() );
SetuViaDiameter( aDefaults.GetuViaDiameter() );
SetuViaDrill( aDefaults.GetuViaDrill() );
}
const BOARD_DESIGN_SETTINGS& g = m_Parent->GetDesignSettings();
SetTrackWidth( g.m_TrackMinWidth );
SetViaDiameter( g.m_ViasMinSize );
SetuViaDiameter( g.m_MicroViasMinSize );
void NETCLASS::SetParams( const BOARD_DESIGN_SETTINGS& aSettings )
{
SetTrackWidth( aSettings.m_TrackMinWidth );
SetViaDiameter( aSettings.m_ViasMinSize );
SetuViaDiameter( aSettings.m_MicroViasMinSize );
// TODO: BOARD_DESIGN_SETTINGS may provide the following parameters - should it?
// Use default values for next parameters:
SetClearance( DEFAULT_CLEARANCE );
SetViaDrill( DEFAULT_VIA_DRILL );
SetuViaDrill( DEFAULT_UVIA_DRILL );
}
}
......@@ -100,9 +84,8 @@ NETCLASS::~NETCLASS()
}
NETCLASSES::NETCLASSES( BOARD* aParent ) :
m_Parent( aParent ),
m_Default( aParent, NETCLASS::Default )
NETCLASSES::NETCLASSES() :
m_Default( NETCLASS::Default )
{
}
......@@ -198,7 +181,7 @@ NETCLASS* NETCLASSES::Find( const wxString& aName ) const
void BOARD::SynchronizeNetsAndNetClasses()
{
// D(printf("start\n");) // simple performance/timing indicator.
NETCLASSES& netClasses = m_designSettings.m_NetClasses;
// set all NETs to the default NETCLASS, then later override some
// as we go through the NETCLASSes.
......@@ -206,17 +189,17 @@ void BOARD::SynchronizeNetsAndNetClasses()
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
{
net->SetClass( m_NetClasses.GetDefault() );
net->SetClass( netClasses.GetDefault() );
}
// Add netclass name and pointer to nets. If a net is in more than one netclass,
// set the net's name and pointer to only the first netclass. Subsequent
// and therefore bogus netclass memberships will be deleted in logic below this loop.
for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz )
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASS* netclass = clazz->second;
for( NETCLASS::iterator member = netclass->begin(); member!=netclass->end(); ++member )
for( NETCLASS::iterator member = netclass->begin(); member != netclass->end(); ++member )
{
const wxString& netname = *member;
......@@ -237,14 +220,14 @@ void BOARD::SynchronizeNetsAndNetClasses()
// contain netnames that do not exist, by deleting all netnames from
// every netclass and re-adding them.
for( NETCLASSES::iterator clazz=m_NetClasses.begin(); clazz!=m_NetClasses.end(); ++clazz )
for( NETCLASSES::iterator clazz = netClasses.begin(); clazz != netClasses.end(); ++clazz )
{
NETCLASS* netclass = clazz->second;
netclass->Clear();
}
m_NetClasses.GetDefault()->Clear();
netClasses.GetDefault()->Clear();
for( NETINFO_LIST::iterator net( m_NetInfo.begin() ), netEnd( m_NetInfo.end() );
net != netEnd; ++net )
......@@ -253,14 +236,12 @@ void BOARD::SynchronizeNetsAndNetClasses()
// because of the std:map<> this should be fast, and because of
// prior logic, netclass should not be NULL.
NETCLASS* netclass = m_NetClasses.Find( classname );
NETCLASS* netclass = netClasses.Find( classname );
wxASSERT( netclass );
netclass->Add( net->GetNetname() );
}
// D(printf("stop\n");)
}
......@@ -286,36 +267,6 @@ void NETCLASS::Show( int nestLevel, std::ostream& os ) const
#endif
int NETCLASS::GetTrackMinWidth() const
{
return m_Parent->GetDesignSettings().m_TrackMinWidth;
}
int NETCLASS::GetViaMinDiameter() const
{
return m_Parent->GetDesignSettings().m_ViasMinSize;
}
int NETCLASS::GetViaMinDrill() const
{
return m_Parent->GetDesignSettings().m_ViasMinDrill;
}
int NETCLASS::GetuViaMinDiameter() const
{
return m_Parent->GetDesignSettings().m_MicroViasMinSize;
}
int NETCLASS::GetuViaMinDrill() const
{
return m_Parent->GetDesignSettings().m_MicroViasMinDrill;
}
void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR )
{
......@@ -333,14 +284,7 @@ void NETCLASS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControl
aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n", FMT_IU( GetuViaDrill() ).c_str() );
for( NETCLASS::const_iterator it = begin(); it != end(); ++it )
{
NETINFO_ITEM* netinfo = m_Parent->FindNet( *it );
if( netinfo && netinfo->GetNodesCount() > 0 )
{
aFormatter->Print( aNestLevel+1, "(add_net %s)\n", aFormatter->Quotew( *it ).c_str() );
}
}
aFormatter->Print( aNestLevel, ")\n\n" );
}
......@@ -41,6 +41,7 @@
class LINE_READER;
class BOARD;
class BOARD_DESIGN_SETTINGS;
/**
......@@ -53,13 +54,11 @@ class NETCLASS
{
private:
// Default values used to init a NETCLASS
static int DEFAULT_CLEARANCE;
static int DEFAULT_VIA_DRILL;
static int DEFAULT_UVIA_DRILL;
static const int DEFAULT_CLEARANCE;
static const int DEFAULT_VIA_DRILL;
static const int DEFAULT_UVIA_DRILL;
protected:
BOARD* m_Parent;
wxString m_Name; ///< Name of the net class
wxString m_Description; ///< what this NETCLASS is for.
......@@ -85,12 +84,9 @@ public:
/**
* Constructor
* stuffs a NETCLASS instance with aParent, aName, and optionally the initialParameters
* @param aParent = the parent board
* @param aName = the name of this new netclass
* @param initialParameters is a NETCLASS to copy parameters from, or if
* NULL tells me to copy default settings from BOARD::m_designSettings.
*/
NETCLASS( BOARD* aParent, const wxString& aName, const NETCLASS* initialParameters = NULL );
NETCLASS( const wxString& aName );
~NETCLASS();
......@@ -115,7 +111,6 @@ public:
return m_Members.size();
}
/**
* Function Clear
* empties the collection of members.
......@@ -125,7 +120,6 @@ public:
m_Members.clear();
}
/**
* Function AddMember
* adds \a aNetname to this NETCLASS if it is not already in this NETCLASS.
......@@ -169,34 +163,35 @@ public:
void SetClearance( int aClearance ) { m_Clearance = aClearance; }
int GetTrackWidth() const { return m_TrackWidth; }
int GetTrackMinWidth() const;
void SetTrackWidth( int aWidth ) { m_TrackWidth = aWidth; }
int GetViaDiameter() const { return m_ViaDia; }
int GetViaMinDiameter() const;
void SetViaDiameter( int aDia ) { m_ViaDia = aDia; }
int GetViaDrill() const { return m_ViaDrill; }
int GetViaMinDrill() const;
void SetViaDrill( int aSize ) { m_ViaDrill = aSize; }
int GetuViaDiameter() const { return m_uViaDia; }
int GetuViaMinDiameter() const;
void SetuViaDiameter( int aSize ) { m_uViaDia = aSize; }
int GetuViaDrill() const { return m_uViaDrill; }
int GetuViaMinDrill() const;
void SetuViaDrill( int aSize ) { m_uViaDrill = aSize; }
/**
* Function SetParams
* will set all the parameters by copying them from \a defaults.
* Parameters are the values like m_ViaSize, etc, but do not include m_Description.
* @param defaults is another NETCLASS to copy from. If NULL, then copy
* from global preferences instead.
* @param aDefaults is another NETCLASS object to copy from.
*/
void SetParams( const NETCLASS& aDefaults );
/**
* Function SetParams
* will set all the parameters by copying them from board design settings.
* @param aSettings is a BOARD_DESIGN_SETTINGS object to copy from. Clearance, via drill and
* microvia drill values are taken from the defaults.
*/
void SetParams( const NETCLASS* defaults = NULL );
void SetParams( const BOARD_DESIGN_SETTINGS& aSettings );
/**
* Function Format
......@@ -225,8 +220,6 @@ public:
class NETCLASSES
{
private:
BOARD* m_Parent;
typedef std::map<wxString, NETCLASS*> NETCLASSMAP;
/// all the NETCLASSes except the default one.
......@@ -236,7 +229,7 @@ private:
NETCLASS m_Default;
public:
NETCLASSES( BOARD* aParent = NULL );
NETCLASSES();
~NETCLASSES();
/**
......@@ -253,7 +246,6 @@ public:
const_iterator begin() const { return m_NetClasses.begin(); }
const_iterator end() const { return m_NetClasses.end(); }
/**
* Function GetCount
* @return the number of netclasses, excluding the default one.
......@@ -263,6 +255,10 @@ public:
return m_NetClasses.size();
}
/**
* Function GetDefault
* @return the default net class.
*/
NETCLASS* GetDefault() const
{
return (NETCLASS*) &m_Default;
......
......@@ -190,15 +190,15 @@ void DIALOG_DESIGN_RULES::PrintCurrentSettings()
m_MessagesList->AppendToPage( _( "<b>Current general settings:</b><br>" ) );
// Display min values:
value = StringFromValue( g_UserUnit, m_BrdSettings.m_TrackMinWidth, true );
value = StringFromValue( g_UserUnit, m_BrdSettings->m_TrackMinWidth, true );
msg.Printf( _( "Minimum value for tracks width: <b>%s</b><br>\n" ), GetChars( value ) );
m_MessagesList->AppendToPage( msg );
value = StringFromValue( g_UserUnit, m_BrdSettings.m_ViasMinSize, true );
value = StringFromValue( g_UserUnit, m_BrdSettings->m_ViasMinSize, true );
msg.Printf( _( "Minimum value for vias diameter: <b>%s</b><br>\n" ), GetChars( value ) );
m_MessagesList->AppendToPage( msg );
value = StringFromValue( g_UserUnit, m_BrdSettings.m_MicroViasMinSize, true );
value = StringFromValue( g_UserUnit, m_BrdSettings->m_MicroViasMinSize, true );
msg.Printf( _( "Minimum value for microvias diameter: <b>%s</b><br>\n" ), GetChars( value ) );
m_MessagesList->AppendToPage( msg );
}
......@@ -212,7 +212,7 @@ void DIALOG_DESIGN_RULES::InitDialogRules()
SetReturnCode( 0 );
m_Pcb = m_Parent->GetBoard();
m_BrdSettings = m_Pcb->GetDesignSettings();
m_BrdSettings = &m_Pcb->GetDesignSettings();
// Initialize the Rules List
InitRulesList();
......@@ -220,13 +220,8 @@ void DIALOG_DESIGN_RULES::InitDialogRules()
// copy all NETs into m_AllNets by adding them as NETCUPs.
// @todo go fix m_Pcb->SynchronizeNetsAndNetClasses() so that the netcode==0 is not present in the BOARD::m_NetClasses
NETCLASS* netclass;
NETCLASSES& netclasses = m_Pcb->m_NetClasses;
netclass = netclasses.GetDefault();
NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
NETCLASS* netclass = netclasses.GetDefault();
// Initialize list of nets for Default Net Class
for( NETCLASS::const_iterator name = netclass->begin(); name != netclass->end(); ++name )
......@@ -262,23 +257,23 @@ void DIALOG_DESIGN_RULES::InitGlobalRules()
AddUnitSymbol( *m_MicroViaMinDrillTitle );
AddUnitSymbol( *m_TrackMinWidthTitle );
PutValueInLocalUnits( *m_SetViasMinSizeCtrl, m_BrdSettings.m_ViasMinSize );
PutValueInLocalUnits( *m_SetViasMinDrillCtrl, m_BrdSettings.m_ViasMinDrill );
PutValueInLocalUnits( *m_SetViasMinSizeCtrl, m_BrdSettings->m_ViasMinSize );
PutValueInLocalUnits( *m_SetViasMinDrillCtrl, m_BrdSettings->m_ViasMinDrill );
if( m_BrdSettings.m_BlindBuriedViaAllowed )
if( m_BrdSettings->m_BlindBuriedViaAllowed )
m_OptViaType->SetSelection( 1 );
m_AllowMicroViaCtrl->SetSelection( m_BrdSettings.m_MicroViasAllowed ? 1 : 0 );
PutValueInLocalUnits( *m_SetMicroViasMinSizeCtrl, m_BrdSettings.m_MicroViasMinSize );
PutValueInLocalUnits( *m_SetMicroViasMinDrillCtrl, m_BrdSettings.m_MicroViasMinDrill );
PutValueInLocalUnits( *m_SetTrackMinWidthCtrl, m_BrdSettings.m_TrackMinWidth );
m_AllowMicroViaCtrl->SetSelection( m_BrdSettings->m_MicroViasAllowed ? 1 : 0 );
PutValueInLocalUnits( *m_SetMicroViasMinSizeCtrl, m_BrdSettings->m_MicroViasMinSize );
PutValueInLocalUnits( *m_SetMicroViasMinDrillCtrl, m_BrdSettings->m_MicroViasMinDrill );
PutValueInLocalUnits( *m_SetTrackMinWidthCtrl, m_BrdSettings->m_TrackMinWidth );
// Initialize Vias and Tracks sizes lists.
// note we display only extra values, never the current netclass value.
// (the first value in history list)
m_TracksWidthList = m_Parent->GetBoard()->m_TrackWidthList;
m_TracksWidthList = m_BrdSettings->m_TrackWidthList;
m_TracksWidthList.erase( m_TracksWidthList.begin() ); // remove the netclass value
m_ViasDimensionsList = m_Parent->GetBoard()->m_ViasDimensionsList;
m_ViasDimensionsList = m_BrdSettings->m_ViasDimensionsList;
m_ViasDimensionsList.erase( m_ViasDimensionsList.begin() ); // remove the netclass value
InitDimensionsLists();
}
......@@ -484,7 +479,7 @@ static void class2gridRow( wxGrid* grid, int row, NETCLASS* nc )
*/
void DIALOG_DESIGN_RULES::InitRulesList()
{
NETCLASSES& netclasses = m_Pcb->m_NetClasses;
NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
// the +1 is for the Default NETCLASS.
if( netclasses.GetCount() + 1 > (unsigned) m_grid->GetNumberRows() )
......@@ -524,7 +519,7 @@ static void gridRow2class( wxGrid* grid, int row, NETCLASS* nc )
*/
void DIALOG_DESIGN_RULES::CopyRulesListToBoard()
{
NETCLASSES& netclasses = m_Pcb->m_NetClasses;
NETCLASSES& netclasses = m_BrdSettings->m_NetClasses;
// Remove all netclasses from board. We'll copy new list after
netclasses.Clear();
......@@ -535,9 +530,9 @@ void DIALOG_DESIGN_RULES::CopyRulesListToBoard()
// Copy other NetClasses :
for( int row = 1; row < m_grid->GetNumberRows(); ++row )
{
NETCLASS* nc = new NETCLASS( m_Pcb, m_grid->GetRowLabelValue( row ) );
NETCLASS* nc = new NETCLASS( m_grid->GetRowLabelValue( row ) );
if( !m_Pcb->m_NetClasses.Add( nc ) )
if( !m_BrdSettings->m_NetClasses.Add( nc ) )
{
// this netclass cannot be added because an other netclass with the same name exists
// Should not occur because OnAddNetclassClick() tests for existing NetClass names
......@@ -568,20 +563,20 @@ void DIALOG_DESIGN_RULES::CopyRulesListToBoard()
void DIALOG_DESIGN_RULES::CopyGlobalRulesToBoard()
/*************************************************/
{
m_BrdSettings.m_BlindBuriedViaAllowed = m_OptViaType->GetSelection() > 0;
m_BrdSettings->m_BlindBuriedViaAllowed = m_OptViaType->GetSelection() > 0;
// Update vias minimum values for DRC
m_BrdSettings.m_ViasMinSize = ValueFromTextCtrl( *m_SetViasMinSizeCtrl );
m_BrdSettings.m_ViasMinDrill = ValueFromTextCtrl( *m_SetViasMinDrillCtrl );
m_BrdSettings->m_ViasMinSize = ValueFromTextCtrl( *m_SetViasMinSizeCtrl );
m_BrdSettings->m_ViasMinDrill = ValueFromTextCtrl( *m_SetViasMinDrillCtrl );
m_BrdSettings.m_MicroViasAllowed = m_AllowMicroViaCtrl->GetSelection() == 1;
m_BrdSettings->m_MicroViasAllowed = m_AllowMicroViaCtrl->GetSelection() == 1;
// Update microvias minimum values for DRC
m_BrdSettings.m_MicroViasMinSize = ValueFromTextCtrl( *m_SetMicroViasMinSizeCtrl );
m_BrdSettings.m_MicroViasMinDrill = ValueFromTextCtrl( *m_SetMicroViasMinDrillCtrl );
m_BrdSettings->m_MicroViasMinSize = ValueFromTextCtrl( *m_SetMicroViasMinSizeCtrl );
m_BrdSettings->m_MicroViasMinDrill = ValueFromTextCtrl( *m_SetMicroViasMinDrillCtrl );
// Update tracks minimum values for DRC
m_BrdSettings.m_TrackMinWidth = ValueFromTextCtrl( *m_SetTrackMinWidthCtrl );
m_BrdSettings->m_TrackMinWidth = ValueFromTextCtrl( *m_SetTrackMinWidthCtrl );
}
......@@ -634,12 +629,12 @@ void DIALOG_DESIGN_RULES::CopyDimensionsListsToBoard()
// Sort new list by by increasing value
sort( m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() );
std::vector <int>* tlist = &m_Parent->GetBoard()->m_TrackWidthList;
std::vector<int>* tlist = &m_BrdSettings->m_TrackWidthList;
tlist->erase( tlist->begin() + 1, tlist->end() ); // Remove old "custom" sizes
tlist->insert( tlist->end(), m_TracksWidthList.begin(), m_TracksWidthList.end() ); //Add new "custom" sizes
// Reinitialize m_ViaSizeList
std::vector <VIA_DIMENSION>* vialist = &m_Parent->GetBoard()->m_ViasDimensionsList;
std::vector<VIA_DIMENSION>* vialist = &m_BrdSettings->m_ViasDimensionsList;
vialist->erase( vialist->begin() + 1, vialist->end() );
vialist->insert( vialist->end(), m_ViasDimensionsList.begin(), m_ViasDimensionsList.end() );
}
......@@ -671,11 +666,9 @@ void DIALOG_DESIGN_RULES::OnOkButtonClick( wxCommandEvent& event )
CopyGlobalRulesToBoard();
CopyDimensionsListsToBoard();
m_Pcb->SetDesignSettings( m_BrdSettings );
EndModal( wxID_OK );
m_Pcb->SetCurrentNetClass( NETCLASS::Default );
m_BrdSettings->SetCurrentNetClass( NETCLASS::Default );
}
......
......@@ -40,7 +40,7 @@ private:
PCB_EDIT_FRAME* m_Parent;
BOARD* m_Pcb;
BOARD_DESIGN_SETTINGS m_BrdSettings;
BOARD_DESIGN_SETTINGS* m_BrdSettings;
static int s_LastTabSelection; ///< which tab user had open last
......
......@@ -46,21 +46,22 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit()
// Display current setup for tracks and vias
BOARD* board = m_Parent->GetBoard();
NETCLASSES& netclasses = board->m_NetClasses;
NETINFO_ITEM* net = board->FindNet( m_Netcode );
BOARD_DESIGN_SETTINGS& dsnSettings = board->GetDesignSettings();
NETCLASSES& netclasses = dsnSettings.m_NetClasses;
NETCLASS* netclass = netclasses.GetDefault();
NETINFO_ITEM* net = board->FindNet( m_Netcode );
if( net )
{
m_CurrentNetName->SetLabel( net->GetNetname() );
m_CurrentNetclassName->SetLabel( board->GetCurrentNetClassName() );
netclass = netclasses.Find( board->GetCurrentNetClassName() );
m_CurrentNetclassName->SetLabel( dsnSettings.GetCurrentNetClassName() );
netclass = netclasses.Find( dsnSettings.GetCurrentNetClassName() );
}
/* Disable the option "copy current to net" if we have only default netclass values
* i.e. when m_TrackWidthSelector and m_ViaSizeSelector are set to 0
*/
if( !board->GetTrackWidthIndex() && !board->GetViaSizeIndex() )
if( !dsnSettings.GetTrackWidthIndex() && !dsnSettings.GetViaSizeIndex() )
{
m_Net2CurrValueButton->Enable( false );
m_OptionID = ID_NETCLASS_VALUES_TO_CURRENT_NET;
......@@ -77,9 +78,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit()
msg = StringFromValue( g_UserUnit, value, true );
m_gridDisplayCurrentSettings->SetCellValue( 0, 0, msg );
if( board->GetTrackWidthIndex() )
if( dsnSettings.GetTrackWidthIndex() )
{
value = board->GetCurrentTrackWidth();
value = dsnSettings.GetCurrentTrackWidth();
msg = StringFromValue( g_UserUnit, value, true );
}
else
......@@ -91,9 +92,9 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit()
msg = StringFromValue( g_UserUnit, value, true );
m_gridDisplayCurrentSettings->SetCellValue( 0, 1, msg );
if( board->GetViaSizeIndex() )
if( dsnSettings.GetViaSizeIndex() )
{
value = board->GetCurrentViaSize();
value = dsnSettings.GetCurrentViaSize();
msg = StringFromValue( g_UserUnit, value, true );
}
else
......@@ -103,7 +104,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::MyInit()
value = netclass->GetViaDrill(); // Display via drill
msg = StringFromValue( g_UserUnit, value, true );
m_gridDisplayCurrentSettings->SetCellValue( 0, 2, msg );
value = board->GetCurrentViaDrill();
value = dsnSettings.GetCurrentViaDrill();
if( value >= 0 )
msg = StringFromValue( g_UserUnit, value, true );
else
......
......@@ -70,8 +70,8 @@ void DIALOG_PLOT::Init_Dialog()
// The reasonable width correction value must be in a range of
// [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
m_widthAdjustMinValue = -(m_board->GetDesignSettings().m_TrackMinWidth - 1);
m_widthAdjustMaxValue = m_board->GetSmallestClearanceValue() - 1;
m_widthAdjustMinValue = -( m_board->GetDesignSettings().m_TrackMinWidth - 1 );
m_widthAdjustMaxValue = m_board->GetDesignSettings().GetSmallestClearanceValue() - 1;
switch( m_plotOpts.GetFormat() )
{
......
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router settings dialog.
*/
#include "dialog_pns_settings.h"
#include <router/pns_routing_settings.h>
DIALOG_PNS_SETTINGS::DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) :
DIALOG_PNS_SETTINGS_BASE( aParent ), m_settings( aSettings )
{
// "Figure out what's best" is not available yet
m_mode->Enable( RM_Smart, false );
// Load widgets' values from settings
m_mode->SetSelection( m_settings.Mode() );
m_shoveVias->SetValue( m_settings.ShoveVias() );
m_backPressure->SetValue( m_settings.JumpOverObstacles() );
m_removeLoops->SetValue( m_settings.RemoveLoops() );
m_suggestEnding->SetValue( m_settings.SuggestFinish() );
m_autoNeckdown->SetValue( m_settings.SmartPads() );
m_effort->SetValue( m_settings.OptimizerEffort() );
m_smoothDragged->SetValue( m_settings.SmoothDraggedSegments() );
m_violateDrc->SetValue( m_settings.CanViolateDRC() );
}
void DIALOG_PNS_SETTINGS::OnClose( wxCloseEvent& aEvent )
{
// Do nothing, it is result of ESC pressing
EndModal( 0 );
}
void DIALOG_PNS_SETTINGS::OnOkClick( wxCommandEvent& aEvent )
{
// Save widgets' values to settings
m_settings.SetMode( (PNS_MODE) m_mode->GetSelection() );
m_settings.SetShoveVias( m_shoveVias->GetValue() );
m_settings.SetJumpOverObstacles( m_backPressure->GetValue() );
m_settings.SetRemoveLoops( m_removeLoops->GetValue() );
m_settings.SetSuggestFinish ( m_suggestEnding->GetValue() );
m_settings.SetSmartPads( m_autoNeckdown->GetValue() );
m_settings.SetOptimizerEffort( (PNS_OPTIMIZATION_EFFORT) m_effort->GetValue() );
m_settings.SetSmoothDraggedSegments( m_smoothDragged->GetValue() );
m_settings.SetCanViolateDRC( m_violateDrc->GetValue() );
EndModal( 1 );
}
void DIALOG_PNS_SETTINGS::OnCancelClick( wxCommandEvent& aEvent )
{
// Do nothing
EndModal( 0 );
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router settings dialog.
*/
#ifndef __dialog_pns_settings__
#define __dialog_pns_settings__
#include "dialog_pns_settings_base.h"
class PNS_ROUTING_SETTINGS;
class DIALOG_PNS_SETTINGS : public DIALOG_PNS_SETTINGS_BASE
{
public:
DIALOG_PNS_SETTINGS( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings );
virtual void OnClose( wxCloseEvent& aEvent );
virtual void OnOkClick( wxCommandEvent& aEvent );
virtual void OnCancelClick( wxCommandEvent& aEvent );
private:
PNS_ROUTING_SETTINGS& m_settings;
};
#endif // __dialog_pns_settings__
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "dialog_pns_settings_base.h"
///////////////////////////////////////////////////////////////////////////
DIALOG_PNS_SETTINGS_BASE::DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
this->SetSizeHints( wxDefaultSize, wxDefaultSize );
wxBoxSizer* bMainSizer;
bMainSizer = new wxBoxSizer( wxVERTICAL );
wxString m_modeChoices[] = { _("Highlight collisions"), _("Shove"), _("Walk around"), _("Figure out what's best") };
int m_modeNChoices = sizeof( m_modeChoices ) / sizeof( wxString );
m_mode = new wxRadioBox( this, wxID_ANY, _("Mode"), wxDefaultPosition, wxDefaultSize, m_modeNChoices, m_modeChoices, 1, wxRA_SPECIFY_COLS );
m_mode->SetSelection( 1 );
bMainSizer->Add( m_mode, 0, wxALL, 5 );
wxStaticBoxSizer* bOptions;
bOptions = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options") ), wxVERTICAL );
m_shoveVias = new wxCheckBox( this, wxID_ANY, _("Shove vias"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_shoveVias, 0, wxALL, 5 );
m_backPressure = new wxCheckBox( this, wxID_ANY, _("Jump over obstacles"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_backPressure, 0, wxALL, 5 );
m_removeLoops = new wxCheckBox( this, wxID_ANY, _("Remove redundant tracks"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_removeLoops, 0, wxALL, 5 );
m_autoNeckdown = new wxCheckBox( this, wxID_ANY, _("Automatic neckdown"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_autoNeckdown, 0, wxALL, 5 );
m_smoothDragged = new wxCheckBox( this, wxID_ANY, _("Smooth dragged segments"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_smoothDragged, 0, wxALL, 5 );
m_violateDrc = new wxCheckBox( this, wxID_ANY, _("Allow DRC violations"), wxDefaultPosition, wxDefaultSize, 0 );
bOptions->Add( m_violateDrc, 0, wxALL, 5 );
m_suggestEnding = new wxCheckBox( this, wxID_ANY, _("Suggest track finish"), wxDefaultPosition, wxDefaultSize, 0 );
m_suggestEnding->Enable( false );
bOptions->Add( m_suggestEnding, 0, wxALL, 5 );
wxBoxSizer* bEffort;
bEffort = new wxBoxSizer( wxHORIZONTAL );
m_effortLabel = new wxStaticText( this, wxID_ANY, _("Optimizer effort"), wxDefaultPosition, wxDefaultSize, 0 );
m_effortLabel->Wrap( -1 );
bEffort->Add( m_effortLabel, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
bEffort->Add( 0, 0, 0, wxEXPAND, 5 );
wxBoxSizer* bSlider;
bSlider = new wxBoxSizer( wxVERTICAL );
m_effort = new wxSlider( this, wxID_ANY, 1, 0, 2, wxDefaultPosition, wxDefaultSize, wxSL_AUTOTICKS|wxSL_BOTTOM|wxSL_HORIZONTAL|wxSL_TOP );
bSlider->Add( m_effort, 1, wxEXPAND, 5 );
wxBoxSizer* bSliderLabels;
bSliderLabels = new wxBoxSizer( wxHORIZONTAL );
m_lowLabel = new wxStaticText( this, wxID_ANY, _("low"), wxDefaultPosition, wxDefaultSize, 0 );
m_lowLabel->Wrap( -1 );
m_lowLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) );
bSliderLabels->Add( m_lowLabel, 0, 0, 5 );
bSliderLabels->Add( 0, 0, 1, wxEXPAND, 5 );
m_highLabel = new wxStaticText( this, wxID_ANY, _("high"), wxDefaultPosition, wxDefaultSize, 0 );
m_highLabel->Wrap( -1 );
m_highLabel->SetFont( wxFont( 8, 70, 90, 90, false, wxEmptyString ) );
bSliderLabels->Add( m_highLabel, 0, 0, 5 );
bSlider->Add( bSliderLabels, 1, wxEXPAND, 5 );
bEffort->Add( bSlider, 1, wxEXPAND, 5 );
bOptions->Add( bEffort, 1, wxALL|wxEXPAND, 5 );
wxBoxSizer* bButtons;
bButtons = new wxBoxSizer( wxHORIZONTAL );
m_ok = new wxButton( this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0 );
m_ok->SetDefault();
bButtons->Add( m_ok, 1, wxALL, 5 );
m_cancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
bButtons->Add( m_cancel, 1, wxALL, 5 );
bOptions->Add( bButtons, 1, wxEXPAND, 5 );
bMainSizer->Add( bOptions, 1, wxEXPAND, 5 );
this->SetSizer( bMainSizer );
this->Layout();
// Connect Events
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) );
m_ok->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this );
m_cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this );
}
DIALOG_PNS_SETTINGS_BASE::~DIALOG_PNS_SETTINGS_BASE()
{
// Disconnect Events
this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_PNS_SETTINGS_BASE::OnClose ) );
m_ok->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnOkClick ), NULL, this );
m_cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_PNS_SETTINGS_BASE::OnCancelClick ), NULL, this );
}
This diff is collapsed.
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Apr 30 2013)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIALOG_PNS_SETTINGS_BASE_H__
#define __DIALOG_PNS_SETTINGS_BASE_H__
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/radiobox.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
#include <wx/slider.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/statbox.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// Class DIALOG_PNS_SETTINGS_BASE
///////////////////////////////////////////////////////////////////////////////
class DIALOG_PNS_SETTINGS_BASE : public wxDialog
{
private:
protected:
wxRadioBox* m_mode;
wxCheckBox* m_shoveVias;
wxCheckBox* m_backPressure;
wxCheckBox* m_removeLoops;
wxCheckBox* m_autoNeckdown;
wxCheckBox* m_smoothDragged;
wxCheckBox* m_violateDrc;
wxCheckBox* m_suggestEnding;
wxStaticText* m_effortLabel;
wxSlider* m_effort;
wxStaticText* m_lowLabel;
wxStaticText* m_highLabel;
wxButton* m_ok;
wxButton* m_cancel;
// Virtual event handlers, overide them in your derived class
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnOkClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCancelClick( wxCommandEvent& event ) { event.Skip(); }
public:
DIALOG_PNS_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Interactive Router settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 289,504 ), long style = wxDEFAULT_DIALOG_STYLE );
~DIALOG_PNS_SETTINGS_BASE();
};
#endif //__DIALOG_PNS_SETTINGS_BASE_H__
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router track width and via size dialog.
*/
#include "dialog_track_via_size.h"
#include <router/pns_routing_settings.h>
#include <base_units.h>
#include <confirm.h>
DIALOG_TRACK_VIA_SIZE::DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) :
DIALOG_TRACK_VIA_SIZE_BASE( aParent ),
m_settings( aSettings )
{
// Load router settings to dialog fields
m_trackWidth->SetValue( To_User_Unit( m_trackWidth->GetUnits(), m_settings.GetTrackWidth() ) );
m_viaDiameter->SetValue( To_User_Unit( m_viaDiameter->GetUnits(), m_settings.GetViaDiameter() ) );
m_viaDrill->SetValue( To_User_Unit( m_viaDrill->GetUnits(), m_settings.GetViaDrill() ) );
m_trackWidth->SetFocus();
// Pressing ENTER when any of the text input fields is active applies changes
#if wxCHECK_VERSION( 3, 0, 0 )
Connect( wxEVT_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this );
#else
Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_TRACK_VIA_SIZE::onOkClick ), NULL, this );
#endif
}
bool DIALOG_TRACK_VIA_SIZE::check()
{
// Wrong input
if( !m_trackWidth->GetValue() || !m_viaDiameter->GetValue() || !m_viaDrill->GetValue() )
return false;
// Via drill should be smaller than via diameter
if( *m_viaDrill->GetValue() >= m_viaDiameter->GetValue() )
return false;
return true;
}
void DIALOG_TRACK_VIA_SIZE::onClose( wxCloseEvent& aEvent )
{
EndModal( 0 );
}
void DIALOG_TRACK_VIA_SIZE::onOkClick( wxCommandEvent& aEvent )
{
if( check() )
{
// Store dialog values to the router settings
m_settings.SetTrackWidth( From_User_Unit( m_trackWidth->GetUnits(), *m_trackWidth->GetValue() ) );
m_settings.SetViaDiameter( From_User_Unit( m_viaDiameter->GetUnits(), *m_viaDiameter->GetValue() ) );
m_settings.SetViaDrill( From_User_Unit( m_viaDrill->GetUnits(), *m_viaDrill->GetValue() ) );
EndModal( 1 );
}
else
{
DisplayError( GetParent(), _( "Settings are incorrect" ) );
m_trackWidth->SetFocus();
}
}
void DIALOG_TRACK_VIA_SIZE::onCancelClick( wxCommandEvent& aEvent )
{
EndModal( 0 );
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2014 CERN
* Author: Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
/**
* Push and Shove router track width and via size dialog.
*/
#ifndef __dialog_track_via_size__
#define __dialog_track_via_size__
#include "dialog_track_via_size_base.h"
class PNS_ROUTING_SETTINGS;
/** Implementing DIALOG_TRACK_VIA_SIZE_BASE */
class DIALOG_TRACK_VIA_SIZE : public DIALOG_TRACK_VIA_SIZE_BASE
{
public:
/** Constructor */
DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings );
protected:
// Routings settings that are modified by the dialog.
PNS_ROUTING_SETTINGS& m_settings;
///> Checks if values given in the dialog are sensible.
bool check();
// Handlers for DIALOG_TRACK_VIA_SIZE_BASE events.
void onClose( wxCloseEvent& aEvent );
void onOkClick( wxCommandEvent& aEvent );
void onCancelClick( wxCommandEvent& aEvent );
};
#endif // __dialog_track_via_size__
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -403,7 +403,7 @@ bool DRC::testNetClasses()
{
bool ret = true;
NETCLASSES& netclasses = m_pcb->m_NetClasses;
NETCLASSES& netclasses = m_pcb->GetDesignSettings().m_NetClasses;
wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
......
......@@ -154,6 +154,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
wxPoint shape_pos;
NETCLASS* netclass = aRefSeg->GetNetClass();
BOARD_DESIGN_SETTINGS& dsnSettings = m_pcb->GetDesignSettings();
/* In order to make some calculations more easier or faster,
* pads and tracks coordinates will be made relative to the reference segment origin
......@@ -173,7 +174,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
// test if the via size is smaller than minimum
if( refvia->GetViaType() == VIA_MICROVIA )
{
if( refvia->GetWidth() < netclass->GetuViaMinDiameter() )
if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
{
m_currentMarker = fillMarker( refvia, NULL,
DRCE_TOO_SMALL_MICROVIA, m_currentMarker );
......@@ -182,7 +183,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
}
else
{
if( refvia->GetWidth() < netclass->GetViaMinDiameter() )
if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
{
m_currentMarker = fillMarker( refvia, NULL,
DRCE_TOO_SMALL_VIA, m_currentMarker );
......@@ -231,7 +232,7 @@ bool DRC::doTrackDrc( TRACK* aRefSeg, TRACK* aStart, bool testPads )
}
else // This is a track segment
{
if( aRefSeg->GetWidth() < netclass->GetTrackMinWidth() )
if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth )
{
m_currentMarker = fillMarker( aRefSeg, NULL,
DRCE_TOO_SMALL_TRACK_WIDTH, m_currentMarker );
......
......@@ -1146,7 +1146,7 @@ BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, const
if( m_rules->mdWireWire )
{
NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault();
NETCLASS* defaultNetclass = designSettings.GetDefault();
int clearance = KiROUND( m_rules->mdWireWire );
if( clearance < defaultNetclass->GetClearance() )
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment