diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 88db67da3b..c9caece966 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -228,6 +228,7 @@ set( COMMON_SRCS math/math_util.cpp + tool/tool_action.cpp tool/tool_base.cpp tool/tool_manager.cpp tool/tool_dispatcher.cpp diff --git a/common/draw_frame.cpp b/common/draw_frame.cpp index 182e54fb6f..b43d1669d0 100644 --- a/common/draw_frame.cpp +++ b/common/draw_frame.cpp @@ -1033,10 +1033,10 @@ void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable ) m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable ); m_auimgr.Update(); - SetGalCanvasActive( aEnable ); + // Reset current tool on switch(); + SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); - if( aEnable ) - GetGalCanvas()->SetFocus(); + m_galCanvasActive = aEnable; } //-----< BASE_SCREEN API moved here >-------------------------------------------- diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp index 1b293c63ac..4bf7835371 100644 --- a/common/draw_panel_gal.cpp +++ b/common/draw_panel_gal.cpp @@ -41,6 +41,8 @@ #include #include +#include + #ifdef __WXDEBUG__ #include #endif /* __WXDEBUG__ */ @@ -50,8 +52,9 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin GalType aGalType ) : wxWindow( aParentWindow, aWindowId, aPosition, aSize ) { + m_parent = aParentWindow; m_gal = NULL; - m_currentGal = GAL_TYPE_NONE; + m_backend = GAL_TYPE_NONE; m_view = NULL; m_painter = NULL; m_eventDispatcher = NULL; @@ -67,33 +70,28 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin m_viewControls = new KIGFX::WX_VIEW_CONTROLS( m_view, this ); - Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); + Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this ); + Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); - /* Generic events for the Tool Dispatcher */ - Connect( wxEVT_MOTION, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_LEFT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_LEFT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_LEFT_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_RIGHT_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_RIGHT_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_RIGHT_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MIDDLE_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MIDDLE_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MIDDLE_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) ); - Connect( wxEVT_CHAR, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); - Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this ); - Connect( KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, - wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); + const wxEventType events[] = + { + wxEVT_LEFT_UP, wxEVT_LEFT_DOWN, wxEVT_LEFT_DCLICK, + wxEVT_RIGHT_UP, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_DCLICK, + wxEVT_MIDDLE_UP, wxEVT_MIDDLE_DOWN, wxEVT_MIDDLE_DCLICK, + wxEVT_MOTION, wxEVT_MOUSEWHEEL, wxEVT_CHAR, KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE + }; + + BOOST_FOREACH( wxEventType eventType, events ) + { + Connect( eventType, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), + NULL, m_eventDispatcher ); + } // Set up timer that prevents too frequent redraw commands m_refreshTimer.SetOwner( this ); m_pendingRefresh = false; m_drawing = false; Connect( wxEVT_TIMER, wxTimerEventHandler( EDA_DRAW_PANEL_GAL::onRefreshTimer ), NULL, this ); - - this->SetFocus(); } @@ -160,7 +158,7 @@ void EDA_DRAW_PANEL_GAL::onRefreshTimer( wxTimerEvent& aEvent ) } -void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) +void EDA_DRAW_PANEL_GAL::Refresh( bool aEraseBackground, const wxRect* aRect ) { if( m_pendingRefresh ) return; @@ -183,6 +181,50 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect ) } +void EDA_DRAW_PANEL_GAL::SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher ) +{ + m_eventDispatcher = aEventDispatcher; + +#if wxCHECK_VERSION( 3, 0, 0 ) + if( m_eventDispatcher ) + { + m_parent->Connect( wxEVT_TOOL, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ); + } + else + { + // While loops are used to be sure, that we are removing all event handlers + while( m_parent->Disconnect( wxEVT_TOOL, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ) ); + } +#else + if( m_eventDispatcher ) + { + m_parent->Connect( wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ); + + m_parent->Connect( wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ); + } + else + { + // While loops are used to be sure, that we are removing all event handlers + while( m_parent->Disconnect( wxEVT_COMMAND_MENU_SELECTED, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ) ); + + while( m_parent->Disconnect( wxEVT_COMMAND_TOOL_CLICKED, + wxCommandEventHandler( TOOL_DISPATCHER::DispatchWxCommand ), + NULL, m_eventDispatcher ) ); + } +#endif +} + + void EDA_DRAW_PANEL_GAL::StartDrawing() { m_pendingRefresh = false; @@ -201,10 +243,32 @@ void EDA_DRAW_PANEL_GAL::StopDrawing() } +void EDA_DRAW_PANEL_GAL::SetHighContrastLayer( LAYER_NUM aLayer ) +{ + // Set display settings for high contrast mode + KIGFX::RENDER_SETTINGS* rSettings = m_view->GetPainter()->GetSettings(); + + SetTopLayer( aLayer ); + + rSettings->ClearActiveLayers(); + rSettings->SetActiveLayer( aLayer ); + + m_view->UpdateAllLayersColor(); +} + + +void EDA_DRAW_PANEL_GAL::SetTopLayer( LAYER_NUM aLayer ) +{ + m_view->ClearTopLayers(); + m_view->SetTopLayer( aLayer ); + m_view->UpdateAllLayersOrder(); +} + + void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) { // Do not do anything if the currently used GAL is correct - if( aGalType == m_currentGal && m_gal != NULL ) + if( aGalType == m_backend && m_gal != NULL ) return; // Prevent refreshing canvas during backend switch @@ -235,21 +299,16 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) if( m_view ) m_view->SetGAL( m_gal ); - m_currentGal = aGalType; + m_backend = aGalType; } void EDA_DRAW_PANEL_GAL::onEvent( wxEvent& aEvent ) { if( !m_eventDispatcher ) - { aEvent.Skip(); - return; - } else - { m_eventDispatcher->DispatchWxEvent( aEvent ); - } Refresh(); } @@ -260,10 +319,3 @@ void EDA_DRAW_PANEL_GAL::onEnter( wxEvent& aEvent ) // Getting focus is necessary in order to receive key events properly SetFocus(); } - - -void EDA_DRAW_PANEL_GAL::skipEvent( wxEvent& aEvent ) -{ - // This is necessary for CHAR_HOOK event to generate KEY_UP and KEY_DOWN events - aEvent.Skip(); -} diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp index e749c4db9a..5afa67d55a 100644 --- a/common/gal/cairo/cairo_compositor.cpp +++ b/common/gal/cairo/cairo_compositor.cpp @@ -55,6 +55,9 @@ void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight ) { clean(); + assert( m_width > 0 ); + assert( m_height > 0 ); + m_width = aWidth; m_height = aHeight; diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 73ca64294d..b0b033d037 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -75,6 +75,9 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, SetSize( aParent->GetSize() ); screenSize = VECTOR2I( aParent->GetSize() ); + + cursorPixels = NULL; + cursorPixelsSaved = NULL; initCursor(); // Grid color settings are different in Cairo and OpenGL @@ -808,6 +811,13 @@ void CAIRO_GAL::ClearTarget( RENDER_TARGET aTarget ) } +void CAIRO_GAL::SetCursorSize( unsigned int aCursorSize ) +{ + GAL::SetCursorSize( aCursorSize ); + initCursor(); +} + + void CAIRO_GAL::DrawCursor( const VECTOR2D& aCursorPosition ) { // Now we should only store the position of the mouse cursor @@ -890,6 +900,12 @@ void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent ) void CAIRO_GAL::initCursor() { + if( cursorPixels ) + delete cursorPixels; + + if( cursorPixelsSaved ) + delete cursorPixelsSaved; + cursorPixels = new wxBitmap( cursorSize, cursorSize ); cursorPixelsSaved = new wxBitmap( cursorSize, cursorSize ); diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index 821df4969f..d21b12b783 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -134,9 +134,6 @@ void GAL::DrawGrid() // Draw the grid // For the drawing the start points, end points and increments have // to be calculated in world coordinates - gridOffset = VECTOR2D( (long) gridOrigin.x % (long) gridSize.x, - (long) gridOrigin.y % (long) gridSize.y ); - VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 ); VECTOR2D worldEndPoint = screenWorldMatrix * VECTOR2D( screenSize ); @@ -160,10 +157,10 @@ void GAL::DrawGrid() assert( gridEndY >= gridStartY ); // Correct the index, else some lines are not correctly painted - gridStartX -= ( gridOrigin.x / gridSize.x ) + 1; - gridStartY -= ( gridOrigin.y / gridSize.y ) + 1; - gridEndX += ( gridOrigin.x / gridSize.x ) + 1; - gridEndY += ( gridOrigin.y / gridSize.y ) + 1; + gridStartX -= abs( gridOrigin.x / gridSize.x ) + 1; + gridStartY -= abs( gridOrigin.y / gridSize.y ) + 1; + gridEndX += abs( gridOrigin.x / gridSize.x ) + 1; + gridEndY += abs( gridOrigin.y / gridSize.y ) + 1; // Draw the grid behind all other layers SetLayerDepth( depthRange.y * 0.75 ); diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp index 3a6721e5c9..2843204d78 100644 --- a/common/gal/opengl/opengl_compositor.cpp +++ b/common/gal/opengl/opengl_compositor.cpp @@ -35,7 +35,7 @@ using namespace KIGFX; OPENGL_COMPOSITOR::OPENGL_COMPOSITOR() : - m_initialized( false ), m_current( 0 ) + m_initialized( false ), m_current( 0 ), m_currentFbo( DIRECT_RENDERING ) { } @@ -52,9 +52,6 @@ void OPENGL_COMPOSITOR::Initialize() if( m_initialized ) return; - // Get the maximum number of buffers - glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &m_maxBuffers ); - // We need framebuffer objects for drawing the screen contents // Generate framebuffer and a depth buffer glGenFramebuffersEXT( 1, &m_framebuffer ); @@ -68,15 +65,13 @@ void OPENGL_COMPOSITOR::Initialize() // Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer // this is required later for anti-aliasing - glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL, m_width, m_height ); + glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, m_width, m_height ); glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER_EXT, m_depthBuffer ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER_EXT, m_depthBuffer ); + GL_RENDERBUFFER_EXT, m_depthBuffer ); // Unbind the framebuffer, so by default all the rendering goes directly to the display glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING ); - m_currentFbo = 0; + m_currentFbo = DIRECT_RENDERING; m_initialized = true; } @@ -96,9 +91,14 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() { wxASSERT( m_initialized ); - if( usedBuffers() >= m_maxBuffers ) + unsigned int maxBuffers; + + // Get the maximum number of buffers + glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers ); + + if( usedBuffers() >= maxBuffers ) { - DisplayError( NULL, wxT( "Cannot create more framebuffers. OpenGL rendering " + DisplayError( NULL, _( "Cannot create more framebuffers. OpenGL rendering " "backend requires at least 3 framebuffers. You may try to update/change " "your graphic drivers." ) ); return 0; // Unfortunately we have no more free buffers left @@ -114,7 +114,7 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() // Set texture parameters glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); @@ -122,7 +122,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() // Bind the texture to the specific attachment point, clear and rebind the screen glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_framebuffer ); m_currentFbo = m_framebuffer; - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, GL_TEXTURE_2D, textureTarget, 0 ); + glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachmentPoint, + GL_TEXTURE_2D, textureTarget, 0 ); // Check the status, exit if the framebuffer can't be created GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); @@ -132,38 +133,38 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer() switch( status ) { case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - DisplayError( NULL, wxT( "Cannot create the framebuffer." ) ); + DisplayError( NULL, _( "Cannot create the framebuffer." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - DisplayError( NULL, wxT( "The framebuffer attachment points are incomplete." ) ); + DisplayError( NULL, _( "The framebuffer attachment points are incomplete." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - DisplayError( NULL, wxT( "The framebuffer does not have at least " - "one image attached to it." ) ); + DisplayError( NULL, _( "The framebuffer does not have at least " + "one image attached to it." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - DisplayError( NULL, wxT( "The framebuffer read buffer is incomplete." ) ); + DisplayError( NULL, _( "The framebuffer read buffer is incomplete." ) ); break; case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - DisplayError( NULL, wxT( "The combination of internal formats of the attached images " - "violates an implementation-dependent set of restrictions." ) ); + DisplayError( NULL, _( "The combination of internal formats of the attached images " + "violates an implementation-dependent set of restrictions." ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: - DisplayError( NULL, wxT( "GL_RENDERBUFFER_SAMPLES is not the same " - "for all attached renderbuffers" ) ); + DisplayError( NULL, _( "GL_RENDERBUFFER_SAMPLES is not the same " + "for all attached renderbuffers" ) ); break; case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT: - DisplayError( NULL, wxT( "Framebuffer incomplete layer targets errors." ) ); + DisplayError( NULL, _( "Framebuffer incomplete layer targets errors." ) ); break; default: - DisplayError( NULL, wxT( "Cannot create the framebuffer." ) ); + DisplayError( NULL, _( "Cannot create the framebuffer." ) ); break; } @@ -192,7 +193,6 @@ void OPENGL_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) // Change the rendering destination to the selected attachment point if( aBufferHandle == DIRECT_RENDERING ) { - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, DIRECT_RENDERING ); m_currentFbo = DIRECT_RENDERING; } else if( m_currentFbo != m_framebuffer ) @@ -221,12 +221,7 @@ void OPENGL_COMPOSITOR::ClearBuffer() void OPENGL_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) { wxASSERT( m_initialized ); - - if( aBufferHandle == 0 || aBufferHandle > usedBuffers() ) - { - DisplayError( NULL, wxT( "Wrong framebuffer handle" ) ); - return; - } + wxASSERT( aBufferHandle != 0 && aBufferHandle <= usedBuffers() ); // Switch to the main framebuffer and blit the scene glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING ); @@ -274,8 +269,8 @@ void OPENGL_COMPOSITOR::clean() { wxASSERT( m_initialized ); - glDeleteFramebuffersEXT( 1, &m_framebuffer ); - glDeleteRenderbuffersEXT( 1, &m_depthBuffer ); + glBindFramebufferEXT( GL_FRAMEBUFFER, DIRECT_RENDERING ); + m_currentFbo = DIRECT_RENDERING; OPENGL_BUFFERS::const_iterator it; @@ -286,8 +281,8 @@ void OPENGL_COMPOSITOR::clean() m_buffers.clear(); + glDeleteFramebuffersEXT( 1, &m_framebuffer ); + glDeleteRenderbuffersEXT( 1, &m_depthBuffer ); + m_initialized = false; } - - -GLuint OPENGL_COMPOSITOR::m_currentFbo = DIRECT_RENDERING; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 568772f96a..f7b7842a04 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -45,6 +45,8 @@ void InitTesselatorCallbacks( GLUtesselator* aTesselator ); const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 }; +wxGLContext* OPENGL_GAL::glContext = NULL; + OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener, const wxString& aName ) : wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition, wxDefaultSize, @@ -54,7 +56,9 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, overlayManager( false ) { // Create the OpenGL-Context - glContext = new wxGLContext( this ); + if( glContext == NULL ) + glContext = new wxGLContext( this ); + parentWindow = aParent; mouseListener = aMouseListener; paintListener = aPaintListener; @@ -113,8 +117,6 @@ OPENGL_GAL::~OPENGL_GAL() gluDeleteTess( tesselator ); ClearCache(); - - delete glContext; } @@ -122,23 +124,22 @@ void OPENGL_GAL::BeginDrawing() { SetCurrent( *glContext ); - clientDC = new wxClientDC( this ); + clientDC = new wxPaintDC( this ); // Initialize GLEW, FBOs & VBOs if( !isGlewInitialized ) initGlew(); + // Set up the view port + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); + + // Create the screen transformation + glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); + if( !isFramebufferInitialized ) { - // Set up the view port - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); - - // Create the screen transformation - glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, - -depthRange.x, -depthRange.y ); - // Prepare rendering target buffers compositor.Initialize(); mainBuffer = compositor.CreateBuffer(); @@ -967,7 +968,7 @@ void OPENGL_GAL::initGlew() exit( 1 ); } - // Vertex buffer have to be supported + // Vertex buffer has to be supported if( !GLEW_ARB_vertex_buffer_object ) { DisplayError( parentWindow, wxT( "Vertex buffer objects are not supported!" ) ); diff --git a/common/gal/opengl/vertex_container.cpp b/common/gal/opengl/vertex_container.cpp index 82658e11ae..fa41ecb808 100644 --- a/common/gal/opengl/vertex_container.cpp +++ b/common/gal/opengl/vertex_container.cpp @@ -31,7 +31,8 @@ #include #include #include -#include +#include +#include using namespace KIGFX; @@ -45,9 +46,11 @@ VERTEX_CONTAINER* VERTEX_CONTAINER::MakeContainer( bool aCached ) VERTEX_CONTAINER::VERTEX_CONTAINER( unsigned int aSize ) : - m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), m_failed( false ) + m_freeSpace( aSize ), m_currentSize( aSize ), m_initialSize( aSize ), + m_failed( false ), m_dirty( true ) { m_vertices = static_cast( malloc( aSize * sizeof( VERTEX ) ) ); + memset( m_vertices, 0x00, aSize * sizeof( VERTEX ) ); } diff --git a/common/painter.cpp b/common/painter.cpp index 785d479a1f..0d6b1f0399 100644 --- a/common/painter.cpp +++ b/common/painter.cpp @@ -38,6 +38,7 @@ RENDER_SETTINGS::RENDER_SETTINGS() m_highlightEnabled = false; m_hiContrastEnabled = false; m_hiContrastFactor = 0.2; + m_highlightNetcode = -1; m_outlineWidth = 1; m_worksheetLineWidth = 100000; diff --git a/common/tool/action_manager.cpp b/common/tool/action_manager.cpp index 444143b0fb..a64ab9e1d5 100644 --- a/common/tool/action_manager.cpp +++ b/common/tool/action_manager.cpp @@ -44,8 +44,6 @@ ACTION_MANAGER::~ACTION_MANAGER() void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) { - // Check if the TOOL_ACTION was not registered before - assert( aAction->GetId() == -1 ); // TOOL_ACTIONs are supposed to be named [appName.]toolName.actionName (with dots between) // action name without specifying at least toolName is not valid assert( aAction->GetName().find( '.', 0 ) != std::string::npos ); @@ -54,15 +52,14 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction ) assert( m_actionNameIndex.find( aAction->m_name ) == m_actionNameIndex.end() ); assert( m_actionIdIndex.find( aAction->m_id ) == m_actionIdIndex.end() ); - aAction->setId( MakeActionId( aAction->m_name ) ); + if( aAction->m_id == -1 ) + aAction->m_id = MakeActionId( aAction->m_name ); m_actionNameIndex[aAction->m_name] = aAction; m_actionIdIndex[aAction->m_id] = aAction; if( aAction->HasHotKey() ) m_actionHotKeys[aAction->m_currentHotKey].push_back( aAction ); - - aAction->setActionMgr( this ); } @@ -71,10 +68,6 @@ void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction ) m_actionNameIndex.erase( aAction->m_name ); 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() ) { std::list& actions = m_actionHotKeys[aAction->m_currentHotKey]; @@ -96,24 +89,14 @@ int ACTION_MANAGER::MakeActionId( const std::string& aActionName ) } -bool ACTION_MANAGER::RunAction( const std::string& aActionName ) const +TOOL_ACTION* ACTION_MANAGER::FindAction( const std::string& aActionName ) const { std::map::const_iterator it = m_actionNameIndex.find( aActionName ); - if( it == m_actionNameIndex.end() ) - return false; // no action with given name found + if( it != m_actionNameIndex.end() ) + return it->second; - RunAction( it->second ); - - return true; -} - - -void ACTION_MANAGER::RunAction( const TOOL_ACTION* aAction ) const -{ - TOOL_EVENT event = aAction->MakeEvent(); - - m_toolMgr->ProcessEvent( event ); + return NULL; } @@ -160,6 +143,8 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const if( tool ) { + // Choose the action that goes to the tool with highest priority + // (i.e. is on the top of active tools stack) priority = m_toolMgr->GetPriority( tool->GetId() ); if( priority >= 0 && priority > highestPriority ) @@ -170,13 +155,16 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const } } - if( !global && !context ) // currently there is no valid action to run - return false; - if( context ) - RunAction( context ); + { + m_toolMgr->RunAction( *context, true ); + return true; + } else if( global ) - RunAction( global ); + { + m_toolMgr->RunAction( *global, true ); + return true; + } - return true; + return false; } diff --git a/common/tool/context_menu.cpp b/common/tool/context_menu.cpp index e68473dd6c..57756e66fc 100644 --- a/common/tool/context_menu.cpp +++ b/common/tool/context_menu.cpp @@ -71,6 +71,47 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) : } +CONTEXT_MENU& CONTEXT_MENU::operator=( const CONTEXT_MENU& aMenu ) +{ + Clear(); + + m_titleSet = aMenu.m_titleSet; + m_selected = aMenu.m_selected; + m_tool = aMenu.m_tool; + m_toolActions = aMenu.m_toolActions; + m_customHandler = aMenu.m_customHandler; + + // Copy all the menu entries + for( unsigned i = 0; i < aMenu.GetMenuItemCount(); ++i ) + { + wxMenuItem* item = aMenu.FindItemByPosition( i ); + + if( item->IsSubMenu() ) + { +#ifdef DEBUG + // Submenus of a CONTEXT_MENU are supposed to be CONTEXT_MENUs as well + assert( dynamic_cast( item->GetSubMenu() ) ); +#endif + + CONTEXT_MENU* menu = new CONTEXT_MENU( static_cast( *item->GetSubMenu() ) ); + AppendSubMenu( menu, item->GetItemLabel(), wxEmptyString ); + } + else + { + wxMenuItem* newItem = new wxMenuItem( this, item->GetId(), item->GetItemLabel(), + wxEmptyString, item->GetKind() ); + + Append( newItem ); + copyItem( item, newItem ); + } + } + + setupEvents(); + + return *this; +} + + void CONTEXT_MENU::setupEvents() { Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CONTEXT_MENU::onMenuEvent ), NULL, this ); @@ -144,11 +185,12 @@ void CONTEXT_MENU::Clear() { m_titleSet = false; - // Remove all the entries from context menu - for( unsigned i = 0; i < GetMenuItemCount(); ++i ) - Destroy( FindItemByPosition( 0 ) ); - + GetMenuItems().DeleteContents( true ); + GetMenuItems().Clear(); m_toolActions.clear(); + GetMenuItems().DeleteContents( false ); // restore the default so destructor does not go wild + + assert( GetMenuItemCount() == 0 ); } diff --git a/common/tool/tool_action.cpp b/common/tool/tool_action.cpp new file mode 100644 index 0000000000..4d1fd9d658 --- /dev/null +++ b/common/tool/tool_action.cpp @@ -0,0 +1,47 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 CERN + * @author Maciej Suminski + * + * 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 + +std::string TOOL_ACTION::GetToolName() const +{ + int dotCount = std::count( m_name.begin(), m_name.end(), '.' ); + + switch( dotCount ) + { + case 0: + assert( false ); // Invalid action name format + return ""; + + case 1: + return m_name; + + case 2: + return m_name.substr( 0, m_name.rfind( '.' ) ); + + default: + assert( false ); // TODO not implemented + return ""; + } +} diff --git a/common/tool/tool_dispatcher.cpp b/common/tool/tool_dispatcher.cpp index 4e66a1271c..cd416f7c50 100644 --- a/common/tool/tool_dispatcher.cpp +++ b/common/tool/tool_dispatcher.cpp @@ -88,8 +88,8 @@ struct TOOL_DISPATCHER::BUTTON_STATE }; -TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditFrame ) : - m_toolMgr( aToolMgr ), m_editFrame( aEditFrame ) +TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr ) : + m_toolMgr( aToolMgr ) { m_buttons.push_back( new BUTTON_STATE( BUT_LEFT, wxEVT_LEFT_DOWN, wxEVT_LEFT_UP, wxEVT_LEFT_DCLICK ) ); @@ -118,7 +118,7 @@ void TOOL_DISPATCHER::ResetState() KIGFX::VIEW* TOOL_DISPATCHER::getView() { - return m_editFrame->GetGalCanvas()->GetView(); + return static_cast( m_toolMgr->GetEditFrame() )->GetGalCanvas()->GetView(); } @@ -229,7 +229,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) { motion = true; m_lastMousePos = pos; - m_editFrame->UpdateStatusBar(); + static_cast( m_toolMgr->GetEditFrame() )->UpdateStatusBar(); } for( unsigned int i = 0; i < m_buttons.size(); i++ ) @@ -245,7 +245,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) // 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(); + static_cast( m_toolMgr->GetEditFrame() )->GetGalCanvas()->SetFocus(); #endif /* __APPLE__ */ } @@ -288,27 +288,10 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) void TOOL_DISPATCHER::DispatchWxCommand( wxCommandEvent& aEvent ) { - boost::optional evt; - - switch( aEvent.GetId() ) - { - case ID_ZOOM_IN: // toolbar button "Zoom In" - evt = COMMON_ACTIONS::zoomInCenter.MakeEvent(); - break; - - case ID_ZOOM_OUT: // toolbar button "Zoom In" - evt = COMMON_ACTIONS::zoomOutCenter.MakeEvent(); - break; - - case ID_ZOOM_PAGE: // toolbar button "Fit on Screen" - evt = COMMON_ACTIONS::zoomFitScreen.MakeEvent(); - break; - - default: - aEvent.Skip(); - break; - } + boost::optional evt = COMMON_ACTIONS::TranslateLegacyId( aEvent.GetId() ); if( evt ) m_toolMgr->ProcessEvent( *evt ); + else + aEvent.Skip(); } diff --git a/common/tool/tool_event.cpp b/common/tool/tool_event.cpp index 50739ba419..68518a2d50 100644 --- a/common/tool/tool_event.cpp +++ b/common/tool/tool_event.cpp @@ -92,6 +92,7 @@ const std::string TOOL_EVENT::Format() const { TA_CONTEXT_MENU_CHOICE, "context-menu-choice" }, { TA_UNDO_REDO, "undo-redo" }, { TA_ACTION, "action" }, + { TA_ACTIVATE, "activate" }, { 0, "" } }; diff --git a/common/tool/tool_manager.cpp b/common/tool/tool_manager.cpp index 605f8505b3..cf64603b4d 100644 --- a/common/tool/tool_manager.cpp +++ b/common/tool/tool_manager.cpp @@ -25,6 +25,8 @@ #include #include +#include +#include #include #include @@ -32,8 +34,10 @@ #include #include +#include #include +#include #include #include @@ -51,6 +55,32 @@ using boost::optional; /// Struct describing the current execution state of a TOOL struct TOOL_MANAGER::TOOL_STATE { + TOOL_STATE( TOOL_BASE* aTool ) : + theTool( aTool ) + { + clear(); + } + + TOOL_STATE( const TOOL_STATE& aState ) + { + theTool = aState.theTool; + idle = aState.idle; + pendingWait = aState.pendingWait; + pendingContextMenu = aState.pendingContextMenu; + contextMenu = aState.contextMenu; + contextMenuTrigger = aState.contextMenuTrigger; + cofunc = aState.cofunc; + wakeupEvent = aState.wakeupEvent; + waitEvents = aState.waitEvents; + transitions = aState.transitions; + // do not copy stateStack + } + + ~TOOL_STATE() + { + assert( stateStack.empty() ); + } + /// The tool itself TOOL_BASE* theTool; @@ -83,6 +113,21 @@ struct TOOL_MANAGER::TOOL_STATE /// upon the event reception std::vector transitions; + void operator=( const TOOL_STATE& aState ) + { + theTool = aState.theTool; + idle = aState.idle; + pendingWait = aState.pendingWait; + pendingContextMenu = aState.pendingContextMenu; + contextMenu = aState.contextMenu; + contextMenuTrigger = aState.contextMenuTrigger; + cofunc = aState.cofunc; + wakeupEvent = aState.wakeupEvent; + waitEvents = aState.waitEvents; + transitions = aState.transitions; + // do not copy stateStack + } + bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const { return aRhs.theTool == this->theTool; @@ -92,6 +137,59 @@ struct TOOL_MANAGER::TOOL_STATE { return aRhs.theTool != this->theTool; } + + /** + * Function Push() + * Stores the current state of the tool on stack. Stacks are stored internally and are not + * shared between different TOOL_STATE objects. + */ + void Push() + { + stateStack.push( *this ); + + clear(); + } + + /** + * Function Pop() + * Restores state of the tool from stack. Stacks are stored internally and are not + * shared between different TOOL_STATE objects. + * @return True if state was restored, false if the stack was empty. + */ + bool Pop() + { + delete cofunc; + + if( !stateStack.empty() ) + { + *this = stateStack.top(); + stateStack.pop(); + + return true; + } + else + { + cofunc = NULL; + + return false; + } + } + +private: + ///> Stack preserving previous states of a TOOL. + std::stack stateStack; + + ///> Restores the initial state. + void clear() + { + idle = true; + pendingWait = false; + pendingContextMenu = false; + cofunc = NULL; + contextMenu = NULL; + contextMenuTrigger = CMENU_OFF; + transitions.clear(); + } }; @@ -99,6 +197,11 @@ TOOL_MANAGER::TOOL_MANAGER() : m_model( NULL ), m_view( NULL ), m_viewControls( NULL ), m_editFrame( NULL ) { m_actionMgr = new ACTION_MANAGER( this ); + + // Register known actions + std::list& actionList = GetActionList(); + BOOST_FOREACH( TOOL_ACTION* action, actionList ) + RegisterAction( action ); } @@ -113,7 +216,6 @@ TOOL_MANAGER::~TOOL_MANAGER() delete it->first; // delete the tool itself } - m_toolState.clear(); delete m_actionMgr; } @@ -124,18 +226,15 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) wxT( "Adding two tools with the same name may result in unexpected behaviour.") ); wxASSERT_MSG( m_toolIdIndex.find( aTool->GetId() ) == m_toolIdIndex.end(), wxT( "Adding two tools with the same ID may result in unexpected behaviour.") ); + wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(), + wxT( "Adding two tools of the same type may result in unexpected behaviour.") ); - TOOL_STATE* st = new TOOL_STATE; - - st->theTool = aTool; - st->pendingWait = false; - st->pendingContextMenu = false; - st->cofunc = NULL; - st->contextMenuTrigger = CMENU_OFF; + TOOL_STATE* st = new TOOL_STATE( aTool ); m_toolState[aTool] = st; m_toolNameIndex[aTool->GetName()] = st; m_toolIdIndex[aTool->GetId()] = st; + m_toolTypes[typeid( *aTool ).name()] = st->theTool; aTool->m_toolMgr = this; @@ -150,6 +249,7 @@ void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) m_toolState.erase( aTool ); m_toolNameIndex.erase( aTool->GetName() ); m_toolIdIndex.erase( aTool->GetId() ); + m_toolTypes.erase( typeid( *aTool ).name() ); delete st; delete aTool; @@ -191,15 +291,40 @@ void TOOL_MANAGER::UnregisterAction( TOOL_ACTION* aAction ) } -bool TOOL_MANAGER::RunAction( const std::string& aActionName ) +bool TOOL_MANAGER::RunAction( const std::string& aActionName, bool aNow ) { - return m_actionMgr->RunAction( aActionName ); + TOOL_ACTION* action = m_actionMgr->FindAction( aActionName ); + + if( action ) + { + if( aNow ) + { + TOOL_EVENT event = action->MakeEvent(); + ProcessEvent( event ); + } + else + { + PostEvent( action->MakeEvent() ); + } + + return true; + } + + return false; } -void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction ) +void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow ) { - m_actionMgr->RunAction( &aAction ); + if( aNow ) + { + TOOL_EVENT event = aAction.MakeEvent(); + ProcessEvent( event ); + } + else + { + PostEvent( aAction.MakeEvent() ); + } } @@ -207,7 +332,7 @@ bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool ) { wxASSERT( aTool != NULL ); - TOOL_EVENT evt( TC_COMMAND, TA_ACTION, aTool->GetName() ); + TOOL_EVENT evt( TC_COMMAND, TA_ACTIVATE, aTool->GetName() ); ProcessEvent( evt ); return true; @@ -325,6 +450,8 @@ optional TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool, { TOOL_STATE* st = m_toolState[aTool]; + assert( !st->pendingWait ); // everything collapses on two Yield() in a row + // indicate to the manager that we are going to sleep and we shall be // woken up when an event matching aConditions arrive st->pendingWait = true; @@ -349,8 +476,8 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) { if( st->waitEvents.Matches( aEvent ) ) { - // By default, already processed events are not passed further - m_passEvent = false; + // By default, only messages are passed further + m_passEvent = ( aEvent.m_category == TC_MESSAGE ); // got matching event? clear wait list and wake up the coroutine st->wakeupEvent = aEvent; @@ -370,35 +497,31 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent ) BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) { - // the tool scheduled next state(s) by calling Go() - if( !st->pendingWait ) + // no state handler in progress - check if there are any transitions (defined by + // Go() method that match the event. + if( !st->pendingWait && !st->transitions.empty() ) { - // no state handler in progress - check if there are any transitions (defined by - // Go() method that match the event. - if( st->transitions.size() ) + BOOST_FOREACH( TRANSITION& tr, st->transitions ) { - BOOST_FOREACH( TRANSITION& tr, st->transitions ) + if( tr.first.Matches( aEvent ) ) { - if( tr.first.Matches( aEvent ) ) - { - // as the state changes, the transition table has to be set up again - st->transitions.clear(); + // if there is already a context, then store it + if( st->cofunc ) + st->Push(); - // no tool context allocated yet? Create one. - if( !st->cofunc ) - st->cofunc = new COROUTINE( tr.second ); - else - st->cofunc->SetEntry( tr.second ); + // as the state changes, the transition table has to be set up again + st->transitions.clear(); - // got match? Run the handler. - st->cofunc->Call( aEvent ); + st->cofunc = new COROUTINE( tr.second ); - if( !st->cofunc->Running() ) - finishTool( st ); // The couroutine has finished immediately? + // got match? Run the handler. + st->cofunc->Call( aEvent ); - // there is no point in further checking, as transitions got cleared - break; - } + if( !st->cofunc->Running() ) + finishTool( st ); // The couroutine has finished immediately? + + // there is no point in further checking, as transitions got cleared + break; } } } @@ -412,12 +535,7 @@ bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) { // Check if there is a hotkey associated if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) ) - return false; // hotkey event was handled so it does not go any further - } - else if( aEvent.Category() == TC_COMMAND ) // it may be a tool activation event - { - dispatchActivation( aEvent ); - // do not return false, as the event has to go on to the destined tool + return false; // hotkey event was handled so it does not go any further } return true; @@ -426,12 +544,13 @@ bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent ) bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent ) { - // Look for the tool that has the same name as parameter in the processed command TOOL_EVENT - BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) + if( aEvent.IsActivate() ) { - if( st->theTool->GetName() == aEvent.m_commandStr ) + std::map::iterator tool = m_toolNameIndex.find( *aEvent.m_commandStr ); + + if( tool != m_toolNameIndex.end() ) { - runTool( st->theTool ); + runTool( tool->second->theTool ); return true; } } @@ -440,36 +559,8 @@ bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent ) } -void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) +void TOOL_MANAGER::dispatchContextMenu( TOOL_EVENT& aEvent ) { - std::deque::iterator it, itEnd; - - // Find the tool and deactivate it - for( it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it ) - { - if( aState == m_toolIdIndex[*it] ) - { - m_activeTools.erase( it ); - break; - } - } - - delete aState->cofunc; - aState->cofunc = NULL; -} - - -bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) -{ -// wxLogDebug( "event: %s", aEvent.Format().c_str() ); - - // Early dispatch of events destined for the TOOL_MANAGER - if( !dispatchStandardEvents( aEvent ) ) - return false; - - dispatchInternal( aEvent ); - - // popup menu handling BOOST_FOREACH( TOOL_ID toolId, m_activeTools ) { TOOL_STATE* st = m_toolIdIndex[toolId]; @@ -487,6 +578,10 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) if( st->contextMenuTrigger == CMENU_NOW ) st->contextMenuTrigger = CMENU_OFF; + // Temporarily store the cursor position, so the tools could execute actions + // using the point where the user has invoked a context menu + m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); + boost::scoped_ptr menu( new CONTEXT_MENU( *st->contextMenu ) ); GetEditFrame()->PopupMenu( menu.get() ); @@ -497,9 +592,45 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) dispatchInternal( evt ); } + m_viewControls->ForceCursorPosition( false ); + break; } } +} + + +void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) +{ + if( !aState->Pop() ) // if there are no other contexts saved on the stack + { + // find the tool and deactivate it + std::deque::iterator tool = std::find( m_activeTools.begin(), m_activeTools.end(), + aState->theTool->GetId() ); + + if( tool != m_activeTools.end() ) + m_activeTools.erase( tool ); + } +} + + +bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) +{ + // Early dispatch of events destined for the TOOL_MANAGER + if( !dispatchStandardEvents( aEvent ) ) + return false; + + dispatchInternal( aEvent ); + dispatchActivation( aEvent ); + dispatchContextMenu( aEvent ); + + // Dispatch queue + while( !m_eventQueue.empty() ) + { + TOOL_EVENT event = m_eventQueue.front(); + m_eventQueue.pop_front(); + ProcessEvent( event ); + } if( m_view->IsDirty() ) { @@ -521,6 +652,41 @@ void TOOL_MANAGER::ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu, } +bool TOOL_MANAGER::SaveClipboard( const std::string& aText ) +{ + if( wxTheClipboard->Open() ) + { + wxTheClipboard->SetData( new wxTextDataObject( wxString( aText.c_str(), wxConvUTF8 ) ) ); + wxTheClipboard->Close(); + + return true; + } + + return false; +} + + +std::string TOOL_MANAGER::GetClipboard() const +{ + std::string result; + + if( wxTheClipboard->Open() ) + { + if( wxTheClipboard->IsSupported( wxDF_TEXT ) ) + { + wxTextDataObject data; + wxTheClipboard->GetData( data ); + + result = data.GetText().mb_str(); + } + + wxTheClipboard->Close(); + } + + return result; +} + + TOOL_ID TOOL_MANAGER::MakeToolId( const std::string& aToolName ) { static int currentId; diff --git a/common/view/view.cpp b/common/view/view.cpp index f877164c5b..981c8b0d31 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -252,9 +252,7 @@ void VIEW::SetGAL( GAL* aGal ) clearGroupCache(); // every target has to be refreshed - MarkTargetDirty( TARGET_CACHED ); - MarkTargetDirty( TARGET_NONCACHED ); - MarkTargetDirty( TARGET_OVERLAY ); + MarkDirty(); // force the new GAL to display the current viewport. SetCenter( m_center ); @@ -274,12 +272,15 @@ BOX2D VIEW::GetViewport() const } -void VIEW::SetViewport( const BOX2D& aViewport, bool aKeepAspect ) +void VIEW::SetViewport( const BOX2D& aViewport ) { VECTOR2D ssize = ToWorld( m_gal->GetScreenPixelSize(), false ); + + wxASSERT( ssize.x > 0 && ssize.y > 0 ); + VECTOR2D centre = aViewport.Centre(); VECTOR2D vsize = aViewport.GetSize(); - double zoom = 1.0 / std::min( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) ); + double zoom = 1.0 / std::max( fabs( vsize.x / ssize.x ), fabs( vsize.y / ssize.y ) ); SetCenter( centre ); SetScale( GetScale() * zoom ); @@ -305,7 +306,7 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor ) m_scale = aScale; // Redraw everything after the viewport has changed - MarkTargetDirty( TARGET_CACHED ); + MarkDirty(); } @@ -317,7 +318,7 @@ void VIEW::SetCenter( const VECTOR2D& aCenter ) m_gal->ComputeWorldScreenMatrix(); // Redraw everything after the viewport has changed - MarkTargetDirty( TARGET_CACHED ); + MarkDirty(); } @@ -574,7 +575,7 @@ struct VIEW::drawItem } VIEW* view; - int layer, layersCount, layers[VIEW_MAX_LAYERS]; + int layer, layers[VIEW_MAX_LAYERS]; }; @@ -734,9 +735,7 @@ void VIEW::ClearTargets() m_gal->ClearTarget( TARGET_NONCACHED ); m_gal->ClearTarget( TARGET_CACHED ); - MarkTargetDirty( TARGET_NONCACHED ); - MarkTargetDirty( TARGET_CACHED ); - MarkTargetDirty( TARGET_OVERLAY ); + MarkDirty(); } if( IsTargetDirty( TARGET_OVERLAY ) ) @@ -855,7 +854,7 @@ void VIEW::sortLayers() sort( m_orderedLayers.begin(), m_orderedLayers.end(), compareRenderingOrder ); - MarkTargetDirty( TARGET_CACHED ); + MarkDirty(); } @@ -1020,33 +1019,34 @@ void VIEW::UpdateItems() m_needsUpdate.clear(); } -struct VIEW::extentsVisitor { - BOX2I extents; - bool first; - extentsVisitor() - { - first = true; - } +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; + } +}; - 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 ); diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 16de3a139c..6d9dae1bba 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -30,9 +30,9 @@ #ifndef PANELGAL_WXSTRUCT_H #define PANELGAL_WXSTRUCT_H -#include #include - +#include +#include #include class BOARD; @@ -68,6 +68,15 @@ public: */ void SwitchBackend( GalType aGalType ); + /** + * Function GetBackend + * Returns the type of backend currently used by GAL canvas. + */ + inline GalType GetBackend() const + { + return m_backend; + } + /** * Function GetGAL() * Returns a pointer to the GAL instance used in the panel. @@ -99,17 +108,16 @@ public: } /// @copydoc wxWindow::Refresh() - void Refresh( bool eraseBackground = true, const wxRect* rect = NULL ); + void Refresh( bool aEraseBackground = true, const wxRect* aRect = NULL ); /** * Function SetEventDispatcher() * Sets a dispatcher that processes events and forwards them to tools. * @param aEventDispatcher is the object that will be used for dispatching events. + * DRAW_PANEL_GAL does not take over the ownership. Passing NULL disconnects all event + * handlers from the DRAW_PANEL_GAL and parent frame. */ - void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher ) - { - m_eventDispatcher = aEventDispatcher; - } + void SetEventDispatcher( TOOL_DISPATCHER* aEventDispatcher ); /** * Function StartDrawing() @@ -124,16 +132,30 @@ public: */ void StopDrawing(); + /** + * Function SetHighContrastLayer + * Takes care of display settings for the given layer to be displayed in high contrast mode. + */ + virtual void SetHighContrastLayer( LAYER_NUM aLayer ); + + /** + * Function SetTopLayer + * Moves the selected layer to the top, so it is displayed above all others. + */ + virtual void SetTopLayer( LAYER_NUM aLayer ); + protected: void onPaint( wxPaintEvent& WXUNUSED( aEvent ) ); void onSize( wxSizeEvent& aEvent ); void onEvent( wxEvent& aEvent ); void onEnter( wxEvent& aEvent ); - void onRefreshTimer ( wxTimerEvent& aEvent ); - void skipEvent( wxEvent& aEvent ); + void onRefreshTimer( wxTimerEvent& aEvent ); static const int MinRefreshPeriod = 17; ///< 60 FPS. + /// Pointer to the parent window + wxWindow* m_parent; + /// Last timestamp when the panel was refreshed wxLongLong m_lastRefresh; @@ -159,7 +181,7 @@ protected: KIGFX::WX_VIEW_CONTROLS* m_viewControls; /// Currently used GAL - GalType m_currentGal; + GalType m_backend; /// Processes and forwards events to tools TOOL_DISPATCHER* m_eventDispatcher; diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index d995b14fcb..dbb066f4a8 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -148,15 +148,15 @@ struct remove_pointer * @return true, if aObject type equals T. */ template -bool IsA(const I *aObject) +bool IsA( const I* aObject ) { - return aObject && remove_pointer::type::ClassOf(aObject); + return aObject && remove_pointer::type::ClassOf( aObject ); } template -bool IsA(const I& aObject) +bool IsA( const I& aObject ) { - return remove_pointer::type::ClassOf(&aObject); + return remove_pointer::type::ClassOf( &aObject ); } /** @@ -168,7 +168,7 @@ bool IsA(const I& aObject) * @return down-casted object or NULL if type doesn't match Casted. */ template -Casted dyn_cast(From aObject) +Casted dyn_cast( From aObject ) { if( remove_pointer::type::ClassOf ( aObject ) ) return static_cast( aObject ); @@ -177,4 +177,3 @@ Casted dyn_cast(From aObject) } #endif // __KICAD_TYPEINFO_H - diff --git a/include/draw_frame.h b/include/draw_frame.h index 6608c4b634..829c9317b5 100644 --- a/include/draw_frame.h +++ b/include/draw_frame.h @@ -675,7 +675,6 @@ public: * @return True for GAL-based canvas, false for standard canvas. */ bool IsGalCanvasActive() const { return m_galCanvasActive; } - void SetGalCanvasActive( bool aState ) { m_galCanvasActive = aState; } /** * Function GetGalCanvas diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index e0b1dba963..dca18acc05 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -229,6 +229,9 @@ public: // Cursor // ------- + /// @copydoc GAL::SetCursorSize() + virtual void SetCursorSize( unsigned int aCursorSize ); + /// @copydoc GAL::DrawCursor() virtual void DrawCursor( const VECTOR2D& aCursorPosition ); diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 24f207f355..3fef15d1fc 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -631,6 +631,9 @@ public: inline void SetGridOrigin( const VECTOR2D& aGridOrigin ) { gridOrigin = aGridOrigin; + + gridOffset = VECTOR2D( (long) gridOrigin.x % (long) gridSize.x, + (long) gridOrigin.y % (long) gridSize.y ); } /** @@ -661,6 +664,9 @@ public: inline void SetGridSize( const VECTOR2D& aGridSize ) { gridSize = aGridSize; + + gridOffset = VECTOR2D( (long) gridOrigin.x % (long) gridSize.x, + (long) gridOrigin.y % (long) gridSize.y ); } /** @@ -777,12 +783,22 @@ public: cursorColor = aCursorColor; } + /** + * @brief Returns the cursor size. + * + * @return The current cursor size (in pixels). + */ + inline unsigned int GetCursorSize() const + { + return cursorSize; + } + /** * @brief Set the cursor size. * * @param aCursorSize is the size of the cursor expressed in pixels. */ - inline void SetCursorSize( unsigned int aCursorSize ) + virtual inline void SetCursorSize( unsigned int aCursorSize ) { cursorSize = aCursorSize; } diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h index 642a7f7bbc..c06add7d2e 100644 --- a/include/gal/opengl/opengl_compositor.h +++ b/include/gal/opengl/opengl_compositor.h @@ -80,18 +80,17 @@ protected: GLuint attachmentPoint; ///< Point to which an image from texture is attached } OPENGL_BUFFER; - bool m_initialized; ///< Initialization status flag - unsigned int m_current; ///< Currently used buffer handle - GLuint m_framebuffer; ///< Main FBO handle - GLuint m_depthBuffer; ///< Depth buffer handle - unsigned int m_maxBuffers; ///< Maximal amount of buffers + bool m_initialized; ///< Initialization status flag + unsigned int m_current; ///< Currently used buffer handle + GLuint m_framebuffer; ///< Main FBO handle + GLuint m_depthBuffer; ///< Depth buffer handle typedef std::deque OPENGL_BUFFERS; /// Stores information about initialized buffers - OPENGL_BUFFERS m_buffers; + OPENGL_BUFFERS m_buffers; /// Store the currently used FBO name in case there was more than one compositor used - static GLuint m_currentFbo; + GLuint m_currentFbo; /** * Function clean() @@ -100,7 +99,7 @@ protected: void clean(); /// Returns number of used buffers - unsigned int usedBuffers() + inline unsigned int usedBuffers() { return m_buffers.size(); } diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h index 10c4fea54d..417cdd389e 100644 --- a/include/gal/opengl/opengl_gal.h +++ b/include/gal/opengl/opengl_gal.h @@ -37,22 +37,12 @@ #include #include -#include #include -#include -#include -#include -#include -#include #include #include #include -#include -#include -#include - #ifndef CALLBACK #define CALLBACK #endif @@ -262,8 +252,8 @@ private: static const int CIRCLE_POINTS = 64; ///< The number of points for circle approximation static const int CURVE_POINTS = 32; ///< The number of points for curve approximation - wxClientDC* clientDC; ///< Drawing context - wxGLContext* glContext; ///< OpenGL context of wxWidgets + wxPaintDC* clientDC; ///< Drawing context + static wxGLContext* glContext; ///< OpenGL context of wxWidgets wxWindow* parentWindow; ///< Parent window wxEvtHandler* mouseListener; wxEvtHandler* paintListener; diff --git a/include/gal/opengl/vertex_container.h b/include/gal/opengl/vertex_container.h index 50c8d7fec1..807731bb37 100644 --- a/include/gal/opengl/vertex_container.h +++ b/include/gal/opengl/vertex_container.h @@ -163,7 +163,7 @@ protected: * returns size of the reserved memory space. * @return Size of the reserved memory space (expressed as a number of vertices). */ - unsigned int reservedSpace() + inline unsigned int reservedSpace() { return m_currentSize - m_freeSpace; } diff --git a/include/tool/action_manager.h b/include/tool/action_manager.h index 626f795eff..7c4c52cd4d 100644 --- a/include/tool/action_manager.h +++ b/include/tool/action_manager.h @@ -75,20 +75,12 @@ public: static int MakeActionId( const std::string& aActionName ); /** - * Function RunAction() - * Runs an action with a given name (if there is one available). - * @param aActionName is the name of action to be run. - * @return True if there was an action associated with the name, false otherwise. + * Function FindAction() + * Finds an action with a given name (if there is one available). + * @param aActionName is the searched action. + * @return Pointer to a TOOL_ACTION object or NULL if there is no such action. */ - bool RunAction( const std::string& aActionName ) const; - - /** - * Function RunAction() - * Prepares an appropriate event and sends it to the destination specified in a TOOL_ACTION - * object. - * @param aAction is the action to be run. - */ - void RunAction( const TOOL_ACTION* aAction ) const; + TOOL_ACTION* FindAction( const std::string& aActionName ) const; /** * Function RunHotKey() diff --git a/include/tool/context_menu.h b/include/tool/context_menu.h index e50ef207c2..72b69315d6 100644 --- a/include/tool/context_menu.h +++ b/include/tool/context_menu.h @@ -47,6 +47,10 @@ public: ///> Copy constructor CONTEXT_MENU( const CONTEXT_MENU& aMenu ); + CONTEXT_MENU& operator=( const CONTEXT_MENU& aMenu ); + + virtual ~CONTEXT_MENU() {} + /** * Function SetTitle() * Sets title for the context menu. The title is shown as a text label shown on the top of @@ -72,7 +76,6 @@ 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 diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h index 9d502ff5c4..3385dece7d 100644 --- a/include/tool/coroutine.h +++ b/include/tool/coroutine.h @@ -56,11 +56,10 @@ template class COROUTINE { public: - COROUTINE() + COROUTINE() : + m_saved( NULL ), m_self( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ), + m_running( false ) { - m_stackSize = c_defaultStackSize; - m_stack = NULL; - m_saved = NULL; } /** @@ -69,7 +68,8 @@ public: */ template COROUTINE( T* object, ReturnType(T::* ptr)( ArgType ) ) : - m_func( object, ptr ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ) + m_func( object, ptr ), m_self( NULL ), m_saved( NULL ), m_stack( NULL ), + m_stackSize( c_defaultStackSize ), m_running( false ) { } @@ -78,8 +78,10 @@ public: * Creates a coroutine from a delegate object */ COROUTINE( DELEGATE aEntry ) : - m_func( aEntry ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ) - {}; + m_func( aEntry ), m_saved( NULL ), m_self( NULL ), m_stack( NULL ), + m_stackSize( c_defaultStackSize ), m_running( false ) + { + } ~COROUTINE() { @@ -115,7 +117,7 @@ public: } /** - * * Function SetEntry() + * Function SetEntry() * * Defines the entry point for the coroutine, if not set in the constructor. */ @@ -138,6 +140,12 @@ public: // align to 16 bytes void* sp = (void*) ( ( ( (ptrdiff_t) m_stack ) + m_stackSize - 0xf ) & ( ~0x0f ) ); + // correct the stack size + m_stackSize -= ( (size_t) m_stack + m_stackSize - (size_t) sp ); + + assert( m_self == NULL ); + assert( m_saved == NULL ); + m_args = &aArgs; m_self = boost::context::make_fcontext( sp, m_stackSize, callerStub ); m_saved = new boost::context::fcontext_t(); diff --git a/include/tool/tool_action.h b/include/tool/tool_action.h index 4097fd2f7f..5db3701301 100644 --- a/include/tool/tool_action.h +++ b/include/tool/tool_action.h @@ -29,7 +29,6 @@ #include #include -#include #include /** @@ -47,10 +46,10 @@ class TOOL_ACTION public: TOOL_ACTION( const std::string& aName, TOOL_ACTION_SCOPE aScope = AS_CONTEXT, int aDefaultHotKey = 0, const std::string& aMenuItem = std::string( "" ), - const std::string& aMenuDesc = std::string( "" ) ) : + const std::string& aMenuDesc = std::string( "" ), TOOL_ACTION_FLAGS aFlags = AF_NONE ) : m_name( aName ), m_scope( aScope ), m_defaultHotKey( aDefaultHotKey ), m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ), - m_menuDescription( aMenuDesc ), m_id( -1 ) + m_menuDescription( aMenuDesc ), m_id( -1 ), m_flags( aFlags ) { TOOL_MANAGER::GetActionList().push_back( this ); } @@ -132,7 +131,6 @@ public: * Checks if the action has a hot key assigned. * * @return True if there is a hot key assigned, false otherwise. - * */ bool HasHotKey() const { @@ -141,14 +139,19 @@ public: /** * Function MakeEvent() - * Returns the event associated with the action (ie. the event that will be sent after + * Returns the event associated with the action (i.e. the event that will be sent after * activating the action). * * @return The event associated with the action. */ TOOL_EVENT MakeEvent() const { - return TOOL_EVENT( TC_COMMAND, TA_ACTION, m_name, m_scope ); + if( IsActivation() ) + return TOOL_EVENT( TC_COMMAND, TA_ACTIVATE, m_name, m_scope ); + else if( IsNotification() ) + return TOOL_EVENT( TC_MESSAGE, TA_ANY, m_name, m_scope ); + else + return TOOL_EVENT( TC_COMMAND, TA_ACTION, m_name, m_scope ); } const std::string& GetMenuItem() const @@ -181,30 +184,31 @@ public: * stripped of the last part (e.g. for "pcbnew.InteractiveDrawing.drawCircle" it is * "pcbnew.InteractiveDrawing"). */ - std::string GetToolName() const + std::string GetToolName() const; + + /** + * Returns true if the action is intended to activate a tool. + */ + bool IsActivation() const { - return m_name.substr( 0, m_name.rfind( '.' ) ); + return m_flags & AF_ACTIVATE; + } + + /** + * Returns true if the action is a notification. + */ + bool IsNotification() const + { + return m_flags & AF_NOTIFY; } private: friend class ACTION_MANAGER; - /// Assigns an unique identifier. It is given by an instance of ACTION_MANAGER. - void setId( int aId ) - { - 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; - /// Scope of the action (ie. the event that is issued after activation). + /// Scope of the action (i.e. the event that is issued after activation). TOOL_ACTION_SCOPE m_scope; /// Default hot key that activates the action. @@ -225,8 +229,8 @@ private: /// Unique ID for fast matching. Assigned by ACTION_MANAGER. int m_id; - /// Action manager that handles this TOOL_ACTION. - ACTION_MANAGER* m_actionMgr; + /// Action flags + TOOL_ACTION_FLAGS m_flags; /// Origin of the action // const TOOL_BASE* m_origin; diff --git a/include/tool/tool_dispatcher.h b/include/tool/tool_dispatcher.h index 8ecd893db1..8a7289e56c 100644 --- a/include/tool/tool_dispatcher.h +++ b/include/tool/tool_dispatcher.h @@ -26,7 +26,7 @@ #define __TOOL_DISPATCHER_H #include - +#include #include class TOOL_MANAGER; @@ -47,7 +47,7 @@ class VIEW; * - issues TOOL_EVENTS to the tool manager */ -class TOOL_DISPATCHER +class TOOL_DISPATCHER : public wxEvtHandler { public: /** @@ -56,7 +56,7 @@ public: * @param aToolMgr: tool manager instance the events will be sent to * @param aEditFrame: the frame wx events come from */ - TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditFrame ); + TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr ); virtual ~TOOL_DISPATCHER(); /** @@ -128,9 +128,6 @@ private: ///> Instance of tool manager that cooperates with the dispatcher. TOOL_MANAGER* m_toolMgr; - - ///> Instance of wxFrame that is the source of UI events. - PCB_BASE_FRAME* m_editFrame; }; #endif diff --git a/include/tool/tool_event.h b/include/tool/tool_event.h index bdfe8a8a10..bffca332f5 100644 --- a/include/tool/tool_event.h +++ b/include/tool/tool_event.h @@ -91,9 +91,12 @@ enum TOOL_ACTIONS // This event is sent *before* undo/redo command is performed. TA_UNDO_REDO = 0x10000, - // Tool action (allows to control tools) + // Tool action (allows to control tools). TA_ACTION = 0x20000, + // Tool activation event. + TA_ACTIVATE = 0x40000, + TA_ANY = 0xffffffff }; @@ -123,6 +126,14 @@ enum TOOL_ACTION_SCOPE AS_GLOBAL ///> Global action (toolbar/main menu event, global shortcut) }; +/// Flags for tool actions +enum TOOL_ACTION_FLAGS +{ + AF_NONE = 0, + AF_ACTIVATE = 1, ///> Action activates a tool + AF_NOTIFY = 2 ///> Action is a notification (it is by default passed to all tools) +}; + /// Defines when a context menu is opened. enum CONTEXT_MENU_TRIGGER { @@ -265,6 +276,11 @@ public: return m_actions == TA_CANCEL_TOOL; } + bool IsActivate() const + { + return m_actions == TA_ACTIVATE; + } + ///> Returns information about key modifiers state (Ctrl, Alt, etc.) int Modifier( int aMask = MD_MODIFIER_MASK ) const { @@ -313,14 +329,11 @@ public: if( m_category == TC_COMMAND || m_category == TC_MESSAGE ) { - if( m_commandStr && aEvent.m_commandStr ) + if( (bool) m_commandStr && (bool) aEvent.m_commandStr ) return *m_commandStr == *aEvent.m_commandStr; - if( m_commandId && aEvent.m_commandId ) + if( (bool) m_commandId && (bool) aEvent.m_commandId ) return *m_commandId == *aEvent.m_commandId; - - // Command-type event has to contain either id or string - assert( false ); } return true; @@ -334,11 +347,16 @@ public: */ bool IsAction( const TOOL_ACTION* aAction ) const; - boost::optional GetCommandId() + boost::optional GetCommandId() const { return m_commandId; } + boost::optional GetCommandStr() const + { + return m_commandStr; + } + private: friend class TOOL_MANAGER; @@ -496,7 +514,6 @@ inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEventA, const TOOL_E return l; } - inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& aEvent, const TOOL_EVENT_LIST& aEventList ) { diff --git a/include/tool/tool_manager.h b/include/tool/tool_manager.h index c8861c7ff1..e5d4ce9458 100644 --- a/include/tool/tool_manager.h +++ b/include/tool/tool_manager.h @@ -26,8 +26,9 @@ #ifndef __TOOL_MANAGER_H #define __TOOL_MANAGER_H -#include #include +#include +#include #include @@ -105,17 +106,21 @@ public: * Runs the specified action. The common format for action names is "application.ToolName.Action". * * @param aActionName is the name of action to be invoked. - * @return True if the action finished successfully, false otherwise. + * @param aNow decides if the action has to be run immediately or after the current coroutine + * is preemptied. + * @return False if the action was not found. */ - bool RunAction( const std::string& aActionName ); + bool RunAction( const std::string& aActionName, bool aNow = false ); /** * Function RunAction() * Runs the specified action. * * @param aAction is the action to be invoked. + * @param aNow decides if the action has to be run immediately or after the current coroutine + * is preemptied. */ - void RunAction( const TOOL_ACTION& aAction ); + void RunAction( const TOOL_ACTION& aAction, bool aNow = false ); /** * Function FindTool() @@ -135,6 +140,21 @@ public: */ TOOL_BASE* FindTool( const std::string& aName ) const; + /* + * Function GetTool() + * Returns the tool of given type or NULL if there is no such tool registered. + */ + template + T* GetTool() + { + std::map::iterator tool = m_toolTypes.find( typeid( T ).name() ); + + if( tool != m_toolTypes.end() ) + return static_cast( tool->second ); + + return NULL; + } + /** * Function ResetTools() * Resets all tools (i.e. calls their Reset() method). @@ -142,11 +162,20 @@ public: void ResetTools( TOOL_BASE::RESET_REASON aReason ); /** - * Takes an event from the TOOL_DISPATCHER and propagates it to - * tools that requested events of matching type(s) + * Propagates an event to tools that requested events of matching type(s). + * @param aEvent is the event to be processed. */ bool ProcessEvent( TOOL_EVENT& aEvent ); + /** + * Puts an event to the event queue to be processed at the end of event processing cycle. + * @param aEvent is the event to be put into the queue. + */ + inline void PostEvent( const TOOL_EVENT& aEvent ) + { + m_eventQueue.push_back( aEvent ); + } + /** * Sets the work environment (model, view, view controls and the parent window). * These are made available to the tool. Called by the parent frame (PCB_EDIT_FRAME) @@ -161,17 +190,17 @@ public: return m_view; } - KIGFX::VIEW_CONTROLS* GetViewControls() const + inline KIGFX::VIEW_CONTROLS* GetViewControls() const { return m_viewControls; } - EDA_ITEM* GetModel() const + inline EDA_ITEM* GetModel() const { return m_model; } - wxWindow* GetEditFrame() const + inline wxWindow* GetEditFrame() const { return m_editFrame; } @@ -181,7 +210,7 @@ public: * (was invoked the most recently). * @return Id of the currently used tool. */ - int GetCurrentToolId() const + inline int GetCurrentToolId() const { return m_activeTools.front(); } @@ -191,7 +220,7 @@ public: * (was invoked the most recently). * @return Pointer to the currently used tool. */ - TOOL_BASE* GetCurrentTool() const + inline TOOL_BASE* GetCurrentTool() const { return FindTool( GetCurrentToolId() ); } @@ -241,6 +270,19 @@ public: m_passEvent = true; } + /** + * Stores an information to the system clipboard. + * @param aText is the information to be stored. + * @return False if error occured. + */ + bool SaveClipboard( const std::string& aText ); + + /** + * Returns the information currently stored in the system clipboard. If data stored in the + * clipboard is in non-text format, empty string is returned. + */ + std::string GetClipboard() const; + /** * Returns list of TOOL_ACTIONs. TOOL_ACTIONs add themselves to the list upon their * creation. @@ -258,6 +300,10 @@ private: struct TOOL_STATE; typedef std::pair TRANSITION; + /** + * Function dispatchInternal + * Passes an event at first to the active tools, then to all others. + */ void dispatchInternal( TOOL_EVENT& aEvent ); /** @@ -276,6 +322,12 @@ private: */ bool dispatchActivation( TOOL_EVENT& aEvent ); + /** + * Function dispatchContextMenu() + * Handles context menu related events. + */ + void dispatchContextMenu( TOOL_EVENT& aEvent ); + /** * Function invokeTool() * Invokes a tool by sending a proper event (in contrary to runTool, which makes the tool run @@ -349,6 +401,9 @@ private: /// Index of the registered tools current states, associated by tools' names. std::map m_toolNameIndex; + /// Index of the registered tools to easily lookup by their type. + std::map m_toolTypes; + /// Index of the registered tools current states, associated by tools' ID numbers. std::map m_toolIdIndex; @@ -363,11 +418,11 @@ private: KIGFX::VIEW_CONTROLS* m_viewControls; wxWindow* m_editFrame; + /// Queue that stores events to be processed at the end of the event processing cycle. + std::list m_eventQueue; + /// Flag saying if the currently processed event should be passed to other tools. bool m_passEvent; - - /// Pointer to the tool on the top of the active tools stack. - TOOL_STATE* m_currentTool; }; #endif diff --git a/include/view/view.h b/include/view/view.h index 1857664af9..529f3c63ce 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -159,9 +159,8 @@ public: * Function SetViewport() * Sets the visible area of the VIEW. * @param aViewport: desired visible area, in world space coordinates. - * @param aKeepProportions: when true, the X/Y size proportions are kept. */ - void SetViewport( const BOX2D& aViewport, bool aKeepProportions = true ); + void SetViewport( const BOX2D& aViewport ); /** * Function GetViewport() @@ -201,7 +200,7 @@ public: * Function GetScale() * @return Current scalefactor of this VIEW */ - double GetScale() const + double GetScale() const { return m_scale; } diff --git a/include/wxBasePcbFrame.h b/include/wxBasePcbFrame.h index d95bdfc64c..ebc694a0f6 100644 --- a/include/wxBasePcbFrame.h +++ b/include/wxBasePcbFrame.h @@ -110,10 +110,6 @@ protected: MODULE* loadFootprint( const FPID& aFootprintId ) throw( IO_ERROR, PARSE_ERROR ); - ///> Rendering order of layers on GAL-based canvas (lower index in the array - ///> means that layer is displayed closer to the user, ie. on the top). - static const LAYER_NUM GAL_LAYER_ORDER[]; - public: PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, @@ -617,6 +613,24 @@ public: virtual void SwitchLayer( wxDC* DC, LAYER_ID layer ); + /** + * Function SetActiveLayer + * will change the currently active layer to \a aLayer. + */ + virtual void SetActiveLayer( LAYER_ID aLayer ) + { + ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer = aLayer; + } + + /** + * Function GetActiveLayer + * returns the active layer + */ + virtual LAYER_ID GetActiveLayer() const + { + return ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer; + } + void LoadSettings( wxConfigBase* aCfg ); // override virtual void SaveSettings( wxConfigBase* aCfg ); // override virtual diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 8153fd9d5e..cc2650fcde 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -30,7 +30,7 @@ #define WXPCB_STRUCT_H_ -#include +#include #include #include #include @@ -73,7 +73,7 @@ namespace PCB { struct IFACE; } // KIFACE_I is in pcbnew.cpp * * See also class PCB_BASE_FRAME(): Basic class for Pcbnew and GerbView. */ -class PCB_EDIT_FRAME : public PCB_BASE_FRAME +class PCB_EDIT_FRAME : public PCB_BASE_EDIT_FRAME { friend class PCB::IFACE; friend class PCB_LAYER_WIDGET; @@ -87,9 +87,6 @@ class PCB_EDIT_FRAME : public PCB_BASE_FRAME /// The auxiliary right vertical tool bar used to access the microwave tools. wxAuiToolBar* m_microWaveToolBar; - /// User defined rotation angle (in tenths of a degree). - int m_rotationAngle; - /** * Function loadFootprints * loads the footprints for each #COMPONENT in \a aNetlist from the list of libraries. @@ -120,9 +117,8 @@ protected: bool m_useCmpFileForFpNames; ///< is true, use the .cmp file from CvPcb, else use the netlist // to know the footprint name of components. + // The Tool Framework initalization void setupTools(); - void destroyTools(); - void onGenericCommand( wxCommandEvent& aEvent ); // we'll use lower case function names for private member functions. void createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* aPopMenu ); @@ -252,6 +248,7 @@ public: void OnUpdateAutoPlaceModulesMode( wxUpdateUIEvent& aEvent ); void OnUpdateAutoPlaceTracksMode( wxUpdateUIEvent& aEvent ); void OnUpdateMuWaveToolbar( wxUpdateUIEvent& aEvent ); + void OnLayerColorChange( wxCommandEvent& aEvent ); /** * Function RecordMacros. @@ -314,9 +311,6 @@ public: */ virtual void SetGridColor(EDA_COLOR_T aColor); - int GetRotationAngle() const { return m_rotationAngle; } - void SetRotationAngle( int aRotationAngle ); - // Configurations: void Process_Config( wxCommandEvent& event ); @@ -531,33 +525,12 @@ public: */ virtual void OnModify(); - /** - * Function SetHighContrastLayer - * takes care of display settings for the given layer to be displayed in high contrast mode. - */ - void SetHighContrastLayer( LAYER_ID aLayer ); - - /** - * Function SetTopLayer - * moves the selected layer to the top, so it is displayed above all others. - */ - void SetTopLayer( LAYER_ID aLayer ); - /** * Function SetActiveLayer * will change the currently active layer to \a aLayer and also * update the PCB_LAYER_WIDGET. */ - void SetActiveLayer( LAYER_ID aLayer, bool doLayerWidgetUpdate = true ); - - /** - * Function GetActiveLayer - * returns the active layer - */ - LAYER_ID GetActiveLayer() const - { - return ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer; - } + virtual void SetActiveLayer( LAYER_ID aLayer ); /** * Function IsElementVisible @@ -679,22 +652,22 @@ public: bool aRebuildRatsnet = true ); /** - * Function GetBoardFromRedoList + * Function RestoreCopyFromRedoList * Redo the last edition: * - Save the current board in Undo list * - Get an old version of the board from Redo list * @return none */ - void GetBoardFromRedoList( wxCommandEvent& aEvent ); + void RestoreCopyFromRedoList( wxCommandEvent& aEvent ); /** - * Function GetBoardFromUndoList + * Function RestoreCopyFromUndoList * Undo the last edition: * - Save the current board in Redo list * - Get an old version of the board from Undo list * @return none */ - void GetBoardFromUndoList( wxCommandEvent& aEvent ); + void RestoreCopyFromUndoList( wxCommandEvent& aEvent ); /* Block operations: */ @@ -890,12 +863,6 @@ public: /// @copydoc PCB_BASE_FRAME::SetBoard() void SetBoard( BOARD* aBoard ); - /** - * Function ViewReloadBoard - * adds all items from the current board to the VIEW, so they can be displayed by GAL. - */ - void ViewReloadBoard( const BOARD* aBoard ) const; - // Drc control /* function GetDrcController diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index d01059707e..8b66ab9a49 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -59,6 +59,8 @@ set( PCBNEW_DIALOGS dialogs/dialog_edit_module_for_Modedit.cpp dialogs/dialog_edit_module_text.cpp dialogs/dialog_edit_module_text_base.cpp + dialogs/dialog_enum_pads.cpp + dialogs/dialog_enum_pads_base.cpp dialogs/dialog_exchange_modules_base.cpp dialogs/dialog_export_idf.cpp dialogs/dialog_export_idf_base.cpp @@ -160,6 +162,7 @@ set( PCBNEW_CLASS_SRCS tool_modview.cpp modview_frame.cpp pcbframe.cpp + pcb_base_edit_frame.cpp attribut.cpp board_items_to_polygon_shape_transform.cpp board_undo_redo.cpp @@ -221,6 +224,7 @@ set( PCBNEW_CLASS_SRCS pad_edition_functions.cpp pcbnew_config.cpp pcbplot.cpp + pcb_draw_panel_gal.cpp plot_board_layers.cpp plot_brditems_plotter.cpp print_board_functions.cpp @@ -254,6 +258,7 @@ set( PCBNEW_CLASS_SRCS tools/selection_tool.cpp tools/selection_area.cpp + tools/selection_conditions.cpp tools/bright_box.cpp tools/edit_points.cpp tools/edit_constraints.cpp @@ -261,7 +266,9 @@ set( PCBNEW_CLASS_SRCS tools/drawing_tool.cpp tools/edit_tool.cpp tools/pcbnew_control.cpp - tools/pcb_tools.cpp + tools/pcb_editor_control.cpp + tools/module_tools.cpp + tools/placement_tool.cpp tools/common_actions.cpp ) diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index f45df75edb..8369cb0a65 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -51,7 +51,7 @@ #include #include -#include +#include #include #include #include @@ -75,82 +75,6 @@ static const wxChar DisplayModuleTextEntry[] = wxT( "DiModTx" ); static const wxChar FastGrid1Entry[] = wxT( "FastGrid1" ); static const wxChar FastGrid2Entry[] = wxT( "FastGrid2" ); -const LAYER_NUM PCB_BASE_FRAME::GAL_LAYER_ORDER[] = -{ - ITEM_GAL_LAYER( GP_OVERLAY ), - ITEM_GAL_LAYER( DRC_VISIBLE ), - NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), - Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts, - - // UNUSED_LAYER_29, UNUSED_LAYER_30, UNUSED_LAYER_31, - - ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ), - ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE), ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ), - - ITEM_GAL_LAYER( RATSNEST_VISIBLE ), - ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), - ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), - - NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_FR_VISIBLE ), F_Mask, - NETNAMES_GAL_LAYER( F_Cu ), F_Cu, - F_SilkS, F_Paste, F_Adhes, - -#if 0 // was: - NETNAMES_GAL_LAYER( LAYER_15_NETNAMES_VISIBLE ), LAYER_N_15, - NETNAMES_GAL_LAYER( LAYER_14_NETNAMES_VISIBLE ), LAYER_N_14, - NETNAMES_GAL_LAYER( LAYER_13_NETNAMES_VISIBLE ), LAYER_N_13, - NETNAMES_GAL_LAYER( LAYER_12_NETNAMES_VISIBLE ), LAYER_N_12, - NETNAMES_GAL_LAYER( LAYER_11_NETNAMES_VISIBLE ), LAYER_N_11, - NETNAMES_GAL_LAYER( LAYER_10_NETNAMES_VISIBLE ), LAYER_N_10, - NETNAMES_GAL_LAYER( LAYER_9_NETNAMES_VISIBLE ), LAYER_N_9, - NETNAMES_GAL_LAYER( LAYER_8_NETNAMES_VISIBLE ), LAYER_N_8, - NETNAMES_GAL_LAYER( LAYER_7_NETNAMES_VISIBLE ), LAYER_N_7, - NETNAMES_GAL_LAYER( LAYER_6_NETNAMES_VISIBLE ), LAYER_N_6, - NETNAMES_GAL_LAYER( LAYER_5_NETNAMES_VISIBLE ), LAYER_N_5, - NETNAMES_GAL_LAYER( LAYER_4_NETNAMES_VISIBLE ), LAYER_N_4, - NETNAMES_GAL_LAYER( LAYER_3_NETNAMES_VISIBLE ), LAYER_N_3, - NETNAMES_GAL_LAYER( LAYER_2_NETNAMES_VISIBLE ), LAYER_N_2, -#else - - NETNAMES_GAL_LAYER( In1_Cu ), In1_Cu, - NETNAMES_GAL_LAYER( In2_Cu ), In2_Cu, - NETNAMES_GAL_LAYER( In3_Cu ), In3_Cu, - NETNAMES_GAL_LAYER( In4_Cu ), In4_Cu, - NETNAMES_GAL_LAYER( In5_Cu ), In5_Cu, - NETNAMES_GAL_LAYER( In6_Cu ), In6_Cu, - NETNAMES_GAL_LAYER( In7_Cu ), In7_Cu, - NETNAMES_GAL_LAYER( In8_Cu ), In8_Cu, - NETNAMES_GAL_LAYER( In9_Cu ), In9_Cu, - NETNAMES_GAL_LAYER( In10_Cu ), In10_Cu, - NETNAMES_GAL_LAYER( In11_Cu ), In11_Cu, - NETNAMES_GAL_LAYER( In12_Cu ), In12_Cu, - NETNAMES_GAL_LAYER( In13_Cu ), In13_Cu, - NETNAMES_GAL_LAYER( In14_Cu ), In14_Cu, - NETNAMES_GAL_LAYER( In15_Cu ), In15_Cu, - NETNAMES_GAL_LAYER( In16_Cu ), In16_Cu, - NETNAMES_GAL_LAYER( In17_Cu ), In17_Cu, - NETNAMES_GAL_LAYER( In18_Cu ), In18_Cu, - NETNAMES_GAL_LAYER( In19_Cu ), In19_Cu, - NETNAMES_GAL_LAYER( In20_Cu ), In20_Cu, - NETNAMES_GAL_LAYER( In21_Cu ), In21_Cu, - NETNAMES_GAL_LAYER( In22_Cu ), In22_Cu, - NETNAMES_GAL_LAYER( In23_Cu ), In23_Cu, - NETNAMES_GAL_LAYER( In24_Cu ), In24_Cu, - NETNAMES_GAL_LAYER( In25_Cu ), In25_Cu, - NETNAMES_GAL_LAYER( In26_Cu ), In26_Cu, - NETNAMES_GAL_LAYER( In27_Cu ), In27_Cu, - NETNAMES_GAL_LAYER( In28_Cu ), In28_Cu, - NETNAMES_GAL_LAYER( In29_Cu ), In29_Cu, - NETNAMES_GAL_LAYER( In30_Cu ), In30_Cu, -#endif - NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_BK_VISIBLE ), B_Mask, - NETNAMES_GAL_LAYER( B_Cu ), B_Cu, - - B_Adhes, B_Paste, B_SilkS, - ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ), - ITEM_GAL_LAYER( WORKSHEET ) -}; - BEGIN_EVENT_TABLE( PCB_BASE_FRAME, EDA_DRAW_FRAME ) EVT_MENU_RANGE( ID_POPUP_PCB_ITEM_SELECTION_START, ID_POPUP_PCB_ITEM_SELECTION_END, @@ -193,16 +117,6 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame m_FastGrid1 = 0; m_FastGrid2 = 0; - SetGalCanvas( new EDA_DRAW_PANEL_GAL( - 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(); - m_auxiliaryToolBar = NULL; } @@ -211,7 +125,10 @@ PCB_BASE_FRAME::~PCB_BASE_FRAME() { delete m_Collector; - delete m_Pcb; // is already NULL for FOOTPRINT_EDIT_FRAME + delete m_toolManager; + delete m_toolDispatcher; + + delete m_Pcb; delete GetGalCanvas(); } @@ -253,8 +170,11 @@ FP_LIB_TABLE* PROJECT::PcbFootprintLibs() void PCB_BASE_FRAME::SetBoard( BOARD* aBoard ) { - delete m_Pcb; - m_Pcb = aBoard; + if( m_Pcb != aBoard ) + { + delete m_Pcb; + m_Pcb = aBoard; + } } @@ -847,52 +767,6 @@ void PCB_BASE_FRAME::LoadSettings( wxConfigBase* aCfg ) if( m_DisplayModText < LINE || m_DisplayModText > SKETCH ) m_DisplayModText = FILLED; - // Apply display settings for GAL - KIGFX::VIEW* view = GetGalCanvas()->GetView(); - - // Set rendering order and properties of layers - for( LAYER_NUM i = 0; i < (int) DIM(GAL_LAYER_ORDER); ++i ) - { - LAYER_NUM layer = GAL_LAYER_ORDER[i]; - wxASSERT( layer < KIGFX::VIEW::VIEW_MAX_LAYERS ); - - view->SetLayerOrder( layer, i ); - - if( IsCopperLayer( layer ) ) - { - // Copper layers are required for netname layers - view->SetRequired( GetNetnameLayer( layer ), layer ); - view->SetLayerTarget( layer, KIGFX::TARGET_CACHED ); - } - else if( IsNetnameLayer( layer ) ) - { - // Netnames are drawn only when scale is sufficient (level of details) - // so there is no point in caching them - view->SetLayerTarget( layer, KIGFX::TARGET_NONCACHED ); - } - } - - // Some more required layers settings - 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 ) ); - - view->SetRequired( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - view->SetRequired( F_Adhes, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - view->SetRequired( F_Paste, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - view->SetRequired( F_Mask, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - - view->SetRequired( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - view->SetRequired( B_Adhes, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - view->SetRequired( B_Paste, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - view->SetRequired( B_Mask, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - - view->SetRequired( ITEM_GAL_LAYER( PAD_FR_VISIBLE ), ITEM_GAL_LAYER( MOD_FR_VISIBLE ) ); - view->SetRequired( ITEM_GAL_LAYER( PAD_BK_VISIBLE ), ITEM_GAL_LAYER( MOD_BK_VISIBLE ) ); - - view->SetLayerTarget( ITEM_GAL_LAYER( GP_OVERLAY ), KIGFX::TARGET_OVERLAY ); - view->SetLayerTarget( ITEM_GAL_LAYER( RATSNEST_VISIBLE ), KIGFX::TARGET_OVERLAY ); - // WxWidgets 2.9.1 seems call setlocale( LC_NUMERIC, "" ) // when reading doubles in config, // but forget to back to current locale. So we call SetLocaleTo_Default diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index 56b5ca63d2..6bef956fc1 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -630,7 +630,7 @@ void PCB_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool aRed } -void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& aEvent ) +void PCB_EDIT_FRAME::RestoreCopyFromUndoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetUndoCommandCount() <= 0 ) return; @@ -653,7 +653,7 @@ void PCB_EDIT_FRAME::GetBoardFromUndoList( wxCommandEvent& aEvent ) } -void PCB_EDIT_FRAME::GetBoardFromRedoList( wxCommandEvent& aEvent ) +void PCB_EDIT_FRAME::RestoreCopyFromRedoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetRedoCommandCount() == 0 ) return; diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index 8e3ac850cd..6496692a47 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -106,11 +106,6 @@ BOARD::BOARD() : // Initialize ratsnest m_ratsnest = new RN_DATA( this ); - m_ratsnestViewItem = new KIGFX::RATSNEST_VIEWITEM( m_ratsnest ); - - // Initialize view item for displaying worksheet frame - m_worksheetViewItem = new KIGFX::WORKSHEET_VIEWITEM( &m_paper, &m_titles ); - m_worksheetViewItem->SetFileName( std::string( m_fileName.mb_str() ) ); } @@ -122,8 +117,6 @@ BOARD::~BOARD() Delete( area_to_remove ); } - delete m_worksheetViewItem; - delete m_ratsnestViewItem; delete m_ratsnest; m_FullRatsnest.clear(); @@ -695,10 +688,12 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, int aControl ) m_Status_Pcb = 0; break; + case PCB_MODULE_EDGE_T: + assert( false ); // TODO Orson: I am just checking if it is supposed to be here + case PCB_DIMENSION_T: case PCB_LINE_T: case PCB_TEXT_T: - case PCB_MODULE_EDGE_T: case PCB_TARGET_T: if( aControl & ADD_APPEND ) m_Drawings.PushBack( aBoardItem ); diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 3bc5c0b73f..3cc7c35731 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -198,8 +198,6 @@ private: EDA_RECT m_BoundingBox; NETINFO_LIST m_NetInfo; ///< net info list (name, design constraints .. RN_DATA* m_ratsnest; - KIGFX::RATSNEST_VIEWITEM* m_ratsnestViewItem; ///< VIEW_ITEM that draws ratsnest - KIGFX::WORKSHEET_VIEWITEM* m_worksheetViewItem; ///< VIEW_ITEM that draws worksheet frame BOARD_DESIGN_SETTINGS m_designSettings; ZONE_SETTINGS m_zoneSettings; @@ -313,24 +311,6 @@ public: return m_ratsnest; } - /** - * Function GetRatsnestViewItem() - * returns VIEW_ITEM responsible for drawing the ratsnest for the board. - */ - KIGFX::RATSNEST_VIEWITEM* GetRatsnestViewItem() const - { - return m_ratsnestViewItem; - } - - /** - * Function GetWorksheetViewItem() - * returns VIEW_ITEM responsible for drawing the worksheet frame. - */ - KIGFX::WORKSHEET_VIEWITEM* GetWorksheetViewItem() const - { - return m_worksheetViewItem; - } - /** * Function DeleteMARKERs * deletes ALL MARKERS from the board. diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 2d1ba56e57..5791563007 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -90,6 +90,25 @@ void EDGE_MODULE::Copy( EDGE_MODULE* source ) } +void EDGE_MODULE::SetLocalCoord() +{ + MODULE* module = (MODULE*) m_Parent; + + if( module == NULL ) + { + m_Start0 = m_Start; + m_End0 = m_End; + return; + } + + m_Start0 = m_Start - module->GetPosition(); + m_End0 = m_End - module->GetPosition(); + double angle = module->GetOrientation(); + RotatePoint( &m_Start0.x, &m_Start0.y, -angle ); + RotatePoint( &m_End0.x, &m_End0.y, -angle ); +} + + void EDGE_MODULE::SetDrawCoord() { MODULE* module = (MODULE*) m_Parent; diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h index 7b8d5b09c8..e7b945a9af 100644 --- a/pcbnew/class_edge_mod.h +++ b/pcbnew/class_edge_mod.h @@ -61,12 +61,23 @@ public: void Copy( EDGE_MODULE* source ); // copy structure + void Move( const wxPoint& aMoveVector ) + { + m_Start += aMoveVector; + m_End += aMoveVector; + SetLocalCoord(); + } + void SetStart0( const wxPoint& aPoint ) { m_Start0 = aPoint; } const wxPoint& GetStart0() const { return m_Start0; } void SetEnd0( const wxPoint& aPoint ) { m_End0 = aPoint; } const wxPoint& GetEnd0() const { return m_End0; } + ///> Set relative coordinates. + void SetLocalCoord(); + + ///> Set absolute coordinates. void SetDrawCoord(); /* drawing functions */ diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 0e3f015d39..4488598fd1 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -295,6 +295,72 @@ void MODULE::Copy( MODULE* aModule ) } +void MODULE::Add( BOARD_ITEM* aBoardItem, bool doAppend ) +{ + switch( aBoardItem->Type() ) + { + case PCB_MODULE_TEXT_T: + // Only common texts can be added this way. Reference and value are not hold in the DLIST. + assert( static_cast( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS ); + /* no break */ + + case PCB_MODULE_EDGE_T: + if( doAppend ) + m_Drawings.PushBack( static_cast( aBoardItem ) ); + else + m_Drawings.PushFront( static_cast( aBoardItem ) ); + break; + + case PCB_PAD_T: + if( doAppend ) + m_Pads.PushBack( static_cast( aBoardItem ) ); + else + m_Pads.PushFront( static_cast( aBoardItem ) ); + break; + + default: + { + wxString msg; + msg.Printf( wxT( "MODULE::Add() needs work: BOARD_ITEM type (%d) not handled" ), + aBoardItem->Type() ); + wxFAIL_MSG( msg ); + + return; + } + } + + aBoardItem->SetParent( this ); +} + + +BOARD_ITEM* MODULE::Remove( BOARD_ITEM* aBoardItem ) +{ + switch( aBoardItem->Type() ) + { + case PCB_MODULE_TEXT_T: + // Only common texts can be added this way. Reference and value are not hold in the DLIST. + assert( static_cast( aBoardItem )->GetType() == TEXTE_MODULE::TEXT_is_DIVERS ); + /* no break */ + + case PCB_MODULE_EDGE_T: + return m_Drawings.Remove( static_cast( aBoardItem ) ); + + case PCB_PAD_T: + return m_Pads.Remove( static_cast( aBoardItem ) ); + + default: + { + wxString msg; + msg.Printf( wxT( "MODULE::Remove() needs work: BOARD_ITEM type (%d) not handled" ), + aBoardItem->Type() ); + wxFAIL_MSG( msg ); + } + } + + return NULL; +} + + void MODULE::CopyNetlistSettings( MODULE* aModule ) { // Don't do anything foolish like trying to copy to yourself. @@ -448,8 +514,12 @@ 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()->GetDesignSettings().GetBiggestClearanceValue(); - area.Inflate( biggest_clearance ); + BOARD* board = GetBoard(); + if( board ) + { + int biggest_clearance = board->GetDesignSettings().GetBiggestClearanceValue(); + area.Inflate( biggest_clearance ); + } return area; } @@ -632,13 +702,6 @@ void MODULE::Add3DModel( S3D_MASTER* a3DModel ) } -void MODULE::AddPad( D_PAD* aPad ) -{ - aPad->SetParent( this ); - m_Pads.PushBack( aPad ); -} - - // see class_module.h SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] ) @@ -734,10 +797,10 @@ EDA_ITEM* MODULE::Clone() const void MODULE::RunOnChildren( boost::function aFunction ) { - for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) + for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) aFunction( static_cast( pad ) ); - for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) + for( BOARD_ITEM* drawing = m_Drawings; drawing; drawing = drawing->Next() ) aFunction( drawing ); aFunction( static_cast( m_Reference ) ); @@ -767,6 +830,21 @@ void MODULE::ViewUpdate( int aUpdateFlags ) } +void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const +{ + aCount = 1; + aLayers[0] = ITEM_GAL_LAYER( ANCHOR_VISIBLE ); +} + + +unsigned int MODULE::ViewGetLOD( int aLayer ) const +{ + // Currently there is only one layer, so there is nothing to check +// if( aLayer == ITEM_GAL_LAYER( ANCHOR_VISIBLE ) ) + return 30; +} + + /* Test for validity of the name in a library of the footprint * ( no spaces, dir separators ... ) * return true if the given name is valid diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 8eac8a87d8..b1309d758d 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -91,9 +91,31 @@ public: * Function Add * adds the given item to this MODULE and takes ownership of its memory. * @param aBoardItem The item to add to this board. - * @param doInsert If true, then insert, else append - * void Add( BOARD_ITEM* aBoardItem, bool doInsert = true ); + * @param doAppend If true, then append, else insert. */ + void Add( BOARD_ITEM* aBoardItem, bool doAppend = true ); + + /** + * Function Delete + * removes the given single item from this MODULE and deletes its memory. + * @param aBoardItem The item to remove from this module and delete + */ + void Delete( BOARD_ITEM* aBoardItem ) + { + // developers should run DEBUG versions and fix such calls with NULL + wxASSERT( aBoardItem ); + + if( aBoardItem ) + delete Remove( aBoardItem ); + } + + /** + * Function Remove + * removes \a aBoardItem from this MODULE and returns it to caller without deleting it. + * @param aBoardItem The item to remove from this module. + * @return BOARD_ITEM* \a aBoardItem which was passed in. + */ + BOARD_ITEM* Remove( BOARD_ITEM* aBoardItem ); /** * Function CalculateBoundingBox @@ -436,14 +458,6 @@ public: */ void Add3DModel( S3D_MASTER* a3DModel ); - /** - * Function AddPad - * adds \a aPad to the end of the pad list. - * - * @param aPad A pointer to a #D_PAD to add to the list. - */ - void AddPad( D_PAD* aPad ); - SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] ); @@ -469,6 +483,12 @@ public: /// @copydoc VIEW_ITEM::ViewUpdate() void ViewUpdate( int aUpdateFlags = KIGFX::VIEW_ITEM::ALL ); + /// @copydoc VIEW_ITEM::ViewGetLayers() + virtual void ViewGetLayers( int aLayers[], int& aCount ) const; + + /// @copydoc VIEW_ITEM::ViewGetLOD() + virtual unsigned int ViewGetLOD( int aLayer ) const; + /** * Function CopyNetlistSettings * copies the netlist settings to \a aModule. diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 36239b7be0..bd20fd83af 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -228,6 +228,37 @@ const EDA_RECT D_PAD::GetBoundingBox() const } +void D_PAD::SetDrawCoord() +{ + MODULE* module = (MODULE*) m_Parent; + + m_Pos = m_Pos0; + + if( module == NULL ) + return; + + double angle = module->GetOrientation(); + + RotatePoint( &m_Pos.x, &m_Pos.y, angle ); + m_Pos += module->GetPosition(); +} + + +void D_PAD::SetLocalCoord() +{ + MODULE* module = (MODULE*) m_Parent; + + if( module == NULL ) + { + m_Pos0 = m_Pos; + return; + } + + m_Pos0 = m_Pos - module->GetPosition(); + RotatePoint( &m_Pos0.x, &m_Pos0.y, -module->GetOrientation() ); +} + + void D_PAD::SetAttribute( PAD_ATTR_T aAttribute ) { m_Attribute = aAttribute; @@ -797,6 +828,13 @@ int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp ) } +void D_PAD::Rotate( const wxPoint& aRotCentre, double aAngle ) +{ + RotatePoint( &m_Pos, aRotCentre, aAngle ); + m_Orient += aAngle; +} + + wxString D_PAD::ShowPadShape() const { switch( GetShape() ) @@ -924,7 +962,7 @@ void D_PAD::ViewGetLayers( int aLayers[], int& aCount ) const unsigned int D_PAD::ViewGetLOD( int aLayer ) const { - // Netnames and soldermasks will be shown only if zoom is appropriate + // Netnames will be shown only if zoom is appropriate if( IsNetnameLayer( aLayer ) ) { return ( 100000000 / std::max( m_Size.x, m_Size.y ) ); diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 1687989462..7fc41f8dcd 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -153,7 +153,7 @@ public: * Function GetOrientation * returns the rotation angle of the pad in tenths of degrees, but soon degrees. */ - double GetOrientation() const { return m_Orient; } + double GetOrientation() const { return m_Orient; } void SetDrillShape( PAD_DRILL_SHAPE_T aDrillShape ) { m_drillShape = aDrillShape; } @@ -381,6 +381,12 @@ public: // Virtual function: const EDA_RECT GetBoundingBox() const; + ///> Set absolute coordinates. + void SetDrawCoord(); + + ///> Set relative coordinates. + void SetLocalCoord(); + /** * Function Compare * compares two pads and return 0 if they are equal. @@ -391,8 +397,10 @@ public: void Move( const wxPoint& aMoveVector ) { m_Pos += aMoveVector; + SetLocalCoord(); } + void Rotate( const wxPoint& aRotCentre, double aAngle ); wxString GetSelectMenuText() const; diff --git a/pcbnew/class_pcb_layer_widget.cpp b/pcbnew/class_pcb_layer_widget.cpp index b0e5910a76..04954b1248 100644 --- a/pcbnew/class_pcb_layer_widget.cpp +++ b/pcbnew/class_pcb_layer_widget.cpp @@ -81,7 +81,7 @@ const LAYER_WIDGET::ROW PCB_LAYER_WIDGET::s_render_rows[] = { }; -PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_EDIT_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize ) : +PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize ) : LAYER_WIDGET( aParent, aFocusOwner, aPointSize ), myframe( aParent ) { @@ -213,7 +213,7 @@ void PCB_LAYER_WIDGET::SetLayersManagerTabsText() void PCB_LAYER_WIDGET::ReFillRender() { - BOARD* board = myframe->GetBoard(); + BOARD* board = myframe->GetBoard(); ClearRenderRows(); // Add "Render" tab rows to LAYER_WIDGET, after setting color and checkbox state. @@ -356,7 +356,6 @@ void PCB_LAYER_WIDGET::ReFill() void PCB_LAYER_WIDGET::OnLayerColorChange( int aLayer, EDA_COLOR_T aColor ) { myframe->GetBoard()->SetLayerColor( ToLAYER_ID( aLayer ), aColor ); - myframe->ReCreateLayerBox( false ); if( myframe->IsGalCanvasActive() ) { @@ -373,7 +372,7 @@ bool PCB_LAYER_WIDGET::OnLayerSelect( int aLayer ) { // the layer change from the PCB_LAYER_WIDGET can be denied by returning // false from this function. - myframe->SetActiveLayer( ToLAYER_ID( aLayer ), false ); + myframe->SetActiveLayer( ToLAYER_ID( aLayer ) ); if( m_alwaysShowActiveCopperLayer ) OnLayerSelected(); diff --git a/pcbnew/class_pcb_layer_widget.h b/pcbnew/class_pcb_layer_widget.h index 4f7d715367..211e603aa4 100644 --- a/pcbnew/class_pcb_layer_widget.h +++ b/pcbnew/class_pcb_layer_widget.h @@ -31,6 +31,8 @@ #ifndef CLASS_PCB_LAYER_WIDGET_H_ #define CLASS_PCB_LAYER_WIDGET_H_ +#include + /** * Class PCB_LAYER_WIDGET * is here to implement the abtract functions of LAYER_WIDGET so they @@ -49,7 +51,7 @@ public: * effectively sets the overal size of the widget via the row height and bitmap * button sizes. */ - PCB_LAYER_WIDGET( PCB_EDIT_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize = 10 ); + PCB_LAYER_WIDGET( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwner, int aPointSize = 10 ); void ReFill(); @@ -108,7 +110,7 @@ protected: bool m_alwaysShowActiveCopperLayer; // If true: Only shows the current active layer // even if it is changed - PCB_EDIT_FRAME* myframe; + PCB_BASE_FRAME* myframe; // popup menu ids. #define ID_SHOW_ALL_COPPERS wxID_HIGHEST diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 5eda7cba6e..48b43b161b 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -129,7 +129,7 @@ int TEXTE_MODULE::GetLength() const return m_Text.Len(); } -// Update draw coordinates + void TEXTE_MODULE::SetDrawCoord() { MODULE* module = (MODULE*) m_Parent; @@ -146,8 +146,6 @@ void TEXTE_MODULE::SetDrawCoord() } -// Update "local" coordinates (coordinates relatives to the footprint -// anchor point) void TEXTE_MODULE::SetLocalCoord() { MODULE* module = (MODULE*) m_Parent; @@ -163,6 +161,7 @@ void TEXTE_MODULE::SetLocalCoord() RotatePoint( &m_Pos0.x, &m_Pos0.y, -angle ); } + bool TEXTE_MODULE::HitTest( const wxPoint& aPosition ) const { wxPoint rel_pos; diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index e9595a307f..fff9f20547 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -71,7 +71,6 @@ public: return aItem && PCB_MODULE_TEXT_T == aItem->Type(); } - virtual const wxPoint& GetPosition() const { return m_Pos; @@ -117,9 +116,11 @@ public: // Virtual function const EDA_RECT GetBoundingBox() const; - void SetDrawCoord(); // Set absolute coordinates. + ///> Set absolute coordinates. + void SetDrawCoord(); - void SetLocalCoord(); // Set relative coordinates. + ///> Set relative coordinates. + void SetLocalCoord(); /* drawing functions */ void Draw( EDA_DRAW_PANEL* panel, diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index a2e1d845f8..cb99353899 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -86,7 +86,7 @@ const KICAD_T GENERAL_COLLECTOR::AllButZones[] = { }; -const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = { +const KICAD_T GENERAL_COLLECTOR::Modules[] = { PCB_MODULE_T, EOT }; @@ -118,12 +118,21 @@ const KICAD_T GENERAL_COLLECTOR::ModulesAndTheirItems[] = { }; +const KICAD_T GENERAL_COLLECTOR::ModuleItems[] = { + PCB_MODULE_TEXT_T, + PCB_MODULE_EDGE_T, + PCB_PAD_T, + EOT +}; + + const KICAD_T GENERAL_COLLECTOR::Tracks[] = { PCB_TRACE_T, PCB_VIA_T, EOT }; + const KICAD_T GENERAL_COLLECTOR::Zones[] = { PCB_ZONE_AREA_T, EOT diff --git a/pcbnew/collectors.h b/pcbnew/collectors.h index 267ec20034..4d2520c06d 100644 --- a/pcbnew/collectors.h +++ b/pcbnew/collectors.h @@ -262,7 +262,7 @@ public: /** * A scan list for only MODULEs */ - static const KICAD_T ModuleItems[]; + static const KICAD_T Modules[]; /** @@ -282,6 +282,12 @@ public: static const KICAD_T ModulesAndTheirItems[]; + /** + * A scan list for primary module items. + */ + static const KICAD_T ModuleItems[]; + + /** * A scan list for only TRACKS */ diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp index c5f1d00f9f..911a473dda 100644 --- a/pcbnew/controle.cpp +++ b/pcbnew/controle.cpp @@ -119,7 +119,7 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode ) else if( GetToolId() == ID_NO_TOOL_SELECTED ) { if( m_mainToolBar->GetToolToggled( ID_TOOLBARH_PCB_MODE_MODULE ) ) - scanList = GENERAL_COLLECTOR::ModuleItems; + scanList = GENERAL_COLLECTOR::Modules; else scanList = (DisplayOpt.DisplayZonesMode == 0) ? GENERAL_COLLECTOR::AllBoardItems : @@ -138,7 +138,7 @@ BOARD_ITEM* PCB_BASE_FRAME::PcbGeneralLocateAndDisplay( int aHotKeyCode ) break; case ID_PCB_MODULE_BUTT: - scanList = GENERAL_COLLECTOR::ModuleItems; + scanList = GENERAL_COLLECTOR::Modules; break; case ID_PCB_ZONES_BUTT: diff --git a/pcbnew/dialogs/dialog_edit_module_text.cpp b/pcbnew/dialogs/dialog_edit_module_text.cpp index 928ca8541c..05ec826763 100644 --- a/pcbnew/dialogs/dialog_edit_module_text.cpp +++ b/pcbnew/dialogs/dialog_edit_module_text.cpp @@ -44,34 +44,12 @@ #include #include -#include +#include extern wxPoint MoveVector; // Move vector for move edge, imported from edtxtmod.cpp -/*************** **************/ -/* class DialogEditModuleText */ -/*************** **************/ -class DialogEditModuleText : public DialogEditModuleText_base -{ -private: - PCB_BASE_FRAME* m_parent; - wxDC* m_dc; - MODULE* m_module; - TEXTE_MODULE* m_currentText; - -public: - DialogEditModuleText( PCB_BASE_FRAME* aParent, TEXTE_MODULE* aTextMod, wxDC* aDC ); - ~DialogEditModuleText() {}; - -private: - void initDlg( ); - void OnOkClick( wxCommandEvent& event ); - void OnCancelClick( wxCommandEvent& event ); -}; - - void PCB_BASE_FRAME::InstallTextModOptionsFrame( TEXTE_MODULE* TextMod, wxDC* DC ) { m_canvas->SetIgnoreMouseEvents( true ); diff --git a/pcbnew/dialogs/dialog_edit_module_text.h b/pcbnew/dialogs/dialog_edit_module_text.h new file mode 100644 index 0000000000..674481b891 --- /dev/null +++ b/pcbnew/dialogs/dialog_edit_module_text.h @@ -0,0 +1,53 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras + * Copyright (C) 2013 Dick Hollenbeck, dick@softplc.com + * Copyright (C) 2008-2013 Wayne Stambaugh + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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 DIALOG_EDIT_MODULE_TEXT_H +#define DIALOG_EDIT_MODULE_TEXT_H + +#include + +/*************** **************/ +/* class DialogEditModuleText */ +/*************** **************/ +class DialogEditModuleText : public DialogEditModuleText_base +{ +private: + PCB_BASE_FRAME* m_parent; + wxDC* m_dc; + MODULE* m_module; + TEXTE_MODULE* m_currentText; + +public: + DialogEditModuleText( PCB_BASE_FRAME* aParent, TEXTE_MODULE* aTextMod, wxDC* aDC ); + ~DialogEditModuleText() {}; + +private: + void initDlg( ); + void OnOkClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); +}; + +#endif /* DIALOG_EDIT_MODULE_TEXT_H */ diff --git a/pcbnew/dialogs/dialog_enum_pads.cpp b/pcbnew/dialogs/dialog_enum_pads.cpp new file mode 100644 index 0000000000..51f822047e --- /dev/null +++ b/pcbnew/dialogs/dialog_enum_pads.cpp @@ -0,0 +1,42 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "dialog_enum_pads.h" + +DIALOG_ENUM_PADS::DIALOG_ENUM_PADS( wxWindow* aParent ) : + DIALOG_ENUM_PADS_BASE( aParent ) +{ +} + + +int DIALOG_ENUM_PADS::GetStartNumber() const +{ + return m_padStartNum->GetValue(); +} + + +wxString DIALOG_ENUM_PADS::GetPrefix() const +{ + return m_padPrefix->GetValue(); +} diff --git a/pcbnew/dialogs/dialog_enum_pads.h b/pcbnew/dialogs/dialog_enum_pads.h new file mode 100644 index 0000000000..188c7328dc --- /dev/null +++ b/pcbnew/dialogs/dialog_enum_pads.h @@ -0,0 +1,49 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 __dialog_enum_pads__ +#define __dialog_enum_pads__ + +/** +@file +Subclass of DIALOG_ENUM_PADS_BASE, which is generated by wxFormBuilder. +*/ + +#include "dialog_enum_pads_base.h" + +/** Implementing DIALOG_ENUM_PADS_BASE */ +class DIALOG_ENUM_PADS : public DIALOG_ENUM_PADS_BASE +{ +public: + /** Constructor */ + DIALOG_ENUM_PADS( wxWindow* parent ); + + ///> Returns the starting number that is going to be used for the first enumerated pad. + int GetStartNumber() const; + + ///> Returns common prefix for all enumerated pads. + wxString GetPrefix() const; +}; + +#endif // __dialog_enum_pads__ diff --git a/pcbnew/dialogs/dialog_enum_pads_base.cpp b/pcbnew/dialogs/dialog_enum_pads_base.cpp new file mode 100644 index 0000000000..af1ac745f3 --- /dev/null +++ b/pcbnew/dialogs/dialog_enum_pads_base.cpp @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_enum_pads_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_ENUM_PADS_BASE::DIALOG_ENUM_PADS_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 ); + + wxBoxSizer* bPrefixSizer; + bPrefixSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_lblPadPrefix = new wxStaticText( this, wxID_ANY, _("Pad name prefix:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblPadPrefix->Wrap( -1 ); + bPrefixSizer->Add( m_lblPadPrefix, 1, wxALL, 5 ); + + m_padPrefix = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_padPrefix->SetMaxLength( 4 ); + bPrefixSizer->Add( m_padPrefix, 0, wxALL, 5 ); + + + bMainSizer->Add( bPrefixSizer, 1, wxEXPAND, 5 ); + + wxBoxSizer* bPadNumSizer; + bPadNumSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_lblPadStartNum = new wxStaticText( this, wxID_ANY, _("First pad number:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblPadStartNum->Wrap( -1 ); + bPadNumSizer->Add( m_lblPadStartNum, 1, wxALL, 5 ); + + m_padStartNum = new wxSpinCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 999, 1 ); + bPadNumSizer->Add( m_padStartNum, 0, wxALL, 5 ); + + + bMainSizer->Add( bPadNumSizer, 1, wxEXPAND, 5 ); + + m_lblInfo = new wxStaticText( this, wxID_ANY, _("Pad names are restricted to 4 characters (including number)."), wxDefaultPosition, wxDefaultSize, 0 ); + m_lblInfo->Wrap( 320 ); + bMainSizer->Add( m_lblInfo, 0, wxALL, 5 ); + + m_stdButtons = new wxStdDialogButtonSizer(); + m_stdButtonsOK = new wxButton( this, wxID_OK ); + m_stdButtons->AddButton( m_stdButtonsOK ); + m_stdButtonsCancel = new wxButton( this, wxID_CANCEL ); + m_stdButtons->AddButton( m_stdButtonsCancel ); + m_stdButtons->Realize(); + + bMainSizer->Add( m_stdButtons, 2, wxEXPAND, 5 ); + + + this->SetSizer( bMainSizer ); + this->Layout(); + + this->Centre( wxBOTH ); +} + +DIALOG_ENUM_PADS_BASE::~DIALOG_ENUM_PADS_BASE() +{ +} diff --git a/pcbnew/dialogs/dialog_enum_pads_base.fbp b/pcbnew/dialogs/dialog_enum_pads_base.fbp new file mode 100644 index 0000000000..f17006d1f9 --- /dev/null +++ b/pcbnew/dialogs/dialog_enum_pads_base.fbp @@ -0,0 +1,572 @@ + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_enum_pads_base + 1000 + none + 1 + DIALOG_ENUM_PADS_BASE + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_ENUM_PADS_BASE + + 340,240 + wxDEFAULT_DIALOG_STYLE + + Pad enumeration settings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bMainSizer + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bPrefixSizer + wxHORIZONTAL + none + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pad name prefix: + + 0 + + + 0 + + 1 + m_lblPadPrefix + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 4 + + 0 + + 1 + m_padPrefix + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bPadNumSizer + wxHORIZONTAL + none + + 5 + wxALL + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + First pad number: + + 0 + + + 0 + + 1 + m_lblPadStartNum + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + 1 + 999 + + 0 + + 0 + + 0 + + 1 + m_padStartNum + 1 + + + protected + 1 + + Resizable + 1 + + wxSP_ARROW_KEYS + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pad names are restricted to 4 characters (including number). + + 0 + + + 0 + + 1 + m_lblInfo + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + 320 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 2 + + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + + m_stdButtons + protected + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_enum_pads_base.h b/pcbnew/dialogs/dialog_enum_pads_base.h new file mode 100644 index 0000000000..caed966dcd --- /dev/null +++ b/pcbnew/dialogs/dialog_enum_pads_base.h @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 30 2013) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_ENUM_PADS_BASE_H__ +#define __DIALOG_ENUM_PADS_BASE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_ENUM_PADS_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_ENUM_PADS_BASE : public wxDialog +{ + private: + + protected: + wxStaticText* m_lblPadPrefix; + wxTextCtrl* m_padPrefix; + wxStaticText* m_lblPadStartNum; + wxSpinCtrl* m_padStartNum; + wxStaticText* m_lblInfo; + wxStdDialogButtonSizer* m_stdButtons; + wxButton* m_stdButtonsOK; + wxButton* m_stdButtonsCancel; + + public: + + DIALOG_ENUM_PADS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Pad enumeration settings"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 340,240 ), long style = wxDEFAULT_DIALOG_STYLE ); + ~DIALOG_ENUM_PADS_BASE(); + +}; + +#endif //__DIALOG_ENUM_PADS_BASE_H__ diff --git a/pcbnew/dialogs/dialog_general_options.cpp b/pcbnew/dialogs/dialog_general_options.cpp index 9adc32bdf6..696859b820 100644 --- a/pcbnew/dialogs/dialog_general_options.cpp +++ b/pcbnew/dialogs/dialog_general_options.cpp @@ -154,11 +154,6 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) { int id = event.GetId(); bool state = event.IsChecked(); - KIGFX::PCB_PAINTER* painter = - static_cast ( GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); - KICAD_T updateType = EOT; switch( id ) { @@ -193,44 +188,33 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) case ID_TB_OPTIONS_SHOW_ZONES: DisplayOpt.DisplayZonesMode = 0; - updateType = PCB_ZONE_AREA_T; m_canvas->Refresh(); break; case ID_TB_OPTIONS_SHOW_ZONES_DISABLE: DisplayOpt.DisplayZonesMode = 1; - updateType = PCB_ZONE_AREA_T; m_canvas->Refresh(); break; case ID_TB_OPTIONS_SHOW_ZONES_OUTLINES_ONLY: DisplayOpt.DisplayZonesMode = 2; - updateType = PCB_ZONE_AREA_T; m_canvas->Refresh(); break; case ID_TB_OPTIONS_SHOW_VIAS_SKETCH: m_DisplayViaFill = DisplayOpt.DisplayViaFill = !state; - updateType = PCB_VIA_T; m_canvas->Refresh(); break; case ID_TB_OPTIONS_SHOW_TRACKS_SKETCH: m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill = !state; - updateType = PCB_TRACE_T; m_canvas->Refresh(); break; case ID_TB_OPTIONS_SHOW_HIGH_CONTRAST_MODE: { DisplayOpt.ContrastModeDisplay = state; - - // Apply new display options to the GAL canvas (this is faster than recaching) - settings->LoadDisplayOptions( DisplayOpt ); - - SetHighContrastLayer( GetActiveLayer() ); m_canvas->Refresh(); - break; } @@ -260,21 +244,4 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) wxT( "PCB_EDIT_FRAME::OnSelectOptionToolbar error \n (event not handled!)" ) ); break; } - - if( updateType != EOT ) - { - // Apply new display options to the GAL canvas - settings->LoadDisplayOptions( DisplayOpt ); - - // Find items that require update - KICAD_T scanList[] = { updateType, EOT }; - TYPE_COLLECTOR collector; - collector.Collect( GetBoard(), scanList ); - - for( int i = 0; i < collector.GetCount(); ++i ) - collector[i]->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - - if( IsGalCanvasActive() ) - GetGalCanvas()->Refresh(); } diff --git a/pcbnew/dialogs/dialog_global_deletion.cpp b/pcbnew/dialogs/dialog_global_deletion.cpp index e06f990b29..b4998f2a4d 100644 --- a/pcbnew/dialogs/dialog_global_deletion.cpp +++ b/pcbnew/dialogs/dialog_global_deletion.cpp @@ -254,6 +254,9 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete( ) if( gen_rastnest ) m_Parent->Compile_Ratsnest( NULL, true ); + if( m_Parent->IsGalCanvasActive() ) + pcb->GetRatsnest()->Recalculate(); + } m_Parent->GetCanvas()->Refresh(); diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index b962b670c0..de92b283a4 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -117,6 +117,8 @@ private: bool padValuesOK(); ///< test if all values are acceptable for the pad + void redraw(); + /** * Function setPadLayersList * updates the CheckBox states in pad layers list, @@ -174,6 +176,21 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aP else // We are editing a "master" pad, i.e. a pad used to create new pads m_dummyPad->Copy( m_padMaster ); + if( m_parent->IsGalCanvasActive() ) + { + m_panelShowPadGal->UseColorScheme( m_board->GetColorsSettings() ); + m_panelShowPadGal->SwitchBackend( m_parent->GetGalCanvas()->GetBackend() ); + m_panelShowPad->Hide(); + m_panelShowPadGal->Show(); + m_panelShowPadGal->GetView()->Add( m_dummyPad ); + m_panelShowPadGal->StartDrawing(); + } + else + { + m_panelShowPad->Show(); + m_panelShowPadGal->Hide(); + } + initValues(); m_sdbSizer1OK->SetDefault(); @@ -537,7 +554,7 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event ) } transferDataToPad( m_dummyPad ); - m_panelShowPad->Refresh(); + redraw(); } @@ -566,7 +583,7 @@ void DIALOG_PAD_PROPERTIES::OnDrillShapeSelected( wxCommandEvent& event ) } transferDataToPad( m_dummyPad ); - m_panelShowPad->Refresh(); + redraw(); } @@ -599,7 +616,7 @@ void DIALOG_PAD_PROPERTIES::PadOrientEvent( wxCommandEvent& event ) m_PadOrientCtrl->SetValue( msg ); transferDataToPad( m_dummyPad ); - m_panelShowPad->Refresh(); + redraw(); } @@ -667,7 +684,7 @@ void DIALOG_PAD_PROPERTIES::setPadLayersList( LSET layer_mask ) void DIALOG_PAD_PROPERTIES::OnSetLayers( wxCommandEvent& event ) { transferDataToPad( m_dummyPad ); - m_panelShowPad->Refresh(); + redraw(); } @@ -758,6 +775,29 @@ bool DIALOG_PAD_PROPERTIES::padValuesOK() } +void DIALOG_PAD_PROPERTIES::redraw() +{ + if( m_parent->IsGalCanvasActive() ) + { + m_dummyPad->ViewUpdate(); + + BOX2I bbox = m_dummyPad->ViewBBox(); + + // Autozoom + m_panelShowPadGal->GetView()->SetViewport( BOX2D( bbox.GetOrigin(), bbox.GetSize() ) ); + + // Add a margin + m_panelShowPadGal->GetView()->SetScale( m_panelShowPadGal->GetView()->GetScale() * 0.7 ); + + m_panelShowPadGal->Refresh(); + } + else + { + m_panelShowPad->Refresh(); + } +} + + void DIALOG_PAD_PROPERTIES::PadPropertiesAccept( wxCommandEvent& event ) { if( !padValuesOK() ) @@ -1132,7 +1172,7 @@ void DIALOG_PAD_PROPERTIES::OnValuesChanged( wxCommandEvent& event ) if( m_canUpdate ) { transferDataToPad( m_dummyPad ); - m_panelShowPad->Refresh(); + redraw(); } } diff --git a/pcbnew/dialogs/dialog_pad_properties_base.cpp b/pcbnew/dialogs/dialog_pad_properties_base.cpp index 6da97464e5..c7a62c1d54 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.cpp +++ b/pcbnew/dialogs/dialog_pad_properties_base.cpp @@ -536,6 +536,9 @@ DIALOG_PAD_PROPERTIES_BASE::DIALOG_PAD_PROPERTIES_BASE( wxWindow* parent, wxWind bSizerDisplayPad->Add( m_panelShowPad, 4, wxRIGHT|wxTOP|wxEXPAND, 5 ); + m_panelShowPadGal = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), wxDefaultSize, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ); + bSizerDisplayPad->Add( m_panelShowPadGal, 4, wxEXPAND|wxRIGHT|wxTOP, 5 ); + bSizerUpper->Add( bSizerDisplayPad, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); diff --git a/pcbnew/dialogs/dialog_pad_properties_base.fbp b/pcbnew/dialogs/dialog_pad_properties_base.fbp index cb8df4557b..8696b831e5 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.fbp +++ b/pcbnew/dialogs/dialog_pad_properties_base.fbp @@ -8310,6 +8310,91 @@ + + 5 + wxEXPAND|wxRIGHT|wxTOP + 4 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + PCB_DRAW_PANEL_GAL + 1 + m_panelShowPadGal = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), wxDefaultSize, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ); + + 1 + PCB_DRAW_PANEL_GAL* m_panelShowPadGal; + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + #include <pcb_draw_panel_gal.h> + + 0 + + + 0 + + 1 + m_panelShowPadGal + 1 + + + protected + 1 + + Resizable + + 1 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_pad_properties_base.h b/pcbnew/dialogs/dialog_pad_properties_base.h index 8a6ffd636d..1170f7bf20 100644 --- a/pcbnew/dialogs/dialog_pad_properties_base.h +++ b/pcbnew/dialogs/dialog_pad_properties_base.h @@ -30,6 +30,7 @@ class DIALOG_SHIM; #include #include #include +#include #include #include @@ -143,6 +144,7 @@ class DIALOG_PAD_PROPERTIES_BASE : public DIALOG_SHIM wxStaticText* m_ThermalGapUnits; wxStaticText* m_staticTextWarning; wxPanel* m_panelShowPad; + PCB_DRAW_PANEL_GAL* m_panelShowPadGal; wxStaticText* m_staticTextWarningPadFlipped; wxStdDialogButtonSizer* m_sdbSizer1; wxButton* m_sdbSizer1OK; diff --git a/pcbnew/dialogs/dialog_track_via_size.cpp b/pcbnew/dialogs/dialog_track_via_size.cpp index 8a51cafdb4..07b681ad43 100644 --- a/pcbnew/dialogs/dialog_track_via_size.cpp +++ b/pcbnew/dialogs/dialog_track_via_size.cpp @@ -26,6 +26,7 @@ #include #include #include +#include DIALOG_TRACK_VIA_SIZE::DIALOG_TRACK_VIA_SIZE( wxWindow* aParent, PNS_ROUTING_SETTINGS& aSettings ) : DIALOG_TRACK_VIA_SIZE_BASE( aParent ), diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index eb6bb85843..787a73827e 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -1213,14 +1213,13 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_GEN_IMPORT_DXF_FILE: - InvokeDXFDialogImport( this ); + InvokeDXFDialogBoardImport( this ); m_canvas->Refresh(); break; default: wxString msg; - msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ), - id ); + msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ), id ); DisplayError( this, msg ); break; } @@ -1385,125 +1384,99 @@ void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) if( GetToolId() == id ) return; - if( IsGalCanvasActive() ) + INSTALL_UNBUFFERED_DC( dc, m_canvas ); + + // Stop the current command and deselect the current tool. + m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); + + switch( id ) { - std::string actionName = COMMON_ACTIONS::TranslateLegacyId( id ); + case ID_NO_TOOL_SELECTED: + SetToolID( id, m_canvas->GetDefaultCursor(), wxEmptyString ); + break; - if( !actionName.empty() || id == ID_NO_TOOL_SELECTED ) + case ID_TRACK_BUTT: + if( g_Drc_On ) + SetToolID( id, wxCURSOR_PENCIL, _( "Add tracks" ) ); + else + SetToolID( id, wxCURSOR_QUESTION_ARROW, _( "Add tracks" ) ); + + if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 ) { - const int MAX_TRIALS = 10; - int trials = 0; - - // Cancel the current tool - // TODO while sending a lot of cancel events works for sure, it is not the most - // elegant way to cancel a tool, this should be probably done another way - while( m_toolManager->GetCurrentTool()->GetName() != "pcbnew.InteractiveSelection" && - trials++ < MAX_TRIALS ) - { - TOOL_EVENT cancel( TC_ANY, TA_CANCEL_TOOL ); - m_toolManager->ProcessEvent( cancel ); - } - - if( !actionName.empty() ) - m_toolManager->RunAction( actionName ); + Compile_Ratsnest( &dc, true ); } - } - else - { - INSTALL_UNBUFFERED_DC( dc, m_canvas ); - // Stop the current command and deselect the current tool. - m_canvas->EndMouseCapture( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor() ); + break; - switch( id ) - { - case ID_NO_TOOL_SELECTED: - SetToolID( id, m_canvas->GetDefaultCursor(), wxEmptyString ); - break; + case ID_PCB_MODULE_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add module" ) ); + break; - case ID_TRACK_BUTT: - if( g_Drc_On ) - SetToolID( id, wxCURSOR_PENCIL, _( "Add tracks" ) ); - else - SetToolID( id, wxCURSOR_QUESTION_ARROW, _( "Add tracks" ) ); + case ID_PCB_ZONES_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add zones" ) ); - if( (GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 ) - { - Compile_Ratsnest( &dc, true ); - } + if( DisplayOpt.DisplayZonesMode != 0 ) + DisplayInfoMessage( this, _( "Warning: zone display is OFF!!!" ) ); - break; + if( !GetBoard()->IsHighLightNetON() && (GetBoard()->GetHighLightNetCode() > 0 ) ) + HighLight( &dc ); - case ID_PCB_MODULE_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add module" ) ); - break; + break; - case ID_PCB_ZONES_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add zones" ) ); + case ID_PCB_KEEPOUT_AREA_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add keepout" ) ); + break; - if( DisplayOpt.DisplayZonesMode != 0 ) - DisplayInfoMessage( this, _( "Warning: zone display is OFF!!!" ) ); + case ID_PCB_MIRE_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add layer alignment target" ) ); + break; - if( !GetBoard()->IsHighLightNetON() && (GetBoard()->GetHighLightNetCode() > 0 ) ) - HighLight( &dc ); + case ID_PCB_PLACE_OFFSET_COORD_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Adjust zero" ) ); + break; - break; + case ID_PCB_PLACE_GRID_COORD_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Adjust grid origin" ) ); + break; - case ID_PCB_KEEPOUT_AREA_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add keepout" ) ); - break; + case ID_PCB_ADD_LINE_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic line" ) ); + break; - case ID_PCB_MIRE_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add layer alignment target" ) ); - break; + case ID_PCB_ARC_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); + break; - case ID_PCB_PLACE_OFFSET_COORD_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Adjust zero" ) ); - break; + case ID_PCB_CIRCLE_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); + break; - case ID_PCB_PLACE_GRID_COORD_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Adjust grid origin" ) ); - break; + case ID_PCB_ADD_TEXT_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add text" ) ); + break; - case ID_PCB_ADD_LINE_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic line" ) ); - break; + case ID_COMPONENT_BUTT: + SetToolID( id, wxCURSOR_HAND, _( "Add module" ) ); + break; - case ID_PCB_ARC_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); - break; + case ID_PCB_DIMENSION_BUTT: + SetToolID( id, wxCURSOR_PENCIL, _( "Add dimension" ) ); + break; - case ID_PCB_CIRCLE_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); - break; + case ID_PCB_DELETE_ITEM_BUTT: + SetToolID( id, wxCURSOR_BULLSEYE, _( "Delete item" ) ); + break; - case ID_PCB_ADD_TEXT_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add text" ) ); - break; + case ID_PCB_HIGHLIGHT_BUTT: + SetToolID( id, wxCURSOR_HAND, _( "Highlight net" ) ); + break; - case ID_COMPONENT_BUTT: - SetToolID( id, wxCURSOR_HAND, _( "Add module" ) ); - break; + case ID_PCB_SHOW_1_RATSNEST_BUTT: + SetToolID( id, wxCURSOR_HAND, _( "Select rats nest" ) ); - case ID_PCB_DIMENSION_BUTT: - SetToolID( id, wxCURSOR_PENCIL, _( "Add dimension" ) ); - break; + if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 ) + Compile_Ratsnest( &dc, true ); - case ID_PCB_DELETE_ITEM_BUTT: - SetToolID( id, wxCURSOR_BULLSEYE, _( "Delete item" ) ); - break; - - case ID_PCB_HIGHLIGHT_BUTT: - SetToolID( id, wxCURSOR_HAND, _( "Highlight net" ) ); - break; - - case ID_PCB_SHOW_1_RATSNEST_BUTT: - SetToolID( id, wxCURSOR_HAND, _( "Select rats nest" ) ); - - if( ( GetBoard()->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK ) == 0 ) - Compile_Ratsnest( &dc, true ); - - break; - } + break; } } diff --git a/pcbnew/gpcb_plugin.cpp b/pcbnew/gpcb_plugin.cpp index def86f32ff..c306aa8639 100644 --- a/pcbnew/gpcb_plugin.cpp +++ b/pcbnew/gpcb_plugin.cpp @@ -637,7 +637,7 @@ MODULE* GPCB_FPL_CACHE::parseMODULE( LINE_READER* aLineReader ) throw( IO_ERROR, pad->SetShape( PAD_OVAL ); } - module->AddPad( pad ); + module->Add( pad ); continue; } @@ -701,7 +701,7 @@ MODULE* GPCB_FPL_CACHE::parseMODULE( LINE_READER* aLineReader ) throw( IO_ERROR, if( pad->GetShape() == PAD_ROUND && pad->GetSize().x != pad->GetSize().y ) pad->SetShape( PAD_OVAL ); - module->AddPad( pad ); + module->Add( pad ); continue; } } diff --git a/pcbnew/import_dxf/dialog_dxf_import.cpp b/pcbnew/import_dxf/dialog_dxf_import.cpp index f442b9a352..5f9ff5acf1 100644 --- a/pcbnew/import_dxf/dialog_dxf_import.cpp +++ b/pcbnew/import_dxf/dialog_dxf_import.cpp @@ -27,42 +27,24 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#include //#include #include -#include -#include #include -#include #include +#include +#include +#include +#include +#include +#include // Keys to store setup in config #define DXF_IMPORT_LAYER_OPTION_KEY wxT("DxfImportBrdLayer") #define DXF_IMPORT_COORD_ORIGIN_KEY wxT("DxfImportCoordOrigin") #define DXF_IMPORT_LAST_FILE_KEY wxT("DxfImportLastFile") -class DIALOG_DXF_IMPORT : public DIALOG_DXF_IMPORT_BASE -{ -private: - PCB_EDIT_FRAME * m_parent; - wxConfigBase* m_config; // Current config - - static wxString m_dxfFilename; - static int m_offsetSelection; - static LAYER_NUM m_layer; - -public: - - DIALOG_DXF_IMPORT( PCB_EDIT_FRAME* aParent ); - ~DIALOG_DXF_IMPORT(); - -private: - // Virtual event handlers - void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } - void OnOKClick( wxCommandEvent& event ); - void OnBrowseDxfFiles( wxCommandEvent& event ); -}; - // Static members of DIALOG_DXF_IMPORT, to remember // the user's choices during the session wxString DIALOG_DXF_IMPORT::m_dxfFilename; @@ -70,8 +52,8 @@ int DIALOG_DXF_IMPORT::m_offsetSelection = 4; LAYER_NUM DIALOG_DXF_IMPORT::m_layer = Dwgs_User; -DIALOG_DXF_IMPORT::DIALOG_DXF_IMPORT( PCB_EDIT_FRAME* aParent ) : - DIALOG_DXF_IMPORT_BASE( aParent ) +DIALOG_DXF_IMPORT::DIALOG_DXF_IMPORT( PCB_BASE_FRAME* aParent ) + : DIALOG_DXF_IMPORT_BASE( aParent ) { m_parent = aParent; m_config = Kiface().KifaceSettings(); @@ -121,16 +103,18 @@ DIALOG_DXF_IMPORT::~DIALOG_DXF_IMPORT() void DIALOG_DXF_IMPORT::OnBrowseDxfFiles( wxCommandEvent& event ) { wxString path; + wxString filename; if( !m_dxfFilename.IsEmpty() ) { wxFileName fn( m_dxfFilename ); path = fn.GetPath(); + filename = fn.GetFullName(); } wxFileDialog dlg( m_parent, wxT( "Open File" ), - path, m_dxfFilename, - wxT( "dxf Files (*.dxf)|*.dxf|*.DXF" ), + path, filename, + wxT( "dxf Files (*.dxf)|*.dxf" ), wxFD_OPEN|wxFD_FILE_MUST_EXIST ); dlg.ShowModal(); @@ -143,6 +127,7 @@ void DIALOG_DXF_IMPORT::OnBrowseDxfFiles( wxCommandEvent& event ) m_textCtrlFileName->SetValue( fileName ); } + void DIALOG_DXF_IMPORT::OnOKClick( wxCommandEvent& event ) { m_dxfFilename = m_textCtrlFileName->GetValue(); @@ -173,41 +158,105 @@ void DIALOG_DXF_IMPORT::OnOKClick( wxCommandEvent& event ) break; } - BOARD * brd = m_parent->GetBoard(); - DXF2BRD_CONVERTER dxf_importer; - // Set coordinates offset for import (offset is given in mm) - dxf_importer.SetOffset( offsetX, offsetY ); + m_dxfImporter.SetOffset( offsetX, offsetY ); m_layer = m_SelLayerBox->GetLayerSelection(); - dxf_importer.SetBrdLayer( m_layer ); + m_dxfImporter.SetBrdLayer( m_layer ); // Read dxf file: - dxf_importer.ImportDxfFile( m_dxfFilename, brd ); - - // Prepare the undo list - std::vector& list = dxf_importer.GetItemsList(); - PICKED_ITEMS_LIST picklist; - - // Build the undo list - for( unsigned ii = 0; ii < list.size(); ii++ ) - { - ITEM_PICKER itemWrapper( list[ii], UR_NEW ); - picklist.PushItem( itemWrapper ); - } - - m_parent->SaveCopyInUndoList( picklist, UR_NEW, wxPoint(0,0) ); + m_dxfImporter.ImportDxfFile( m_dxfFilename ); EndModal( wxID_OK ); } -bool InvokeDXFDialogImport( PCB_EDIT_FRAME* aCaller ) +bool InvokeDXFDialogBoardImport( PCB_BASE_FRAME* aCaller ) { DIALOG_DXF_IMPORT dlg( aCaller ); - bool success = dlg.ShowModal() == wxID_OK; + bool success = ( dlg.ShowModal() == wxID_OK ); if( success ) + { + const std::list& list = dlg.GetImportedItems(); + PICKED_ITEMS_LIST picklist; + + BOARD* board = aCaller->GetBoard(); + KIGFX::VIEW* view = aCaller->GetGalCanvas()->GetView(); + + std::list::const_iterator it, itEnd; + for( it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) + { + BOARD_ITEM* item = *it; + board->Add( item ); + + ITEM_PICKER itemWrapper( item, UR_NEW ); + picklist.PushItem( itemWrapper ); + + if( aCaller->IsGalCanvasActive() ) + view->Add( item ); + } + + aCaller->SaveCopyInUndoList( picklist, UR_NEW, wxPoint( 0, 0 ) ); aCaller->OnModify(); + } + + return success; +} + + +bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule ) +{ + DIALOG_DXF_IMPORT dlg( aCaller ); + bool success = ( dlg.ShowModal() == wxID_OK ); + + if( success ) + { + const std::list& list = dlg.GetImportedItems(); + MODULE* module = aCaller->GetBoard()->m_Modules; + KIGFX::VIEW* view = aCaller->GetGalCanvas()->GetView(); + + aCaller->SaveCopyInUndoList( module, UR_MODEDIT ); + aCaller->OnModify(); + + std::list::const_iterator it, itEnd; + for( it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) + { + BOARD_ITEM* item = *it; + BOARD_ITEM* converted = NULL; + + // Modules use different types for the same things, + // so we need to convert imported items to appropriate classes. + switch( item->Type() ) + { + case PCB_LINE_T: + { + converted = new EDGE_MODULE( module ); + *static_cast( converted ) = *static_cast( item ); + module->Add( converted ); + static_cast( converted )->SetLocalCoord(); + delete item; + break; + } + + case PCB_TEXT_T: + { + converted = new TEXTE_MODULE( module ); + *static_cast( converted ) = *static_cast( item ); + module->Add( module ); + static_cast( converted )->SetLocalCoord(); + delete item; + break; + } + + default: + assert( false ); // there is a type that is currently not handled here + break; + } + + if( aCaller->IsGalCanvasActive() ) + view->Add( converted ); + } + } return success; } diff --git a/pcbnew/import_dxf/dialog_dxf_import.h b/pcbnew/import_dxf/dialog_dxf_import.h new file mode 100644 index 0000000000..2785732841 --- /dev/null +++ b/pcbnew/import_dxf/dialog_dxf_import.h @@ -0,0 +1,58 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors. + * + * 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 +#include +#include + +class DIALOG_DXF_IMPORT : public DIALOG_DXF_IMPORT_BASE +{ +public: + DIALOG_DXF_IMPORT( PCB_BASE_FRAME* aParent ); + ~DIALOG_DXF_IMPORT(); + + /** + * Function GetImportedItems() + * + * Returns a list of items imported from a DXF file. + */ + const std::list& GetImportedItems() const + { + return m_dxfImporter.GetItemsList(); + } + +private: + PCB_BASE_FRAME* m_parent; + wxConfigBase* m_config; // Current config + DXF2BRD_CONVERTER m_dxfImporter; + + static wxString m_dxfFilename; + static int m_offsetSelection; + static LAYER_NUM m_layer; + + // Virtual event handlers + void OnCancelClick( wxCommandEvent& event ) { event.Skip(); } + void OnOKClick( wxCommandEvent& event ); + void OnBrowseDxfFiles( wxCommandEvent& event ); +}; diff --git a/pcbnew/import_dxf/dxf2brd_items.cpp b/pcbnew/import_dxf/dxf2brd_items.cpp index 6cd7e86fc4..d9ffbbf63b 100644 --- a/pcbnew/import_dxf/dxf2brd_items.cpp +++ b/pcbnew/import_dxf/dxf2brd_items.cpp @@ -52,7 +52,6 @@ DXF2BRD_CONVERTER::DXF2BRD_CONVERTER() : DRW_Interface() m_xOffset = 0.0; // X coord offset for conversion (in mm) m_yOffset = 0.0; // Y coord offset for conversion (in mm) m_Dfx2mm = 1.0; // The scale factor to convert DXF units to mm - m_brd = NULL; m_version = 0; m_defaultThickness = 0.1; m_brdLayer = Dwgs_User; @@ -67,13 +66,13 @@ DXF2BRD_CONVERTER::~DXF2BRD_CONVERTER() // coordinate conversions from dxf to internal units int DXF2BRD_CONVERTER::mapX( double aDxfCoordX ) { - return Millimeter2iu( m_xOffset + (aDxfCoordX * m_Dfx2mm) ); + return Millimeter2iu( m_xOffset + ( aDxfCoordX * m_Dfx2mm ) ); } int DXF2BRD_CONVERTER::mapY( double aDxfCoordY ) { - return Millimeter2iu( m_yOffset - (aDxfCoordY * m_Dfx2mm) ); + return Millimeter2iu( m_yOffset - ( aDxfCoordY * m_Dfx2mm ) ); } @@ -83,10 +82,8 @@ int DXF2BRD_CONVERTER::mapDim( double aDxfValue ) } -bool DXF2BRD_CONVERTER::ImportDxfFile( const wxString& aFile, BOARD* aBoard ) +bool DXF2BRD_CONVERTER::ImportDxfFile( const wxString& aFile ) { - m_brd = aBoard; - dxfRW* dxf = new dxfRW( aFile.ToUTF8() ); bool success = dxf->read( this, true ); @@ -95,23 +92,15 @@ bool DXF2BRD_CONVERTER::ImportDxfFile( const wxString& aFile, BOARD* aBoard ) return success; } -// Add aItem the the board -// this item is also added to the list of new items -// (for undo command for instance) -void DXF2BRD_CONVERTER::appendToBoard( BOARD_ITEM * aItem ) -{ - m_brd->Add( aItem ); - m_newItemsList.push_back( aItem ); -} /* * Implementation of the method which handles layers. */ -void DXF2BRD_CONVERTER::addLayer( const DRW_Layer& data ) +void DXF2BRD_CONVERTER::addLayer( const DRW_Layer& aData ) { // Not yet useful in Pcbnew. #if 0 - wxString name = wxString::FromUTF8( data.name.c_str() ); + wxString name = wxString::FromUTF8( aData.name.c_str() ); wxLogMessage( name ); #endif } @@ -120,25 +109,20 @@ void DXF2BRD_CONVERTER::addLayer( const DRW_Layer& data ) /* * Import line entities. */ -void DXF2BRD_CONVERTER::addLine( const DRW_Line& data ) +void DXF2BRD_CONVERTER::addLine( const DRW_Line& aData ) { - DRAWSEGMENT* segm = new DRAWSEGMENT( m_brd ); + DRAWSEGMENT* segm = new DRAWSEGMENT; segm->SetLayer( ToLAYER_ID( m_brdLayer ) ); - - wxPoint start( mapX( data.basePoint.x ), mapY( data.basePoint.y ) ); - + wxPoint start( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) ); segm->SetStart( start ); - - wxPoint end( mapX( data.secPoint.x ), mapY( data.secPoint.y ) ); - + wxPoint end( mapX( aData.secPoint.x ), mapY( aData.secPoint.y ) ); segm->SetEnd( end ); - - segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness : data.thickness ) ); - appendToBoard( segm ); + segm->SetWidth( mapDim( aData.thickness == 0 ? m_defaultThickness : aData.thickness ) ); + m_newItemsList.push_back( segm ); } -void DXF2BRD_CONVERTER::addPolyline(const DRW_Polyline& data ) +void DXF2BRD_CONVERTER::addPolyline(const DRW_Polyline& aData ) { // Currently, Pcbnew does not know polylines, for boards. // So we have to convert a polyline to a set of segments. @@ -146,9 +130,9 @@ void DXF2BRD_CONVERTER::addPolyline(const DRW_Polyline& data ) wxPoint startpoint; - for( unsigned ii = 0; ii < data.vertlist.size(); ii++ ) + for( unsigned ii = 0; ii < aData.vertlist.size(); ii++ ) { - DRW_Vertex* vertex = data.vertlist[ii]; + DRW_Vertex* vertex = aData.vertlist[ii]; if( ii == 0 ) { @@ -157,20 +141,20 @@ void DXF2BRD_CONVERTER::addPolyline(const DRW_Polyline& data ) continue; } - DRAWSEGMENT* segm = new DRAWSEGMENT( m_brd ); + DRAWSEGMENT* segm = new DRAWSEGMENT( NULL ); segm->SetLayer( ToLAYER_ID( m_brdLayer ) ); segm->SetStart( startpoint ); wxPoint endpoint( mapX( vertex->basePoint.x ), mapY( vertex->basePoint.y ) ); segm->SetEnd( endpoint ); - segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); - appendToBoard( segm ); + segm->SetWidth( mapDim( aData.thickness == 0 ? m_defaultThickness + : aData.thickness ) ); + m_newItemsList.push_back( segm ); startpoint = endpoint; } } -void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& data ) +void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& aData ) { // Currently, Pcbnew does not know polylines, for boards. // So we have to convert a polyline to a set of segments. @@ -179,9 +163,9 @@ void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& data ) // the variable width of each vertex (when exists) is not used. wxPoint startpoint; - for( unsigned ii = 0; ii < data.vertlist.size(); ii++ ) + for( unsigned ii = 0; ii < aData.vertlist.size(); ii++ ) { - DRW_Vertex2D* vertex = data.vertlist[ii]; + DRW_Vertex2D* vertex = aData.vertlist[ii]; if( ii == 0 ) { @@ -190,15 +174,15 @@ void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& data ) continue; } - DRAWSEGMENT* segm = new DRAWSEGMENT( m_brd ); + DRAWSEGMENT* segm = new DRAWSEGMENT( NULL ); segm->SetLayer( ToLAYER_ID( m_brdLayer ) ); segm->SetStart( startpoint ); wxPoint endpoint( mapX( vertex->x ), mapY( vertex->y ) ); segm->SetEnd( endpoint ); - segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); - appendToBoard( segm ); + segm->SetWidth( mapDim( aData.thickness == 0 ? m_defaultThickness + : aData.thickness ) ); + m_newItemsList.push_back( segm ); startpoint = endpoint; } } @@ -206,20 +190,18 @@ void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& data ) /* * Import Circle entities. */ -void DXF2BRD_CONVERTER::addCircle( const DRW_Circle& data ) +void DXF2BRD_CONVERTER::addCircle( const DRW_Circle& aData ) { - DRAWSEGMENT* segm = new DRAWSEGMENT( m_brd ); + DRAWSEGMENT* segm = new DRAWSEGMENT; segm->SetLayer( ToLAYER_ID( m_brdLayer ) ); segm->SetShape( S_CIRCLE ); - wxPoint center( mapX( data.basePoint.x ), mapY( data.basePoint.y ) ); + wxPoint center( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) ); segm->SetCenter( center ); - wxPoint circle_start( mapX( data.basePoint.x + data.radious ), - mapY( data.basePoint.y ) ); + wxPoint circle_start( mapX( aData.basePoint.x + aData.radious ), mapY( aData.basePoint.y ) ); segm->SetArcStart( circle_start ); - segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); - appendToBoard( segm ); + segm->SetWidth( mapDim( aData.thickness == 0 ? m_defaultThickness : aData.thickness ) ); + m_newItemsList.push_back( segm ); } @@ -228,7 +210,7 @@ void DXF2BRD_CONVERTER::addCircle( const DRW_Circle& data ) */ void DXF2BRD_CONVERTER::addArc( const DRW_Arc& data ) { - DRAWSEGMENT* segm = new DRAWSEGMENT( m_brd ); + DRAWSEGMENT* segm = new DRAWSEGMENT; segm->SetLayer( ToLAYER_ID( m_brdLayer ) ); segm->SetShape( S_ARC ); @@ -256,25 +238,24 @@ void DXF2BRD_CONVERTER::addArc( const DRW_Arc& data ) segm->SetAngle( angle ); - segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); - appendToBoard( segm ); + segm->SetWidth( mapDim( data.thickness == 0 ? m_defaultThickness : data.thickness ) ); + m_newItemsList.push_back( segm ); } /** * Import texts (TEXT). */ -void DXF2BRD_CONVERTER::addText(const DRW_Text& data) +void DXF2BRD_CONVERTER::addText( const DRW_Text& aData ) { - TEXTE_PCB* pcb_text = new TEXTE_PCB( m_brd ); + TEXTE_PCB* pcb_text = new TEXTE_PCB( NULL ); pcb_text->SetLayer( ToLAYER_ID( m_brdLayer ) ); - wxPoint refPoint( mapX(data.basePoint.x), mapY(data.basePoint.y) ); - wxPoint secPoint( mapX(data.secPoint.x), mapY(data.secPoint.y) ); + wxPoint refPoint( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) ); + wxPoint secPoint( mapX( aData.secPoint.x ), mapY( aData.secPoint.y ) ); - if (data.alignV !=0 || data.alignH !=0 ||data.alignH ==DRW_Text::HMiddle) + if( aData.alignV != 0 || aData.alignH != 0 || aData.alignH == DRW_Text::HMiddle ) { - if (data.alignH !=DRW_Text::HAligned && data.alignH !=DRW_Text::HFit) + if( aData.alignH != DRW_Text::HAligned && aData.alignH != DRW_Text::HFit ) { wxPoint tmp = secPoint; secPoint = refPoint; @@ -282,7 +263,7 @@ void DXF2BRD_CONVERTER::addText(const DRW_Text& data) } } - switch( data.alignV ) + switch( aData.alignV ) { case DRW_Text::VBaseLine: pcb_text->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); @@ -301,7 +282,7 @@ void DXF2BRD_CONVERTER::addText(const DRW_Text& data) break; } - switch( data.alignH ) + switch( aData.alignH ) { case DRW_Text::HLeft: pcb_text->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); @@ -332,13 +313,13 @@ void DXF2BRD_CONVERTER::addText(const DRW_Text& data) } #if 0 - wxString sty = wxString::FromUTF8(data.style.c_str()); + wxString sty = wxString::FromUTF8(aData.style.c_str()); sty=sty.ToLower(); - if (data.textgen==2) + if (aData.textgen==2) { // Text dir = left to right; - } else if (data.textgen==4) + } else if (aData.textgen==4) { / Text dir = top to bottom; } else @@ -346,27 +327,26 @@ void DXF2BRD_CONVERTER::addText(const DRW_Text& data) } #endif - wxString text = toNativeString( wxString::FromUTF8( data.text.c_str() ) ); + wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) ); pcb_text->SetTextPosition( refPoint ); - pcb_text->SetOrientation( data.angle * 10 ); + pcb_text->SetOrientation( aData.angle * 10 ); // The 0.8 factor gives a better height/width ratio with our font - pcb_text->SetWidth( mapDim( data.height * 0.8 ) ); - pcb_text->SetHeight( mapDim( data.height ) ); - pcb_text->SetThickness( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); + pcb_text->SetWidth( mapDim( aData.height * 0.8 ) ); + pcb_text->SetHeight( mapDim( aData.height ) ); + pcb_text->SetThickness( mapDim( aData.thickness == 0 ? m_defaultThickness : aData.thickness ) ); pcb_text->SetText( text ); - appendToBoard( pcb_text ); + m_newItemsList.push_back( pcb_text ); } /** * Import multi line texts (MTEXT). */ -void DXF2BRD_CONVERTER::addMText( const DRW_MText& data ) +void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData ) { - wxString text = toNativeString( wxString::FromUTF8( data.text.c_str() ) ); + wxString text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) ); wxString attrib, tmp; /* Some texts start by '\' and have formating chars (font name, font option...) @@ -394,25 +374,23 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& data ) text = tmp; } - TEXTE_PCB* pcb_text = new TEXTE_PCB( m_brd ); + TEXTE_PCB* pcb_text = new TEXTE_PCB( NULL ); pcb_text->SetLayer( ToLAYER_ID( m_brdLayer ) ); - - wxPoint textpos( mapX( data.basePoint.x ), mapY( data.basePoint.y ) ); + wxPoint textpos( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) ); pcb_text->SetTextPosition( textpos ); - pcb_text->SetOrientation( data.angle * 10 ); + pcb_text->SetOrientation( aData.angle * 10 ); // The 0.8 factor gives a better height/width ratio with our font - pcb_text->SetWidth( mapDim( data.height * 0.8 ) ); - pcb_text->SetHeight( mapDim( data.height ) ); - pcb_text->SetThickness( mapDim( data.thickness == 0 ? m_defaultThickness - : data.thickness ) ); + pcb_text->SetWidth( mapDim( aData.height * 0.8 ) ); + pcb_text->SetHeight( mapDim( aData.height ) ); + pcb_text->SetThickness( mapDim( aData.thickness == 0 ? m_defaultThickness : aData.thickness ) ); pcb_text->SetText( text ); // Initialize text justifications: - if( data.textgen <= 3 ) + if( aData.textgen <= 3 ) { pcb_text->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); } - else if( data.textgen <= 6 ) + else if( aData.textgen <= 6 ) { pcb_text->SetVertJustify( GR_TEXT_VJUSTIFY_CENTER ); } @@ -421,11 +399,11 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& data ) pcb_text->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); } - if( data.textgen % 3 == 1 ) + if( aData.textgen % 3 == 1 ) { pcb_text->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); } - else if( data.textgen % 3 == 2 ) + else if( aData.textgen % 3 == 2 ) { pcb_text->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER ); } @@ -448,7 +426,7 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& data ) // use ByStyle; } - if( data.alignV==1 ) + if( aData.alignV==1 ) { // use AtLeast; } @@ -458,7 +436,7 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& data ) } #endif - appendToBoard( pcb_text ); + m_newItemsList.push_back( pcb_text ); } @@ -490,24 +468,24 @@ void DXF2BRD_CONVERTER::addHeader( const DRW_Header* data ) * - %%%d for a degree sign * - %%%p for a plus/minus sign */ -wxString DXF2BRD_CONVERTER::toDxfString( const wxString& str ) +wxString DXF2BRD_CONVERTER::toDxfString( const wxString& aStr ) { wxString res; int j = 0; - for( unsigned i = 0; i175 || c<11 ) + if( c > 175 || c < 11 ) { - res.append( str.Mid( j, i - j ) ); + res.append( aStr.Mid( j, i - j ) ); j = i; switch( c ) { case 0x0A: - res += wxT("\\P"); + res += wxT( "\\P" ); break; // diameter: @@ -517,17 +495,17 @@ wxString DXF2BRD_CONVERTER::toDxfString( const wxString& str ) #else case 0x2205: #endif - res += wxT("%%C"); + res += wxT( "%%C" ); break; // degree: case 0x00B0: - res += wxT("%%D"); + res += wxT( "%%D" ); break; // plus/minus case 0x00B1: - res += wxT("%%P"); + res += wxT( "%%P" ); break; default: @@ -539,7 +517,7 @@ wxString DXF2BRD_CONVERTER::toDxfString( const wxString& str ) } } - res.append( str.Mid( j ) ); + res.append( aStr.Mid( j ) ); return res; } @@ -547,26 +525,26 @@ wxString DXF2BRD_CONVERTER::toDxfString( const wxString& str ) /** * Converts a DXF encoded string into a native Unicode string. */ -wxString DXF2BRD_CONVERTER::toNativeString( const wxString& data ) +wxString DXF2BRD_CONVERTER::toNativeString( const wxString& aData ) { wxString res; // Ignore font tags: int j = 0; - for( unsigned i = 0; i class BOARD; class BOARD_ITEM; @@ -41,16 +42,14 @@ class BOARD_ITEM; class DXF2BRD_CONVERTER : public DRW_Interface { private: - std::vector m_newItemsList; // The list of new items added - // to the board - BOARD * m_brd; + std::list m_newItemsList; // The list of new items added to the board double m_xOffset; // X coord offset for conversion (in mm) double m_yOffset; // Y coord offset for conversion (in mm) double m_defaultThickness; // default line thickness for conversion (in mm) double m_Dfx2mm; // The scale factor to convert DXF units to mm // Seems DRW_Interface always converts DXF coordinates in mm // (to be confirmed) - int m_brdLayer; // The board layer to place imported dfx items + int m_brdLayer; // The board layer to place imported dfx items int m_version; // the dxf version, not used here std::string m_codePage; // The code page, not used here @@ -83,14 +82,13 @@ public: * with this filter. * * @param aFile = the full filename. - * @param aBoard = where to store the graphical items and text */ - bool ImportDxfFile( const wxString& aFile, BOARD * aBoard ); + bool ImportDxfFile( const wxString& aFile ); /** * @return the list of new BOARD_ITEM */ - std::vector& GetItemsList() + const std::list& GetItemsList() const { return m_newItemsList; } @@ -101,68 +99,63 @@ private: int mapY( double aDxfCoordY ); int mapDim( double aDxfValue ); - // Add aItem the the board - // this item is also added to the list of new items - // (for undo command for instance) - void appendToBoard( BOARD_ITEM * aItem ); - // Methods from DRW_CreationInterface: // They are "call back" fonctions, called when the corresponding object // is read in dxf file // Depending of the application, they can do something or not - virtual void addHeader( const DRW_Header* data ); - virtual void addLType( const DRW_LType& data ){} - virtual void addLayer( const DRW_Layer& data ); - virtual void addDimStyle( const DRW_Dimstyle& data ){} - virtual void addBlock(const DRW_Block& data ){} - virtual void endBlock(){} - virtual void addPoint(const DRW_Point& data ){} - virtual void addLine(const DRW_Line& data); - virtual void addRay(const DRW_Ray& data ){} - virtual void addXline(const DRW_Xline& data ){} - virtual void addCircle(const DRW_Circle& data ); - virtual void addArc(const DRW_Arc& data ); - virtual void addEllipse(const DRW_Ellipse& data ){} - virtual void addLWPolyline(const DRW_LWPolyline& data ); - virtual void addText(const DRW_Text& data ); - virtual void addPolyline(const DRW_Polyline& data ); - virtual void addSpline(const DRW_Spline* data ){} - virtual void addKnot(const DRW_Entity&) {} - virtual void addInsert(const DRW_Insert& data ){} - virtual void addTrace(const DRW_Trace& data ){} - virtual void addSolid(const DRW_Solid& data ){} - virtual void addMText(const DRW_MText& data); - virtual void addDimAlign(const DRW_DimAligned *data ){} - virtual void addDimLinear(const DRW_DimLinear *data ){} - virtual void addDimRadial(const DRW_DimRadial *data ){} - virtual void addDimDiametric(const DRW_DimDiametric *data ){} - virtual void addDimAngular(const DRW_DimAngular *data ){} - virtual void addDimAngular3P(const DRW_DimAngular3p *data ){} - virtual void addDimOrdinate(const DRW_DimOrdinate *data ){} - virtual void addLeader(const DRW_Leader *data ){} - virtual void addHatch(const DRW_Hatch* data ){} - virtual void addImage(const DRW_Image* data ){} - virtual void linkImage(const DRW_ImageDef* data ){} + virtual void addHeader( const DRW_Header* aData ); + virtual void addLType( const DRW_LType& aData ) {} + virtual void addLayer( const DRW_Layer& aData ); + virtual void addDimStyle( const DRW_Dimstyle& aData ) {} + virtual void addBlock( const DRW_Block& aData ) {} + virtual void endBlock() {} + virtual void addPoint( const DRW_Point& aData ) {} + virtual void addLine( const DRW_Line& aData); + virtual void addRay( const DRW_Ray& aData ) {} + virtual void addXline( const DRW_Xline& aData ) {} + virtual void addCircle( const DRW_Circle& aData ); + virtual void addArc( const DRW_Arc& aData ); + virtual void addEllipse( const DRW_Ellipse& aData ) {} + virtual void addLWPolyline( const DRW_LWPolyline& aData ); + virtual void addText( const DRW_Text& aData ); + virtual void addPolyline( const DRW_Polyline& aData ); + virtual void addSpline( const DRW_Spline* aData ) {} + virtual void addKnot( const DRW_Entity&) {} + virtual void addInsert( const DRW_Insert& aData ){} + virtual void addTrace( const DRW_Trace& aData ){} + virtual void addSolid( const DRW_Solid& aData ){} + virtual void addMText( const DRW_MText& aData); + virtual void addDimAlign( const DRW_DimAligned* aData ) {} + virtual void addDimLinear( const DRW_DimLinear* aData ) {} + virtual void addDimRadial( const DRW_DimRadial* aData ) {} + virtual void addDimDiametric( const DRW_DimDiametric* aData ) {} + virtual void addDimAngular( const DRW_DimAngular* aData ) {} + virtual void addDimAngular3P( const DRW_DimAngular3p* aData ) {} + virtual void addDimOrdinate( const DRW_DimOrdinate* aData ) {} + virtual void addLeader( const DRW_Leader* aData ) {} + virtual void addHatch( const DRW_Hatch* aData ) {} + virtual void addImage( const DRW_Image* aData ) {} + virtual void linkImage( const DRW_ImageDef* aData ) {} - virtual void add3dFace(const DRW_3Dface& data ){} - virtual void addComment(const char*){} + virtual void add3dFace( const DRW_3Dface& aData ) {} + virtual void addComment( const char*) {} - virtual void addVport(const DRW_Vport& data) {} + virtual void addVport( const DRW_Vport& aData ) {} - virtual void addTextStyle(const DRW_Textstyle& data); + virtual void addTextStyle( const DRW_Textstyle& aData ); - virtual void addViewport(const DRW_Viewport& data) {} + virtual void addViewport( const DRW_Viewport& aData ) {} - virtual void setBlock(const int handle) {} + virtual void setBlock( const int aHandle ) {} - static wxString toDxfString(const wxString& str); - static wxString toNativeString(const wxString& data); + static wxString toDxfString( const wxString& aStr ); + static wxString toNativeString( const wxString& aData ); // These functions are not used in Kicad. // But because they are virtual pure in DRW_Interface, they should be defined virtual void writeTextstyles() {} virtual void writeVports() {} - virtual void writeHeader(DRW_Header& data) {} + virtual void writeHeader( DRW_Header& aData ) {} virtual void writeEntities() {} virtual void writeLTypes() {} virtual void writeLayers() {} @@ -172,7 +165,6 @@ private: void writeLine(); void writeMtext(); - }; #endif // FILTERDXFRW_H diff --git a/pcbnew/initpcb.cpp b/pcbnew/initpcb.cpp index 05ac3198f4..d0d6ba49e7 100644 --- a/pcbnew/initpcb.cpp +++ b/pcbnew/initpcb.cpp @@ -61,9 +61,6 @@ bool PCB_EDIT_FRAME::Clear_Pcb( bool aQuery ) // Update display GetBoard()->SetVisibleLayers( LSET().set() ); - // Set currently selected layer to be shown in high contrast mode, when enabled` - SetHighContrastLayer( GetScreen()->m_Active_Layer ); - ReFillLayerWidget(); Zoom_Automatique( false ); diff --git a/pcbnew/invoke_pcb_dialog.h b/pcbnew/invoke_pcb_dialog.h index ff9e89e40a..5f264ca000 100644 --- a/pcbnew/invoke_pcb_dialog.h +++ b/pcbnew/invoke_pcb_dialog.h @@ -49,10 +49,12 @@ class wxSize; //class wxRealPoint; class wxString; +class BOARD; +class MODULE; // Often this is not used in the prototypes, since wxFrame is good enough and would // represent maximum information hiding. -class PCB_EDIT_FRAME; +class PCB_BASE_FRAME; class FP_LIB_TABLE; class BOARD; class PCB_PLOT_PARAMS; @@ -81,13 +83,22 @@ void InvokePluginOptionsEditor( wxTopLevelWindow* aCaller, const wxString& aNick const wxString& aPluginType, const wxString& aOptions, wxString* aResult ); /** - * Function InvokePcbLibTableEditor - * shows the modal DIALOG_FP_LIB_TABLE for purposes of editing two lib tables. + * Function InvokeDXFDialogBoardImport + * shows the modal DIALOG_DXF_IMPORT for importing a DXF file to a board. + + * @param aCaller is the wxTopLevelWindow which is invoking the dialog. + * @return true if the import was made. + */ +bool InvokeDXFDialogBoardImport( PCB_BASE_FRAME* aCaller ); + +/** + * Function InvokeDXFDialogModuleImport + * shows the modal DIALOG_DXF_IMPORT for importing a DXF file.to a module. * * @param aCaller is the wxTopLevelWindow which is invoking the dialog. - * @return true if the ilport was made. + * @return true if the import was made. */ -bool InvokeDXFDialogImport( PCB_EDIT_FRAME* aCaller ); +bool InvokeDXFDialogModuleImport( PCB_BASE_FRAME* aCaller, MODULE* aModule ); /** * Function InvokeLayerSetup diff --git a/pcbnew/layer_widget.cpp b/pcbnew/layer_widget.cpp index fda117b8e4..84cad5da02 100644 --- a/pcbnew/layer_widget.cpp +++ b/pcbnew/layer_widget.cpp @@ -44,6 +44,8 @@ #define BUTT_SIZE_Y 18 #define BUTT_VOID 4 +const wxEventType LAYER_WIDGET::EVT_LAYER_COLOR_CHANGE = wxNewEventType(); + /* XPM * This bitmap is used for not selected layers */ @@ -294,6 +296,10 @@ void LAYER_WIDGET::OnMiddleDownLayerColor( wxMouseEvent& event ) // tell the client code. OnLayerColorChange( layer, newColor ); + + // notify others + wxCommandEvent event( EVT_LAYER_COLOR_CHANGE ); + wxPostEvent( this, event ); } passOnFocus(); @@ -581,6 +587,15 @@ LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, int aPoint } +LAYER_WIDGET::~LAYER_WIDGET() +{ + delete m_BlankBitmap; + delete m_BlankAlternateBitmap; + delete m_RightArrowBitmap; + delete m_RightArrowAlternateBitmap; +} + + wxSize LAYER_WIDGET::GetBestSize() const { // size of m_LayerScrolledWindow -------------- diff --git a/pcbnew/layer_widget.h b/pcbnew/layer_widget.h index 347038919c..e788cc4608 100644 --- a/pcbnew/layer_widget.h +++ b/pcbnew/layer_widget.h @@ -98,6 +98,7 @@ public: } }; + static const wxEventType EVT_LAYER_COLOR_CHANGE; protected: @@ -226,6 +227,8 @@ public: wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL ); + virtual ~LAYER_WIDGET(); + /** * Function GetBestSize * returns the preferred minimum size, taking into consideration the diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index 556726d826..b793856792 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -274,6 +274,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module() PlaceModule( module, NULL ); GetBoard()->m_Status_Pcb = 0; GetBoard()->BuildListOfNets(); + updateView(); return module; } diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 02c0601e10..6d6f6395b7 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include static void DisplayCmpDoc( wxString& Name ); @@ -105,6 +107,7 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) SetCrossHairPosition( wxPoint( 0, 0 ) ); PlaceModule( newModule, NULL ); + newModule->SetPosition( wxPoint( 0, 0 ) ); // cursor in GAL may not be initialized at the moment // Put it on FRONT layer, // because this is the default in ModEdit, and in libs @@ -117,6 +120,9 @@ bool FOOTPRINT_EDIT_FRAME::Load_Module_From_BOARD( MODULE* aModule ) GetScreen()->ClrModify(); Zoom_Automatique( false ); + if( IsGalCanvasActive() ) + updateView(); + return true; } diff --git a/pcbnew/menubar_modedit.cpp b/pcbnew/menubar_modedit.cpp index ffbe9a681f..418cc5c342 100644 --- a/pcbnew/menubar_modedit.cpp +++ b/pcbnew/menubar_modedit.cpp @@ -125,6 +125,13 @@ void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar() _( "&Export Module" ), _( "Save current loaded module into file" ), KiBitmap( export_module_xpm ) ); + + // Import DXF File + AddMenuItem( fileMenu, ID_GEN_IMPORT_DXF_FILE, + _( "&Import DXF File" ), + _( "Import a 2D Drawing DXF file to Pcbnew on the Drawings layer" ), + KiBitmap( import_xpm ) ); + fileMenu->AppendSeparator(); // Print diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index ed81bc7989..ff22550845 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -38,17 +39,20 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -56,6 +60,8 @@ #include #include +#include + // Functions defined in block_module_editor, but used here // These 2 functions are used in modedit to rotate or mirror the whole footprint @@ -289,7 +295,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) case ID_MODEDIT_NEW_MODULE: { - if( ! Clear_Pcb( true ) ) + if( !Clear_Pcb( true ) ) break; SetCrossHairPosition( wxPoint( 0, 0 ) ); @@ -311,6 +317,9 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) Zoom_Automatique( false ); } + if( IsGalCanvasActive() ) + updateView(); + GetScreen()->ClrModify(); } break; @@ -449,15 +458,31 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) pcbframe->SetCrossHairPosition( wxPoint( 0, 0 ) ); pcbframe->PlaceModule( newmodule, NULL ); + newmodule->SetPosition( wxPoint( 0, 0 ) ); pcbframe->SetCrossHairPosition( cursor_pos ); newmodule->SetTimeStamp( GetNewTimeStamp() ); pcbframe->SaveCopyInUndoList( newmodule, UR_NEW ); + + if( IsGalCanvasActive() ) + { + KIGFX::VIEW* view = pcbframe->GetGalCanvas()->GetView(); + + newmodule->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + view->Add( newmodule ); + } } newmodule->ClearFlags(); GetScreen()->ClrModify(); pcbframe->SetCurItem( NULL ); mainpcb->m_Status_Pcb = 0; + + if( IsGalCanvasActive() ) + { + RN_DATA* ratsnest = pcbframe->GetBoard()->GetRatsnest(); + ratsnest->Update( newmodule ); + ratsnest->Recalculate(); + } } break; @@ -539,6 +564,7 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) m_Draw3DFrame->NewDisplay(); GetScreen()->ClrModify(); + updateView(); break; @@ -774,6 +800,11 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) HandleBlockEnd( &dc ); break; + case ID_GEN_IMPORT_DXF_FILE: + InvokeDXFDialogModuleImport( this, GetBoard()->m_Modules ); + m_canvas->Refresh(); + break; + default: DisplayError( this, wxT( "FOOTPRINT_EDIT_FRAME::Process_Special_Functions error" ) ); @@ -914,3 +945,26 @@ EDA_COLOR_T FOOTPRINT_EDIT_FRAME::GetGridColor() const return g_ColorsSettings.GetItemColor( GRID_VISIBLE ); } + +void FOOTPRINT_EDIT_FRAME::SetActiveLayer( LAYER_ID aLayer ) +{ + PCB_BASE_FRAME::SetActiveLayer( aLayer ); + + GetGalCanvas()->SetHighContrastLayer( aLayer ); + + if( IsGalCanvasActive() ) + GetGalCanvas()->Refresh(); +} + + +void FOOTPRINT_EDIT_FRAME::UseGalCanvas( bool aEnable ) +{ + EDA_DRAW_FRAME::UseGalCanvas( aEnable ); + + if( aEnable ) + { + SetBoard( m_Pcb ); + updateView(); + GetGalCanvas()->StartDrawing(); + } +} diff --git a/pcbnew/modedit_onclick.cpp b/pcbnew/modedit_onclick.cpp index 5fa0abb448..b6f4437e53 100644 --- a/pcbnew/modedit_onclick.cpp +++ b/pcbnew/modedit_onclick.cpp @@ -418,41 +418,7 @@ void FOOTPRINT_EDIT_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos ) // Item found SetCurItem( item ); - - switch( item->Type() ) - { - case PCB_PAD_T: - InstallPadOptionsFrame( (D_PAD*) item ); - m_canvas->MoveCursorToCrossHair(); - break; - - case PCB_MODULE_T: - { - DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) item ); - int ret = dialog.ShowModal(); - GetScreen()->GetCurItem()->ClearFlags(); - m_canvas->MoveCursorToCrossHair(); - - if( ret > 0 ) - m_canvas->Refresh(); - } - break; - - case PCB_MODULE_TEXT_T: - InstallTextModOptionsFrame( (TEXTE_MODULE*) item, DC ); - m_canvas->MoveCursorToCrossHair(); - break; - - case PCB_MODULE_EDGE_T : - m_canvas->MoveCursorToCrossHair(); - InstallFootprintBodyItemPropertiesDlg( (EDGE_MODULE*) item ); - m_canvas->Refresh(); - break; - - default: - break; - } - + OnEditItemRequest( DC, item ); break; // end case 0 case ID_PCB_ADD_LINE_BUTT: @@ -471,3 +437,41 @@ void FOOTPRINT_EDIT_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos ) break; } } + + +void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem ) +{ + switch( aItem->Type() ) + { + case PCB_PAD_T: + InstallPadOptionsFrame( (D_PAD*) aItem ); + m_canvas->MoveCursorToCrossHair(); + break; + + case PCB_MODULE_T: + { + DIALOG_MODULE_MODULE_EDITOR dialog( this, (MODULE*) aItem ); + int ret = dialog.ShowModal(); + GetScreen()->GetCurItem()->ClearFlags(); + m_canvas->MoveCursorToCrossHair(); + + if( ret > 0 ) + m_canvas->Refresh(); + } + break; + + case PCB_MODULE_TEXT_T: + InstallTextModOptionsFrame( (TEXTE_MODULE*) aItem, aDC ); + m_canvas->MoveCursorToCrossHair(); + break; + + case PCB_MODULE_EDGE_T : + m_canvas->MoveCursorToCrossHair(); + InstallFootprintBodyItemPropertiesDlg( (EDGE_MODULE*) aItem ); + m_canvas->Refresh(); + break; + + default: + break; + } +} diff --git a/pcbnew/modedit_undo_redo.cpp b/pcbnew/modedit_undo_redo.cpp index 613f4d8d2b..2b61e1e78e 100644 --- a/pcbnew/modedit_undo_redo.cpp +++ b/pcbnew/modedit_undo_redo.cpp @@ -2,8 +2,11 @@ /* library editor: undo and redo functions */ /********************************************/ +#include #include #include +#include +#include #include #include @@ -50,31 +53,52 @@ void FOOTPRINT_EDIT_FRAME::SaveCopyInUndoList( const PICKED_ITEMS_LIST& aItemsLi UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint ) { - // Currently unused in modedit, because the module itself is saved for each change - wxMessageBox( wxT( "SaveCopyInUndoList( PICKED_ITEMS_LIST& aItemsList..) not yet in use" ) ); + assert( aItemsList.GetPickedItem( 0 )->GetParent()->Type() == PCB_MODULE_T ); + MODULE* owner = static_cast( aItemsList.GetPickedItem( 0 )->GetParent() ); + +#ifndef NDEBUG + // All items should have the same parent (MODULE) to make undo/redo entry valid + for( unsigned int i = 0; i < aItemsList.GetCount(); ++i ) + assert( aItemsList.GetPickedItem( i )->GetParent() == owner ); +#endif /* not NDEBUG */ + + SaveCopyInUndoList( owner, aTypeCommand, aTransformPoint ); } -void FOOTPRINT_EDIT_FRAME::GetComponentFromRedoList( wxCommandEvent& event ) +void FOOTPRINT_EDIT_FRAME::RestoreCopyFromRedoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetRedoCommandCount() <= 0 ) return; + // Inform tools that undo command was issued + TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); + m_toolManager->ProcessEvent( event ); + // Save current module state in undo list PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - MODULE * module = GetBoard()->m_Modules.PopFront(); - ITEM_PICKER wrapper( module, UR_MODEDIT ); + MODULE* module = GetBoard()->m_Modules.PopFront(); + ITEM_PICKER wrapper( module, UR_MODEDIT ); + KIGFX::VIEW* view = GetGalCanvas()->GetView(); lastcmd->PushItem( wrapper ); GetScreen()->PushCommandToUndoList( lastcmd ); + view->Remove( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + // Retrieve last module state from undo list lastcmd = GetScreen()->PopCommandFromRedoList(); wrapper = lastcmd->PopItem(); - module = (MODULE *)wrapper.GetItem(); + module = (MODULE*) wrapper.GetItem(); delete lastcmd; if( module ) + { GetBoard()->Add( module ); + GetGalCanvas()->GetView()->Add( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + module->ViewUpdate(); + } SetCurItem( NULL ); @@ -83,27 +107,39 @@ void FOOTPRINT_EDIT_FRAME::GetComponentFromRedoList( wxCommandEvent& event ) } -void FOOTPRINT_EDIT_FRAME::GetComponentFromUndoList( wxCommandEvent& event ) +void FOOTPRINT_EDIT_FRAME::RestoreCopyFromUndoList( wxCommandEvent& aEvent ) { if( GetScreen()->GetUndoCommandCount() <= 0 ) return; + // Inform tools that undo command was issued + TOOL_EVENT event( TC_MESSAGE, TA_UNDO_REDO, AS_GLOBAL ); + m_toolManager->ProcessEvent( event ); + // Save current module state in redo list PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - MODULE * module = GetBoard()->m_Modules.PopFront(); - ITEM_PICKER wrapper( module, UR_MODEDIT ); + MODULE* module = GetBoard()->m_Modules.PopFront(); + ITEM_PICKER wrapper( module, UR_MODEDIT ); + KIGFX::VIEW* view = GetGalCanvas()->GetView(); lastcmd->PushItem( wrapper ); GetScreen()->PushCommandToRedoList( lastcmd ); + view->Remove( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Remove, view, _1 ) ); + // Retrieve last module state from undo list lastcmd = GetScreen()->PopCommandFromUndoList(); wrapper = lastcmd->PopItem(); - module = (MODULE *)wrapper.GetItem(); + module = (MODULE*) wrapper.GetItem(); delete lastcmd; if( module ) + { GetBoard()->Add( module, ADD_APPEND ); - + view->Add( module ); + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); + module->ViewUpdate(); + } SetCurItem( NULL ); diff --git a/pcbnew/module_editor_frame.h b/pcbnew/module_editor_frame.h index 1e10a01b09..9a3f0379a2 100644 --- a/pcbnew/module_editor_frame.h +++ b/pcbnew/module_editor_frame.h @@ -30,6 +30,7 @@ #define MODULE_EDITOR_FRAME_H_ #include +#include #include @@ -38,7 +39,7 @@ class FP_LIB_TABLE; namespace PCB { struct IFACE; } // A KIFACE_I coded in pcbnew.c -class FOOTPRINT_EDIT_FRAME : public PCB_BASE_FRAME +class FOOTPRINT_EDIT_FRAME : public PCB_BASE_EDIT_FRAME { friend struct PCB::IFACE; @@ -148,6 +149,9 @@ public: void OnUpdateReplaceModuleInBoard( wxUpdateUIEvent& aEvent ); void OnUpdateSelectCurrentLib( wxUpdateUIEvent& aEvent ); + ///> @copydoc PCB_BASE_EDIT_FRAME::OnEditItemRequest() + void OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem ); + /** * Function LoadModuleFromBoard * called from the main toolbar to load a footprint from board mainly to edit it. @@ -161,7 +165,7 @@ public: * and prepare, if needed the refresh of the 3D frame showing the footprint * do not forget to call the basic OnModify function to update auxiliary info */ - virtual void OnModify( ); + virtual void OnModify(); /** * Function ToPrinter @@ -217,7 +221,6 @@ public: BOARD_ITEM* ModeditLocateAndDisplay( int aHotKeyCode = 0 ); /* Undo and redo functions */ -public: /** * Function SaveCopyInUndoList. @@ -245,6 +248,22 @@ public: UNDO_REDO_T aTypeCommand, const wxPoint& aTransformPoint = wxPoint( 0, 0 ) ); + /** + * Function RestoreCopyFromUndoList + * performs an undo operation on the last edition: + * - Place the current edited library component in Redo list + * - Get old version of the current edited library component + */ + void RestoreCopyFromUndoList( wxCommandEvent& aEvent ); + + /** + * Function RestoreCopyFromRedoList + * performs a redo operation on the the last edition: + * - Place the current edited library component in undo list + * - Get old version of the current edited library component + */ + void RestoreCopyFromRedoList( wxCommandEvent& aEvent ); + /// Return the current library nickname. const wxString GetCurrentLib() const; @@ -399,6 +418,12 @@ public: virtual EDA_COLOR_T GetGridColor() const; + ///> @copydoc PCB_BASE_FRAME::SetActiveLayer() + void SetActiveLayer( LAYER_ID aLayer ); + + ///> @copydoc EDA_DRAW_FRAME::UseGalCanvas() + virtual void UseGalCanvas( bool aEnable ); + DECLARE_EVENT_TABLE() protected: @@ -406,22 +431,7 @@ protected: /// protected so only friend PCB::IFACE::CreateWindow() can act as sole factory. FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ); - - /** - * Function GetComponentFromUndoList - * performs an undo operation on the last edition: - * - Place the current edited library component in Redo list - * - Get old version of the current edited library component - */ - void GetComponentFromUndoList( wxCommandEvent& event ); - - /** - * Function GetComponentFromRedoList - * performs a redo operation on the the last edition: - * - Place the current edited library component in undo list - * - Get old version of the current edited library component - */ - void GetComponentFromRedoList( wxCommandEvent& event ); + PCB_LAYER_WIDGET* m_Layers; /** * Function UpdateTitle @@ -429,6 +439,9 @@ protected: */ void updateTitle(); + /// Reloads displayed items and sets view. + void updateView(); + /// The libPath is not publicly visible, grab it from the FP_LIB_TABLE if we must. const wxString getLibPath(); diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index d844321bdc..58dc823b44 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,18 @@ #include #include #include +#include + +#include +#include +#include "tools/selection_tool.h" +#include "tools/edit_tool.h" +#include "tools/drawing_tool.h" +#include "tools/point_editor.h" +#include "tools/pcbnew_control.h" +#include "tools/module_tools.h" +#include "tools/placement_tool.h" +#include "tools/common_actions.h" BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) @@ -80,6 +93,7 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) EVT_TOOL( ID_MODEDIT_CREATE_NEW_LIB_AND_SAVE_CURRENT_PART, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_SHEET_SET, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) + EVT_TOOL( ID_GEN_IMPORT_DXF_FILE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_PRINT, FOOTPRINT_EDIT_FRAME::ToPrinter ) EVT_TOOL( ID_MODEDIT_LOAD_MODULE, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_CHECK, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) @@ -88,8 +102,8 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME ) EVT_TOOL( ID_MODEDIT_INSERT_MODULE_IN_BOARD, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_UPDATE_MODULE_IN_BOARD, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( ID_MODEDIT_EDIT_MODULE_PROPERTIES, FOOTPRINT_EDIT_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_UNDO, FOOTPRINT_EDIT_FRAME::GetComponentFromUndoList ) - EVT_TOOL( wxID_REDO, FOOTPRINT_EDIT_FRAME::GetComponentFromRedoList ) + EVT_TOOL( wxID_UNDO, FOOTPRINT_EDIT_FRAME::RestoreCopyFromUndoList ) + EVT_TOOL( wxID_REDO, FOOTPRINT_EDIT_FRAME::RestoreCopyFromRedoList ) // Vertical tool bar button click event handler. EVT_TOOL( ID_NO_TOOL_SELECTED, FOOTPRINT_EDIT_FRAME::OnVerticalToolbar ) @@ -149,9 +163,9 @@ END_EVENT_TABLE() #define FOOTPRINT_EDIT_FRAME_NAME wxT( "ModEditFrame" ) FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : - PCB_BASE_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString, - wxDefaultPosition, wxDefaultSize, - KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ) + PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString, + wxDefaultPosition, wxDefaultSize, + KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ) { m_FrameName = GetFootprintEditorFrameName(); m_showBorderAndTitleBlock = false; // true to show the frame references @@ -167,6 +181,12 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // Show a title (frame title + footprint name): updateTitle(); + // Create GAL canvas + PCB_BASE_FRAME* parentFrame = static_cast( Kiway().Player( FRAME_PCB, true ) ); + PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, + parentFrame->GetGalCanvas()->GetBackend() ); + SetGalCanvas( drawPanel ); + SetBoard( new BOARD() ); // restore the last footprint from the project, if any @@ -175,6 +195,9 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : // Ensure all layers and items are visible: GetBoard()->SetVisibleAlls(); + wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT ); + m_Layers = new PCB_LAYER_WIDGET( this, GetCanvas(), font.GetPointSize() ); + SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) ); GetScreen()->SetCurItem( NULL ); @@ -208,6 +231,14 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : EDA_PANEINFO mesg_pane; mesg_pane.MessageToolbarPane(); + // Create a wxAuiPaneInfo for the Layers Manager, not derived from the template. + // LAYER_WIDGET is floatable, but initially docked at far right + EDA_PANEINFO lyrs; + lyrs.LayersToolbarPane(); + lyrs.MinSize( m_Layers->GetBestSize() ); // updated in ReFillLayerWidget + lyrs.BestSize( m_Layers->GetBestSize() ); + lyrs.Caption( _( "Visibles" ) ); + m_auimgr.AddPane( m_mainToolBar, wxAuiPaneInfo( horiz ).Name( wxT( "m_mainToolBar" ) ).Top(). Row( 0 ) ); @@ -218,16 +249,54 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_auimgr.AddPane( m_drawToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_VToolBar" ) ).Right().Layer(1) ); + // Add the layer manager ( most right side of pcbframe ) + m_auimgr.AddPane( m_Layers, lyrs.Name( wxT( "m_LayersManagerToolBar" ) ).Right().Layer( 2 ) ); + // Layers manager is visible and served only in GAL canvas mode. + m_auimgr.GetPane( wxT( "m_LayersManagerToolBar" ) ).Show( parentFrame->IsGalCanvasActive() ); + // The left vertical toolbar (fast acces to display options) m_auimgr.AddPane( m_optionsToolBar, wxAuiPaneInfo( vert ).Name( wxT( "m_optionsToolBar" ) ). Left().Layer(1) ); m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); + m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), + wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); m_auimgr.AddPane( m_messagePanel, wxAuiPaneInfo( mesg_pane ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) ); + // Create the manager and dispatcher & route draw panel events to the dispatcher + m_toolManager = new TOOL_MANAGER; + m_toolManager->SetEnvironment( GetBoard(), drawPanel->GetView(), + drawPanel->GetViewControls(), this ); + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager ); + + if( parentFrame->IsGalCanvasActive() ) + { + drawPanel->SetEventDispatcher( m_toolDispatcher ); + + m_toolManager->RegisterTool( new SELECTION_TOOL ); + m_toolManager->RegisterTool( new EDIT_TOOL ); + m_toolManager->RegisterTool( new DRAWING_TOOL ); + m_toolManager->RegisterTool( new POINT_EDITOR ); + m_toolManager->RegisterTool( new PCBNEW_CONTROL ); + m_toolManager->RegisterTool( new MODULE_TOOLS ); + m_toolManager->RegisterTool( new PLACEMENT_TOOL ); + + m_toolManager->GetTool()->EditModules( true ); + m_toolManager->GetTool()->EditModules( true ); + m_toolManager->GetTool()->EditModules( true ); + + m_toolManager->ResetTools( TOOL_BASE::RUN ); + m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); + + UseGalCanvas( true ); + } + + m_Layers->ReFill(); + m_Layers->ReFillRender(); + m_auimgr.Update(); } @@ -236,6 +305,8 @@ FOOTPRINT_EDIT_FRAME::~FOOTPRINT_EDIT_FRAME() { // save the footprint in the PROJECT retainLastFootprint(); + + delete m_Layers; } @@ -620,3 +691,11 @@ void FOOTPRINT_EDIT_FRAME::updateTitle() SetTitle( title ); } + + +void FOOTPRINT_EDIT_FRAME::updateView() +{ + static_cast( GetGalCanvas() )->DisplayBoard( GetBoard() ); + m_toolManager->RunAction( COMMON_ACTIONS::zoomFitScreen ); + m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); +} diff --git a/pcbnew/modview_frame.cpp b/pcbnew/modview_frame.cpp index 1f80fe663e..d83e220234 100644 --- a/pcbnew/modview_frame.cpp +++ b/pcbnew/modview_frame.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include <3d_viewer.h> #include @@ -54,6 +55,13 @@ #include #include +#include +#include +#include "tools/pcbnew_control.h" +#include "tools/common_actions.h" + +#include + #define NEXT_PART 1 #define NEW_PART 0 @@ -160,6 +168,23 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent ReCreateLibraryList(); UpdateTitle(); + PCB_BASE_FRAME* parentFrame = static_cast( Kiway().Player( FRAME_PCB, true ) ); + + // Create GAL canvas + PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, + parentFrame->GetGalCanvas()->GetBackend() ); + SetGalCanvas( drawPanel ); + + // Create the manager and dispatcher & route draw panel events to the dispatcher + m_toolManager = new TOOL_MANAGER; + m_toolManager->SetEnvironment( GetBoard(), drawPanel->GetView(), + drawPanel->GetViewControls(), this ); + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager ); + drawPanel->SetEventDispatcher( m_toolDispatcher ); + + m_toolManager->RegisterTool( new PCBNEW_CONTROL ); + m_toolManager->ResetTools( TOOL_BASE::RUN ); + // If a footprint was previously loaded, reload it if( getCurNickname().size() && getCurFootprintName().size() ) { @@ -170,6 +195,9 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent GetBoard()->Add( loadFootprint( id ) ); } + drawPanel->DisplayBoard( m_Pcb ); + updateView(); + if( m_canvas ) m_canvas->SetAcceleratorTable( table ); @@ -207,6 +235,8 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent // Manage the draw panel, right pane. m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); + m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), + wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); // Manage the message panel, bottom pane. m_auimgr.AddPane( m_messagePanel, @@ -244,6 +274,8 @@ FOOTPRINT_VIEWER_FRAME::FOOTPRINT_VIEWER_FRAME( KIWAY* aKiway, wxWindow* aParent #endif Show( true ); + + UseGalCanvas( parentFrame->IsGalCanvasActive() ); } @@ -263,6 +295,10 @@ const wxChar* FOOTPRINT_VIEWER_FRAME::GetFootprintViewerFrameName() void FOOTPRINT_VIEWER_FRAME::OnCloseWindow( wxCloseEvent& Event ) { DBG(printf( "%s:\n", __func__ );) + + if( IsGalCanvasActive() ) + GetGalCanvas()->StopDrawing(); + if( IsModal() ) { // Only dismiss a modal frame once, so that the return values set by @@ -324,6 +360,15 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateLibraryList() } +void FOOTPRINT_VIEWER_FRAME::UseGalCanvas( bool aEnable ) +{ + EDA_DRAW_FRAME::UseGalCanvas( aEnable ); + + if( aEnable ) + GetGalCanvas()->StartDrawing(); +} + + void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList() { m_footprintList->Clear(); @@ -421,6 +466,10 @@ void FOOTPRINT_VIEWER_FRAME::ClickOnFootprintList( wxCommandEvent& event ) } UpdateTitle(); + + if( IsGalCanvasActive() ) + updateView(); + Zoom_Automatique( false ); m_canvas->Refresh(); Update3D_Frame(); @@ -802,8 +851,12 @@ void FOOTPRINT_VIEWER_FRAME::SelectAndViewFootprint( int aMode ) GetBoard()->Add( footprint, ADD_APPEND ); Update3D_Frame(); + + if( IsGalCanvasActive() ) + updateView(); } + UpdateTitle(); Zoom_Automatique( false ); m_canvas->Refresh(); @@ -827,3 +880,28 @@ void FOOTPRINT_VIEWER_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg ) if( module ) SetMsgPanel( module ); } + + +void FOOTPRINT_VIEWER_FRAME::updateView() +{ + static_cast( GetGalCanvas() )->DisplayBoard( GetBoard() ); + + m_Pcb->ComputeBoundingBox( false ); + EDA_RECT boardBbox = m_Pcb->GetBoundingBox(); + BOX2D bbox; + + // Autozoom + if( boardBbox.GetSize().x > 0 && boardBbox.GetSize().y > 0 ) + { + bbox.SetOrigin( VECTOR2D( boardBbox.GetOrigin() ) ); + bbox.SetSize( VECTOR2D( boardBbox.GetSize() ) ); + } + else + { + // Default empty view + bbox.SetOrigin( VECTOR2D( -1000, -1000 ) ); + bbox.SetSize( VECTOR2D( 2000, 2000 ) ); + } + + GetGalCanvas()->GetView()->SetViewport( bbox ); +} diff --git a/pcbnew/modview_frame.h b/pcbnew/modview_frame.h index aaa04afaf7..311f150ed8 100644 --- a/pcbnew/modview_frame.h +++ b/pcbnew/modview_frame.h @@ -69,6 +69,8 @@ public: */ void ReCreateLibraryList(); + ///> @copydoc EDA_DRAW_FRAME::UseGalCanvas() + virtual void UseGalCanvas( bool aEnable ); private: @@ -170,6 +172,8 @@ private: void SaveCopyInUndoList( BOARD_ITEM*, UNDO_REDO_T, const wxPoint& ) {} void SaveCopyInUndoList( const PICKED_ITEMS_LIST&, UNDO_REDO_T, const wxPoint &) {} + void updateView(); + DECLARE_EVENT_TABLE() }; diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp new file mode 100644 index 0000000000..e4aa24108b --- /dev/null +++ b/pcbnew/pcb_base_edit_frame.cpp @@ -0,0 +1,33 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 + +void PCB_BASE_EDIT_FRAME::SetRotationAngle( int aRotationAngle ) +{ + wxCHECK2_MSG( aRotationAngle > 0 && aRotationAngle <= 900, aRotationAngle = 900, + wxT( "Invalid rotation angle, defaulting to 90." ) ); + + m_rotationAngle = aRotationAngle; +} diff --git a/pcbnew/pcb_base_edit_frame.h b/pcbnew/pcb_base_edit_frame.h new file mode 100644 index 0000000000..3d867874d6 --- /dev/null +++ b/pcbnew/pcb_base_edit_frame.h @@ -0,0 +1,77 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 BASE_EDIT_FRAME_H +#define BASE_EDIT_FRAME_H + +#include + +/** + * Common, abstract interface for edit frames. + */ +class PCB_BASE_EDIT_FRAME : public PCB_BASE_FRAME +{ +public: + PCB_BASE_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType, + const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize, + long aStyle, const wxString& aFrameName ) : + PCB_BASE_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ), + m_rotationAngle( 900 ) + {} + + virtual ~PCB_BASE_EDIT_FRAME() {}; + + /** + * Function OnEditItemRequest + * Install the corresponding dialog editor for the given item + * @param aDC = the current device context + * @param aItem = a pointer to the BOARD_ITEM to edit + */ + virtual void OnEditItemRequest( wxDC* aDC, BOARD_ITEM* aItem ) = 0; + + /** + * Function RestoreCopyFromRedoList + * Redo the last edition: + * - Save the current data in Undo list + * - Get an old version of the data from Redo list + */ + virtual void RestoreCopyFromRedoList( wxCommandEvent& aEvent ) = 0; + + /** + * Function RestoreCopyFromUndoList + * Undo the last edition: + * - Save the current board in Redo list + * - Get an old version of the data from Undo list + */ + virtual void RestoreCopyFromUndoList( wxCommandEvent& aEvent ) = 0; + + int GetRotationAngle() const { return m_rotationAngle; } + void SetRotationAngle( int aRotationAngle ); + +protected: + /// User defined rotation angle (in tenths of a degree). + int m_rotationAngle; +}; + +#endif diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp new file mode 100644 index 0000000000..8d2e89f275 --- /dev/null +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -0,0 +1,347 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "pcb_draw_panel_gal.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +const LAYER_NUM GAL_LAYER_ORDER[] = +{ + ITEM_GAL_LAYER( GP_OVERLAY ), + ITEM_GAL_LAYER( DRC_VISIBLE ), + NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), + Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts, + + ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ), + ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE), ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ), + + ITEM_GAL_LAYER( RATSNEST_VISIBLE ), ITEM_GAL_LAYER( ANCHOR_VISIBLE ), + ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), + ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), + + NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_FR_VISIBLE ), F_Mask, + NETNAMES_GAL_LAYER( F_Cu ), F_Cu, + F_SilkS, F_Paste, F_Adhes, + +#if 0 // was: + NETNAMES_GAL_LAYER( LAYER_15_NETNAMES_VISIBLE ), LAYER_N_15, + NETNAMES_GAL_LAYER( LAYER_14_NETNAMES_VISIBLE ), LAYER_N_14, + NETNAMES_GAL_LAYER( LAYER_13_NETNAMES_VISIBLE ), LAYER_N_13, + NETNAMES_GAL_LAYER( LAYER_12_NETNAMES_VISIBLE ), LAYER_N_12, + NETNAMES_GAL_LAYER( LAYER_11_NETNAMES_VISIBLE ), LAYER_N_11, + NETNAMES_GAL_LAYER( LAYER_10_NETNAMES_VISIBLE ), LAYER_N_10, + NETNAMES_GAL_LAYER( LAYER_9_NETNAMES_VISIBLE ), LAYER_N_9, + NETNAMES_GAL_LAYER( LAYER_8_NETNAMES_VISIBLE ), LAYER_N_8, + NETNAMES_GAL_LAYER( LAYER_7_NETNAMES_VISIBLE ), LAYER_N_7, + NETNAMES_GAL_LAYER( LAYER_6_NETNAMES_VISIBLE ), LAYER_N_6, + NETNAMES_GAL_LAYER( LAYER_5_NETNAMES_VISIBLE ), LAYER_N_5, + NETNAMES_GAL_LAYER( LAYER_4_NETNAMES_VISIBLE ), LAYER_N_4, + NETNAMES_GAL_LAYER( LAYER_3_NETNAMES_VISIBLE ), LAYER_N_3, + NETNAMES_GAL_LAYER( LAYER_2_NETNAMES_VISIBLE ), LAYER_N_2, +#else + NETNAMES_GAL_LAYER( In1_Cu ), In1_Cu, + NETNAMES_GAL_LAYER( In2_Cu ), In2_Cu, + NETNAMES_GAL_LAYER( In3_Cu ), In3_Cu, + NETNAMES_GAL_LAYER( In4_Cu ), In4_Cu, + NETNAMES_GAL_LAYER( In5_Cu ), In5_Cu, + NETNAMES_GAL_LAYER( In6_Cu ), In6_Cu, + NETNAMES_GAL_LAYER( In7_Cu ), In7_Cu, + NETNAMES_GAL_LAYER( In8_Cu ), In8_Cu, + NETNAMES_GAL_LAYER( In9_Cu ), In9_Cu, + NETNAMES_GAL_LAYER( In10_Cu ), In10_Cu, + NETNAMES_GAL_LAYER( In11_Cu ), In11_Cu, + NETNAMES_GAL_LAYER( In12_Cu ), In12_Cu, + NETNAMES_GAL_LAYER( In13_Cu ), In13_Cu, + NETNAMES_GAL_LAYER( In14_Cu ), In14_Cu, + NETNAMES_GAL_LAYER( In15_Cu ), In15_Cu, + NETNAMES_GAL_LAYER( In16_Cu ), In16_Cu, + NETNAMES_GAL_LAYER( In17_Cu ), In17_Cu, + NETNAMES_GAL_LAYER( In18_Cu ), In18_Cu, + NETNAMES_GAL_LAYER( In19_Cu ), In19_Cu, + NETNAMES_GAL_LAYER( In20_Cu ), In20_Cu, + NETNAMES_GAL_LAYER( In21_Cu ), In21_Cu, + NETNAMES_GAL_LAYER( In22_Cu ), In22_Cu, + NETNAMES_GAL_LAYER( In23_Cu ), In23_Cu, + NETNAMES_GAL_LAYER( In24_Cu ), In24_Cu, + NETNAMES_GAL_LAYER( In25_Cu ), In25_Cu, + NETNAMES_GAL_LAYER( In26_Cu ), In26_Cu, + NETNAMES_GAL_LAYER( In27_Cu ), In27_Cu, + NETNAMES_GAL_LAYER( In28_Cu ), In28_Cu, + NETNAMES_GAL_LAYER( In29_Cu ), In29_Cu, + NETNAMES_GAL_LAYER( In30_Cu ), In30_Cu, +#endif + NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_BK_VISIBLE ), B_Mask, + NETNAMES_GAL_LAYER( B_Cu ), B_Cu, + + B_Adhes, B_Paste, B_SilkS, + ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ), + ITEM_GAL_LAYER( WORKSHEET ) +}; + + +PCB_DRAW_PANEL_GAL::PCB_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, + const wxPoint& aPosition, const wxSize& aSize, + GalType aGalType ) : +EDA_DRAW_PANEL_GAL( aParentWindow, aWindowId, aPosition, aSize, aGalType ) +{ + m_worksheet = NULL; + m_ratsnest = NULL; + + // Set rendering order and properties of layers + for( LAYER_NUM i = 0; (unsigned) i < sizeof(GAL_LAYER_ORDER) / sizeof(LAYER_NUM); ++i ) + { + LAYER_NUM layer = GAL_LAYER_ORDER[i]; + wxASSERT( layer < KIGFX::VIEW::VIEW_MAX_LAYERS ); + + m_view->SetLayerOrder( layer, i ); + + if( IsCopperLayer( layer ) ) + { + // Copper layers are required for netname layers + m_view->SetRequired( GetNetnameLayer( layer ), layer ); + m_view->SetLayerTarget( layer, KIGFX::TARGET_CACHED ); + } + else if( IsNetnameLayer( layer ) ) + { + // Netnames are drawn only when scale is sufficient (level of details) + // so there is no point in caching them + m_view->SetLayerTarget( layer, KIGFX::TARGET_NONCACHED ); + } + } + + m_view->SetLayerTarget( ITEM_GAL_LAYER( ANCHOR_VISIBLE ), KIGFX::TARGET_NONCACHED ); + + // Some more required layers settings + m_view->SetRequired( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ) ); + m_view->SetRequired( ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) ); + m_view->SetRequired( NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ) ); + + m_view->SetRequired( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + m_view->SetRequired( F_Adhes, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + m_view->SetRequired( F_Paste, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + m_view->SetRequired( F_Mask, ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + + m_view->SetRequired( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ), ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + m_view->SetRequired( B_Adhes, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + m_view->SetRequired( B_Paste, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + m_view->SetRequired( B_Mask, ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + + m_view->SetRequired( ITEM_GAL_LAYER( PAD_FR_VISIBLE ), ITEM_GAL_LAYER( MOD_FR_VISIBLE ) ); + m_view->SetRequired( ITEM_GAL_LAYER( PAD_BK_VISIBLE ), ITEM_GAL_LAYER( MOD_BK_VISIBLE ) ); + + m_view->SetLayerTarget( ITEM_GAL_LAYER( GP_OVERLAY ), KIGFX::TARGET_OVERLAY ); + m_view->SetLayerTarget( ITEM_GAL_LAYER( RATSNEST_VISIBLE ), KIGFX::TARGET_OVERLAY ); + + // Load display options (such as filled/outline display of items) + static_cast( m_view->GetPainter()->GetSettings() )->LoadDisplayOptions( DisplayOpt ); +} + + +PCB_DRAW_PANEL_GAL::~PCB_DRAW_PANEL_GAL() +{ + delete m_worksheet; + delete m_ratsnest; +} + + +void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard ) +{ + m_view->Clear(); + + // Load zones + for( int i = 0; i < aBoard->GetAreaCount(); ++i ) + m_view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); + + // Load drawings + for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) + m_view->Add( drawing ); + + // Load tracks + for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) + m_view->Add( track ); + + // Load modules and its additional elements + for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) + { + module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, m_view, _1 ) ); + m_view->Add( module ); + } + + // Segzones (equivalent of ZONE_CONTAINER for legacy boards) + for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) + m_view->Add( zone ); + + // Ratsnest + if( m_ratsnest ) + { + m_view->Remove( m_ratsnest ); + delete m_ratsnest; + } + + m_ratsnest = new KIGFX::RATSNEST_VIEWITEM( aBoard->GetRatsnest() ); + m_view->Add( m_ratsnest ); + + UseColorScheme( aBoard->GetColorsSettings() ); + + m_view->RecacheAllItems( true ); +} + + +void PCB_DRAW_PANEL_GAL::SetWorksheet( KIGFX::WORKSHEET_VIEWITEM* aWorksheet ) +{ + if( m_worksheet ) + { + m_view->Remove( m_worksheet ); + delete m_worksheet; + } + + m_worksheet = aWorksheet; + m_view->Add( m_worksheet ); +} + + +void PCB_DRAW_PANEL_GAL::UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings ) +{ + KIGFX::PCB_RENDER_SETTINGS* rs; + rs = static_cast( m_view->GetPainter()->GetSettings() ); + rs->ImportLegacyColors( aSettings ); +} + + +void PCB_DRAW_PANEL_GAL::SetHighContrastLayer( LAYER_ID aLayer ) +{ + // Set display settings for high contrast mode + KIGFX::RENDER_SETTINGS* rSettings = m_view->GetPainter()->GetSettings(); + + SetTopLayer( aLayer ); + + rSettings->ClearActiveLayers(); + rSettings->SetActiveLayer( aLayer ); + + if( IsCopperLayer( aLayer ) ) + { + // Bring some other layers to the front in case of copper layers and make them colored + // fixme do not like the idea of storing the list of layers here, + // should be done in some other way I guess.. + LAYER_NUM layers[] = { + GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), + ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), + ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), + ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( RATSNEST_VISIBLE ) + }; + + for( unsigned int i = 0; i < sizeof( layers ) / sizeof( LAYER_NUM ); ++i ) + rSettings->SetActiveLayer( layers[i] ); + + // Pads should be shown too + if( aLayer == B_Cu ) + { + rSettings->SetActiveLayer( ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + rSettings->SetActiveLayer( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ) ); + } + else if( aLayer == F_Cu ) + { + rSettings->SetActiveLayer( ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + rSettings->SetActiveLayer( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ) ); + } + } + + m_view->UpdateAllLayersColor(); +} + + +void PCB_DRAW_PANEL_GAL::SetTopLayer( LAYER_ID aLayer ) +{ + m_view->ClearTopLayers(); + m_view->SetTopLayer( aLayer ); + + if( IsCopperLayer( aLayer ) ) + { + // Bring some other layers to the front in case of copper layers and make them colored + // fixme do not like the idea of storing the list of layers here, + // should be done in some other way I guess.. + LAYER_NUM layers[] = { + GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), + ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), + ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), + ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( RATSNEST_VISIBLE ), Dwgs_User, + ITEM_GAL_LAYER( DRC_VISIBLE ) + }; + + for( unsigned int i = 0; i < sizeof( layers ) / sizeof( LAYER_NUM ); ++i ) + { + m_view->SetTopLayer( layers[i] ); + } + + // Pads should be shown too + if( aLayer == B_Cu ) + { + m_view->SetTopLayer( ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); + m_view->SetTopLayer( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ) ); + } + else if( aLayer == F_Cu ) + { + m_view->SetTopLayer( ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); + m_view->SetTopLayer( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ) ); + } + } + + m_view->UpdateAllLayersOrder(); +} + + +void PCB_DRAW_PANEL_GAL::SyncLayersVisibility( const BOARD* aBoard ) +{ + // Load layer & elements visibility settings + for( LAYER_NUM i = 0; i < LAYER_ID_COUNT; ++i ) + { + m_view->SetLayerVisible( i, aBoard->IsLayerVisible( LAYER_ID( i ) ) ); + + // Synchronize netname layers as well + if( IsCopperLayer( i ) ) + m_view->SetLayerVisible( GetNetnameLayer( i ), aBoard->IsLayerVisible( LAYER_ID( i ) ) ); + } + + for( LAYER_NUM i = 0; i < END_PCB_VISIBLE_LIST; ++i ) + { + m_view->SetLayerVisible( ITEM_GAL_LAYER( i ), aBoard->IsElementVisible( i ) ); + } + + // Enable some layers that are GAL specific + m_view->SetLayerVisible( ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), true ); + m_view->SetLayerVisible( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), true ); + m_view->SetLayerVisible( ITEM_GAL_LAYER( WORKSHEET ), true ); + m_view->SetLayerVisible( ITEM_GAL_LAYER( GP_OVERLAY ), true ); +} diff --git a/pcbnew/pcb_draw_panel_gal.h b/pcbnew/pcb_draw_panel_gal.h new file mode 100644 index 0000000000..26ac94f968 --- /dev/null +++ b/pcbnew/pcb_draw_panel_gal.h @@ -0,0 +1,88 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 PCB_DRAW_PANEL_GAL_H_ +#define PCB_DRAW_PANEL_GAL_H_ + +#include + +namespace KIGFX +{ + class WORKSHEET_VIEWITEM; + class RATSNEST_VIEWITEM; +} +class COLORS_DESIGN_SETTINGS; + +class PCB_DRAW_PANEL_GAL : public EDA_DRAW_PANEL_GAL +{ +public: + PCB_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId, const wxPoint& aPosition, + const wxSize& aSize, GalType aGalType = GAL_TYPE_OPENGL ); + + virtual ~PCB_DRAW_PANEL_GAL(); + + /** + * Function DisplayBoard + * adds all items from the current board to the VIEW, so they can be displayed by GAL. + * @param aBoard is the PCB to be loaded. + */ + void DisplayBoard( const BOARD* aBoard ); + + /** + * Function SetWorksheet + * Sets (or updates) worksheet used by the draw panel. + * @param aWorksheet is the worksheet to be used. + * The object is then owned by PCB_DRAW_PANEL_GAL. + */ + void SetWorksheet( KIGFX::WORKSHEET_VIEWITEM* aWorksheet ); + + /** + * Function UseColorScheme + * Applies layer color settings. + * @param aSettings are the new settings. + */ + void UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings ); + + ///> @copydoc EDA_DRAW_PANEL_GAL::SetHighContrastLayer() + virtual void SetHighContrastLayer( LAYER_ID aLayer ); + + ///> @copydoc EDA_DRAW_PANEL_GAL::SetTopLayer() + virtual void SetTopLayer( LAYER_ID aLayer ); + + /** + * Function SyncLayersVisibility + * Updates "visibility" property of each layer of a given BOARD. + * @param aBoard contains layers visibility settings to be applied. + */ + void SyncLayersVisibility( const BOARD* aBoard ); + +protected: + ///> Currently used worksheet + KIGFX::WORKSHEET_VIEWITEM* m_worksheet; + + ///> Ratsnest view item + KIGFX::RATSNEST_VIEWITEM* m_ratsnest; +}; + +#endif /* PCB_DRAW_PANEL_GAL_H_ */ diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 9a9ac26e31..4adc0bc13c 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -50,7 +50,7 @@ PCB_RENDER_SETTINGS::PCB_RENDER_SETTINGS() m_displayZoneMode = DZ_SHOW_FILLED; // By default everything should be displayed as filled - for( unsigned int i = 0; i < END_PCB_VISIBLE_LIST; ++i ) + for( unsigned int i = 0; i < TOTAL_LAYER_COUNT; ++i ) { m_sketchMode[i] = false; } @@ -79,6 +79,7 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSet m_layerColors[NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE )] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); m_layerColors[NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE )] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); m_layerColors[NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE )] = COLOR4D( 1.0, 1.0, 1.0, 0.9 ); + m_layerColors[ITEM_GAL_LAYER( ANCHOR_VISIBLE )] = COLOR4D( 0.3, 0.3, 1.0, 0.9 ); m_layerColors[ITEM_GAL_LAYER( RATSNEST_VISIBLE )] = COLOR4D( 0.4, 0.4, 0.4, 0.8 ); m_layerColors[ITEM_GAL_LAYER( WORKSHEET )] = COLOR4D( 0.5, 0.0, 0.0, 0.8 ); m_layerColors[ITEM_GAL_LAYER( DRC_VISIBLE )] = COLOR4D( 1.0, 0.0, 0.0, 0.8 ); @@ -101,9 +102,9 @@ void PCB_RENDER_SETTINGS::LoadDisplayOptions( const DISPLAY_OPTIONS& aOptions ) m_padNumbers = aOptions.DisplayPadNum; // Whether to draw tracks, vias & pads filled or as outlines - m_sketchMode[PADS_VISIBLE] = !aOptions.DisplayPadFill; - m_sketchMode[VIA_THROUGH_VISIBLE] = !aOptions.DisplayViaFill; - m_sketchMode[TRACKS_VISIBLE] = !aOptions.DisplayPcbTrackFill; + m_sketchMode[ITEM_GAL_LAYER( PADS_VISIBLE )] = !aOptions.DisplayPadFill; + m_sketchMode[ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE )] = !aOptions.DisplayViaFill; + m_sketchMode[ITEM_GAL_LAYER( TRACKS_VISIBLE )] = !aOptions.DisplayPcbTrackFill; switch( aOptions.DisplayNetNamesMode ) { @@ -222,7 +223,7 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) case PCB_LINE_T: case PCB_MODULE_EDGE_T: - draw( (DRAWSEGMENT*) item ); + draw( (DRAWSEGMENT*) item, aLayer ); break; case PCB_TEXT_T: @@ -233,6 +234,10 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) draw( (TEXTE_MODULE*) item, aLayer ); break; + case PCB_MODULE_T: + draw( (MODULE*) item ); + break; + case PCB_ZONE_AREA_T: draw( (ZONE_CONTAINER*) item ); break; @@ -284,7 +289,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) // Set a proper color for the label const COLOR4D& color = m_pcbSettings.GetColor( aTrack, aTrack->GetLayer() ); - COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); + const COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); if( color.GetBrightness() > 0.5 ) m_gal->SetStrokeColor( labelColor.Inverted() ); @@ -308,7 +313,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) m_gal->SetStrokeColor( color ); m_gal->SetIsStroke( true ); - if( m_pcbSettings.m_sketchMode[TRACKS_VISIBLE] ) + if( m_pcbSettings.m_sketchMode[ITEM_GAL_LAYER( TRACKS_VISIBLE )] ) { // Outline mode m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); @@ -320,6 +325,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) m_gal->SetFillColor( color ); m_gal->SetIsFill( true ); } + m_gal->DrawSegment( start, end, width ); } } @@ -344,7 +350,7 @@ void PCB_PAINTER::draw( const VIA* aVia, int aLayer ) const COLOR4D& color = m_pcbSettings.GetColor( aVia, aLayer ); - if( m_pcbSettings.m_sketchMode[VIA_THROUGH_VISIBLE] ) + if( m_pcbSettings.m_sketchMode[ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE )] ) { // Outline mode m_gal->SetIsFill( false ); @@ -421,7 +427,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) // Set a proper color for the label const COLOR4D& color = m_pcbSettings.GetColor( aPad, aPad->GetLayer() ); - COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); + const COLOR4D labelColor = m_pcbSettings.GetColor( NULL, aLayer ); if( color.GetBrightness() > 0.5 ) m_gal->SetStrokeColor( labelColor.Inverted() ); @@ -475,7 +481,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) // Pad drawing const COLOR4D& color = m_pcbSettings.GetColor( aPad, aLayer ); - if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) + if( m_pcbSettings.m_sketchMode[ITEM_GAL_LAYER( PADS_VISIBLE )] ) { // Outline mode m_gal->SetIsFill( false ); @@ -538,7 +544,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) m = ( size.y - size.x ); n = size.x; - if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) + if( m_pcbSettings.m_sketchMode[ITEM_GAL_LAYER( PADS_VISIBLE )] ) { // Outline mode m_gal->DrawArc( VECTOR2D( 0, -m ), n, -M_PI, 0 ); @@ -559,7 +565,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) m = ( size.x - size.y ); n = size.y; - if( m_pcbSettings.m_sketchMode[PADS_VISIBLE] ) + if( m_pcbSettings.m_sketchMode[ITEM_GAL_LAYER( PADS_VISIBLE )] ) { // Outline mode m_gal->DrawArc( VECTOR2D( -m, 0 ), n, M_PI / 2, 3 * M_PI / 2 ); @@ -617,14 +623,24 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) } -void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment ) +void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer ) { const COLOR4D& color = m_pcbSettings.GetColor( aSegment, aSegment->GetLayer() ); m_gal->SetIsFill( false ); m_gal->SetIsStroke( true ); m_gal->SetStrokeColor( color ); - m_gal->SetLineWidth( aSegment->GetWidth() ); + + if( m_pcbSettings.m_sketchMode[aLayer] ) + { + // Outline mode + m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); + } + else + { + // Filled mode + m_gal->SetLineWidth( aSegment->GetWidth() ); + } switch( aSegment->GetShape() ) { @@ -699,12 +715,24 @@ void PCB_PAINTER::draw( const TEXTE_PCB* aText, int aLayer ) if( aText->GetText().Length() == 0 ) return; - const COLOR4D& strokeColor = m_pcbSettings.GetColor( aText, aText->GetLayer() ); + const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() ); VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); double orientation = aText->GetOrientation() * M_PI / 1800.0; - m_gal->SetStrokeColor( strokeColor ); - m_gal->SetLineWidth( aText->GetThickness() ); + if( m_pcbSettings.m_sketchMode[aLayer] ) + { + // Outline mode + m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); + } + else + { + // Filled mode + m_gal->SetLineWidth( aText->GetThickness() ); + } + + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + m_gal->SetStrokeColor( color ); m_gal->SetTextAttributes( aText ); m_gal->StrokeText( aText->GetText(), position, orientation ); } @@ -715,17 +743,46 @@ void PCB_PAINTER::draw( const TEXTE_MODULE* aText, int aLayer ) if( aText->GetLength() == 0 ) return; - const COLOR4D& strokeColor = m_pcbSettings.GetColor( aText, aLayer ); + const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer ); VECTOR2D position( aText->GetTextPosition().x, aText->GetTextPosition().y ); double orientation = aText->GetDrawRotation() * M_PI / 1800.0; - m_gal->SetStrokeColor( strokeColor ); - m_gal->SetLineWidth( aText->GetThickness() ); + if( m_pcbSettings.m_sketchMode[aLayer] ) + { + // Outline mode + m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); + } + else + { + // Filled mode + m_gal->SetLineWidth( aText->GetThickness() ); + } + + m_gal->SetIsFill( false ); + m_gal->SetIsStroke( true ); + m_gal->SetStrokeColor( color ); m_gal->SetTextAttributes( aText ); m_gal->StrokeText( aText->GetText(), position, orientation ); } +void PCB_PAINTER::draw( const MODULE* aModule ) +{ + const COLOR4D color = m_pcbSettings.GetColor( aModule, ITEM_GAL_LAYER( ANCHOR_VISIBLE ) ); + + // Draw anchor + m_gal->SetStrokeColor( color ); + m_gal->SetLineWidth( 1.0 ); + + // Keep the size constant, not related to the scale + double anchorSize = 5.0 / m_gal->GetWorldScale(); + + VECTOR2D center = aModule->GetPosition(); + m_gal->DrawLine( center - VECTOR2D( anchorSize, 0 ), center + VECTOR2D( anchorSize, 0 ) ); + m_gal->DrawLine( center - VECTOR2D( 0, anchorSize ), center + VECTOR2D( 0, anchorSize ) ); +} + + void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone ) { const COLOR4D& color = m_pcbSettings.GetColor( aZone, aZone->GetLayer() ); diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h index 46e7bb7da3..2b79696ec3 100644 --- a/pcbnew/pcb_painter.h +++ b/pcbnew/pcb_painter.h @@ -124,9 +124,6 @@ public: */ inline void SetSketchMode( int aItemLayer, bool aEnabled ) { - // It is supposed to work only with item layers - assert( aItemLayer >= ITEM_GAL_LAYER( 0 ) ); - m_sketchMode[aItemLayer] = aEnabled; } @@ -137,9 +134,6 @@ public: */ inline bool GetSketchMode( int aItemLayer ) const { - // It is supposed to work only with item layers - assert( aItemLayer >= ITEM_GAL_LAYER( 0 ) ); - return m_sketchMode[aItemLayer]; } @@ -210,9 +204,10 @@ protected: void draw( const TRACK* aTrack, int aLayer ); void draw( const VIA* aVia, int aLayer ); void draw( const D_PAD* aPad, int aLayer ); - void draw( const DRAWSEGMENT* aSegment ); + void draw( const DRAWSEGMENT* aSegment, int aLayer ); void draw( const TEXTE_PCB* aText, int aLayer ); void draw( const TEXTE_MODULE* aText, int aLayer ); + void draw( const MODULE* aModule ); void draw( const ZONE_CONTAINER* aZone ); void draw( const DIMENSION* aDimension, int aLayer ); void draw( const PCB_TARGET* aTarget ); diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index 475a844948..33783ea548 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -1856,7 +1856,7 @@ MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERR RotatePoint( &pt, module->GetOrientation() ); pad->SetPosition( pt + module->GetPosition() ); - module->AddPad( pad ); + module->Add( pad ); } break; diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 36dbaf748d..08eb9e36a0 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -70,13 +70,24 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + #if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON) #include // The name of the pane info handling the python console: #define PYTHONCONSOLE_STRID wxT( "PythonPanel" ) #endif -#include +#include #include // Keys used in read/write config @@ -174,9 +185,9 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_MENU( ID_MENU_PCB_SHOW_3D_FRAME, PCB_EDIT_FRAME::Show3D_Frame ) // Switching canvases - EVT_MENU( ID_MENU_CANVAS_DEFAULT, PCB_EDIT_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_EDIT_FRAME::SwitchCanvas ) - EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_EDIT_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_DEFAULT, PCB_EDIT_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_CAIRO, PCB_EDIT_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_OPENGL, PCB_EDIT_FRAME::SwitchCanvas ) // Menu Get Design Rules Editor EVT_MENU( ID_MENU_PCB_SHOW_DESIGN_RULES_DIALOG, PCB_EDIT_FRAME::ShowDesignRulesEditor ) @@ -187,8 +198,8 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) EVT_TOOL( wxID_CUT, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_COPY, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_TOOL( wxID_PASTE, PCB_EDIT_FRAME::Process_Special_Functions ) - EVT_TOOL( wxID_UNDO, PCB_EDIT_FRAME::GetBoardFromUndoList ) - EVT_TOOL( wxID_REDO, PCB_EDIT_FRAME::GetBoardFromRedoList ) + EVT_TOOL( wxID_UNDO, PCB_EDIT_FRAME::RestoreCopyFromUndoList ) + EVT_TOOL( wxID_REDO, PCB_EDIT_FRAME::RestoreCopyFromRedoList ) EVT_TOOL( wxID_PRINT, PCB_EDIT_FRAME::ToPrinter ) EVT_TOOL( ID_GEN_PLOT_SVG, PCB_EDIT_FRAME::SVG_Print ) EVT_TOOL( ID_GEN_PLOT, PCB_EDIT_FRAME::Process_Special_Functions ) @@ -294,6 +305,8 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) PCB_EDIT_FRAME::OnUpdateZoneDisplayStyle ) EVT_UPDATE_UI_RANGE( ID_PCB_MUWAVE_START_CMD, ID_PCB_MUWAVE_END_CMD, PCB_EDIT_FRAME::OnUpdateMuWaveToolbar ) + + EVT_COMMAND( wxID_ANY, LAYER_WIDGET::EVT_LAYER_COLOR_CHANGE, PCB_EDIT_FRAME::OnLayerColorChange ) END_EVENT_TABLE() @@ -302,7 +315,7 @@ END_EVENT_TABLE() #define PCB_EDIT_FRAME_NAME wxT( "PcbFrame" ) PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : - PCB_BASE_FRAME( aKiway, aParent, FRAME_PCB, wxT( "Pcbnew" ), wxDefaultPosition, + PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB, wxT( "Pcbnew" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, PCB_EDIT_FRAME_NAME ) { m_FrameName = PCB_EDIT_FRAME_NAME; @@ -330,6 +343,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : for ( int i = 0; i < 10; i++ ) m_Macros[i].m_Record.clear(); + // Create GAL canvas + SetGalCanvas( new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, + PCB_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) ); + SetBoard( new BOARD() ); // Create the PCB_LAYER_WIDGET *after* SetBoard(): @@ -404,7 +421,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : lyrs.BestSize( m_Layers->GetBestSize() ); lyrs.Caption( _( "Visibles" ) ); - if( m_mainToolBar ) // The main horizontal toolbar { m_auimgr.AddPane( m_mainToolBar, @@ -464,7 +480,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) : PCB_EDIT_FRAME::~PCB_EDIT_FRAME() { - destroyTools(); m_RecordingMacros = -1; for( int i = 0; i < 10; i++ ) @@ -480,89 +495,69 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard ) if( IsGalCanvasActive() ) { - ViewReloadBoard( aBoard ); + PCB_DRAW_PANEL_GAL* drawPanel = static_cast( GetGalCanvas() ); + + drawPanel->DisplayBoard( aBoard ); + aBoard->GetRatsnest()->Recalculate(); + + // Prepare worksheet template + KIGFX::WORKSHEET_VIEWITEM* worksheet; + worksheet = new KIGFX::WORKSHEET_VIEWITEM( &aBoard->GetPageSettings(), + &aBoard->GetTitleBlock() ); + worksheet->SetSheetName( std::string( GetScreenDesc().mb_str() ) ); + + BASE_SCREEN* screen = GetScreen(); + + if( screen != NULL ) + { + worksheet->SetSheetNumber( screen->m_ScreenNumber ); + worksheet->SetSheetCount( screen->m_NumberOfScreens ); + } + + // PCB_DRAW_PANEL_GAL takes ownership of the worksheet + drawPanel->SetWorksheet( worksheet ); // update the tool manager with the new board and its view. - m_toolManager->SetEnvironment( aBoard, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); + if( m_toolManager ) + { + m_toolManager->SetEnvironment( aBoard, drawPanel->GetView(), + drawPanel->GetViewControls(), this ); + m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); + } } } -void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const -{ - KIGFX::VIEW* view = GetGalCanvas()->GetView(); - view->Clear(); - - // All of PCB drawing elements should be added to the VIEW - // in order to be displayed - - // Load zones - for( int i = 0; i < aBoard->GetAreaCount(); ++i ) - view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) ); - - // Load drawings - for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() ) - view->Add( drawing ); - - // Load tracks - for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) - view->Add( track ); - - // Load modules and its additional elements - for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) - { - module->RunOnChildren( boost::bind( &KIGFX::VIEW::Add, view, _1 ) ); - view->Add( module ); - } - - // Segzones (equivalent of ZONE_CONTAINER for legacy boards) - for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() ) - view->Add( zone ); - - KIGFX::WORKSHEET_VIEWITEM* worksheet = aBoard->GetWorksheetViewItem(); - worksheet->SetSheetName( std::string( GetScreenDesc().mb_str() ) ); - - BASE_SCREEN* screen = GetScreen(); - - if( screen != NULL ) - { - worksheet->SetSheetNumber( screen->m_ScreenNumber ); - worksheet->SetSheetCount( screen->m_NumberOfScreens ); - } - - view->Add( worksheet ); - view->Add( aBoard->GetRatsnestViewItem() ); - aBoard->GetRatsnest()->Recalculate(); - - // Apply layer coloring scheme & display options - if( view->GetPainter() ) - { - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast( view->GetPainter()->GetSettings() ); - - // Load layers' colors from PCB data - settings->ImportLegacyColors( m_Pcb->GetColorsSettings() ); - - // Load display options (such as filled/outline display of items) - settings->LoadDisplayOptions( DisplayOpt ); - } - - // Limit panning to the size of worksheet frame - view->RecacheAllItems( true ); - - if( IsGalCanvasActive() ) - GetGalCanvas()->Refresh(); -} - - bool PCB_EDIT_FRAME::isAutoSaveRequired() const { return GetScreen()->IsSave(); } +void PCB_EDIT_FRAME::setupTools() +{ + // Create the manager and dispatcher & route draw panel events to the dispatcher + m_toolManager = new TOOL_MANAGER; + m_toolManager->SetEnvironment( NULL, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager ); + + // Register tools + m_toolManager->RegisterTool( new SELECTION_TOOL ); + m_toolManager->RegisterTool( new ROUTER_TOOL ); + m_toolManager->RegisterTool( new EDIT_TOOL ); + m_toolManager->RegisterTool( new DRAWING_TOOL ); + m_toolManager->RegisterTool( new POINT_EDITOR ); + m_toolManager->RegisterTool( new PCBNEW_CONTROL ); + m_toolManager->RegisterTool( new PCB_EDITOR_CONTROL ); + m_toolManager->RegisterTool( new PLACEMENT_TOOL ); + m_toolManager->ResetTools( TOOL_BASE::RUN ); + + // Run the selection tool, it is supposed to be always active + m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); +} + + void PCB_EDIT_FRAME::ReFillLayerWidget() { m_Layers->ReFill(); @@ -675,15 +670,16 @@ void PCB_EDIT_FRAME::UseGalCanvas( bool aEnable ) if( aEnable ) { - ViewReloadBoard( m_Pcb ); - GetGalCanvas()->GetView()->RecacheAllItems(); - - m_toolManager->SetEnvironment( m_Pcb, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); - + SetBoard( m_Pcb ); + GetGalCanvas()->GetView()->RecacheAllItems( true ); + GetGalCanvas()->SetEventDispatcher( m_toolDispatcher ); GetGalCanvas()->StartDrawing(); } + else + { + // Redirect all events to the legacy canvas + GetGalCanvas()->SetEventDispatcher( NULL ); + } } @@ -823,103 +819,20 @@ bool PCB_EDIT_FRAME::IsMicroViaAcceptable() } -void PCB_EDIT_FRAME::SetHighContrastLayer( LAYER_ID aLayer ) +void PCB_EDIT_FRAME::SetActiveLayer( LAYER_ID aLayer ) { - // Set display settings for high contrast mode - KIGFX::VIEW* view = GetGalCanvas()->GetView(); - KIGFX::RENDER_SETTINGS* rSettings = view->GetPainter()->GetSettings(); + PCB_BASE_FRAME::SetActiveLayer( aLayer ); - SetTopLayer( aLayer ); + GetGalCanvas()->SetHighContrastLayer( aLayer ); - rSettings->ClearActiveLayers(); - rSettings->SetActiveLayer( aLayer ); - - if( IsCopperLayer( aLayer ) ) - { - // Bring some other layers to the front in case of copper layers and make them colored - // fixme do not like the idea of storing the list of layers here, - // should be done in some other way I guess.. - LAYER_NUM layers[] = { - GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), - ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), - ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), - ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( RATSNEST_VISIBLE ) - }; - - for( unsigned i = 0; i < DIM( layers ); ++i ) - rSettings->SetActiveLayer( layers[i] ); - - // Pads should be shown too - if( aLayer == B_Cu ) - { - rSettings->SetActiveLayer( ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - rSettings->SetActiveLayer( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ) ); - } - else if( aLayer == F_Cu ) - { - rSettings->SetActiveLayer( ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - rSettings->SetActiveLayer( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ) ); - } - } - - view->UpdateAllLayersColor(); -} - - -void PCB_EDIT_FRAME::SetTopLayer( LAYER_ID aLayer ) -{ - // Set display settings for high contrast mode - KIGFX::VIEW* view = GetGalCanvas()->GetView(); - - view->ClearTopLayers(); - view->SetTopLayer( aLayer ); - - if( IsCopperLayer( aLayer ) ) - { - // Bring some other layers to the front in case of copper layers and make them colored - // fixme do not like the idea of storing the list of layers here, - // should be done in some other way I guess.. - LAYER_NUM layers[] = { - GetNetnameLayer( aLayer ), ITEM_GAL_LAYER( VIA_THROUGH_VISIBLE ), - ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), ITEM_GAL_LAYER( PADS_VISIBLE ), - ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), NETNAMES_GAL_LAYER( PADS_NETNAMES_VISIBLE ), - ITEM_GAL_LAYER( GP_OVERLAY ), ITEM_GAL_LAYER( RATSNEST_VISIBLE ), Dwgs_User, - ITEM_GAL_LAYER( DRC_VISIBLE ) - }; - - for( unsigned i = 0; i < DIM( layers ); ++i ) - { - view->SetTopLayer( layers[i] ); - } - - // Pads should be shown too - if( aLayer == B_Cu ) - { - view->SetTopLayer( ITEM_GAL_LAYER( PAD_BK_VISIBLE ) ); - view->SetTopLayer( NETNAMES_GAL_LAYER( PAD_BK_NETNAMES_VISIBLE ) ); - } - else if( aLayer == F_Cu ) - { - view->SetTopLayer( ITEM_GAL_LAYER( PAD_FR_VISIBLE ) ); - view->SetTopLayer( NETNAMES_GAL_LAYER( PAD_FR_NETNAMES_VISIBLE ) ); - } - } - - view->UpdateAllLayersOrder(); -} - - -void PCB_EDIT_FRAME::SetActiveLayer( LAYER_ID aLayer, bool doLayerWidgetUpdate ) -{ - ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer = aLayer; - - SetHighContrastLayer( aLayer ); - - if( doLayerWidgetUpdate ) - syncLayerWidgetLayer(); + syncLayerWidgetLayer(); if( IsGalCanvasActive() ) + { + m_toolManager->RunAction( COMMON_ACTIONS::layerChanged ); // notify other tools + GetGalCanvas()->SetFocus(); // otherwise hotkeys are stuck somewhere GetGalCanvas()->Refresh(); + } } @@ -939,29 +852,7 @@ void PCB_EDIT_FRAME::syncRenderStates() void PCB_EDIT_FRAME::syncLayerVisibilities() { m_Layers->SyncLayerVisibilities(); - - KIGFX::VIEW* view = GetGalCanvas()->GetView(); - - // Load layer & elements visibility settings - for( LAYER_NUM i = 0; i < LAYER_ID_COUNT; ++i ) - { - view->SetLayerVisible( i, m_Pcb->IsLayerVisible( LAYER_ID( i ) ) ); - - // Synchronize netname layers as well - if( IsCopperLayer( i ) ) - view->SetLayerVisible( GetNetnameLayer( i ), m_Pcb->IsLayerVisible( LAYER_ID( i ) ) ); - } - - for( LAYER_NUM i = 0; i < END_PCB_VISIBLE_LIST; ++i ) - { - view->SetLayerVisible( ITEM_GAL_LAYER( i ), m_Pcb->IsElementVisible( i ) ); - } - - // Enable some layers that are GAL specific - view->SetLayerVisible( ITEM_GAL_LAYER( PADS_HOLES_VISIBLE ), true ); - view->SetLayerVisible( ITEM_GAL_LAYER( VIAS_HOLES_VISIBLE ), true ); - view->SetLayerVisible( ITEM_GAL_LAYER( WORKSHEET ), true ); - view->SetLayerVisible( ITEM_GAL_LAYER( GP_OVERLAY ), true ); + static_cast( GetGalCanvas() )->SyncLayersVisibility( m_Pcb ); } @@ -1156,19 +1047,15 @@ void PCB_EDIT_FRAME::OnSelectAutoPlaceMode( wxCommandEvent& aEvent ) } +void PCB_EDIT_FRAME::OnLayerColorChange( wxCommandEvent& aEvent ) +{ + ReCreateLayerBox(); +} + + void PCB_EDIT_FRAME::ToPlotter( wxCommandEvent& event ) { DIALOG_PLOT dlg( this ); dlg.ShowModal(); } - - -void PCB_EDIT_FRAME::SetRotationAngle( int aRotationAngle ) -{ - wxCHECK2_MSG( aRotationAngle > 0 && aRotationAngle <= 900, aRotationAngle = 900, - wxT( "Invalid rotation angle, defaulting to 90." ) ); - - m_rotationAngle = aRotationAngle; -} - diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index d8eda36868..963f9c4ba2 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -99,7 +99,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) if( !GetBoard()->GetEnabledLayers()[ cur_layer ] ) cur_layer = F_Cu; - SetActiveLayer( cur_layer, true ); + SetActiveLayer( cur_layer ); OnModify(); ReCreateLayerBox(); diff --git a/pcbnew/ratsnest_data.cpp b/pcbnew/ratsnest_data.cpp index 9271f00f42..deb6d08024 100644 --- a/pcbnew/ratsnest_data.cpp +++ b/pcbnew/ratsnest_data.cpp @@ -305,7 +305,7 @@ void RN_NET::clearNode( const RN_NODE_PTR& aNode ) // Remove all ratsnest edges for associated with the node newEnd = std::remove_if( m_rnEdges->begin(), m_rnEdges->end(), - boost::bind( isEdgeConnectingNode, _1, aNode ) ); + boost::bind( isEdgeConnectingNode, _1, boost::ref( aNode ) ) ); m_rnEdges->resize( std::distance( m_rnEdges->begin(), newEnd ) ); } @@ -629,7 +629,7 @@ std::list RN_NET::GetClosestNodes( const RN_NODE_PTR& aNode, int aN closest.push_back( node ); // Sort by the distance from aNode - closest.sort( boost::bind( sortDistance, aNode, _1, _2 ) ); + closest.sort( boost::bind( sortDistance, boost::ref( aNode ), _1, _2 ) ); // Remove the first node (==aNode), as it is surely located within the smallest distance closest.pop_front(); @@ -653,7 +653,7 @@ std::list RN_NET::GetClosestNodes( const RN_NODE_PTR& aNode, closest.push_back( node ); // Sort by the distance from aNode - closest.sort( boost::bind( sortDistance, aNode, _1, _2 ) ); + closest.sort( boost::bind( sortDistance, boost::ref( aNode ), _1, _2 ) ); // Remove the first node (==aNode), as it is surely located within the smallest distance closest.pop_front(); @@ -1009,6 +1009,8 @@ void RN_DATA::ProcessBoard() if( netCode > 0 ) m_nets[netCode].AddItem( zone ); } + + Recalculate(); } diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 2c26df7c96..c967008b74 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -758,9 +758,12 @@ void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, co } -void PNS_LINE_PLACER::SetLayer(int aLayer) +void PNS_LINE_PLACER::SetLayer( int aLayer ) { m_currentLayer = aLayer; + + m_head.SetLayer( aLayer ); + m_tail.SetLayer( aLayer ); } @@ -790,12 +793,12 @@ void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) m_currentEnd = p; m_currentNet = net; - PNS_NODE *rootNode = Router()->GetWorld()->Branch(); + PNS_NODE* rootNode = Router()->GetWorld()->Branch(); if( splitSeg ) splitAdjacentSegments( rootNode, aStartItem, p ); - setWorld ( rootNode ); + setWorld( rootNode ); setInitialDirection( Settings().InitialDirection() ); startPlacement( p, m_currentNet, m_currentWidth, m_currentLayer ); } @@ -848,7 +851,7 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) PNS_LINE pl = Trace(); - if (m_currentMode == RM_MarkObstacles && + if( m_currentMode == RM_MarkObstacles && !Settings().CanViolateDRC() && m_world->CheckColliding( &pl ) ) return false; @@ -889,9 +892,9 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) m_lastNode->Add( pl.Via().Clone() ); if( realEnd ) - simplifyNewLine ( m_lastNode, lastSeg ); + simplifyNewLine( m_lastNode, lastSeg ); - Router()->CommitRouting ( m_lastNode ); + Router()->CommitRouting( m_lastNode ); m_lastNode = NULL; @@ -901,9 +904,18 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) VECTOR2I p_start = m_placingVia ? p_last : p_pre_last; if( m_placingVia ) - m_currentLayer = Router()->NextCopperLayer( true ); + { + int layerTop = Router()->Settings().GetLayerTop(); + int layerBottom = Router()->Settings().GetLayerBottom(); - setWorld ( Router()->GetWorld()->Branch() ); + // Change the current layer to the other side of the board + if( m_currentLayer == layerTop ) + m_currentLayer = layerBottom; + else + m_currentLayer = layerTop; + } + + setWorld( Router()->GetWorld()->Branch() ); startPlacement( p_start, m_head.Net(), m_head.Width(), m_currentLayer ); m_startsOnVia = m_placingVia; diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 1ae3b2d69c..4d126866ea 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -55,7 +55,7 @@ public: * Starts routing a single track at point aP, taking item aStartItem as anchor * (unless NULL). */ - void Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem ); + void Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ); /** * Function Move() @@ -212,7 +212,7 @@ private: * * Sets the board to route. */ - void setWorld ( PNS_NODE* aWorld ); + void setWorld( PNS_NODE* aWorld ); /** * Function startPlacement() diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 8813a854f1..d9db594a0f 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -323,6 +323,7 @@ PNS_ROUTER::PNS_ROUTER() m_currentLayer = 1; m_placingVia = false; + m_startsOnVia = false; m_currentNet = -1; m_state = IDLE; m_world = NULL; @@ -612,7 +613,7 @@ void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* aEndItem ) m_dragger->Drag( aP ); PNS_ITEMSET dragged = m_dragger->Traces(); - updateView ( m_dragger->CurrentNode(), dragged ); + updateView( m_dragger->CurrentNode(), dragged ); } @@ -758,6 +759,8 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode ) via_board->SetWidth( via->Diameter() ); via_board->SetDrill( via->Drill() ); via_board->SetNetCode( via->Net() ); + via_board->SetLayerPair( ToLAYER_ID( m_settings.GetLayerTop() ), + ToLAYER_ID( m_settings.GetLayerBottom() ) ); newBI = via_board; break; } @@ -809,6 +812,7 @@ bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { case ROUTE_TRACK: rv = m_placer->FixRoute( aP, aEndItem ); + m_startsOnVia = m_placingVia; m_placingVia = false; break; @@ -874,8 +878,7 @@ void PNS_ROUTER::SwitchLayer( int aLayer ) if( m_startsOnVia ) { m_currentLayer = aLayer; - //m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth, - // m_currentLayer ); + m_placer->SetLayer( aLayer ); } break; diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index b5fc2a6daa..fc22c60d16 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -107,7 +107,7 @@ public: void DisplayItems( const PNS_ITEMSET& aItems ); void DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType = 0, int aWidth = 0 ); - void DisplayDebugPoint( const VECTOR2I aPos, int aType = 0); + void DisplayDebugPoint( const VECTOR2I aPos, int aType = 0 ); void DisplayDebugBox( const BOX2I& aBox, int aType = 0, int aWidth = 0 ); void SwitchLayer( int layer ); @@ -223,7 +223,7 @@ private: void highlightCurrent( bool enabled ); - void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ITEM_VECTOR& aRemoved ); + void markViolations( PNS_NODE* aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ITEM_VECTOR& aRemoved ); int m_currentLayer; int m_currentNet; @@ -234,7 +234,7 @@ private: PNS_NODE* m_world; PNS_NODE* m_lastNode; PNS_LINE_PLACER* m_placer; - PNS_DRAGGER *m_dragger; + PNS_DRAGGER* m_dragger; PNS_LINE* m_draggedLine; PNS_SHOVE* m_shove; int m_draggedSegmentIndex; diff --git a/pcbnew/router/pns_routing_settings.cpp b/pcbnew/router/pns_routing_settings.cpp index cf87359674..bb67840fbe 100644 --- a/pcbnew/router/pns_routing_settings.cpp +++ b/pcbnew/router/pns_routing_settings.cpp @@ -19,6 +19,7 @@ */ #include "pns_routing_settings.h" +#include "direction.h" PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS() { @@ -39,6 +40,15 @@ PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS() } +const DIRECTION_45 PNS_ROUTING_SETTINGS::InitialDirection() const +{ + if( m_startDiagonal ) + return DIRECTION_45( DIRECTION_45::NE ); + else + return DIRECTION_45( DIRECTION_45::N ); +} + + TIME_LIMIT PNS_ROUTING_SETTINGS::ShoveTimeLimit() const { return TIME_LIMIT ( m_shoveTimeLimit ); diff --git a/pcbnew/router/pns_routing_settings.h b/pcbnew/router/pns_routing_settings.h index 5f6de3fa92..0cd615cecb 100644 --- a/pcbnew/router/pns_routing_settings.h +++ b/pcbnew/router/pns_routing_settings.h @@ -21,8 +21,9 @@ #ifndef __PNS_ROUTING_SETTINGS #define __PNS_ROUTING_SETTINGS -#include "direction.h" #include "time_limit.h" + +class DIRECTION_45; ///> Routing modes enum PNS_MODE @@ -118,13 +119,7 @@ public: void SetViaDrill( int aDrill ) { m_viaDrill = aDrill; } int GetViaDrill() const { return m_viaDrill; } - const DIRECTION_45 InitialDirection() const - { - if( m_startDiagonal ) - return DIRECTION_45( DIRECTION_45::NE ); - else - return DIRECTION_45( DIRECTION_45::N ); - } + const DIRECTION_45 InitialDirection() const; int ShoveIterationLimit() const; TIME_LIMIT ShoveTimeLimit() const; @@ -132,6 +127,23 @@ public: int WalkaroundIterationLimit() const { return m_walkaroundIterationLimit; }; TIME_LIMIT WalkaroundTimeLimit() const; + void SetLayerPair( int aLayer1, int aLayer2 ) + { + if( aLayer1 > aLayer2 ) + { + m_layerTop = aLayer1; + m_layerBottom = aLayer2; + } + else + { + m_layerBottom = aLayer1; + m_layerTop = aLayer2; + } + } + + int GetLayerTop() const { return m_layerTop; } + int GetLayerBottom() const { return m_layerBottom; } + private: bool m_shoveVias; bool m_startDiagonal; @@ -155,6 +167,10 @@ private: int m_shoveIterationLimit; TIME_LIMIT m_shoveTimeLimit; TIME_LIMIT m_walkaroundTimeLimit; + + // Routing layers pair + int m_layerTop; + int m_layerBottom; }; #endif diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index e1c7f90ab8..29de1909db 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -212,15 +212,15 @@ public: Add( ACT_PlaceThroughVia ); Add( ACT_SwitchPosture ); - AppendSeparator ( ); - + AppendSeparator(); + CONTEXT_TRACK_WIDTH_MENU* trackMenu = new CONTEXT_TRACK_WIDTH_MENU; trackMenu->SetBoard( aBoard ); AppendSubMenu( trackMenu, wxT( "Select Track Width" ) ); Add( ACT_CustomTrackWidth ); - AppendSeparator ( ); + AppendSeparator(); Add( ACT_RouterOptions ); } }; @@ -404,11 +404,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& aEvent ) bds.SetCustomViaDrill( m_router->Settings().GetViaDrill() ); bds.UseCustomTrackViaSize( true ); - // TODO Should be done another way, but RunAction() won't work here. As the ROUTER_TOOL - // did not call Wait(), it does not wait for events and therefore the sent event - // won't arrive here - TOOL_EVENT event = COMMON_ACTIONS::trackViaSizeChanged.MakeEvent(); - handleCommonEvents( event ); + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); } else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) ) @@ -480,10 +476,9 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) VECTOR2I p = getView()->ToWorld( ctls->GetMousePosition() ); VECTOR2I cp = ctls->GetCursorPosition(); int layer; + bool snapEnabled = !aEvent.Modifier( MD_SHIFT ); - bool snapEnabled = !aEvent.Modifier(MD_SHIFT); - - m_router->EnableSnapping ( snapEnabled ); + m_router->EnableSnapping( snapEnabled ); if( !snapEnabled || m_router->GetCurrentNet() < 0 || !m_startItem ) { @@ -537,9 +532,7 @@ void ROUTER_TOOL::performRouting() } m_router->SwitchLayer( m_startLayer ); - frame->SetActiveLayer( ToLAYER_ID( m_startLayer ) ); - frame->GetGalCanvas()->SetFocus(); if( m_startItem && m_startItem->Net() >= 0 ) highlightNet( true, m_startItem->Net() ); @@ -554,7 +547,7 @@ void ROUTER_TOOL::performRouting() while( OPT_TOOL_EVENT evt = Wait() ) { - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) break; else if( evt->Action() == TA_UNDO_REDO ) { @@ -573,39 +566,36 @@ void ROUTER_TOOL::performRouting() if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) break; + // Synchronize the indicated layer + frame->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); + m_router->Move( m_endSnapPoint, m_endItem ); } else if( evt->IsAction( &ACT_PlaceThroughVia ) ) { + m_router->Settings().SetLayerPair( frame->GetScreen()->m_Route_Layer_TOP, + frame->GetScreen()->m_Route_Layer_BOTTOM ); m_router->ToggleViaPlacement(); - frame->SetTopLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); - m_router->Move( m_endSnapPoint, m_endItem ); + m_router->Move( m_endSnapPoint, m_endItem ); // refresh } else if( evt->IsAction( &ACT_SwitchPosture ) ) { m_router->FlipPosture(); - m_router->Move( m_endSnapPoint, m_endItem ); + m_router->Move( m_endSnapPoint, m_endItem ); // refresh } - else if( evt->IsAction( &COMMON_ACTIONS::layerNext ) ) + else if( evt->IsAction( &COMMON_ACTIONS::layerChanged ) ) { - m_router->SwitchLayer( m_router->NextCopperLayer( true ) ); updateEndItem( *evt ); - frame->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); - m_router->Move( m_endSnapPoint, m_endItem ); - } - else if( evt->IsAction( &COMMON_ACTIONS::layerPrev ) ) - { - m_router->SwitchLayer( m_router->NextCopperLayer( false ) ); - frame->SetActiveLayer( ToLAYER_ID( m_router->GetCurrentLayer() ) ); - m_router->Move( m_endSnapPoint, m_endItem ); + m_router->SwitchLayer( frame->GetActiveLayer() ); + m_router->Move( m_endSnapPoint, m_endItem ); // refresh } else if( evt->IsAction( &ACT_EndTrack ) ) { if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) break; } - - handleCommonEvents(*evt); + + handleCommonEvents( *evt ); } m_router->StopRouting(); @@ -636,7 +626,7 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings(); // Deselect all items - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); getEditFrame()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Interactive Router" ) ); @@ -649,7 +639,7 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) m_router->Settings().SetViaDiameter( bds.GetCurrentViaSize() ); m_router->Settings().SetViaDrill( bds.GetCurrentViaDrill() ); - ROUTER_TOOL_MENU *ctxMenu = new ROUTER_TOOL_MENU( board ); + ROUTER_TOOL_MENU* ctxMenu = new ROUTER_TOOL_MENU( board ); SetContextMenu ( ctxMenu ); @@ -663,7 +653,7 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) m_needsSync = false; } - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) break; // Finish else if( evt->Action() == TA_UNDO_REDO ) m_needsSync = true; @@ -677,10 +667,11 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) performDragging(); else performRouting(); - } else if ( evt->IsAction( &ACT_Drag ) ) + } + else if ( evt->IsAction( &ACT_Drag ) ) performDragging(); - handleCommonEvents(*evt); + handleCommonEvents( *evt ); } // Restore the default settings @@ -715,7 +706,7 @@ void ROUTER_TOOL::performDragging() while( OPT_TOOL_EVENT evt = Wait() ) { - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) break; else if( evt->Action() == TA_UNDO_REDO ) { diff --git a/pcbnew/router/router_tool.h b/pcbnew/router/router_tool.h index 4ad339f3a5..06dc75b7fe 100644 --- a/pcbnew/router/router_tool.h +++ b/pcbnew/router/router_tool.h @@ -22,18 +22,13 @@ #ifndef __ROUTER_TOOL_H #define __ROUTER_TOOL_H -#include -#include - #include #include #include -#include #include -#include "pns_layerset.h" #include "pns_routing_settings.h" class PNS_ROUTER; diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp index 285d662aed..0ce1c0f806 100644 --- a/pcbnew/tools/common_actions.cpp +++ b/pcbnew/tools/common_actions.cpp @@ -29,24 +29,28 @@ // Selection tool actions TOOL_ACTION COMMON_ACTIONS::selectionActivate( "pcbnew.InteractiveSelection", - AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere + AS_GLOBAL, 0, + "", "", AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere TOOL_ACTION COMMON_ACTIONS::selectionSingle( "pcbnew.InteractiveSelection.Single", - AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere + AS_GLOBAL, 0, + "", "" ); // No description, it is not supposed to be shown anywhere TOOL_ACTION COMMON_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear", - AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere + AS_GLOBAL, 0, + "", "" ); // No description, it is not supposed to be shown anywhere + // Edit tool actions TOOL_ACTION COMMON_ACTIONS::editActivate( "pcbnew.InteractiveEdit", AS_GLOBAL, 'M', - "Move", "Moves the selected item(s)" ); + "Move", "Moves the selected item(s)", AF_ACTIVATE ); -TOOL_ACTION COMMON_ACTIONS::rotate( "pcbnew.rotate", +TOOL_ACTION COMMON_ACTIONS::rotate( "pcbnew.InteractiveEdit.rotate", AS_GLOBAL, 'R', "Rotate", "Rotates selected item(s)" ); -TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.flip", +TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.InteractiveEdit.flip", AS_GLOBAL, 'F', "Flip", "Flips selected item(s)" ); @@ -62,244 +66,421 @@ TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties", // Drawing tool actions TOOL_ACTION COMMON_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line", AS_GLOBAL, 0, - "Draw a line", "Draw a line" ); + "Draw a line", "Draw a line", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::drawCircle( "pcbnew.InteractiveDrawing.circle", AS_GLOBAL, 0, - "Draw a circle", "Draw a circle" ); + "Draw a circle", "Draw a circle", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::drawArc( "pcbnew.InteractiveDrawing.arc", AS_GLOBAL, 0, - "Draw an arc", "Draw an arc" ); + "Draw an arc", "Draw an arc", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::placeText( "pcbnew.InteractiveDrawing.text", AS_GLOBAL, 0, - "Add a text", "Add a text" ); + "Add a text", "Add a text", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::drawDimension( "pcbnew.InteractiveDrawing.dimension", AS_GLOBAL, 0, - "Add a dimension", "Add a dimension" ); + "Add a dimension", "Add a dimension", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::drawZone( "pcbnew.InteractiveDrawing.zone", AS_GLOBAL, 0, - "Add a filled zone", "Add a filled zone" ); + "Add a filled zone", "Add a filled zone", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::drawKeepout( "pcbnew.InteractiveDrawing.keepout", AS_GLOBAL, 0, - "Add a keepout area", "Add a keepout area" ); + "Add a keepout area", "Add a keepout area", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::placeTarget( "pcbnew.InteractiveDrawing.placeTarget", AS_GLOBAL, 0, - "Add layer alignment target", "Add layer alignment target" ); + "Add layer alignment target", "Add layer alignment target", AF_ACTIVATE ); TOOL_ACTION COMMON_ACTIONS::placeModule( "pcbnew.InteractiveDrawing.placeModule", AS_GLOBAL, 'O', - "Add modules", "Add modules" ); + "Add modules", "Add modules", AF_ACTIVATE ); -TOOL_ACTION COMMON_ACTIONS::routerActivate( "pcbnew.InteractiveRouter", - AS_GLOBAL, 'X', - "Run push & shove router", "Run push & shove router" ); +TOOL_ACTION COMMON_ACTIONS::placeDXF( "pcbnew.InteractiveDrawing.placeDXF", + AS_GLOBAL, 0, + "", "", AF_ACTIVATE ); -TOOL_ACTION COMMON_ACTIONS::pointEditorUpdate( "pcbnew.PointEditor.update", - AS_GLOBAL, 0, "", "" ); // No description, it is not supposed to be shown anywhere +TOOL_ACTION COMMON_ACTIONS::setAnchor( "pcbnew.InteractiveDrawing.setAnchor", + AS_GLOBAL, 0, + "Place the footprint anchor", "Place the footprint anchor", + AF_ACTIVATE ); // View Controls -TOOL_ACTION COMMON_ACTIONS::zoomIn( "pcbnew.zoomIn", +TOOL_ACTION COMMON_ACTIONS::zoomIn( "pcbnew.Control.zoomIn", AS_GLOBAL, WXK_F1, "", "" ); -TOOL_ACTION COMMON_ACTIONS::zoomOut( "pcbnew.zoomOut", +TOOL_ACTION COMMON_ACTIONS::zoomOut( "pcbnew.Control.zoomOut", AS_GLOBAL, WXK_F2, "", "" ); -TOOL_ACTION COMMON_ACTIONS::zoomInCenter( "pcbnew.zoomInCenter", +TOOL_ACTION COMMON_ACTIONS::zoomInCenter( "pcbnew.Control.zoomInCenter", AS_GLOBAL, 0, "", "" ); -TOOL_ACTION COMMON_ACTIONS::zoomOutCenter( "pcbnew.zoomOutCenter", +TOOL_ACTION COMMON_ACTIONS::zoomOutCenter( "pcbnew.Control.zoomOutCenter", AS_GLOBAL, 0, "", "" ); -TOOL_ACTION COMMON_ACTIONS::zoomCenter( "pcbnew.zoomCenter", +TOOL_ACTION COMMON_ACTIONS::zoomCenter( "pcbnew.Control.zoomCenter", AS_GLOBAL, WXK_F4, "", "" ); -TOOL_ACTION COMMON_ACTIONS::zoomFitScreen( "pcbnew.zoomFitScreen", +TOOL_ACTION COMMON_ACTIONS::zoomFitScreen( "pcbnew.Control.zoomFitScreen", AS_GLOBAL, WXK_HOME, "", "" ); // Display modes -TOOL_ACTION COMMON_ACTIONS::trackDisplayMode( "pcbnew.trackDisplayMode", +TOOL_ACTION COMMON_ACTIONS::trackDisplayMode( "pcbnew.Control.trackDisplayMode", AS_GLOBAL, 'K', "", "" ); -TOOL_ACTION COMMON_ACTIONS::padDisplayMode( "pcbnew.padDisplayMode", +TOOL_ACTION COMMON_ACTIONS::padDisplayMode( "pcbnew.Control.padDisplayMode", AS_GLOBAL, 'J', // TODO temporarily, find a better hot key "", "" ); -TOOL_ACTION COMMON_ACTIONS::viaDisplayMode( "pcbnew.viaDisplayMode", +TOOL_ACTION COMMON_ACTIONS::viaDisplayMode( "pcbnew.Control.viaDisplayMode", AS_GLOBAL, 'L', // TODO temporarily, find a better hot key "", "" ); -TOOL_ACTION COMMON_ACTIONS::highContrastMode( "pcbnew.highContrastMode", +TOOL_ACTION COMMON_ACTIONS::zoneDisplayEnable( "pcbnew.Control.zoneDisplayEnable", + AS_GLOBAL, 0, + "", "" ); + +TOOL_ACTION COMMON_ACTIONS::zoneDisplayDisable( "pcbnew.Control.zoneDisplayDisable", + AS_GLOBAL, 0, + "", "" ); + +TOOL_ACTION COMMON_ACTIONS::zoneDisplayOutlines( "pcbnew.Control.zoneDisplayOutlines", + AS_GLOBAL, 0, + "", "" ); + +TOOL_ACTION COMMON_ACTIONS::highContrastMode( "pcbnew.Control.highContrastMode", AS_GLOBAL, 'H', "", "" ); -TOOL_ACTION COMMON_ACTIONS::highContrastInc( "pcbnew.highContrastInc", +TOOL_ACTION COMMON_ACTIONS::highContrastInc( "pcbnew.Control.highContrastInc", AS_GLOBAL, '>', "", "" ); -TOOL_ACTION COMMON_ACTIONS::highContrastDec( "pcbnew.highContrastDec", +TOOL_ACTION COMMON_ACTIONS::highContrastDec( "pcbnew.Control.highContrastDec", AS_GLOBAL, '<', "", "" ); // Layer control -TOOL_ACTION COMMON_ACTIONS::layerTop( "pcbnew.layerTop", +TOOL_ACTION COMMON_ACTIONS::layerTop( "pcbnew.Control.layerTop", AS_GLOBAL, WXK_PAGEUP, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner1( "pcbnew.layerInner1", +TOOL_ACTION COMMON_ACTIONS::layerInner1( "pcbnew.Control.layerInner1", AS_GLOBAL, WXK_F5, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner2( "pcbnew.layerInner2", +TOOL_ACTION COMMON_ACTIONS::layerInner2( "pcbnew.Control.layerInner2", AS_GLOBAL, WXK_F6, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner3( "pcbnew.layerInner3", +TOOL_ACTION COMMON_ACTIONS::layerInner3( "pcbnew.Control.layerInner3", AS_GLOBAL, WXK_F7, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner4( "pcbnew.layerInner4", +TOOL_ACTION COMMON_ACTIONS::layerInner4( "pcbnew.Control.layerInner4", AS_GLOBAL, WXK_F8, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner5( "pcbnew.layerInner5", +TOOL_ACTION COMMON_ACTIONS::layerInner5( "pcbnew.Control.layerInner5", AS_GLOBAL, WXK_F9, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerInner6( "pcbnew.layerInner6", +TOOL_ACTION COMMON_ACTIONS::layerInner6( "pcbnew.Control.layerInner6", AS_GLOBAL, WXK_F10, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerBottom( "pcbnew.layerBottom", +TOOL_ACTION COMMON_ACTIONS::layerBottom( "pcbnew.Control.layerBottom", AS_GLOBAL, WXK_PAGEDOWN, "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerNext( "pcbnew.layerNext", +TOOL_ACTION COMMON_ACTIONS::layerNext( "pcbnew.Control.layerNext", AS_GLOBAL, '=', "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerPrev( "pcbnew.layerPrev", +TOOL_ACTION COMMON_ACTIONS::layerPrev( "pcbnew.Control.layerPrev", AS_GLOBAL, '-', "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerAlphaInc( "pcbnew.layerAlphaInc", +TOOL_ACTION COMMON_ACTIONS::layerAlphaInc( "pcbnew.Control.layerAlphaInc", AS_GLOBAL, '}', "", "" ); -TOOL_ACTION COMMON_ACTIONS::layerAlphaDec( "pcbnew.layerAlphaDec", +TOOL_ACTION COMMON_ACTIONS::layerAlphaDec( "pcbnew.Control.layerAlphaDec", AS_GLOBAL, '{', "", "" ); +TOOL_ACTION COMMON_ACTIONS::layerChanged( "pcbnew.Control.layerChanged", + AS_GLOBAL, 0, + "", "", AF_NOTIFY ); + // Grid control -TOOL_ACTION COMMON_ACTIONS::gridFast1( "pcbnew.gridFast1", +TOOL_ACTION COMMON_ACTIONS::gridFast1( "pcbnew.Control.gridFast1", AS_GLOBAL, MD_ALT + int( '1' ), "", "" ); -TOOL_ACTION COMMON_ACTIONS::gridFast2( "pcbnew.gridFast2", +TOOL_ACTION COMMON_ACTIONS::gridFast2( "pcbnew.Control.gridFast2", AS_GLOBAL, MD_ALT + int( '2' ), "", "" ); -TOOL_ACTION COMMON_ACTIONS::gridNext( "pcbnew.gridNext", +TOOL_ACTION COMMON_ACTIONS::gridNext( "pcbnew.Control.gridNext", AS_GLOBAL, '`', "", "" ); -TOOL_ACTION COMMON_ACTIONS::gridPrev( "pcbnew.gridPrev", +TOOL_ACTION COMMON_ACTIONS::gridPrev( "pcbnew.Control.gridPrev", AS_GLOBAL, MD_CTRL + int( '`' ), "", "" ); -TOOL_ACTION COMMON_ACTIONS::gridSetOrigin( "pcbnew.gridSetOrigin", +TOOL_ACTION COMMON_ACTIONS::gridSetOrigin( "pcbnew.Control.gridSetOrigin", AS_GLOBAL, 0, "", "" ); // Track & via size control -TOOL_ACTION COMMON_ACTIONS::trackWidthInc( "pcbnew.trackWidthInc", +TOOL_ACTION COMMON_ACTIONS::trackWidthInc( "pcbnew.EditorControl.trackWidthInc", AS_GLOBAL, '[', "", "" ); -TOOL_ACTION COMMON_ACTIONS::trackWidthDec( "pcbnew.trackWidthDec", +TOOL_ACTION COMMON_ACTIONS::trackWidthDec( "pcbnew.EditorControl.trackWidthDec", AS_GLOBAL, ']', "", "" ); -TOOL_ACTION COMMON_ACTIONS::viaSizeInc( "pcbnew.viaSizeInc", +TOOL_ACTION COMMON_ACTIONS::viaSizeInc( "pcbnew.EditorControl.viaSizeInc", AS_GLOBAL, '\'', "", "" ); -TOOL_ACTION COMMON_ACTIONS::viaSizeDec( "pcbnew.viaSizeDec", +TOOL_ACTION COMMON_ACTIONS::viaSizeDec( "pcbnew.EditorControl.viaSizeDec", AS_GLOBAL, '\\', "", "" ); -TOOL_ACTION COMMON_ACTIONS::trackViaSizeChanged( "pcbnew.trackViaSizeChanged", +TOOL_ACTION COMMON_ACTIONS::trackViaSizeChanged( "pcbnew.EditorControl.trackViaSizeChanged", + AS_GLOBAL, 0, + "", "", AF_NOTIFY ); + + +// Zone actions +TOOL_ACTION COMMON_ACTIONS::zoneFill( "pcbnew.EditorControl.zoneFill", + AS_GLOBAL, 0, + "Fill", "Fill zone(s)" ); + +TOOL_ACTION COMMON_ACTIONS::zoneFillAll( "pcbnew.EditorControl.zoneFillAll", + AS_GLOBAL, 0, + "Fill all", "Fill all zones" ); + +TOOL_ACTION COMMON_ACTIONS::zoneUnfill( "pcbnew.EditorControl.zoneUnfill", + AS_GLOBAL, 0, + "Unfill", "Unfill zone(s)" ); + + +// Module editor tools +TOOL_ACTION COMMON_ACTIONS::placePad( "pcbnew.ModuleEditor.placePad", + AS_GLOBAL, 0, + "Add pads", "Add pads", AF_ACTIVATE ); + +TOOL_ACTION COMMON_ACTIONS::enumeratePads( "pcbnew.ModuleEditor.enumeratePads", + AS_GLOBAL, 0, + "Enumerate pads", "Enumerate pads", AF_ACTIVATE ); + +TOOL_ACTION COMMON_ACTIONS::copyItems( "pcbnew.ModuleEditor.copyItems", + AS_GLOBAL, MD_CTRL + int( 'C' ), + "Copy items", "Copy items", AF_ACTIVATE ); + +TOOL_ACTION COMMON_ACTIONS::pasteItems( "pcbnew.ModuleEditor.pasteItems", + AS_GLOBAL, MD_CTRL + int( 'V' ), + "Paste items", "Paste items", AF_ACTIVATE ); + +TOOL_ACTION COMMON_ACTIONS::moduleEdgeOutlines( "pcbnew.ModuleEditor.graphicOutlines", AS_GLOBAL, 0, "", "" ); +TOOL_ACTION COMMON_ACTIONS::moduleTextOutlines( "pcbnew.ModuleEditor.textOutlines", + AS_GLOBAL, 0, + "", "" ); + + // Miscellaneous -TOOL_ACTION COMMON_ACTIONS::resetCoords( "pcbnew.resetCoords", +TOOL_ACTION COMMON_ACTIONS::resetCoords( "pcbnew.Control.resetCoords", AS_GLOBAL, ' ', "", "" ); -TOOL_ACTION COMMON_ACTIONS::switchUnits( "pcbnew.switchUnits", +TOOL_ACTION COMMON_ACTIONS::switchCursor( "pcbnew.Control.switchCursor", + AS_GLOBAL, 0, + "", "" ); + +TOOL_ACTION COMMON_ACTIONS::switchUnits( "pcbnew.Control.switchUnits", AS_GLOBAL, MD_CTRL + int( 'U' ), "", "" ); -TOOL_ACTION COMMON_ACTIONS::showHelp( "pcbnew.showHelp", +TOOL_ACTION COMMON_ACTIONS::showHelp( "pcbnew.Control.showHelp", AS_GLOBAL, '?', "", "" ); +TOOL_ACTION COMMON_ACTIONS::toBeDone( "pcbnew.Control.toBeDone", + AS_GLOBAL, 0, // dialog saying it is not implemented yet + "", "" ); // so users are aware of that -std::string COMMON_ACTIONS::TranslateLegacyId( int aId ) +TOOL_ACTION COMMON_ACTIONS::routerActivate( "pcbnew.InteractiveRouter", + AS_GLOBAL, 'X', + "Run push & shove router", "Run push & shove router", AF_ACTIVATE ); + + +// Point editor +TOOL_ACTION COMMON_ACTIONS::pointEditorUpdate( "pcbnew.PointEditor.update", + AS_GLOBAL, 0, + "", "" ); // No description, it is not supposed to be shown anywhere + +TOOL_ACTION COMMON_ACTIONS::pointEditorBreakOutline( "pcbnew.PointEditor.breakOutline", + AS_GLOBAL, 0, + "Create corner", "Create corner" ); + + +// Placement tool +TOOL_ACTION COMMON_ACTIONS::alignTop( "pcbnew.Place.alignTop", + AS_GLOBAL, 0, + "Align items to the top", + "Aligns selected items to the top edge" ); + +TOOL_ACTION COMMON_ACTIONS::alignBottom( "pcbnew.Place.alignBottom", + AS_GLOBAL, 0, + "Align items to the bottom", + "Aligns selected items to the bottom edge" ); + +TOOL_ACTION COMMON_ACTIONS::alignLeft( "pcbnew.Place.alignLeft", + AS_GLOBAL, 0, + "Align items to the left", + "Aligns selected items to the top left" ); + +TOOL_ACTION COMMON_ACTIONS::alignRight( "pcbnew.Place.alignRight", + AS_GLOBAL, 0, + "Align items to the right", + "Aligns selected items to the right edge" ); + +TOOL_ACTION COMMON_ACTIONS::distributeHorizontally( "pcbnew.Place.distributeHorizontally", + AS_GLOBAL, 0, + "Distribute horizontally", + "Distributes selected items along the horizontal axis" ); + +TOOL_ACTION COMMON_ACTIONS::distributeVertically( "pcbnew.Place.distributeVertically", + AS_GLOBAL, 0, + "Distribure vertically", + "Distributes selected items along the vertical axis" ); + + +boost::optional COMMON_ACTIONS::TranslateLegacyId( int aId ) { switch( aId ) { case ID_PCB_MODULE_BUTT: - return COMMON_ACTIONS::placeModule.GetName(); + return COMMON_ACTIONS::placeModule.MakeEvent(); case ID_TRACK_BUTT: - return COMMON_ACTIONS::routerActivate.GetName(); + return COMMON_ACTIONS::routerActivate.MakeEvent(); case ID_PCB_ZONES_BUTT: - return COMMON_ACTIONS::drawZone.GetName(); + return COMMON_ACTIONS::drawZone.MakeEvent(); case ID_PCB_KEEPOUT_AREA_BUTT: - return COMMON_ACTIONS::drawKeepout.GetName(); + return COMMON_ACTIONS::drawKeepout.MakeEvent(); case ID_PCB_ADD_LINE_BUTT: - return COMMON_ACTIONS::drawLine.GetName(); + case ID_MODEDIT_LINE_TOOL: + return COMMON_ACTIONS::drawLine.MakeEvent(); case ID_PCB_CIRCLE_BUTT: - return COMMON_ACTIONS::drawCircle.GetName(); + case ID_MODEDIT_CIRCLE_TOOL: + return COMMON_ACTIONS::drawCircle.MakeEvent(); case ID_PCB_ARC_BUTT: - return COMMON_ACTIONS::drawArc.GetName(); + case ID_MODEDIT_ARC_TOOL: + return COMMON_ACTIONS::drawArc.MakeEvent(); case ID_PCB_ADD_TEXT_BUTT: - return COMMON_ACTIONS::placeText.GetName(); + case ID_MODEDIT_TEXT_TOOL: + return COMMON_ACTIONS::placeText.MakeEvent(); case ID_PCB_DIMENSION_BUTT: - return COMMON_ACTIONS::drawDimension.GetName(); + return COMMON_ACTIONS::drawDimension.MakeEvent(); case ID_PCB_MIRE_BUTT: - return COMMON_ACTIONS::placeTarget.GetName(); + return COMMON_ACTIONS::placeTarget.MakeEvent(); + + case ID_MODEDIT_PAD_TOOL: + return COMMON_ACTIONS::placePad.MakeEvent(); + + case ID_GEN_IMPORT_DXF_FILE: + return COMMON_ACTIONS::placeDXF.MakeEvent(); + + case ID_MODEDIT_ANCHOR_TOOL: + return COMMON_ACTIONS::setAnchor.MakeEvent(); case ID_PCB_PLACE_GRID_COORD_BUTT: - return COMMON_ACTIONS::gridSetOrigin.GetName(); + case ID_MODEDIT_PLACE_GRID_COORD: + return COMMON_ACTIONS::gridSetOrigin.MakeEvent(); + + case ID_ZOOM_IN: // toolbar button "Zoom In" + return COMMON_ACTIONS::zoomInCenter.MakeEvent(); + + case ID_ZOOM_OUT: // toolbar button "Zoom In" + return COMMON_ACTIONS::zoomOutCenter.MakeEvent(); + + case ID_ZOOM_PAGE: // toolbar button "Fit on Screen" + return COMMON_ACTIONS::zoomFitScreen.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_TRACKS_SKETCH: + return COMMON_ACTIONS::trackDisplayMode.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_PADS_SKETCH: + return COMMON_ACTIONS::padDisplayMode.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_VIAS_SKETCH: + return COMMON_ACTIONS::viaDisplayMode.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_ZONES: + return COMMON_ACTIONS::zoneDisplayEnable.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_ZONES_DISABLE: + return COMMON_ACTIONS::zoneDisplayDisable.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_ZONES_OUTLINES_ONLY: + return COMMON_ACTIONS::zoneDisplayOutlines.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_MODULE_EDGE_SKETCH: + return COMMON_ACTIONS::moduleEdgeOutlines.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_MODULE_TEXT_SKETCH: + return COMMON_ACTIONS::moduleTextOutlines.MakeEvent(); + + case ID_TB_OPTIONS_SHOW_HIGH_CONTRAST_MODE: + return COMMON_ACTIONS::highContrastMode.MakeEvent(); + + case ID_TB_OPTIONS_SELECT_CURSOR: + return COMMON_ACTIONS::switchCursor.MakeEvent(); + + case ID_PCB_DELETE_ITEM_BUTT: + case ID_PCB_HIGHLIGHT_BUTT: + case ID_PCB_SHOW_1_RATSNEST_BUTT: + case ID_PCB_PLACE_OFFSET_COORD_BUTT: + case ID_TB_OPTIONS_SHOW_MODULE_RATSNEST: + case ID_TB_OPTIONS_SHOW_EXTRA_VERTICAL_TOOLBAR_MICROWAVE: + case ID_MENU_PCB_SHOW_HIDE_MUWAVE_TOOLBAR: + case ID_MICROWAVE_V_TOOLBAR: + case ID_MODEDIT_DELETE_TOOL: + return COMMON_ACTIONS::toBeDone.MakeEvent(); } - return ""; + return boost::optional(); } diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h index 428115bb6e..4712b42525 100644 --- a/pcbnew/tools/common_actions.h +++ b/pcbnew/tools/common_actions.h @@ -23,6 +23,9 @@ */ #include +#include + +class TOOL_EVENT; /** * Class COMMON_ACTIONS @@ -87,6 +90,12 @@ public: /// Activation of the drawing tool (placing a MODULE) static TOOL_ACTION placeModule; + /// Activation of the drawing tool (placing a drawing from DXF file) + static TOOL_ACTION placeDXF; + + /// Activation of the drawing tool (placing the footprint anchor) + static TOOL_ACTION setAnchor; + // Push and Shove Router Tool /// Activation of the Push and Shove router static TOOL_ACTION routerActivate; @@ -95,6 +104,28 @@ public: /// Update edit points static TOOL_ACTION pointEditorUpdate; + /// Break outline (insert additional points to an edge) + static TOOL_ACTION pointEditorBreakOutline; + + // Placement tool + /// Align items to the top edge of selection bounding box + static TOOL_ACTION alignTop; + + /// Align items to the bottom edge of selection bounding box + static TOOL_ACTION alignBottom; + + /// Align items to the left edge of selection bounding box + static TOOL_ACTION alignLeft; + + /// Align items to the right edge of selection bounding box + static TOOL_ACTION alignRight; + + /// Distributes items evenly along the horizontal axis + static TOOL_ACTION distributeHorizontally; + + /// Distributes items evenly along the vertical axis + static TOOL_ACTION distributeVertically; + // View controls static TOOL_ACTION zoomIn; static TOOL_ACTION zoomOut; @@ -107,6 +138,9 @@ public: static TOOL_ACTION trackDisplayMode; static TOOL_ACTION padDisplayMode; static TOOL_ACTION viaDisplayMode; + static TOOL_ACTION zoneDisplayEnable; + static TOOL_ACTION zoneDisplayDisable; + static TOOL_ACTION zoneDisplayOutlines; static TOOL_ACTION highContrastMode; static TOOL_ACTION highContrastInc; static TOOL_ACTION highContrastDec; @@ -125,6 +159,8 @@ public: static TOOL_ACTION layerAlphaInc; static TOOL_ACTION layerAlphaDec; + static TOOL_ACTION layerChanged; // notification + // Grid control static TOOL_ACTION gridFast1; static TOOL_ACTION gridFast2; @@ -140,10 +176,36 @@ public: static TOOL_ACTION trackViaSizeChanged; // notification + // Zone actions + static TOOL_ACTION zoneFill; + static TOOL_ACTION zoneFillAll; + static TOOL_ACTION zoneUnfill; + + // Module editor tools + /// Activation of the drawing tool (placing a PAD) + static TOOL_ACTION placePad; + + /// Tool for quick pad enumeration + static TOOL_ACTION enumeratePads; + + /// Copying module items to clipboard + static TOOL_ACTION copyItems; + + /// Pasting module items from clipboard + static TOOL_ACTION pasteItems; + + /// Display module edges as outlines + static TOOL_ACTION moduleEdgeOutlines; + + /// Display module texts as outlines + static TOOL_ACTION moduleTextOutlines; + // Miscellaneous static TOOL_ACTION resetCoords; + static TOOL_ACTION switchCursor; static TOOL_ACTION switchUnits; static TOOL_ACTION showHelp; + static TOOL_ACTION toBeDone; /** * Function TranslateLegacyId() @@ -152,5 +214,5 @@ public: * @return std::string is name of the corresponding TOOL_ACTION. It may be empty, if there is * no corresponding TOOL_ACTION. */ - static std::string TranslateLegacyId( int aId ); + static boost::optional TranslateLegacyId( int aId ); }; diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index db5d6900e8..e1e15322fa 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -23,14 +23,19 @@ */ #include +#include + #include "drawing_tool.h" #include "common_actions.h" #include +#include #include #include #include #include +#include +#include #include #include @@ -39,7 +44,7 @@ #include #include -#include +#include #include #include #include @@ -47,7 +52,7 @@ #include DRAWING_TOOL::DRAWING_TOOL() : - TOOL_INTERACTIVE( "pcbnew.InteractiveDrawing" ) + TOOL_INTERACTIVE( "pcbnew.InteractiveDrawing" ), m_editModules( false ) { } @@ -71,206 +76,155 @@ void DRAWING_TOOL::Reset( RESET_REASON aReason ) int DRAWING_TOOL::DrawLine( TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) ); + boost::optional startingPoint; - return drawSegment( S_SEGMENT, true ); + if( m_editModules ) + { + m_frame->SetToolID( ID_MODEDIT_LINE_TOOL, wxCURSOR_PENCIL, _( "Add graphic line" ) ); + + MODULE* module = m_board->m_Modules; + EDGE_MODULE* line = new EDGE_MODULE( module ); + + while( drawSegment( S_SEGMENT, reinterpret_cast( line ), startingPoint ) ) + { + if( line ) + { + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + line->SetLocalCoord(); + line->SetParent( module ); + module->GraphicalItems().PushFront( line ); + startingPoint = line->GetEnd(); + } + else + { + startingPoint = boost::none; + } + + line = new EDGE_MODULE( module ); + } + } + else + { + m_frame->SetToolID( ID_PCB_ADD_LINE_BUTT, wxCURSOR_PENCIL, _( "Add graphic line" ) ); + + DRAWSEGMENT* line = new DRAWSEGMENT; + + while( drawSegment( S_SEGMENT, line, startingPoint ) ) + { + if( line ) + { + m_board->Add( line ); + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( line, UR_NEW ); + startingPoint = line->GetEnd(); + } + else + { + startingPoint = boost::none; + } + + line = new DRAWSEGMENT; + } + } + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; } int DRAWING_TOOL::DrawCircle( TOOL_EVENT& aEvent ) { - m_frame->SetToolID( ID_PCB_CIRCLE_BUTT, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); + if( m_editModules ) + { + m_frame->SetToolID( ID_MODEDIT_CIRCLE_TOOL, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); - return drawSegment( S_CIRCLE, false ); + MODULE* module = m_board->m_Modules; + EDGE_MODULE* circle = new EDGE_MODULE( module ); + + while( drawSegment( S_CIRCLE, reinterpret_cast( circle ) ) ) + { + if( circle ) + { + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + circle->SetLocalCoord(); + circle->SetParent( module ); + module->GraphicalItems().PushFront( circle ); + } + + circle = new EDGE_MODULE( module ); + } + } + else + { + m_frame->SetToolID( ID_PCB_CIRCLE_BUTT, wxCURSOR_PENCIL, _( "Add graphic circle" ) ); + + DRAWSEGMENT* circle = new DRAWSEGMENT; + + while( drawSegment( S_CIRCLE, circle ) ) + { + if( circle ) + { + m_board->Add( circle ); + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( circle, UR_NEW ); + } + + circle = new DRAWSEGMENT; + } + } + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; } int DRAWING_TOOL::DrawArc( TOOL_EVENT& aEvent ) { - bool clockwise = true; // drawing direction of the arc - double startAngle = 0.0f; // angle of the first arc line - VECTOR2I cursorPos = m_controls->GetCursorPosition(); - - DRAWSEGMENT* arc = NULL; - DRAWSEGMENT helperLine; - helperLine.SetShape( S_SEGMENT ); - helperLine.SetLayer( Dwgs_User ); - helperLine.SetWidth( 1 ); - - // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); - m_view->Add( &preview ); - - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); - m_controls->ShowCursor( true ); - m_controls->SetSnapping( true ); - - Activate(); - m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); - - enum ARC_STEPS + if( m_editModules ) { - SET_ORIGIN = 0, - SET_END, - SET_ANGLE, - FINISHED - }; - int step = SET_ORIGIN; + m_frame->SetToolID( ID_MODEDIT_ARC_TOOL, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); - // Main loop: keep receiving events - while( OPT_TOOL_EVENT evt = Wait() ) - { - cursorPos = m_controls->GetCursorPosition(); + MODULE* module = m_board->m_Modules; + EDGE_MODULE* arc = new EDGE_MODULE( module ); - if( evt->IsCancel() ) + while( drawArc( reinterpret_cast( arc ) ) ) { - if( step != SET_ORIGIN ) // start from the beginning + if( arc ) { - preview.Clear(); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - - delete arc; - step = SET_ORIGIN; - } - else - break; - } - - else if( evt->IsKeyPressed() && step != SET_ORIGIN ) - { - int width = arc->GetWidth(); - - // Modify the new item width - if( evt->KeyCode() == '-' && width > WIDTH_STEP ) - arc->SetWidth( width - WIDTH_STEP ); - else if( evt->KeyCode() == '=' ) - arc->SetWidth( width + WIDTH_STEP ); - else if( evt->KeyCode() == '/' ) - { - if( clockwise ) - arc->SetAngle( arc->GetAngle() - 3600.0 ); - else - arc->SetAngle( arc->GetAngle() + 3600.0 ); - - clockwise = !clockwise; + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + arc->SetLocalCoord(); + arc->SetParent( module ); + module->GraphicalItems().PushFront( arc ); } - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - - else if( evt->IsClick( BUT_LEFT ) ) - { - switch( step ) - { - case SET_ORIGIN: - { - LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer; - - if( IsCopperLayer( layer ) ) - { - DisplayInfoMessage( NULL, _( "Graphic not allowed on Copper layers" ) ); - --step; - } - else - { - // Init the new item attributes - arc = new DRAWSEGMENT( m_board ); - arc->SetShape( S_ARC ); - arc->SetAngle( 0.0 ); - arc->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); - arc->SetCenter( wxPoint( cursorPos.x, cursorPos.y ) ); - arc->SetLayer( layer ); - - helperLine.SetStart( arc->GetCenter() ); - helperLine.SetEnd( arc->GetCenter() ); - - preview.Add( arc ); - preview.Add( &helperLine ); - - m_controls->SetAutoPan( true ); - } - } - break; - - case SET_END: - { - if( wxPoint( cursorPos.x, cursorPos.y ) != arc->GetCenter() ) - { - VECTOR2D startLine( arc->GetArcStart() - arc->GetCenter() ); - startAngle = startLine.Angle(); - arc->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) ); - } - else - --step; // one another chance to draw a proper arc - - } - break; - - case SET_ANGLE: - { - if( wxPoint( cursorPos.x, cursorPos.y ) != arc->GetArcStart() ) - { - assert( arc->GetAngle() != 0 ); - assert( arc->GetArcStart() != arc->GetArcEnd() ); - assert( arc->GetWidth() > 0 ); - - m_view->Add( arc ); - m_board->Add( arc ); - arc->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - - m_frame->OnModify(); - m_frame->SaveCopyInUndoList( arc, UR_NEW ); - - preview.Remove( arc ); - preview.Remove( &helperLine ); - } - else - --step; // one another chance to draw a proper arc - } - break; - } - - if( ++step == FINISHED ) - { - step = SET_ORIGIN; - m_controls->SetAutoPan( false ); - } - } - - else if( evt->IsMotion() ) - { - switch( step ) - { - case SET_END: - helperLine.SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); - arc->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) ); - break; - - case SET_ANGLE: - { - VECTOR2D endLine( wxPoint( cursorPos.x, cursorPos.y ) - arc->GetCenter() ); - double newAngle = RAD2DECIDEG( endLine.Angle() - startAngle ); - - // Adjust the new angle to (counter)clockwise setting - if( clockwise && newAngle < 0.0 ) - newAngle += 3600.0; - else if( !clockwise && newAngle > 0.0 ) - newAngle -= 3600.0; - - arc->SetAngle( newAngle ); - } - break; - } - - // Show a preview of the item - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + arc = new EDGE_MODULE( module ); } } + else + { + m_frame->SetToolID( ID_PCB_ARC_BUTT, wxCURSOR_PENCIL, _( "Add graphic arc" ) ); - m_controls->ShowCursor( false ); - m_controls->SetSnapping( false ); - m_controls->SetAutoPan( false ); - m_view->Remove( &preview ); + DRAWSEGMENT* arc = new DRAWSEGMENT; + + while( drawArc( arc ) ) + { + if( arc ) + { + m_board->Add( arc ); + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( arc, UR_NEW ); + } + + arc = new DRAWSEGMENT; + } + } setTransitions(); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); @@ -281,106 +235,10 @@ int DRAWING_TOOL::DrawArc( TOOL_EVENT& aEvent ) int DRAWING_TOOL::PlaceText( TOOL_EVENT& aEvent ) { - TEXTE_PCB* text = NULL; - - // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); - m_view->Add( &preview ); - - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); - m_controls->ShowCursor( true ); - m_controls->SetSnapping( true ); - m_controls->SetAutoPan( true ); - - Activate(); - m_frame->SetToolID( ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); - - // Main loop: keep receiving events - while( OPT_TOOL_EVENT evt = Wait() ) - { - VECTOR2I cursorPos = m_controls->GetCursorPosition(); - - if( evt->IsCancel() ) - { - if( text ) - { - // Delete the old text and have another try - m_board->Delete( text ); // it was already added by CreateTextPcb() - text = NULL; - - preview.Clear(); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - m_controls->ShowCursor( true ); - } - else - break; - } - - else if( text && evt->Category() == TC_COMMAND ) - { - if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) - { - text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) - { - text->Flip( text->GetPosition() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - } - - else if( evt->IsClick( BUT_LEFT ) ) - { - if( !text ) - { - // Init the new item attributes - text = m_frame->CreateTextePcb( NULL ); - - if( text == NULL ) - continue; - - m_controls->ShowCursor( false ); - preview.Add( text ); - } - else - { - assert( text->GetText().Length() > 0 ); - assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); - - text->ClearFlags(); - m_view->Add( text ); - // m_board->Add( text ); // it is already added by CreateTextePcb() - text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - - m_frame->OnModify(); - m_frame->SaveCopyInUndoList( text, UR_NEW ); - - preview.Remove( text ); - m_controls->ShowCursor( true ); - - text = NULL; - } - } - - else if( text && evt->IsMotion() ) - { - text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - - // Show a preview of the item - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - } - - m_controls->ShowCursor( false ); - m_controls->SetSnapping( false ); - m_controls->SetAutoPan( false ); - m_view->Remove( &preview ); - - setTransitions(); - m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); - - return 0; + if( m_editModules ) + return placeTextModule(); + else + return placeTextPcb(); } @@ -393,7 +251,7 @@ int DRAWING_TOOL::DrawDimension( TOOL_EVENT& aEvent ) KIGFX::VIEW_GROUP preview( m_view ); m_view->Add( &preview ); - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); @@ -414,7 +272,7 @@ int DRAWING_TOOL::DrawDimension( TOOL_EVENT& aEvent ) { VECTOR2I cursorPos = m_controls->GetCursorPosition(); - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) { if( step != SET_ORIGIN ) // start from the beginning { @@ -426,6 +284,9 @@ int DRAWING_TOOL::DrawDimension( TOOL_EVENT& aEvent ) } else break; + + if( evt->IsActivate() ) // now finish unconditionally + break; } else if( evt->IsKeyPressed() && step != SET_ORIGIN ) @@ -589,7 +450,7 @@ int DRAWING_TOOL::PlaceTarget( TOOL_EVENT& aEvent ) m_view->Add( &preview ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->SetSnapping( true ); m_controls->SetAutoPan( true ); @@ -601,7 +462,7 @@ int DRAWING_TOOL::PlaceTarget( TOOL_EVENT& aEvent ) { cursorPos = m_controls->GetCursorPosition(); - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) break; else if( evt->IsKeyPressed() ) @@ -664,7 +525,7 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) KIGFX::VIEW_GROUP preview( m_view ); m_view->Add( &preview ); - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); m_controls->SetAutoPan( true ); @@ -677,7 +538,7 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) { VECTOR2I cursorPos = m_controls->GetCursorPosition(); - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) { if( module ) { @@ -690,6 +551,9 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) } else break; + + if( evt->IsActivate() ) // now finish unconditionally + break; } else if( module && evt->Category() == TC_COMMAND ) @@ -763,82 +627,336 @@ int DRAWING_TOOL::PlaceModule( TOOL_EVENT& aEvent ) } -int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) +int DRAWING_TOOL::PlaceDXF( TOOL_EVENT& aEvent ) +{ + DIALOG_DXF_IMPORT dlg( m_frame ); + int dlgResult = dlg.ShowModal(); + + const std::list& list = dlg.GetImportedItems(); + MODULE* module = m_board->m_Modules; + + if( dlgResult != wxID_OK || module == NULL || list.empty() ) + { + setTransitions(); + + return 0; + } + + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + VECTOR2I delta = cursorPos - (*list.begin())->GetPosition(); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + + // Build the undo list & add items to the current view + std::list::const_iterator it, itEnd; + for( it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) + { + BOARD_ITEM* item = *it; + BOARD_ITEM* converted = NULL; + + // Modules use different types for the same things, + // so we need to convert imported items to appropriate classes. + switch( item->Type() ) + { + case PCB_LINE_T: + { + if( m_editModules ) + { + converted = new EDGE_MODULE( module ); + *static_cast( converted ) = *static_cast( item ); + converted->Move( wxPoint( delta.x, delta.y ) ); + preview.Add( converted ); + delete item; + } + else + { + preview.Add( item ); + } + + break; + } + + case PCB_TEXT_T: + { + if( m_editModules ) + { + converted = new TEXTE_MODULE( module ); + *static_cast( converted ) = *static_cast( item ); + converted->Move( wxPoint( delta.x, delta.y ) ); + preview.Add( converted ); + delete item; + } + else + { + preview.Add( item ); + } + break; + } + + default: + assert( false ); // there is a type that is currently not handled here + break; + } + } + + BOARD_ITEM* firstItem = static_cast( *preview.Begin() ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + + Activate(); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsMotion() ) + { + delta = cursorPos - firstItem->GetPosition(); + + for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) + static_cast( *it )->Move( wxPoint( delta.x, delta.y ) ); + + preview.ViewUpdate(); + } + + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) + static_cast( *it )->Rotate( wxPoint( cursorPos.x, cursorPos.y ), + m_frame->GetRotationAngle() ); + + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) + static_cast( *it )->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); + + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + preview.FreeItems(); + break; + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + // Place the drawing + + if( m_editModules ) + { + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + module->SetLastEditTime(); + + for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) + { + BOARD_ITEM* item = static_cast( *it ); + module->Add( item ); + + switch( item->Type() ) + { + case PCB_MODULE_TEXT_T: + static_cast( item )->SetLocalCoord(); + break; + + case PCB_MODULE_EDGE_T: + static_cast( item )->SetLocalCoord(); + break; + + default: + assert( false ); + break; + } + + m_view->Add( item ); + } + } + else + { + PICKED_ITEMS_LIST picklist; + + for( KIGFX::VIEW_GROUP::iter it = preview.Begin(), end = preview.End(); it != end; ++it ) + { + BOARD_ITEM* item = static_cast( *it ); + m_board->Add( item ); + + ITEM_PICKER itemWrapper( item, UR_NEW ); + picklist.PushItem( itemWrapper ); + + m_view->Add( item ); + } + + m_frame->SaveCopyInUndoList( picklist, UR_NEW ); + } + + m_frame->OnModify(); + + break; + } + } + + preview.Clear(); + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + + return 0; +} + + +int DRAWING_TOOL::SetAnchor( TOOL_EVENT& aEvent ) +{ + assert( m_editModules ); + + Activate(); + m_frame->SetToolID( ID_MODEDIT_ANCHOR_TOOL, wxCURSOR_PENCIL, + _( "Place the footprint anchor" ) ); + + KIGFX::VIEW_CONTROLS* controls = getViewControls(); + controls->ShowCursor( true ); + controls->SetSnapping( true ); + controls->SetAutoPan( true ); + + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsClick( BUT_LEFT ) ) + { + MODULE* module = m_board->m_Modules; + + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + + // set the new relative internal local coordinates of footprint items + VECTOR2I cursorPos = controls->GetCursorPosition(); + wxPoint moveVector = module->GetPosition() - wxPoint( cursorPos.x, cursorPos.y ); + module->MoveAnchorPosition( moveVector ); + + module->ViewUpdate(); + + // Usually, we do not need to change twice the anchor position, + // so deselect the active tool + break; + } + + else if( evt->IsCancel() || evt->IsActivate() ) + break; + } + + controls->SetAutoPan( false ); + controls->SetSnapping( false ); + controls->ShowCursor( false ); + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + +bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, + boost::optional aStartingPoint ) { // Only two shapes are currently supported assert( aShape == S_SEGMENT || aShape == S_CIRCLE ); - DRAWSEGMENT* graphic = NULL; DRAWSEGMENT line45; // Add a VIEW_GROUP that serves as a preview for the new item KIGFX::VIEW_GROUP preview( m_view ); m_view->Add( &preview ); - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); Activate(); bool direction45 = false; // 45 degrees only mode - int addedSegments = 0; + bool started = false; + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + if( aStartingPoint ) + { + LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer; + + // Init the new item attributes + aGraphic->SetShape( (STROKE_T) aShape ); + aGraphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); + aGraphic->SetStart( wxPoint( aStartingPoint->x, aStartingPoint->y ) ); + aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetLayer( layer ); + + if( aShape == S_SEGMENT ) + line45 = *aGraphic; // used only for direction 45 mode with lines + + preview.Add( aGraphic ); + m_controls->SetAutoPan( true ); + + started = true; + } // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { bool updatePreview = false; // should preview be updated - VECTOR2I cursorPos = m_controls->GetCursorPosition(); + cursorPos = m_controls->GetCursorPosition(); // Enable 45 degrees lines only mode by holding control - if( direction45 != evt->Modifier( MD_CTRL ) && graphic && aShape == S_SEGMENT ) + if( direction45 != evt->Modifier( MD_CTRL ) && started && aShape == S_SEGMENT ) { direction45 = evt->Modifier( MD_CTRL ); if( direction45 ) { preview.Add( &line45 ); - make45DegLine( graphic, &line45 ); + make45DegLine( aGraphic, &line45 ); } else { preview.Remove( &line45 ); - graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); } updatePreview = true; } - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) { - if( !graphic ) - break; - preview.Clear(); updatePreview = true; - - delete graphic; - graphic = NULL; - - m_controls->SetAutoPan( false ); + delete aGraphic; + aGraphic = NULL; + break; } - else if( graphic && evt->IsKeyPressed() ) + else if( evt->IsKeyPressed() ) { - int width = graphic->GetWidth(); + int width = aGraphic->GetWidth(); // Modify the new item width - if( evt->KeyCode() == '-' && width > WIDTH_STEP ) - graphic->SetWidth( width - WIDTH_STEP ); + if( evt->KeyCode() == '-' && width > WIDTH_STEP ) // TODO change it to TOOL_ACTIONs + aGraphic->SetWidth( width - WIDTH_STEP ); else if( evt->KeyCode() == '=' ) - graphic->SetWidth( width + WIDTH_STEP ); + aGraphic->SetWidth( width + WIDTH_STEP ); updatePreview = true; } else if( evt->IsClick( BUT_LEFT ) ) { - if( !graphic ) + if( !started ) { LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer; @@ -849,78 +967,49 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) else { // Init the new item attributes - graphic = new DRAWSEGMENT( m_board ); - graphic->SetShape( (STROKE_T) aShape ); - graphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); - graphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) ); - graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); - graphic->SetLayer( layer ); + aGraphic->SetShape( (STROKE_T) aShape ); + aGraphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); + aGraphic->SetStart( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetLayer( layer ); if( aShape == S_SEGMENT ) - { - line45 = *graphic; // used only for direction 45 mode with lines - line45.SetLayer( layer ); - } + line45 = *aGraphic; // used only for direction 45 mode with lines - preview.Add( graphic ); + preview.Add( aGraphic ); m_controls->SetAutoPan( true ); + + started = true; } } else { - if( graphic->GetEnd() != graphic->GetStart() ) + if( aGraphic->GetEnd() != aGraphic->GetStart() ) { - assert( graphic->GetLength() > 0 ); - assert( graphic->GetWidth() > 0 ); + assert( aGraphic->GetLength() > 0 ); + assert( aGraphic->GetWidth() > 0 ); - m_view->Add( graphic ); - m_board->Add( graphic ); - graphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - - m_frame->OnModify(); - m_frame->SaveCopyInUndoList( graphic, UR_NEW ); - - preview.Remove( graphic ); - ++addedSegments; - - if( aContinous ) - { - graphic = new DRAWSEGMENT( *graphic ); - - // Start the new line in the same spot where the previous one has ended - graphic->SetStart( graphic->GetEnd() ); - - if( direction45 ) - graphic->SetEnd( line45.GetEnd() ); - - preview.Add( graphic ); - } - else // start a new graphic - { - addedSegments = 0; - m_controls->SetAutoPan( false ); - graphic = NULL; - } + m_view->Add( aGraphic ); + aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } - else if( addedSegments > 0 ) // User has clicked twice in the same spot + else // User has clicked twice in the same spot { // a clear sign that the current drawing is finished - preview.Clear(); // but only if at least one graphic was created - // otherwise - force user to draw more or cancel - delete graphic; - graphic = NULL; - - m_controls->SetAutoPan( false ); + delete aGraphic; // but only if at least one graphic was created + aGraphic = NULL; // otherwise - force user to draw more or cancel } + + preview.Clear(); + break; } } - else if( graphic && evt->IsMotion() ) + else if( evt->IsMotion() ) { // 45 degree lines if( direction45 && aShape == S_SEGMENT ) - make45DegLine( graphic, &line45 ); + make45DegLine( aGraphic, &line45 ); else - graphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); updatePreview = true; } @@ -934,10 +1023,182 @@ int DRAWING_TOOL::drawSegment( int aShape, bool aContinous ) m_controls->SetAutoPan( false ); m_view->Remove( &preview ); - setTransitions(); - m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + return started; +} - return 0; + +bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) +{ + bool clockwise = true; // drawing direction of the arc + double startAngle = 0.0f; // angle of the first arc line + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + DRAWSEGMENT helperLine; + helperLine.SetShape( S_SEGMENT ); + helperLine.SetLayer( Dwgs_User ); + helperLine.SetWidth( 1 ); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + + Activate(); + + enum ARC_STEPS + { + SET_ORIGIN = 0, + SET_END, + SET_ANGLE, + FINISHED + }; + int step = SET_ORIGIN; + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + delete aGraphic; + aGraphic = NULL; + break; + } + + else if( evt->IsKeyPressed() && step != SET_ORIGIN ) + { + int width = aGraphic->GetWidth(); + + // Modify the new item width + if( evt->KeyCode() == '-' && width > WIDTH_STEP ) // TODO convert to tool actions + aGraphic->SetWidth( width - WIDTH_STEP ); + else if( evt->KeyCode() == '=' ) + aGraphic->SetWidth( width + WIDTH_STEP ); + else if( evt->KeyCode() == '/' ) + { + if( clockwise ) + aGraphic->SetAngle( aGraphic->GetAngle() - 3600.0 ); + else + aGraphic->SetAngle( aGraphic->GetAngle() + 3600.0 ); + + clockwise = !clockwise; + } + + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + switch( step ) + { + case SET_ORIGIN: + { + LAYER_ID layer = m_frame->GetScreen()->m_Active_Layer; + + if( IsCopperLayer( layer ) ) + { + DisplayInfoMessage( NULL, _( "Graphic not allowed on Copper layers" ) ); + --step; + } + else + { + // Init the new item attributes + aGraphic->SetShape( S_ARC ); + aGraphic->SetAngle( 0.0 ); + aGraphic->SetWidth( m_board->GetDesignSettings().m_DrawSegmentWidth ); + aGraphic->SetCenter( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetLayer( layer ); + + helperLine.SetStart( aGraphic->GetCenter() ); + helperLine.SetEnd( aGraphic->GetCenter() ); + + preview.Add( aGraphic ); + preview.Add( &helperLine ); + + m_controls->SetAutoPan( true ); + } + } + break; + + case SET_END: + { + if( wxPoint( cursorPos.x, cursorPos.y ) != aGraphic->GetCenter() ) + { + VECTOR2D startLine( aGraphic->GetArcStart() - aGraphic->GetCenter() ); + startAngle = startLine.Angle(); + aGraphic->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) ); + } + else + --step; // one another chance to draw a proper arc + } + break; + + case SET_ANGLE: + { + if( wxPoint( cursorPos.x, cursorPos.y ) != aGraphic->GetArcStart() ) + { + assert( aGraphic->GetAngle() != 0 ); + assert( aGraphic->GetArcStart() != aGraphic->GetArcEnd() ); + assert( aGraphic->GetWidth() > 0 ); + + m_view->Add( aGraphic ); + aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + preview.Remove( aGraphic ); + preview.Remove( &helperLine ); + } + else + --step; // one another chance to draw a proper arc + } + break; + } + + if( ++step == FINISHED ) + break; + } + + else if( evt->IsMotion() ) + { + switch( step ) + { + case SET_END: + helperLine.SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); + aGraphic->SetArcStart( wxPoint( cursorPos.x, cursorPos.y ) ); + break; + + case SET_ANGLE: + { + VECTOR2D endLine( wxPoint( cursorPos.x, cursorPos.y ) - aGraphic->GetCenter() ); + double newAngle = RAD2DECIDEG( endLine.Angle() - startAngle ); + + // Adjust the new angle to (counter)clockwise setting + if( clockwise && newAngle < 0.0 ) + newAngle += 3600.0; + else if( !clockwise && newAngle > 0.0 ) + newAngle -= 3600.0; + + aGraphic->SetAngle( newAngle ); + } + break; + } + + // Show a preview of the item + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + return ( step > SET_ORIGIN ); } @@ -951,7 +1212,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) KIGFX::VIEW_GROUP preview( m_view ); m_view->Add( &preview ); - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); @@ -987,7 +1248,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) updatePreview = true; } - if( evt->IsCancel() ) + if( evt->IsCancel() || evt->IsActivate() ) { if( numPoints > 0 ) // cancel the current zone { @@ -1008,6 +1269,9 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) } else // there is no zone currently drawn - just stop the tool break; + + if( evt->IsActivate() ) // now finish unconditionally + break; } else if( evt->IsClick( BUT_LEFT ) ) @@ -1027,7 +1291,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) m_view->Add( zone ); if( !aKeepout ) - m_frame->Fill_Zone( zone ); + static_cast( m_frame )->Fill_Zone( zone ); zone->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); @@ -1085,7 +1349,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) // Apply the selected settings zone = new ZONE_CONTAINER( m_board ); zoneInfo.ExportSetting( *zone ); - m_frame->SetTopLayer( zoneInfo.m_CurrentZone_Layer ); + m_frame->GetGalCanvas()->SetTopLayer( zoneInfo.m_CurrentZone_Layer ); // Add the first point zone->Outline()->Start( zoneInfo.m_CurrentZone_Layer, @@ -1147,6 +1411,234 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) } +int DRAWING_TOOL::placeTextModule() +{ + TEXTE_MODULE* text = new TEXTE_MODULE( NULL ); + const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings(); + MODULE* module = m_board->m_Modules; + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + m_controls->SetAutoPan( true ); + + Activate(); + m_frame->SetToolID( ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); + bool placing = false; + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + preview.ViewUpdate(); + m_controls->ShowCursor( true ); + + if( !placing || evt->IsActivate() ) + { + delete text; + break; + } + else + { + placing = false; // start from the beginning + } + } + + else if( text && evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + text->Flip( text->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + if( !placing ) + { + text->SetSize( dsnSettings.m_ModuleTextSize ); + text->SetThickness( dsnSettings.m_ModuleTextWidth ); + text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + DialogEditModuleText textDialog( m_frame, text, NULL ); + placing = textDialog.ShowModal() && ( text->GetText().Length() > 0 ); + + if( !placing ) + continue; + + m_controls->ShowCursor( false ); + text->SetParent( module ); // it has to set after the settings dialog + // otherwise the dialog stores it in undo buffer + preview.Add( text ); + } + else + { + assert( text->GetText().Length() > 0 ); + assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); + + text->SetLocalCoord(); + text->ClearFlags(); + + // Module has to be saved before any modification is made + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + module->GraphicalItems().PushFront( text ); + + m_view->Add( text ); + text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_frame->OnModify(); + + preview.Remove( text ); + m_controls->ShowCursor( true ); + + text = new TEXTE_MODULE( NULL ); + placing = false; + } + } + + else if( text && evt->IsMotion() ) + { + text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Show a preview of the item + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + +int DRAWING_TOOL::placeTextPcb() +{ + TEXTE_PCB* text = NULL; + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + m_controls->SetAutoPan( true ); + + Activate(); + m_frame->SetToolID( ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsCancel() || evt->IsActivate() ) + { + if( text ) + { + // Delete the old text and have another try + m_board->Delete( text ); // it was already added by CreateTextPcb() + text = NULL; + + preview.Clear(); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_controls->ShowCursor( true ); + } + else + break; + + if( evt->IsActivate() ) // now finish unconditionally + break; + } + + else if( text && evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + text->Flip( text->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + if( !text ) + { + // Init the new item attributes + text = static_cast( m_frame )->CreateTextePcb( NULL ); + + if( text == NULL ) + continue; + + m_controls->ShowCursor( false ); + preview.Add( text ); + } + else + { + assert( text->GetText().Length() > 0 ); + assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); + + text->ClearFlags(); + m_view->Add( text ); + // m_board->Add( text ); // it is already added by CreateTextePcb() + text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( text, UR_NEW ); + + preview.Remove( text ); + m_controls->ShowCursor( true ); + + text = NULL; + } + } + + else if( text && evt->IsMotion() ) + { + text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Show a preview of the item + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const { VECTOR2I cursorPos = m_controls->GetCursorPosition(); @@ -1171,13 +1663,15 @@ void DRAWING_TOOL::make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) void DRAWING_TOOL::setTransitions() { - Go( &DRAWING_TOOL::DrawLine, COMMON_ACTIONS::drawLine.MakeEvent() ); - Go( &DRAWING_TOOL::DrawCircle, COMMON_ACTIONS::drawCircle.MakeEvent() ); - Go( &DRAWING_TOOL::DrawArc, COMMON_ACTIONS::drawArc.MakeEvent() ); - Go( &DRAWING_TOOL::DrawDimension, COMMON_ACTIONS::drawDimension.MakeEvent() ); - Go( &DRAWING_TOOL::DrawZone, COMMON_ACTIONS::drawZone.MakeEvent() ); - Go( &DRAWING_TOOL::DrawKeepout, COMMON_ACTIONS::drawKeepout.MakeEvent() ); - Go( &DRAWING_TOOL::PlaceText, COMMON_ACTIONS::placeText.MakeEvent() ); - Go( &DRAWING_TOOL::PlaceTarget, COMMON_ACTIONS::placeTarget.MakeEvent() ); - Go( &DRAWING_TOOL::PlaceModule, COMMON_ACTIONS::placeModule.MakeEvent() ); + Go( &DRAWING_TOOL::DrawLine, COMMON_ACTIONS::drawLine.MakeEvent() ); + Go( &DRAWING_TOOL::DrawCircle, COMMON_ACTIONS::drawCircle.MakeEvent() ); + Go( &DRAWING_TOOL::DrawArc, COMMON_ACTIONS::drawArc.MakeEvent() ); + Go( &DRAWING_TOOL::DrawDimension, COMMON_ACTIONS::drawDimension.MakeEvent() ); + Go( &DRAWING_TOOL::DrawZone, COMMON_ACTIONS::drawZone.MakeEvent() ); + Go( &DRAWING_TOOL::DrawKeepout, COMMON_ACTIONS::drawKeepout.MakeEvent() ); + Go( &DRAWING_TOOL::PlaceText, COMMON_ACTIONS::placeText.MakeEvent() ); + Go( &DRAWING_TOOL::PlaceTarget, COMMON_ACTIONS::placeTarget.MakeEvent() ); + Go( &DRAWING_TOOL::PlaceModule, COMMON_ACTIONS::placeModule.MakeEvent() ); + Go( &DRAWING_TOOL::PlaceDXF, COMMON_ACTIONS::placeDXF.MakeEvent() ); + Go( &DRAWING_TOOL::SetAnchor, COMMON_ACTIONS::setAnchor.MakeEvent() ); } diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index e05a3a59ce..178d751a8f 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -26,6 +26,7 @@ #define __DRAWING_TOOL_H #include +#include namespace KIGFX { @@ -76,9 +77,9 @@ public: int DrawArc( TOOL_EVENT& aEvent ); /** - * Function DrawText() + * Function PlaceText() * Displays a dialog that allows to input text and its settings and then lets the user decide - * where to place the text. + * where to place the text in editor. */ int PlaceText( TOOL_EVENT& aEvent ); @@ -116,25 +117,75 @@ public: /** * Function PlaceModule() - * Displays a dialog to selected a module to be added and then allows user to set its position. + * Displays a dialog to select a module to be added and allows the user to set its position. */ int PlaceModule( TOOL_EVENT& aEvent ); + /** + * Function PlaceDXF() + * Places a drawing imported from a DXF file in module editor. + */ + int PlaceDXF( TOOL_EVENT& aEvent ); + + /** + * Function SetAnchor() + * Places the footprint anchor (only in module editor). + */ + int SetAnchor( TOOL_EVENT& aEvent ); + + /** + * Function EditModules() + * Toggles edit module mode. When enabled, one may select parts of modules individually + * (graphics, pads, etc.), so they can be modified. + * @param aEnabled decides if the mode should be enabled. + */ + void EditModules( bool aEnabled ) + { + m_editModules = aEnabled; + } + private: ///> Starts drawing a selected shape (i.e. DRAWSEGMENT). ///> @param aShape is the type of created shape (@see STROKE_T). - ///> @param aContinous decides if there is only one or multiple shapes to draw. - int drawSegment( int aShape, bool aContinous ); + ///> @param aGraphic is an object that is going to be used by the tool for drawing. It has to + ///> be already created. The tool deletes the object if it is not added to a BOARD. + ///> @return False if the tool was cancelled before the origin was set or origin and end are + ///> the same point. + bool drawSegment( int aShape, DRAWSEGMENT*& aGraphic, + boost::optional aStartingPoint = boost::none ); + + ///> Starts drawing an arc. + ///> @param aGraphic is an object that is going to be used by the tool for drawing. It has to + ///> be already created. The tool deletes the object if it is not added to a BOARD. + ///> @return False if the tool was cancelled before the origin was set or origin and end are + ///> the same point. + bool drawArc( DRAWSEGMENT*& aGraphic ); ///> Draws a polygon, that is added as a zone or a keepout area. ///> @param aKeepout decides if the drawn polygon is a zone or a keepout area. int drawZone( bool aKeepout ); - ///> Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin - ///> stays the same, the end of the aSegment is modified according to the - ///> current cursor position. - ///> @param aSegment is the segment that is currently drawn. - ///> @param aHelper is a helper line that shows the next possible segment. + /** + * Function placeTextModule() + * Displays a dialog that allows to input text and its settings and then lets the user decide + * where to place the text in module . + */ + int placeTextModule(); + + /** + * Function placeTextPcb() + * Displays a dialog that allows to input text and its settings and then lets the user decide + * where to place the text in board editor. + */ + int placeTextPcb(); + + /** + * Function make45DegLine() + * Forces a DRAWSEGMENT to be drawn at multiple of 45 degrees. The origin stays the same, + * the end of the aSegment is modified according to the current cursor position. + * @param aSegment is the segment that is currently drawn. + * @param aHelper is a helper line that shows the next possible segment. + */ void make45DegLine( DRAWSEGMENT* aSegment, DRAWSEGMENT* aHelper ) const; ///> Sets up handlers for various events. @@ -145,6 +196,9 @@ private: BOARD* m_board; PCB_EDIT_FRAME* m_frame; + /// Edit module mode flag + bool m_editModules; + // How does line width change after one -/+ key press. static const int WIDTH_STEP = 100000; }; diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index db08a607a5..f174753c6d 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -24,10 +24,13 @@ #include #include +#include #include #include + #include #include +#include #include #include @@ -40,7 +43,7 @@ #include "edit_tool.h" EDIT_TOOL::EDIT_TOOL() : - TOOL_INTERACTIVE( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ) + TOOL_INTERACTIVE( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ), m_editModules( false ) { } @@ -57,11 +60,14 @@ bool EDIT_TOOL::Init() } // Add context menu entries that are displayed when selection tool is active - m_selectionTool->AddMenuItem( COMMON_ACTIONS::editActivate ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::remove ); - m_selectionTool->AddMenuItem( COMMON_ACTIONS::properties ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::editActivate, SELECTION_CONDITIONS::NotEmpty ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::rotate, SELECTION_CONDITIONS::NotEmpty ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::flip, SELECTION_CONDITIONS::NotEmpty ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::remove, SELECTION_CONDITIONS::NotEmpty ); + m_selectionTool->AddMenuItem( COMMON_ACTIONS::properties, SELECTION_CONDITIONS::NotEmpty ); + + m_offset.x = 0; + m_offset.y = 0; setTransitions(); @@ -71,7 +77,7 @@ bool EDIT_TOOL::Init() int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + const SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); @@ -93,7 +99,7 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; KIGFX::VIEW_CONTROLS* controls = getViewControls(); - PCB_EDIT_FRAME* editFrame = getEditFrame(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); controls->ShowCursor( true ); controls->SetSnapping( true ); controls->SetAutoPan( true ); @@ -153,6 +159,9 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) } else // Prepare to start dragging { + if( m_selectionTool->CheckLock() ) + break; + // Save items, so changes can be undone editFrame->OnModify(); editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); @@ -167,16 +176,18 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) } else { + const VECTOR2D& dragOrigin = getView()->GetGAL()->GetGridPoint( evt->DragOrigin() ); + // Update dragging offset (distance between cursor and the first dragged item) m_offset = static_cast( selection.items.GetPickedItem( 0 ) )->GetPosition() - - wxPoint( m_cursor.x, m_cursor.y ); + wxPoint( dragOrigin.x, dragOrigin.y ); } m_dragging = true; } selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate ); + m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } else if( evt->IsMouseUp( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) @@ -184,12 +195,14 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) } m_dragging = false; + m_offset.x = 0; + m_offset.y = 0; if( restore ) { // Modifications have to be rollbacked, so restore the previous state of items wxCommandEvent dummy; - editFrame->GetBoardFromUndoList( dummy ); + editFrame->RestoreCopyFromUndoList( dummy ); } else { @@ -198,7 +211,7 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) } if( unselect ) - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); RN_DATA* ratsnest = getModel()->GetRatsnest(); ratsnest->ClearSimple(); @@ -216,11 +229,8 @@ int EDIT_TOOL::Main( TOOL_EVENT& aEvent ) int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); - PCB_EDIT_FRAME* editFrame = getEditFrame(); - - // Shall the selection be cleared at the end? - bool unselect = selection.Empty(); + const SELECTION& selection = m_selectionTool->GetSelection(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); if( !makeSelection( selection ) ) { @@ -238,9 +248,11 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) // Check if user wants to edit pad or module properties if( item->Type() == PCB_MODULE_T ) { + VECTOR2D cursor = getViewControls()->GetCursorPosition(); + for( D_PAD* pad = static_cast( item )->Pads(); pad; pad = pad->Next() ) { - if( pad->ViewBBox().Contains( getViewControls()->GetCursorPosition() ) ) + if( pad->ViewBBox().Contains( cursor ) ) { // Turns out that user wants to edit a pad properties item = pad; @@ -252,7 +264,7 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) std::vector& undoList = editFrame->GetScreen()->m_UndoList.m_CommandsList; // Some of properties dialogs alter pointers, so we should deselect them - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); STATUS_FLAGS flags = item->GetFlags(); item->ClearFlags(); @@ -270,16 +282,14 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) updateRatsnest( true ); getModel()->GetRatsnest()->Recalculate(); + item->ViewUpdate(); - m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate ); + m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); } item->SetFlags( flags ); } - if( unselect ) - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); - setTransitions(); return 0; @@ -288,13 +298,13 @@ int EDIT_TOOL::Properties( TOOL_EVENT& aEvent ) int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); - PCB_EDIT_FRAME* editFrame = getEditFrame(); + const SELECTION& selection = m_selectionTool->GetSelection(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); - if( !makeSelection( selection ) ) + if( !makeSelection( selection ) || m_selectionTool->CheckLock() ) { setTransitions(); @@ -331,9 +341,9 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) getModel()->GetRatsnest()->Recalculate(); if( unselect ) - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate ); + m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); setTransitions(); return 0; @@ -342,13 +352,13 @@ int EDIT_TOOL::Rotate( TOOL_EVENT& aEvent ) int EDIT_TOOL::Flip( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); - PCB_EDIT_FRAME* editFrame = getEditFrame(); + const SELECTION& selection = m_selectionTool->GetSelection(); + PCB_BASE_FRAME* editFrame = getEditFrame(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); - if( !makeSelection( selection ) ) + if( !makeSelection( selection ) || m_selectionTool->CheckLock() ) { setTransitions(); @@ -385,9 +395,9 @@ int EDIT_TOOL::Flip( TOOL_EVENT& aEvent ) getModel()->GetRatsnest()->Recalculate(); if( unselect ) - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate ); + m_toolMgr->RunAction( COMMON_ACTIONS::pointEditorUpdate, true ); setTransitions(); return 0; @@ -396,9 +406,9 @@ int EDIT_TOOL::Flip( TOOL_EVENT& aEvent ) int EDIT_TOOL::Remove( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + const SELECTION& selection = m_selectionTool->GetSelection(); - if( !makeSelection( selection ) ) + if( !makeSelection( selection ) || m_selectionTool->CheckLock() ) { setTransitions(); @@ -407,10 +417,10 @@ int EDIT_TOOL::Remove( TOOL_EVENT& aEvent ) // Get a copy of the selected items set PICKED_ITEMS_LIST selectedItems = selection.items; - PCB_EDIT_FRAME* editFrame = getEditFrame(); + PCB_BASE_FRAME* editFrame = getEditFrame(); // As we are about to remove items, they have to be removed from the selection first - m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); // Save them for( unsigned int i = 0; i < selectedItems.GetCount(); ++i ) @@ -451,11 +461,43 @@ void EDIT_TOOL::remove( BOARD_ITEM* aItem ) } break; - // These are not supposed to be removed - case PCB_PAD_T: + // Default removal procedure case PCB_MODULE_TEXT_T: + { + if( m_editModules ) + { + TEXTE_MODULE* text = static_cast( aItem ); + + switch( text->GetType() ) + { + case TEXTE_MODULE::TEXT_is_REFERENCE: + DisplayError( getEditFrame(), _( "Cannot delete REFERENCE!" ) ); + return; + + case TEXTE_MODULE::TEXT_is_VALUE: + DisplayError( getEditFrame(), _( "Cannot delete VALUE!" ) ); + return; + + default: // suppress warnings + break; + } + } + } + /* no break */ + + case PCB_PAD_T: case PCB_MODULE_EDGE_T: + if( m_editModules ) + { + MODULE* module = static_cast( aItem->GetParent() ); + module->SetLastEditTime(); + + board->m_Status_Pcb = 0; // it is done in the legacy view + aItem->DeleteStructure(); + } + return; + break; case PCB_LINE_T: // a segment not on copper layers case PCB_TEXT_T: // a text on a layer @@ -491,7 +533,7 @@ void EDIT_TOOL::setTransitions() void EDIT_TOOL::updateRatsnest( bool aRedraw ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + const SELECTION& selection = m_selectionTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); ratsnest->ClearSimple(); @@ -507,7 +549,7 @@ void EDIT_TOOL::updateRatsnest( bool aRedraw ) } -wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection ) +wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection ) { if( aSelection.Size() == 1 ) { @@ -525,10 +567,10 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION_TOOL::SELECTION& aSelec } -bool EDIT_TOOL::makeSelection( const SELECTION_TOOL::SELECTION& aSelection ) +bool EDIT_TOOL::makeSelection( const SELECTION& aSelection ) { if( aSelection.Empty() ) // Try to find an item that could be modified - m_toolMgr->RunAction( COMMON_ACTIONS::selectionSingle ); + m_toolMgr->RunAction( COMMON_ACTIONS::selectionSingle, true ); return !aSelection.Empty(); } @@ -544,6 +586,7 @@ void EDIT_TOOL::processChanges( const PICKED_ITEMS_LIST* aList ) switch( operation ) { case UR_CHANGED: + case UR_MODEDIT: updItem->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); break; diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 207e446493..76b161ae01 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -91,6 +91,18 @@ public: */ int Remove( TOOL_EVENT& aEvent ); + /** + * Function EditModules() + * + * Toggles edit module mode. When enabled, one may select parts of modules individually + * (graphics, pads, etc.), so they can be modified. + * @param aEnabled decides if the mode should be enabled. + */ + void EditModules( bool aEnabled ) + { + m_editModules = aEnabled; + } + private: ///> Selection tool used for obtaining selected items SELECTION_TOOL* m_selectionTool; @@ -105,6 +117,9 @@ private: ///> of edit reference point). VECTOR2I m_cursor; + /// Edit module mode flag + bool m_editModules; + ///> Removes and frees a single BOARD_ITEM. void remove( BOARD_ITEM* aItem ); @@ -128,11 +143,11 @@ private: ///> Returns the right modification point (e.g. for rotation), depending on the number of ///> selected items. - wxPoint getModificationPoint( const SELECTION_TOOL::SELECTION& aSelection ); + wxPoint getModificationPoint( const SELECTION& aSelection ); ///> If there are no items currently selected, it tries to choose the item that is under ///> the cursor or displays a disambiguation menu if there are multpile items. - bool makeSelection( const SELECTION_TOOL::SELECTION& aSelection ); + bool makeSelection( const SELECTION& aSelection ); ///> Updates view with the changes in the list. void processChanges( const PICKED_ITEMS_LIST* aList ); diff --git a/pcbnew/tools/module_tools.cpp b/pcbnew/tools/module_tools.cpp new file mode 100644 index 0000000000..a03ea3adcf --- /dev/null +++ b/pcbnew/tools/module_tools.cpp @@ -0,0 +1,613 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "module_tools.h" +#include "selection_tool.h" +#include "common_actions.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +MODULE_TOOLS::MODULE_TOOLS() : + TOOL_INTERACTIVE( "pcbnew.ModuleEditor" ) +{ +} + + +void MODULE_TOOLS::Reset( RESET_REASON aReason ) +{ + // Init variables used by every drawing tool + m_view = getView(); + m_controls = getViewControls(); + m_board = getModel(); + m_frame = getEditFrame(); +} + + +bool MODULE_TOOLS::Init() +{ + // Find the selection tool, so they can cooperate + SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); + + if( !selectionTool ) + { + DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) ); + return false; + } + + selectionTool->AddMenuItem( COMMON_ACTIONS::enumeratePads ); + + setTransitions(); + + return true; +} + + +static wxString getNextPadName( MODULE* aModule ) +{ + std::set usedNumbers; + + // Create a set of used pad numbers + for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() ) + { + wxString padName = pad->GetPadName(); + int padNumber = 0; + int base = 1; + + // Trim and extract the trailing numeric part + while( padName.Len() && padName.Last() >= '0' && padName.Last() <= '9' ) + { + padNumber += ( padName.Last() - '0' ) * base; + padName.RemoveLast(); + base *= 10; + } + + usedNumbers.insert( padNumber ); + } + + int candidate = *usedNumbers.begin(); + + // Look for a gap in pad numbering + for( std::set::iterator it = usedNumbers.begin(), + itEnd = usedNumbers.end(); it != itEnd; ++it ) + { + if( *it - candidate > 1 ) + break; + + candidate = *it; + } + + return wxString::Format( wxT( "%i" ), ++candidate ); +} + + +int MODULE_TOOLS::PlacePad( TOOL_EVENT& aEvent ) +{ + m_frame->SetToolID( ID_MODEDIT_PAD_TOOL, wxCURSOR_PENCIL, _( "Add pads" ) ); + + MODULE* module = m_board->m_Modules; + assert( module ); + + D_PAD* pad = new D_PAD( module ); + m_frame->Import_Pad_Settings( pad, false ); // use the global settings for pad + + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + preview.Add( pad ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + + Activate(); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsMotion() ) + { + pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate(); + } + + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + pad->Rotate( pad->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + pad->Flip( pad->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + delete pad; + break; + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + + m_board->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view + module->SetLastEditTime(); + module->Pads().PushBack( pad ); + + pad->SetNetCode( NETINFO_LIST::UNCONNECTED ); + + // Set the relative pad position + // ( pad position for module orient, 0, and relative to the module position) + pad->SetLocalCoord(); + + /* NPTH pads take empty pad number (since they can't be connected), + * other pads get incremented from the last one edited */ + wxString padName; + + if( pad->GetAttribute() != PAD_HOLE_NOT_PLATED ) + padName = getNextPadName( module ); + + pad->SetPadName( padName ); + + // Handle the view aspect + preview.Remove( pad ); + m_view->Add( pad ); + + // Start placing next pad + pad = new D_PAD( module ); + m_frame->Import_Pad_Settings( pad, false ); + pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.Add( pad ); + } + } + + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); + + return 0; +} + + +int MODULE_TOOLS::EnumeratePads( TOOL_EVENT& aEvent ) +{ + std::list pads; + std::set allPads; + MODULE* module = m_board->m_Modules; + + GENERAL_COLLECTOR collector; + const KICAD_T types[] = { PCB_PAD_T, EOT }; + + GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide(); + guide.SetIgnoreMTextsMarkedNoShow( true ); + guide.SetIgnoreMTextsOnCopper( true ); + guide.SetIgnoreMTextsOnCmp( true ); + guide.SetIgnoreModulesVals( true ); + guide.SetIgnoreModulesRefs( true ); + + // Create a set containing all pads (to avoid double adding to a list) + for( D_PAD* p = module->Pads(); p; p = p->Next() ) + allPads.insert( p ); + + DIALOG_ENUM_PADS settingsDlg( m_frame ); + + if( settingsDlg.ShowModal() == wxID_CANCEL ) + { + setTransitions(); + + return 0; + } + + int padNumber = settingsDlg.GetStartNumber(); + wxString padPrefix = settingsDlg.GetPrefix(); + + m_frame->DisplayToolMsg( _( "Hold left mouse button and move cursor over pads to enumerate them" ) ); + + Activate(); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) + { + // Add pads to the list according to the selection order + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + collector.Empty(); + collector.Collect( m_board, types, wxPoint( cursorPos.x, cursorPos.y ), guide ); + + for( int i = 0; i < collector.GetCount(); ++i ) + { + if( collector[i]->Type() == PCB_PAD_T ) + { + D_PAD* pad = static_cast( collector[i] ); + + std::set::iterator it = allPads.find( pad ); + + // Add the pad to the list, if it was not selected previously.. + if( it != allPads.end() ) + { + allPads.erase( it ); + pads.push_back( pad ); + pad->SetSelected(); + } + + // ..or remove it from the list if it was clicked + else if( evt->IsClick( BUT_LEFT ) ) + { + allPads.insert( pad ); + pads.remove( pad ); + pad->ClearSelected(); + } + } + } + } + + else if( ( evt->IsKeyPressed() && evt->KeyCode() == WXK_RETURN ) || + evt->IsDblClick( BUT_LEFT ) ) + { + // Accept changes + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( module, UR_MODEDIT ); + + BOOST_FOREACH( D_PAD* pad, pads ) + pad->SetPadName( wxString::Format( wxT( "%s%d" ), padPrefix.c_str(), padNumber++ ) ); + + break; + } + + else if( evt->IsCancel() || evt->IsActivate() ) + { + break; + } + } + + BOOST_FOREACH( D_PAD* pad, pads ) + pad->ClearSelected(); + + m_frame->DisplayToolMsg( wxEmptyString ); + m_controls->ShowCursor( false ); + + setTransitions(); + + return 0; +} + + +int MODULE_TOOLS::CopyItems( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_toolMgr->GetTool()->GetSelection(); + + Activate(); + + m_controls->SetSnapping( true ); + m_controls->ShowCursor( true ); + m_controls->SetAutoPan( true ); + + m_frame->DisplayToolMsg( _( "Select reference point" ) ); + + bool cancelled = false; + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + while( OPT_TOOL_EVENT evt = Wait() ) + { + if( evt->IsMotion() ) + { + cursorPos = m_controls->GetCursorPosition(); + } + else if( evt->IsClick( BUT_LEFT ) ) + { + break; + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + cancelled = true; + break; + } + } + + if( !cancelled ) + { + PCB_IO io( CTL_FOR_CLIPBOARD ); + + // Create a temporary module that contains selected items to ease serialization + MODULE module( m_board ); + + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* clone = static_cast( selection.Item( i )->Clone() ); + + // Do not add reference/value - convert them to the common type + if( TEXTE_MODULE* text = dyn_cast( clone ) ) + text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); + + module.Add( clone ); + } + + // Set the new relative internal local coordinates of copied items + MODULE* editedModule = m_board->m_Modules; + wxPoint moveVector = module.GetPosition() + editedModule->GetPosition() - + wxPoint( cursorPos.x, cursorPos.y ); + module.MoveAnchorPosition( moveVector ); + + io.Format( &module, 0 ); + std::string data = io.GetStringOutput( true ); + m_toolMgr->SaveClipboard( data ); + } + + m_frame->DisplayToolMsg( wxString::Format( _( "Copied %d item(s)" ), selection.Size() ) ); + m_controls->SetSnapping( false ); + m_controls->ShowCursor( false ); + m_controls->SetAutoPan( false ); + + setTransitions(); + + return 0; +} + + +int MODULE_TOOLS::PasteItems( TOOL_EVENT& aEvent ) +{ + // Parse clipboard + PCB_IO io( CTL_FOR_CLIPBOARD ); + MODULE* currentModule = m_board->m_Modules; + MODULE* pastedModule = NULL; + + try + { + BOARD_ITEM* item = io.Parse( wxString( m_toolMgr->GetClipboard().c_str(), wxConvUTF8 ) ); + assert( item->Type() == PCB_MODULE_T ); + pastedModule = dyn_cast( item ); + } + catch( ... ) + { + m_frame->DisplayToolMsg( _( "Invalid clipboard contents" ) ); + setTransitions(); + + return 0; + } + + // Placement tool part + VECTOR2I cursorPos = m_controls->GetCursorPosition(); + + // Add a VIEW_GROUP that serves as a preview for the new item + KIGFX::VIEW_GROUP preview( m_view ); + pastedModule->SetParent( m_board ); + pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + pastedModule->RunOnChildren( boost::bind( &KIGFX::VIEW_GROUP::Add, boost::ref( preview ), _1 ) ); + preview.Add( pastedModule ); + m_view->Add( &preview ); + + m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); + m_controls->ShowCursor( true ); + m_controls->SetSnapping( true ); + m_controls->SetAutoPan( true ); + + Activate(); + + // Main loop: keep receiving events + while( OPT_TOOL_EVENT evt = Wait() ) + { + cursorPos = m_controls->GetCursorPosition(); + + if( evt->IsMotion() ) + { + pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); + preview.ViewUpdate(); + } + + else if( evt->Category() == TC_COMMAND ) + { + if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) + { + pastedModule->Rotate( pastedModule->GetPosition(), m_frame->GetRotationAngle() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) + { + pastedModule->Flip( pastedModule->GetPosition() ); + preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + else if( evt->IsCancel() || evt->IsActivate() ) + { + preview.Clear(); + break; + } + } + + else if( evt->IsClick( BUT_LEFT ) ) + { + m_frame->OnModify(); + m_frame->SaveCopyInUndoList( currentModule, UR_MODEDIT ); + + m_board->m_Status_Pcb = 0; // I have no clue why, but it is done in the legacy view + currentModule->SetLastEditTime(); + + // MODULE::RunOnChildren is infeasible here: we need to create copies of items, do not + // directly modify them + + for( D_PAD* pad = pastedModule->Pads(); pad; pad = pad->Next() ) + { + D_PAD* clone = static_cast( pad->Clone() ); + + currentModule->Add( clone ); + clone->SetLocalCoord(); + m_view->Add( clone ); + } + + for( BOARD_ITEM* drawing = pastedModule->GraphicalItems(); + drawing; drawing = drawing->Next() ) + { + BOARD_ITEM* clone = static_cast( drawing->Clone() ); + + if( TEXTE_MODULE* text = dyn_cast( clone ) ) + { + // Do not add reference/value - convert them to the common type + text->SetType( TEXTE_MODULE::TEXT_is_DIVERS ); + currentModule->Add( text ); + text->SetLocalCoord(); + + // Whyyyyyyyyyyyyyyyyyyyyyy?! All other items conform to rotation performed + // on its parent module, but texts are so independent.. + text->Rotate( text->GetPosition(), pastedModule->GetOrientation() ); + } + else if( EDGE_MODULE* edge = dyn_cast( clone ) ) + { + currentModule->Add( edge ); + edge->SetLocalCoord(); + } + + m_view->Add( clone ); + } + + preview.Clear(); + + break; + } + } + + delete pastedModule; + m_controls->ShowCursor( false ); + m_controls->SetSnapping( false ); + m_controls->SetAutoPan( false ); + m_view->Remove( &preview ); + + setTransitions(); + + return 0; +} + + +int MODULE_TOOLS::ModuleTextOutlines( TOOL_EVENT& aEvent ) +{ + KIGFX::PCB_PAINTER* painter = + static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); + KIGFX::PCB_RENDER_SETTINGS* settings = + static_cast( painter->GetSettings() ); + + const LAYER_NUM layers[] = { ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ), + ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ), + ITEM_GAL_LAYER( MOD_TEXT_INVISIBLE ), + ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE ), + ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ) }; + + bool enable = !settings->GetSketchMode( layers[0] ); + + BOOST_FOREACH( LAYER_NUM layer, layers ) + settings->SetSketchMode( layer, enable ); + + for( MODULE* module = getModel()->m_Modules; module; module = module->Next() ) + { + for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item ->Next() ) + { + if( item->Type() == PCB_MODULE_TEXT_T ) + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + module->Reference().ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + module->Value().ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + m_frame->GetGalCanvas()->Refresh(); + setTransitions(); + + return 0; +} + + +int MODULE_TOOLS::ModuleEdgeOutlines( TOOL_EVENT& aEvent ) +{ + KIGFX::PCB_PAINTER* painter = + static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); + KIGFX::PCB_RENDER_SETTINGS* settings = + static_cast( painter->GetSettings() ); + + const LAYER_ID layers[] = { F_Adhes, B_Adhes, F_Paste, B_Paste, + F_SilkS, B_SilkS, F_Mask, B_Mask, + Dwgs_User, Cmts_User, Eco1_User, Eco2_User, Edge_Cuts }; + + bool enable = !settings->GetSketchMode( layers[0] ); + + BOOST_FOREACH( LAYER_NUM layer, layers ) + settings->SetSketchMode( layer, enable ); + + for( MODULE* module = getModel()->m_Modules; module; module = module->Next() ) + { + for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item ->Next() ) + { + if( item->Type() == PCB_MODULE_EDGE_T ) + item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + } + + m_frame->GetGalCanvas()->Refresh(); + setTransitions(); + + return 0; +} + + +void MODULE_TOOLS::setTransitions() +{ + Go( &MODULE_TOOLS::PlacePad, COMMON_ACTIONS::placePad.MakeEvent() ); + Go( &MODULE_TOOLS::EnumeratePads, COMMON_ACTIONS::enumeratePads.MakeEvent() ); + Go( &MODULE_TOOLS::CopyItems, COMMON_ACTIONS::copyItems.MakeEvent() ); + Go( &MODULE_TOOLS::PasteItems, COMMON_ACTIONS::pasteItems.MakeEvent() ); + Go( &MODULE_TOOLS::ModuleTextOutlines, COMMON_ACTIONS::moduleTextOutlines.MakeEvent() ); + Go( &MODULE_TOOLS::ModuleEdgeOutlines, COMMON_ACTIONS::moduleEdgeOutlines.MakeEvent() ); +} diff --git a/pcbnew/tools/module_tools.h b/pcbnew/tools/module_tools.h new file mode 100644 index 0000000000..71d83acc7e --- /dev/null +++ b/pcbnew/tools/module_tools.h @@ -0,0 +1,104 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 MODULE_TOOLS_H +#define MODULE_TOOLS_H + +#include + +namespace KIGFX +{ + class VIEW; + class VIEW_CONTROLS; +} +class BOARD; +class PCB_EDIT_FRAME; + +/** + * Class MODULE_TOOLS + * + * Module editor specific tools. + */ +class MODULE_TOOLS : public TOOL_INTERACTIVE +{ +public: + MODULE_TOOLS(); + + /// @copydoc TOOL_INTERACTIVE::Reset() + void Reset( RESET_REASON aReason ); + + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init(); + + /** + * Function PlacePad() + * Places a pad in module editor. + */ + int PlacePad( TOOL_EVENT& aEvent ); + + /** + * Function EnumeratePads() + * Tool for quick pad enumeration. + */ + int EnumeratePads( TOOL_EVENT& aEvent ); + + /** + * Function CopyItems() + * + * Copies selected items to the clipboard. Works only in "edit modules" mode. + */ + int CopyItems( TOOL_EVENT& aEvent ); + + /** + * Function PastePad() + * + * Pastes items from the clipboard. Works only in "edit modules" mode. + */ + int PasteItems( TOOL_EVENT& aEvent ); + + /** + * Function ModuleTextOutlines() + * + * Toggles display mode for module texts (outline/filled). + */ + int ModuleTextOutlines( TOOL_EVENT& aEvent ); + + /** + * Function ModuleEdgeOutlines() + * + * Toggles display mode for module edges (outline/filled). + */ + int ModuleEdgeOutlines( TOOL_EVENT& aEvent ); + +private: + ///> Sets up handlers for various events. + void setTransitions(); + + KIGFX::VIEW* m_view; + KIGFX::VIEW_CONTROLS* m_controls; + BOARD* m_board; + PCB_EDIT_FRAME* m_frame; +}; + +#endif diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp new file mode 100644 index 0000000000..f1c8fe3833 --- /dev/null +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -0,0 +1,234 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "pcb_editor_control.h" +#include "common_actions.h" + +#include "selection_tool.h" + +#include +#include +#include +#include + + +class ZONE_CONTEXT_MENU : public CONTEXT_MENU +{ +public: + ZONE_CONTEXT_MENU() + { + Add( COMMON_ACTIONS::zoneFill ); + Add( COMMON_ACTIONS::zoneFillAll ); + Add( COMMON_ACTIONS::zoneUnfill ); + } +}; + + +PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() : + TOOL_INTERACTIVE( "pcbnew.EditorControl" ) +{ +} + + +void PCB_EDITOR_CONTROL::Reset( RESET_REASON aReason ) +{ + m_frame = getEditFrame(); +} + + +bool PCB_EDITOR_CONTROL::Init() +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + + if( selTool ) + { + selTool->AddSubMenu( new ZONE_CONTEXT_MENU, wxT( "Zones" ), + SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) ); + } + + setTransitions(); + + return true; +} + + +// Track & via size control +int PCB_EDITOR_CONTROL::TrackWidthInc( TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel(); + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() + 1; + + if( widthIndex >= (int) board->GetDesignSettings().m_TrackWidthList.size() ) + widthIndex = board->GetDesignSettings().m_TrackWidthList.size() - 1; + + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectTrackWidth( dummy ); + setTransitions(); + + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::TrackWidthDec( TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel(); + int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() - 1; + + if( widthIndex < 0 ) + widthIndex = 0; + + board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectTrackWidth( dummy ); + setTransitions(); + + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ViaSizeInc( TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel(); + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() + 1; + + if( sizeIndex >= (int) board->GetDesignSettings().m_ViasDimensionsList.size() ) + sizeIndex = board->GetDesignSettings().m_ViasDimensionsList.size() - 1; + + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectViaSize( dummy ); + setTransitions(); + + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ViaSizeDec( TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel(); + int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() - 1; + + if( sizeIndex < 0 ) + sizeIndex = 0; + + board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); + board->GetDesignSettings().UseCustomTrackViaSize( false ); + + wxUpdateUIEvent dummy; + m_frame->OnUpdateSelectViaSize( dummy ); + setTransitions(); + + m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); + + return 0; +} + + +// Zone actions +int PCB_EDITOR_CONTROL::ZoneFill( TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + const SELECTION& selection = selTool->GetSelection(); + + for( int i = 0; i < selection.Size(); ++i ) + { + assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + + ZONE_CONTAINER* zone = selection.Item( i ); + m_frame->Fill_Zone( zone ); + zone->SetIsFilled( true ); + zone->ViewUpdate(); + } + + setTransitions(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneFillAll( TOOL_EVENT& aEvent ) +{ + BOARD* board = getModel(); + + for( int i = 0; i < board->GetAreaCount(); ++i ) + { + ZONE_CONTAINER* zone = board->GetArea( i ); + m_frame->Fill_Zone( zone ); + zone->SetIsFilled( true ); + zone->ViewUpdate(); + } + + setTransitions(); + + return 0; +} + + +int PCB_EDITOR_CONTROL::ZoneUnfill( TOOL_EVENT& aEvent ) +{ + SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + const SELECTION& selection = selTool->GetSelection(); + + for( int i = 0; i < selection.Size(); ++i ) + { + assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + + ZONE_CONTAINER* zone = selection.Item( i ); + zone->SetIsFilled( false ); + zone->ClearFilledPolysList(); + zone->ViewUpdate(); + } + + setTransitions(); + + return 0; +} + + +void PCB_EDITOR_CONTROL::setTransitions() +{ + // Track & via size control + Go( &PCB_EDITOR_CONTROL::TrackWidthInc, COMMON_ACTIONS::trackWidthInc.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::TrackWidthDec, COMMON_ACTIONS::trackWidthDec.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ViaSizeInc, COMMON_ACTIONS::viaSizeInc.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ViaSizeDec, COMMON_ACTIONS::viaSizeDec.MakeEvent() ); + + // Zone actions + Go( &PCB_EDITOR_CONTROL::ZoneFill, COMMON_ACTIONS::zoneFill.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneFillAll, COMMON_ACTIONS::zoneFillAll.MakeEvent() ); + Go( &PCB_EDITOR_CONTROL::ZoneUnfill, COMMON_ACTIONS::zoneUnfill.MakeEvent() ); +} diff --git a/pcbnew/tools/pcb_editor_control.h b/pcbnew/tools/pcb_editor_control.h new file mode 100644 index 0000000000..6d272884c9 --- /dev/null +++ b/pcbnew/tools/pcb_editor_control.h @@ -0,0 +1,67 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 PCB_EDITOR_CONTROL_H +#define PCB_EDITOR_CONTROL_H + +#include + +class PCB_EDIT_FRAME; + +/** + * Class PCB_EDITOR_CONTROL + * + * Handles actions specific to the board editor in pcbnew. + */ +class PCB_EDITOR_CONTROL : public TOOL_INTERACTIVE +{ +public: + PCB_EDITOR_CONTROL(); + + /// @copydoc TOOL_INTERACTIVE::Reset() + void Reset( RESET_REASON aReason ); + + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init(); + + // Track & via size control + int TrackWidthInc( TOOL_EVENT& aEvent ); + int TrackWidthDec( TOOL_EVENT& aEvent ); + int ViaSizeInc( TOOL_EVENT& aEvent ); + int ViaSizeDec( TOOL_EVENT& aEvent ); + + // Zone actions + int ZoneFill( TOOL_EVENT& aEvent ); + int ZoneFillAll( TOOL_EVENT& aEvent ); + int ZoneUnfill( TOOL_EVENT& aEvent ); + +private: + ///> Sets up handlers for various events. + void setTransitions(); + + ///> Pointer to the currently used edit frame. + PCB_EDIT_FRAME* m_frame; +}; + +#endif diff --git a/pcbnew/tools/pcb_tools.cpp b/pcbnew/tools/pcb_tools.cpp deleted file mode 100644 index eaefa97678..0000000000 --- a/pcbnew/tools/pcb_tools.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2013 CERN - * @author Tomasz Wlostowski - * - * 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 -#include -#include - -#include -#include - -#include -#include - -#include -#include - -#include "selection_tool.h" -#include "edit_tool.h" -#include "drawing_tool.h" -#include "point_editor.h" -#include "pcbnew_control.h" -#include "common_actions.h" -#include - -void PCB_EDIT_FRAME::setupTools() -{ - // Create the manager and dispatcher & route draw panel events to the dispatcher - m_toolManager = new TOOL_MANAGER; - m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, this ); - GetGalCanvas()->SetEventDispatcher( m_toolDispatcher ); - - // Connect handlers to toolbar buttons -#if wxCHECK_VERSION( 3, 0, 0 ) - Connect( wxEVT_TOOL, wxCommandEventHandler( PCB_EDIT_FRAME::onGenericCommand ), NULL, this ); -#else - Connect( wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler( PCB_EDIT_FRAME::onGenericCommand ), NULL, this ); - Connect( wxEVT_COMMAND_TOOL_CLICKED, - wxCommandEventHandler( PCB_EDIT_FRAME::onGenericCommand ), NULL, this ); -#endif - - // Register actions - std::list& actionList = m_toolManager->GetActionList(); - BOOST_FOREACH( TOOL_ACTION* action, actionList ) - m_toolManager->RegisterAction( action ); - - // Register tools - m_toolManager->RegisterTool( new SELECTION_TOOL ); - m_toolManager->RegisterTool( new ROUTER_TOOL ); - m_toolManager->RegisterTool( new EDIT_TOOL ); - m_toolManager->RegisterTool( new DRAWING_TOOL ); - m_toolManager->RegisterTool( new POINT_EDITOR ); - m_toolManager->RegisterTool( new PCBNEW_CONTROL ); - - m_toolManager->SetEnvironment( NULL, GetGalCanvas()->GetView(), - GetGalCanvas()->GetViewControls(), this ); - m_toolManager->ResetTools( TOOL_BASE::RUN ); - - // Run the selection tool, it is supposed to be always active - m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" ); -} - - -void PCB_EDIT_FRAME::destroyTools() -{ - delete m_toolManager; - delete m_toolDispatcher; -} - - -void PCB_EDIT_FRAME::onGenericCommand( wxCommandEvent& aEvent ) -{ - if( IsGalCanvasActive() ) - m_toolDispatcher->DispatchWxCommand( aEvent ); - else - aEvent.Skip(); -} diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 80cf1511d5..a0573b3118 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -28,7 +28,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -38,6 +40,7 @@ #include #include + PCBNEW_CONTROL::PCBNEW_CONTROL() : TOOL_INTERACTIVE( "pcbnew.Control" ) { @@ -46,7 +49,7 @@ PCBNEW_CONTROL::PCBNEW_CONTROL() : void PCBNEW_CONTROL::Reset( RESET_REASON aReason ) { - m_frame = getEditFrame(); + m_frame = getEditFrame(); } @@ -80,9 +83,9 @@ int PCBNEW_CONTROL::ZoomInOutCenter( TOOL_EVENT& aEvent ) KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); double zoomScale = 1.0; - if( aEvent.IsAction( &COMMON_ACTIONS::zoomIn ) ) + if( aEvent.IsAction( &COMMON_ACTIONS::zoomInCenter ) ) zoomScale = 1.3; - else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOut ) ) + else if( aEvent.IsAction( &COMMON_ACTIONS::zoomOutCenter ) ) zoomScale = 0.7; view->SetScale( view->GetScale() * zoomScale ); @@ -107,17 +110,29 @@ int PCBNEW_CONTROL::ZoomFitScreen( TOOL_EVENT& aEvent ) KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL(); BOX2I boardBBox = getModel()->ViewBBox(); - VECTOR2I screenSize = gal->GetScreenPixelSize(); - double iuPerX = screenSize.x ? boardBBox.GetWidth() / screenSize.x : 1.0; - double iuPerY = screenSize.y ? boardBBox.GetHeight() / screenSize.y : 1.0; + if( boardBBox.GetSize().x == 0 || boardBBox.GetSize().y == 0 ) + { + // Empty view + view->SetScale( 100000.0 ); + view->SetCenter( VECTOR2D( 0, 0 ) ); + } + else + { + // Autozoom to board + VECTOR2I screenSize = gal->GetScreenPixelSize(); - double bestZoom = std::max( iuPerX, iuPerY ); - double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); - double zoom = 1.0 / ( zoomFactor * bestZoom ); + double iuPerX = screenSize.x ? boardBBox.GetWidth() / screenSize.x : 1.0; + double iuPerY = screenSize.y ? boardBBox.GetHeight() / screenSize.y : 1.0; + + double bestZoom = std::max( iuPerX, iuPerY ); + double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); + double zoom = 1.0 / ( zoomFactor * bestZoom ); + + view->SetScale( zoom ); + view->SetCenter( boardBBox.Centre() ); + } - view->SetScale( zoom ); - view->SetCenter( boardBBox.Centre() ); setTransitions(); return 0; @@ -129,17 +144,20 @@ int PCBNEW_CONTROL::TrackDisplayMode( TOOL_EVENT& aEvent ) KIGFX::PCB_PAINTER* painter = static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + static_cast( painter->GetSettings() ); // Apply new display options to the GAL canvas DisplayOpt.DisplayPcbTrackFill = !DisplayOpt.DisplayPcbTrackFill; m_frame->m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill; settings->LoadDisplayOptions( DisplayOpt ); - BOARD* board = getModel(); - for( TRACK* track = board->m_Track; track; track = track->Next() ) - track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + for( TRACK* track = getModel()->m_Track; track; track = track->Next() ) + { + if( track->Type() == PCB_TRACE_T ) + track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + m_frame->GetGalCanvas()->Refresh(); setTransitions(); return 0; @@ -148,8 +166,23 @@ int PCBNEW_CONTROL::TrackDisplayMode( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::PadDisplayMode( TOOL_EVENT& aEvent ) { - wxCommandEvent dummy; - getEditFrame()->OnTogglePadDrawMode( dummy ); + KIGFX::PCB_PAINTER* painter = + static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); + KIGFX::PCB_RENDER_SETTINGS* settings = + static_cast( painter->GetSettings() ); + + // Apply new display options to the GAL canvas + DisplayOpt.DisplayPadFill = !DisplayOpt.DisplayPadFill; + m_frame->m_DisplayPadFill = DisplayOpt.DisplayPadFill; + settings->LoadDisplayOptions( DisplayOpt ); + + for( MODULE* module = getModel()->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) + pad->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } + + m_frame->GetGalCanvas()->Refresh(); setTransitions(); return 0; @@ -161,20 +194,50 @@ int PCBNEW_CONTROL::ViaDisplayMode( TOOL_EVENT& aEvent ) KIGFX::PCB_PAINTER* painter = static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + static_cast( painter->GetSettings() ); // Apply new display options to the GAL canvas DisplayOpt.DisplayViaFill = !DisplayOpt.DisplayViaFill; m_frame->m_DisplayViaFill = DisplayOpt.DisplayViaFill; settings->LoadDisplayOptions( DisplayOpt ); - BOARD* board = getModel(); - for( TRACK* track = board->m_Track; track; track = track->Next() ) + for( TRACK* track = getModel()->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_VIA_T ) track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } + m_frame->GetGalCanvas()->Refresh(); + setTransitions(); + + return 0; +} + + +int PCBNEW_CONTROL::ZoneDisplayMode( TOOL_EVENT& aEvent ) +{ + KIGFX::PCB_PAINTER* painter = + static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); + KIGFX::PCB_RENDER_SETTINGS* settings = + static_cast( painter->GetSettings() ); + + // Apply new display options to the GAL canvas + if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayEnable ) ) + DisplayOpt.DisplayZonesMode = 0; + else if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayDisable ) ) + DisplayOpt.DisplayZonesMode = 1; + else if( aEvent.IsAction( &COMMON_ACTIONS::zoneDisplayOutlines ) ) + DisplayOpt.DisplayZonesMode = 2; + else + assert( false ); + + settings->LoadDisplayOptions( DisplayOpt ); + + BOARD* board = getModel(); + for( int i = 0; i < board->GetAreaCount(); ++i ) + board->GetArea( i )->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + + m_frame->GetGalCanvas()->Refresh(); setTransitions(); return 0; @@ -190,7 +253,7 @@ int PCBNEW_CONTROL::HighContrastMode( TOOL_EVENT& aEvent ) DisplayOpt.ContrastModeDisplay = !DisplayOpt.ContrastModeDisplay; settings->LoadDisplayOptions( DisplayOpt ); - m_frame->SetHighContrastLayer( m_frame->GetActiveLayer() ); + m_frame->GetGalCanvas()->SetHighContrastLayer( m_frame->GetActiveLayer() ); setTransitions(); @@ -217,80 +280,25 @@ int PCBNEW_CONTROL::HighContrastDec( TOOL_EVENT& aEvent ) // Layer control -int PCBNEW_CONTROL::LayerTop( TOOL_EVENT& aEvent ) +int PCBNEW_CONTROL::LayerSwitch( TOOL_EVENT& aEvent ) { - getEditFrame()->SwitchLayer( NULL, F_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); + if( aEvent.IsAction( &COMMON_ACTIONS::layerTop ) ) + m_frame->SwitchLayer( NULL, F_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner1 ) ) + m_frame->SwitchLayer( NULL, In1_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner2 ) ) + m_frame->SwitchLayer( NULL, In2_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner3 ) ) + m_frame->SwitchLayer( NULL, In3_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner4 ) ) + m_frame->SwitchLayer( NULL, In4_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner5 ) ) + m_frame->SwitchLayer( NULL, In5_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerInner6 ) ) + m_frame->SwitchLayer( NULL, In6_Cu ); + else if( aEvent.IsAction( &COMMON_ACTIONS::layerBottom ) ) + m_frame->SwitchLayer( NULL, B_Cu ); - return 0; -} - - -int PCBNEW_CONTROL::LayerInner1( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In1_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerInner2( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In2_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerInner3( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In3_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerInner4( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In4_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerInner5( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In5_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerInner6( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SwitchLayer( NULL, In6_Cu ); - getEditFrame()->GetGalCanvas()->SetFocus(); - setTransitions(); - - return 0; -} - - -int PCBNEW_CONTROL::LayerBottom( TOOL_EVENT& aEvent ) -{ - getEditFrame()->SetActiveLayer( B_Cu, true ); - getEditFrame()->GetGalCanvas()->SetFocus(); setTransitions(); return 0; @@ -299,24 +307,26 @@ int PCBNEW_CONTROL::LayerBottom( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::LayerNext( TOOL_EVENT& aEvent ) { - PCB_EDIT_FRAME* editFrame = getEditFrame(); - LAYER_NUM layer = editFrame->GetActiveLayer(); + PCB_BASE_FRAME* editFrame = m_frame; + LAYER_NUM layer = editFrame->GetActiveLayer(); - if( layer < F_Cu || layer >= B_Cu ) + if( layer < F_Cu || layer > B_Cu ) { setTransitions(); return 0; } - if( getModel()->GetCopperLayerCount() < 2 ) // Single layer - layer = B_Cu; - else if( layer >= getModel()->GetCopperLayerCount() - 2 ) + int layerCount = getModel()->GetCopperLayerCount(); + + if( layer == layerCount - 2 || layerCount < 2 ) layer = B_Cu; + else if( layer == B_Cu ) + layer = F_Cu; else ++layer; + assert( IsCopperLayer( layer ) ); editFrame->SwitchLayer( NULL, ToLAYER_ID( layer ) ); - editFrame->GetGalCanvas()->SetFocus(); setTransitions(); return 0; @@ -325,25 +335,26 @@ int PCBNEW_CONTROL::LayerNext( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::LayerPrev( TOOL_EVENT& aEvent ) { - PCB_EDIT_FRAME* editFrame = getEditFrame(); - LAYER_NUM layer = editFrame->GetActiveLayer(); + PCB_BASE_FRAME* editFrame = m_frame; + LAYER_NUM layer = editFrame->GetActiveLayer(); - if( layer <= F_Cu || layer > B_Cu ) + if( layer < F_Cu || layer > B_Cu ) { setTransitions(); return 0; } - if( getModel()->GetCopperLayerCount() < 2 ) // Single layer + int layerCount = getModel()->GetCopperLayerCount(); + + if( layer == F_Cu || layerCount < 2 ) layer = B_Cu; else if( layer == B_Cu ) - layer = std::max( int( F_Cu ), getModel()->GetCopperLayerCount() - 2 ); + layer = layerCount - 2; else --layer; assert( IsCopperLayer( layer ) ); editFrame->SwitchLayer( NULL, ToLAYER_ID( layer ) ); - editFrame->GetGalCanvas()->SetFocus(); setTransitions(); return 0; @@ -399,7 +410,7 @@ int PCBNEW_CONTROL::LayerAlphaDec( TOOL_EVENT& aEvent ) // Grid control int PCBNEW_CONTROL::GridFast1( TOOL_EVENT& aEvent ) { - getEditFrame()->SetFastGrid1(); + m_frame->SetFastGrid1(); setTransitions(); return 0; @@ -408,7 +419,7 @@ int PCBNEW_CONTROL::GridFast1( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::GridFast2( TOOL_EVENT& aEvent ) { - getEditFrame()->SetFastGrid2(); + m_frame->SetFastGrid2(); setTransitions(); return 0; @@ -417,7 +428,7 @@ int PCBNEW_CONTROL::GridFast2( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::GridNext( TOOL_EVENT& aEvent ) { - getEditFrame()->SetNextGrid(); + m_frame->SetNextGrid(); setTransitions(); return 0; @@ -426,7 +437,7 @@ int PCBNEW_CONTROL::GridNext( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::GridPrev( TOOL_EVENT& aEvent ) { - getEditFrame()->SetPrevGrid(); + m_frame->SetPrevGrid(); setTransitions(); return 0; @@ -436,7 +447,7 @@ int PCBNEW_CONTROL::GridPrev( TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::GridSetOrigin( TOOL_EVENT& aEvent ) { Activate(); - getEditFrame()->SetToolID( ID_PCB_PLACE_GRID_COORD_BUTT, wxCURSOR_PENCIL, + m_frame->SetToolID( ID_PCB_PLACE_GRID_COORD_BUTT, wxCURSOR_PENCIL, _( "Adjust grid origin" ) ); KIGFX::VIEW_CONTROLS* controls = getViewControls(); @@ -452,7 +463,7 @@ int PCBNEW_CONTROL::GridSetOrigin( TOOL_EVENT& aEvent ) getView()->MarkDirty(); } - else if( evt->IsCancel() ) + else if( evt->IsCancel() || evt->IsActivate() ) break; } @@ -466,91 +477,6 @@ int PCBNEW_CONTROL::GridSetOrigin( TOOL_EVENT& aEvent ) } -// Track & via size control -int PCBNEW_CONTROL::TrackWidthInc( TOOL_EVENT& aEvent ) -{ - BOARD* board = getModel(); - int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() + 1; - - if( widthIndex >= (int) board->GetDesignSettings().m_TrackWidthList.size() ) - widthIndex = board->GetDesignSettings().m_TrackWidthList.size() - 1; - - board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); - board->GetDesignSettings().UseCustomTrackViaSize( false ); - - wxUpdateUIEvent dummy; - getEditFrame()->OnUpdateSelectTrackWidth( dummy ); - setTransitions(); - - m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); - - return 0; -} - - -int PCBNEW_CONTROL::TrackWidthDec( TOOL_EVENT& aEvent ) -{ - BOARD* board = getModel(); - int widthIndex = board->GetDesignSettings().GetTrackWidthIndex() - 1; - - if( widthIndex < 0 ) - widthIndex = 0; - - board->GetDesignSettings().SetTrackWidthIndex( widthIndex ); - board->GetDesignSettings().UseCustomTrackViaSize( false ); - - wxUpdateUIEvent dummy; - getEditFrame()->OnUpdateSelectTrackWidth( dummy ); - setTransitions(); - - m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); - - return 0; -} - - -int PCBNEW_CONTROL::ViaSizeInc( TOOL_EVENT& aEvent ) -{ - BOARD* board = getModel(); - int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() + 1; - - if( sizeIndex >= (int) board->GetDesignSettings().m_ViasDimensionsList.size() ) - sizeIndex = board->GetDesignSettings().m_ViasDimensionsList.size() - 1; - - board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); - board->GetDesignSettings().UseCustomTrackViaSize( false ); - - wxUpdateUIEvent dummy; - getEditFrame()->OnUpdateSelectViaSize( dummy ); - setTransitions(); - - m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); - - return 0; -} - - -int PCBNEW_CONTROL::ViaSizeDec( TOOL_EVENT& aEvent ) -{ - BOARD* board = getModel(); - int sizeIndex = board->GetDesignSettings().GetViaSizeIndex() - 1; - - if( sizeIndex < 0 ) - sizeIndex = 0; - - board->GetDesignSettings().SetViaSizeIndex( sizeIndex ); - board->GetDesignSettings().UseCustomTrackViaSize( false ); - - wxUpdateUIEvent dummy; - getEditFrame()->OnUpdateSelectViaSize( dummy ); - setTransitions(); - - m_toolMgr->RunAction( COMMON_ACTIONS::trackViaSizeChanged ); - - return 0; -} - - // Miscellaneous int PCBNEW_CONTROL::ResetCoords( TOOL_EVENT& aEvent ) { @@ -564,6 +490,24 @@ int PCBNEW_CONTROL::ResetCoords( TOOL_EVENT& aEvent ) } +int PCBNEW_CONTROL::SwitchCursor( TOOL_EVENT& aEvent ) +{ + const unsigned int BIG_CURSOR = 4000; + const unsigned int SMALL_CURSOR = 80; + + KIGFX::GAL* gal = getEditFrame()->GetGalCanvas()->GetGAL(); + + if( gal->GetCursorSize() == BIG_CURSOR ) + gal->SetCursorSize( SMALL_CURSOR ); + else + gal->SetCursorSize( BIG_CURSOR ); + + setTransitions(); + + return 0; +} + + int PCBNEW_CONTROL::SwitchUnits( TOOL_EVENT& aEvent ) { // TODO should not it be refactored to pcb_frame member function? @@ -591,6 +535,15 @@ int PCBNEW_CONTROL::ShowHelp( TOOL_EVENT& aEvent ) } +int PCBNEW_CONTROL::ToBeDone( TOOL_EVENT& aEvent ) +{ + DisplayInfoMessage( m_frame, _( "Not implemented yet." ) ); + setTransitions(); + + return 0; +} + + void PCBNEW_CONTROL::setTransitions() { // View controls @@ -605,19 +558,22 @@ void PCBNEW_CONTROL::setTransitions() Go( &PCBNEW_CONTROL::TrackDisplayMode, COMMON_ACTIONS::trackDisplayMode.MakeEvent() ); Go( &PCBNEW_CONTROL::PadDisplayMode, COMMON_ACTIONS::padDisplayMode.MakeEvent() ); Go( &PCBNEW_CONTROL::ViaDisplayMode, COMMON_ACTIONS::viaDisplayMode.MakeEvent() ); + Go( &PCBNEW_CONTROL::ZoneDisplayMode, COMMON_ACTIONS::zoneDisplayEnable.MakeEvent() ); + Go( &PCBNEW_CONTROL::ZoneDisplayMode, COMMON_ACTIONS::zoneDisplayDisable.MakeEvent() ); + Go( &PCBNEW_CONTROL::ZoneDisplayMode, COMMON_ACTIONS::zoneDisplayOutlines.MakeEvent() ); Go( &PCBNEW_CONTROL::HighContrastMode, COMMON_ACTIONS::highContrastMode.MakeEvent() ); Go( &PCBNEW_CONTROL::HighContrastInc, COMMON_ACTIONS::highContrastInc.MakeEvent() ); Go( &PCBNEW_CONTROL::HighContrastDec, COMMON_ACTIONS::highContrastDec.MakeEvent() ); // Layer control - Go( &PCBNEW_CONTROL::LayerTop, COMMON_ACTIONS::layerTop.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner1, COMMON_ACTIONS::layerInner1.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner2, COMMON_ACTIONS::layerInner2.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner3, COMMON_ACTIONS::layerInner3.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner4, COMMON_ACTIONS::layerInner4.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner5, COMMON_ACTIONS::layerInner5.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerInner6, COMMON_ACTIONS::layerInner6.MakeEvent() ); - Go( &PCBNEW_CONTROL::LayerBottom, COMMON_ACTIONS::layerBottom.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerTop.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner1.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner2.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner3.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner4.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner5.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerInner6.MakeEvent() ); + Go( &PCBNEW_CONTROL::LayerSwitch, COMMON_ACTIONS::layerBottom.MakeEvent() ); Go( &PCBNEW_CONTROL::LayerNext, COMMON_ACTIONS::layerNext.MakeEvent() ); Go( &PCBNEW_CONTROL::LayerPrev, COMMON_ACTIONS::layerPrev.MakeEvent() ); Go( &PCBNEW_CONTROL::LayerAlphaInc, COMMON_ACTIONS::layerAlphaInc.MakeEvent() ); @@ -630,14 +586,10 @@ void PCBNEW_CONTROL::setTransitions() Go( &PCBNEW_CONTROL::GridPrev, COMMON_ACTIONS::gridPrev.MakeEvent() ); Go( &PCBNEW_CONTROL::GridSetOrigin, COMMON_ACTIONS::gridSetOrigin.MakeEvent() ); - // Track & via size control - Go( &PCBNEW_CONTROL::TrackWidthInc, COMMON_ACTIONS::trackWidthInc.MakeEvent() ); - Go( &PCBNEW_CONTROL::TrackWidthDec, COMMON_ACTIONS::trackWidthDec.MakeEvent() ); - Go( &PCBNEW_CONTROL::ViaSizeInc, COMMON_ACTIONS::viaSizeInc.MakeEvent() ); - Go( &PCBNEW_CONTROL::ViaSizeDec, COMMON_ACTIONS::viaSizeDec.MakeEvent() ); - // Miscellaneous Go( &PCBNEW_CONTROL::ResetCoords, COMMON_ACTIONS::resetCoords.MakeEvent() ); + Go( &PCBNEW_CONTROL::SwitchCursor, COMMON_ACTIONS::switchCursor.MakeEvent() ); Go( &PCBNEW_CONTROL::SwitchUnits, COMMON_ACTIONS::switchUnits.MakeEvent() ); Go( &PCBNEW_CONTROL::ShowHelp, COMMON_ACTIONS::showHelp.MakeEvent() ); + Go( &PCBNEW_CONTROL::ToBeDone, COMMON_ACTIONS::toBeDone.MakeEvent() ); } diff --git a/pcbnew/tools/pcbnew_control.h b/pcbnew/tools/pcbnew_control.h index e4920484db..e9e87cb1e4 100644 --- a/pcbnew/tools/pcbnew_control.h +++ b/pcbnew/tools/pcbnew_control.h @@ -27,12 +27,12 @@ #include -class PCB_EDIT_FRAME; +class PCB_BASE_FRAME; /** * Class PCBNEW_CONTROL * - * Handles hot keys that are not accepted by any other tool. + * Handles actions that are shared between different frames in pcbnew. */ class PCBNEW_CONTROL : public TOOL_INTERACTIVE @@ -56,19 +56,13 @@ public: int TrackDisplayMode( TOOL_EVENT& aEvent ); int PadDisplayMode( TOOL_EVENT& aEvent ); int ViaDisplayMode( TOOL_EVENT& aEvent ); + int ZoneDisplayMode( TOOL_EVENT& aEvent ); int HighContrastMode( TOOL_EVENT& aEvent ); int HighContrastInc( TOOL_EVENT& aEvent ); int HighContrastDec( TOOL_EVENT& aEvent ); // Layer control - int LayerTop( TOOL_EVENT& aEvent ); - int LayerInner1( TOOL_EVENT& aEvent ); - int LayerInner2( TOOL_EVENT& aEvent ); - int LayerInner3( TOOL_EVENT& aEvent ); - int LayerInner4( TOOL_EVENT& aEvent ); - int LayerInner5( TOOL_EVENT& aEvent ); - int LayerInner6( TOOL_EVENT& aEvent ); - int LayerBottom( TOOL_EVENT& aEvent ); + int LayerSwitch( TOOL_EVENT& aEvent ); int LayerNext( TOOL_EVENT& aEvent ); int LayerPrev( TOOL_EVENT& aEvent ); int LayerAlphaInc( TOOL_EVENT& aEvent ); @@ -81,23 +75,19 @@ public: int GridPrev( TOOL_EVENT& aEvent ); int GridSetOrigin( TOOL_EVENT& aEvent ); - // Track & via size control - int TrackWidthInc( TOOL_EVENT& aEvent ); - int TrackWidthDec( TOOL_EVENT& aEvent ); - int ViaSizeInc( TOOL_EVENT& aEvent ); - int ViaSizeDec( TOOL_EVENT& aEvent ); - // Miscellaneous int ResetCoords( TOOL_EVENT& aEvent ); + int SwitchCursor( TOOL_EVENT& aEvent ); int SwitchUnits( TOOL_EVENT& aEvent ); int ShowHelp( TOOL_EVENT& aEvent ); + int ToBeDone( TOOL_EVENT& aEvent ); private: ///> Sets up handlers for various events. void setTransitions(); ///> Pointerto the currently used edit frame. - PCB_EDIT_FRAME* m_frame; + PCB_BASE_FRAME* m_frame; }; #endif diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp new file mode 100644 index 0000000000..d77f05089b --- /dev/null +++ b/pcbnew/tools/placement_tool.cpp @@ -0,0 +1,366 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "placement_tool.h" +#include "common_actions.h" +#include "selection_tool.h" + +#include +#include +#include + +#include +#include + +PLACEMENT_TOOL::PLACEMENT_TOOL() : + TOOL_INTERACTIVE( "pcbnew.Placement" ) +{ +} + +PLACEMENT_TOOL::~PLACEMENT_TOOL() +{ +} + + +bool PLACEMENT_TOOL::Init() +{ + // Find the selection tool, so they can cooperate + m_selectionTool = static_cast( m_toolMgr->FindTool( "pcbnew.InteractiveSelection" ) ); + + if( !m_selectionTool ) + { + DisplayError( NULL, wxT( "pcbnew.InteractiveSelection tool is not available" ) ); + return false; + } + + // Create a context menu and make it available through selection tool + CONTEXT_MENU* menu = new CONTEXT_MENU; + menu->Add( COMMON_ACTIONS::alignTop ); + menu->Add( COMMON_ACTIONS::alignBottom ); + menu->Add( COMMON_ACTIONS::alignLeft ); + menu->Add( COMMON_ACTIONS::alignRight ); + menu->AppendSeparator(); + menu->Add( COMMON_ACTIONS::distributeHorizontally ); + menu->Add( COMMON_ACTIONS::distributeVertically ); + m_selectionTool->AddSubMenu( menu, _( "Align/distribute" ), + SELECTION_CONDITIONS::MoreThan( 1 ) ); + + setTransitions(); + + return true; +} + + +int PLACEMENT_TOOL::AlignTop( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Compute the highest point of selection - it will be the edge of alignment + int top = selection.Item( 0 )->GetBoundingBox().GetY(); + + for( int i = 1; i < selection.Size(); ++i ) + { + int currentTop = selection.Item( i )->GetBoundingBox().GetY(); + + if( top > currentTop ) // Y decreases when going up + top = currentTop; + } + + // Move the selected items + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* item = selection.Item( i ); + int difference = top - item->GetBoundingBox().GetY(); + + item->Move( wxPoint( 0, difference ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +int PLACEMENT_TOOL::AlignBottom( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Compute the lowest point of selection - it will be the edge of alignment + int bottom = selection.Item( 0 )->GetBoundingBox().GetBottom(); + + for( int i = 1; i < selection.Size(); ++i ) + { + int currentBottom = selection.Item( i )->GetBoundingBox().GetBottom(); + + if( bottom < currentBottom ) // Y increases when going down + bottom = currentBottom; + } + + // Move the selected items + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* item = selection.Item( i ); + int difference = bottom - item->GetBoundingBox().GetBottom(); + + item->Move( wxPoint( 0, difference ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +int PLACEMENT_TOOL::AlignLeft( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Compute the leftmost point of selection - it will be the edge of alignment + int left = selection.Item( 0 )->GetBoundingBox().GetX(); + + for( int i = 1; i < selection.Size(); ++i ) + { + int currentLeft = selection.Item( i )->GetBoundingBox().GetX(); + + if( left > currentLeft ) // X decreases when going left + left = currentLeft; + } + + // Move the selected items + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* item = selection.Item( i ); + int difference = left - item->GetBoundingBox().GetX(); + + item->Move( wxPoint( difference, 0 ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +int PLACEMENT_TOOL::AlignRight( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Compute the rightmost point of selection - it will be the edge of alignment + int right = selection.Item( 0 )->GetBoundingBox().GetRight(); + + for( int i = 1; i < selection.Size(); ++i ) + { + int currentRight = selection.Item( i )->GetBoundingBox().GetRight(); + + if( right < currentRight ) // X increases when going right + right = currentRight; + } + + // Move the selected items + for( int i = 0; i < selection.Size(); ++i ) + { + BOARD_ITEM* item = selection.Item( i ); + int difference = right - item->GetBoundingBox().GetRight(); + + item->Move( wxPoint( difference, 0 ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +static bool compareX( const BOARD_ITEM* aA, const BOARD_ITEM* aB ) +{ + return aA->GetBoundingBox().Centre().x < aB->GetBoundingBox().Centre().x; +} + + +static bool compareY( const BOARD_ITEM* aA, const BOARD_ITEM* aB ) +{ + return aA->GetBoundingBox().Centre().y < aB->GetBoundingBox().Centre().y; +} + + +int PLACEMENT_TOOL::DistributeHorizontally( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Prepare a list, so the items can be sorted by their X coordinate + std::list itemsList; + for( int i = 0; i < selection.Size(); ++i ) + itemsList.push_back( selection.Item( i ) ); + + // Sort items by X coordinate + itemsList.sort( compareX ); + + // Expected X coordinate for the next item (=minX) + int position = (*itemsList.begin())->GetBoundingBox().Centre().x; + + // X coordinate for the last item + const int maxX = (*itemsList.rbegin())->GetBoundingBox().Centre().x; + + // Distance between items + const int distance = ( maxX - position ) / ( itemsList.size() - 1 ); + + BOOST_FOREACH( BOARD_ITEM* item, itemsList ) + { + int difference = position - item->GetBoundingBox().Centre().x; + + item->Move( wxPoint( difference, 0 ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + + position += distance; + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +int PLACEMENT_TOOL::DistributeVertically( TOOL_EVENT& aEvent ) +{ + const SELECTION& selection = m_selectionTool->GetSelection(); + + if( selection.Size() > 1 ) + { + PCB_BASE_FRAME* editFrame = getEditFrame(); + RN_DATA* ratsnest = getModel()->GetRatsnest(); + + editFrame->OnModify(); + editFrame->SaveCopyInUndoList( selection.items, UR_CHANGED ); + + // Prepare a list, so the items can be sorted by their Y coordinate + std::list itemsList; + for( int i = 0; i < selection.Size(); ++i ) + itemsList.push_back( selection.Item( i ) ); + + // Sort items by Y coordinate + itemsList.sort( compareY ); + + // Expected Y coordinate for the next item (=minY) + int position = (*itemsList.begin())->GetBoundingBox().Centre().y; + + // Y coordinate for the last item + const int maxY = (*itemsList.rbegin())->GetBoundingBox().Centre().y; + + // Distance between items + const int distance = ( maxY - position ) / ( itemsList.size() - 1 ); + + BOOST_FOREACH( BOARD_ITEM* item, itemsList ) + { + int difference = position - item->GetBoundingBox().Centre().y; + + item->Move( wxPoint( 0, difference ) ); + item->ViewUpdate(); + ratsnest->Update( item ); + + position += distance; + } + + getModel()->GetRatsnest()->Recalculate(); + } + + setTransitions(); + + return 0; +} + + +void PLACEMENT_TOOL::setTransitions() +{ + Go( &PLACEMENT_TOOL::AlignTop, COMMON_ACTIONS::alignTop.MakeEvent() ); + Go( &PLACEMENT_TOOL::AlignBottom, COMMON_ACTIONS::alignBottom.MakeEvent() ); + Go( &PLACEMENT_TOOL::AlignLeft, COMMON_ACTIONS::alignLeft.MakeEvent() ); + Go( &PLACEMENT_TOOL::AlignRight, COMMON_ACTIONS::alignRight.MakeEvent() ); + + Go( &PLACEMENT_TOOL::DistributeHorizontally, COMMON_ACTIONS::distributeHorizontally.MakeEvent() ); + Go( &PLACEMENT_TOOL::DistributeVertically, COMMON_ACTIONS::distributeVertically.MakeEvent() ); +} diff --git a/pcbnew/tools/placement_tool.h b/pcbnew/tools/placement_tool.h new file mode 100644 index 0000000000..09f6983ac2 --- /dev/null +++ b/pcbnew/tools/placement_tool.h @@ -0,0 +1,73 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 PLACEMENT_TOOL_H_ +#define PLACEMENT_TOOL_H_ + +#include + +class SELECTION_TOOL; + +/** + * TODO description + */ + +class PLACEMENT_TOOL : public TOOL_INTERACTIVE +{ +public: + PLACEMENT_TOOL(); + virtual ~PLACEMENT_TOOL(); + + /// @copydoc TOOL_INTERACTIVE::Reset() + void Reset( RESET_REASON aReason ) {}; + + /// @copydoc TOOL_INTERACTIVE::Init() + bool Init(); + + /// TODO + int AlignTop( TOOL_EVENT& aEvent ); + + /// TODO + int AlignBottom( TOOL_EVENT& aEvent ); + + /// TODO + int AlignLeft( TOOL_EVENT& aEvent ); + + /// TODO + int AlignRight( TOOL_EVENT& aEvent ); + + /// TODO + int DistributeHorizontally( TOOL_EVENT& aEvent ); + + /// TODO + int DistributeVertically( TOOL_EVENT& aEvent ); + +private: + /// TODO + void setTransitions(); + + SELECTION_TOOL* m_selectionTool; +}; + +#endif /* PLACEMENT_TOOL_H_ */ diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index eab541add2..8951cb3f25 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -36,10 +36,11 @@ #include "point_editor.h" #include -#include +#include #include #include #include +#include // Few constants to avoid using bare numbers for point indices enum SEG_POINTS @@ -77,6 +78,7 @@ public: switch( aItem->Type() ) { case PCB_LINE_T: + case PCB_MODULE_EDGE_T: { const DRAWSEGMENT* segment = static_cast( aItem ); @@ -193,6 +195,9 @@ bool POINT_EDITOR::Init() return false; } + m_selectionTool->AddMenuItem( COMMON_ACTIONS::pointEditorBreakOutline, + POINT_EDITOR::breakOutlineCondition ); + setTransitions(); return true; @@ -201,7 +206,7 @@ bool POINT_EDITOR::Init() int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) { - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + const SELECTION& selection = m_selectionTool->GetSelection(); if( selection.Size() == 1 ) { @@ -209,7 +214,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW* view = getView(); - PCB_EDIT_FRAME* editFrame = getEditFrame(); + PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); EDA_ITEM* item = selection.items.GetPickedItem( 0 ); m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() ); @@ -257,9 +262,10 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) m_dragPoint = point; } - else if( evt->IsDblClick( BUT_LEFT ) ) + else if( evt->IsAction( &COMMON_ACTIONS::pointEditorBreakOutline ) ) { breakOutline( controls->GetCursorPosition() ); + updatePoints(); } else if( evt->IsDrag( BUT_LEFT ) && m_dragPoint ) @@ -309,7 +315,7 @@ int POINT_EDITOR::OnSelectionChange( TOOL_EVENT& aEvent ) if( modified ) // Restore the last change { wxCommandEvent dummy; - editFrame->GetBoardFromUndoList( dummy ); + editFrame->RestoreCopyFromUndoList( dummy ); updatePoints(); modified = false; @@ -354,6 +360,7 @@ void POINT_EDITOR::updateItem() const switch( item->Type() ) { case PCB_LINE_T: + case PCB_MODULE_EDGE_T: { DRAWSEGMENT* segment = static_cast( item ); switch( segment->GetShape() ) @@ -428,6 +435,10 @@ void POINT_EDITOR::updateItem() const break; } + // Update relative coordinates for module edges + if( EDGE_MODULE* edge = dyn_cast( item ) ) + edge->SetLocalCoord(); + break; } @@ -439,8 +450,9 @@ void POINT_EDITOR::updateItem() const for( int i = 0; i < outline->GetCornersCount(); ++i ) { - outline->SetX( i, m_editPoints->Point( i ).GetPosition().x ); - outline->SetY( i, m_editPoints->Point( i ).GetPosition().y ); + VECTOR2I point = m_editPoints->Point( i ).GetPosition(); + outline->SetX( i, point.x ); + outline->SetY( i, point.y ); } break; @@ -514,13 +526,14 @@ void POINT_EDITOR::finishItem() const } -void POINT_EDITOR::updatePoints() const +void POINT_EDITOR::updatePoints() { EDA_ITEM* item = m_editPoints->GetParent(); switch( item->Type() ) { case PCB_LINE_T: + case PCB_MODULE_EDGE_T: { const DRAWSEGMENT* segment = static_cast( item ); { @@ -555,8 +568,17 @@ void POINT_EDITOR::updatePoints() const const ZONE_CONTAINER* zone = static_cast( item ); const CPolyLine* outline = zone->Outline(); - for( int i = 0; i < outline->GetCornersCount(); ++i ) - m_editPoints->Point( i ).SetPosition( outline->GetPos( i ) ); + if( m_editPoints->PointsSize() != (unsigned) outline->GetCornersCount() ) + { + getView()->Remove( m_editPoints.get() ); + m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() ); + getView()->Add( m_editPoints.get() ); + } + else + { + for( int i = 0; i < outline->GetCornersCount(); ++i ) + m_editPoints->Point( i ).SetPosition( outline->GetPos( i ) ); + } break; } @@ -610,6 +632,7 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const switch( item->Type() ) { case PCB_LINE_T: + case PCB_MODULE_EDGE_T: { const DRAWSEGMENT* segment = static_cast( item ); { @@ -657,12 +680,12 @@ EDIT_POINT POINT_EDITOR::get45DegConstrainer() const void POINT_EDITOR::breakOutline( const VECTOR2I& aBreakPoint ) { EDA_ITEM* item = m_editPoints->GetParent(); - const SELECTION_TOOL::SELECTION& selection = m_selectionTool->GetSelection(); + const SELECTION& selection = m_selectionTool->GetSelection(); if( item->Type() == PCB_ZONE_AREA_T ) { - getEditFrame()->OnModify(); - getEditFrame()->SaveCopyInUndoList( selection.items, UR_CHANGED ); + getEditFrame()->OnModify(); + getEditFrame()->SaveCopyInUndoList( selection.items, UR_CHANGED ); ZONE_CONTAINER* zone = static_cast( item ); CPolyLine* outline = zone->Outline(); @@ -700,10 +723,16 @@ void POINT_EDITOR::breakOutline( const VECTOR2I& aBreakPoint ) outline->InsertCorner( nearestIdx, nearestPoint.x, nearestPoint.y ); } - else if( item->Type() == PCB_LINE_T ) + else if( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T ) { - getEditFrame()->OnModify(); - getEditFrame()->SaveCopyInUndoList( selection.items, UR_CHANGED ); + bool moduleEdge = item->Type() == PCB_MODULE_EDGE_T; + + getEditFrame()->OnModify(); + + if( moduleEdge ) + getEditFrame()->SaveCopyInUndoList( getModel()->m_Modules, UR_MODEDIT ); + else + getEditFrame()->SaveCopyInUndoList( selection.items, UR_CHANGED ); DRAWSEGMENT* segment = static_cast( item ); @@ -716,13 +745,56 @@ void POINT_EDITOR::breakOutline( const VECTOR2I& aBreakPoint ) segment->SetEnd( wxPoint( nearestPoint.x, nearestPoint.y ) ); // and add another one starting from the break point - DRAWSEGMENT* newSegment = new DRAWSEGMENT( *segment ); + DRAWSEGMENT* newSegment; + + if( moduleEdge ) + { + EDGE_MODULE* edge = static_cast( segment ); + assert( segment->GetParent()->Type() == PCB_MODULE_T ); + newSegment = new EDGE_MODULE( *edge ); + edge->SetLocalCoord(); + } + else + { + newSegment = new DRAWSEGMENT( *segment ); + } + newSegment->ClearSelected(); newSegment->SetStart( wxPoint( nearestPoint.x, nearestPoint.y ) ); newSegment->SetEnd( wxPoint( seg.B.x, seg.B.y ) ); - getModel()->Add( newSegment ); + if( moduleEdge ) + { + static_cast( newSegment )->SetLocalCoord(); + getModel()->m_Modules->Add( newSegment ); + } + else + { + getModel()->Add( newSegment ); + } + getView()->Add( newSegment ); } } } + + +void POINT_EDITOR::setTransitions() +{ + Go( &POINT_EDITOR::OnSelectionChange, m_selectionTool->SelectedEvent ); + Go( &POINT_EDITOR::OnSelectionChange, m_selectionTool->DeselectedEvent ); +} + + +bool POINT_EDITOR::breakOutlineCondition( const SELECTION& aSelection ) +{ + if( aSelection.Size() != 1 ) + return false; + + BOARD_ITEM* item = aSelection.Item( 0 ); + + // Works only for zones and line segments + return item->Type() == PCB_ZONE_AREA_T || + ( ( item->Type() == PCB_LINE_T || item->Type() == PCB_MODULE_EDGE_T ) && + static_cast( item )->GetShape() == S_SEGMENT ); +} diff --git a/pcbnew/tools/point_editor.h b/pcbnew/tools/point_editor.h index b87224f613..d6f4b30611 100644 --- a/pcbnew/tools/point_editor.h +++ b/pcbnew/tools/point_editor.h @@ -81,7 +81,7 @@ private: void finishItem() const; ///> Updates edit points with item's points. - void updatePoints() const; + void updatePoints(); ///> Returns true if aPoint is the currently modified point. inline bool isModified( const EDIT_POINT& aPoint ) const @@ -95,15 +95,14 @@ private: ///> Returns a point that should be used as a constrainer for 45 degrees mode. EDIT_POINT get45DegConstrainer() const; - ///> Adds a new edit point on a zone outline. + ///> Adds a new edit point on a zone outline/line. void breakOutline( const VECTOR2I& aBreakPoint ); ///> Sets up handlers for various events. - void setTransitions() - { - Go( &POINT_EDITOR::OnSelectionChange, m_selectionTool->SelectedEvent ); - Go( &POINT_EDITOR::OnSelectionChange, m_selectionTool->DeselectedEvent ); - } + void setTransitions(); + + ///> Condition to display "Create corner" context menu entry. + static bool breakOutlineCondition( const SELECTION& aSelection ); }; #endif diff --git a/pcbnew/tools/selection_conditions.cpp b/pcbnew/tools/selection_conditions.cpp new file mode 100644 index 0000000000..fe130b9db4 --- /dev/null +++ b/pcbnew/tools/selection_conditions.cpp @@ -0,0 +1,123 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 "selection_conditions.h" +#include "selection_tool.h" + +#include + + +bool SELECTION_CONDITIONS::NotEmpty( const SELECTION& aSelection ) +{ + return !aSelection.Empty(); +} + + +SELECTION_CONDITION SELECTION_CONDITIONS::HasType( KICAD_T aType ) +{ + return boost::bind( &SELECTION_CONDITIONS::hasTypeFunc, _1, aType ); +} + + +SELECTION_CONDITION SELECTION_CONDITIONS::OnlyType( KICAD_T aType ) +{ + return boost::bind( &SELECTION_CONDITIONS::onlyTypeFunc, _1, aType ); +} + + +SELECTION_CONDITION SELECTION_CONDITIONS::Count( int aNumber ) +{ + return boost::bind( &SELECTION_CONDITIONS::countFunc, _1, aNumber ); +} + + +SELECTION_CONDITION SELECTION_CONDITIONS::MoreThan( int aNumber ) +{ + return boost::bind( &SELECTION_CONDITIONS::moreThanFunc, _1, aNumber ); +} + + +SELECTION_CONDITION SELECTION_CONDITIONS::LessThan( int aNumber ) +{ + return boost::bind( &SELECTION_CONDITIONS::lessThanFunc, _1, aNumber ); +} + + +bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ) +{ + for( int i = 0; i < aSelection.Size(); ++i ) + { + if( aSelection.Item( i )->Type() == aType ) + return true; + } + + return false; +} + + +bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType ) +{ + if( aSelection.Empty() ) + return false; + + for( int i = 0; i < aSelection.Size(); ++i ) + { + if( aSelection.Item( i )->Type() != aType ) + return false; + } + + return true; +} + + +bool SELECTION_CONDITIONS::countFunc( const SELECTION& aSelection, int aNumber ) +{ + return aSelection.Size() == aNumber; +} + + +bool SELECTION_CONDITIONS::moreThanFunc( const SELECTION& aSelection, int aNumber ) +{ + return aSelection.Size() > aNumber; +} + + +bool SELECTION_CONDITIONS::lessThanFunc( const SELECTION& aSelection, int aNumber ) +{ + return aSelection.Size() > aNumber; +} + + +SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ) +{ + return boost::bind( &SELECTION_CONDITIONS::orFunc, aConditionA, aConditionB, _1 ); +} + + +SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ) +{ + return boost::bind( &SELECTION_CONDITIONS::andFunc, aConditionA, aConditionB, _1 ); +} diff --git a/pcbnew/tools/selection_conditions.h b/pcbnew/tools/selection_conditions.h new file mode 100644 index 0000000000..39827b3bd0 --- /dev/null +++ b/pcbnew/tools/selection_conditions.h @@ -0,0 +1,148 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 CERN + * @author Maciej Suminski + * + * 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 SELECTION_CONDITIONS_H_ +#define SELECTION_CONDITIONS_H_ + +#include +#include + +class SELECTION; + +///> Functor type that checks a specific condition for selected items. +typedef boost::function SELECTION_CONDITION; + +SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ); + +SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ); + + +/** + * Class that groups generic conditions for selected items. + */ +class SELECTION_CONDITIONS +{ +public: + /** + * Function ShowAlways + * The default condition function (always returns true). + * @param aSelection is the selection to be tested. + * @return Always true; + */ + static bool ShowAlways( const SELECTION& aSelection ) + { + return true; + } + + /** + * Function NotEmpty + * Tests if there are any items selected. + * @param aSelection is the selection to be tested. + * @return True if there is at least one item selected. + */ + static bool NotEmpty( const SELECTION& aSelection ); + + /** + * Function HasType + * Creates functor that tests if among the selected items there is at least one of a given type. + * @param aType is the type that is searched. + * @return Functor testing for presence of items of a given type. + */ + static SELECTION_CONDITION HasType( KICAD_T aType ); + + /** + * Function OnlyType + * Creates functor that tests if the selected items are *only* of given type. + * @param aType is the type that is searched. + * @return Functor testing if selected items are exclusively of one type.. + */ + static SELECTION_CONDITION OnlyType( KICAD_T aType ); + + /** + * Function Count + * Creates functor that tests if the number of selected items is equal to the value given as + * parameter. + * @param aNumber is the number of expected items. + * @return Functor testing if the number of selected items is equal aNumber. + */ + static SELECTION_CONDITION Count( int aNumber ); + + /** + * Function MoreThan + * Creates functor that tests if the number of selected items is greater than the value given + * as parameter. + * @param aNumber is the number used for comparison. + * @return Functor testing if the number of selected items is greater than aNumber. + */ + static SELECTION_CONDITION MoreThan( int aNumber ); + + /** + * Function LessThan + * Creates functor that tests if the number of selected items is smaller than the value given + * as parameter. + * @param aNumber is the number used for comparison. + * @return Functor testing if the number of selected items is smaller than aNumber. + */ + static SELECTION_CONDITION LessThan( int aNumber ); + +private: + ///> Helper function used by HasType() + static bool hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ); + + ///> Helper function used by OnlyType() + static bool onlyTypeFunc( const SELECTION& aSelection, KICAD_T aType ); + + ///> Helper function used by Count() + static bool countFunc( const SELECTION& aSelection, int aNumber ); + + ///> Helper function used by MoreThan() + static bool moreThanFunc( const SELECTION& aSelection, int aNumber ); + + ///> Helper function used by LessThan() + static bool lessThanFunc( const SELECTION& aSelection, int aNumber ); + + ///> Helper function used by operator|| + static bool orFunc( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection ) + { + return aConditionA( aSelection ) || aConditionB( aSelection ); + } + + ///> Helper function used by operator&& + static bool andFunc( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB, const SELECTION& aSelection ) + { + return aConditionA( aSelection ) && aConditionB( aSelection ); + } + + friend SELECTION_CONDITION operator||( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ); + + friend SELECTION_CONDITION operator&&( const SELECTION_CONDITION& aConditionA, + const SELECTION_CONDITION& aConditionB ); +}; + +#endif /* SELECTION_CONDITIONS_H_ */ diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 34f8c5b6f9..13151cdf65 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -24,11 +24,8 @@ */ #include -#include #include -#include -#include #include #include #include @@ -36,6 +33,9 @@ #include #include +#include + +#include #include #include #include @@ -48,14 +48,13 @@ #include "bright_box.h" #include "common_actions.h" -using boost::optional; - SELECTION_TOOL::SELECTION_TOOL() : TOOL_INTERACTIVE( "pcbnew.InteractiveSelection" ), SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" ), DeselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.deselected" ), ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" ), - m_additive( false ), m_multiple( false ) + m_frame( NULL ), m_additive( false ), m_multiple( false ), + m_editModules( false ), m_locked( true ) { m_selArea = new SELECTION_AREA; m_selection.group = new KIGFX::VIEW_GROUP; @@ -79,12 +78,14 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) // Restore previous properties of selected items and remove them from containers clearSelection(); + m_frame = getEditFrame(); + m_locked = true; + // Reinsert the VIEW_GROUP, in case it was removed from the VIEW getView()->Remove( m_selection.group ); getView()->Add( m_selection.group ); - // The tool launches upon reception of action event ("pcbnew.InteractiveSelection") - Go( &SELECTION_TOOL::Main, COMMON_ACTIONS::selectionActivate.MakeEvent() ); + setTransitions(); } @@ -97,20 +98,8 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) // become the new selection (discarding previously selected items) m_additive = evt->Modifier( MD_SHIFT ); - if( evt->IsAction( &COMMON_ACTIONS::selectionSingle ) ) - { - // GetMousePosition() is used, as it is independent of snapping settings - selectSingle( getView()->ToWorld( getViewControls()->GetMousePosition() ) ); - } - - else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO || - evt->IsAction( &COMMON_ACTIONS::selectionClear ) ) - { - clearSelection(); - } - // single click? Select single object - else if( evt->IsClick( BUT_LEFT ) ) + if( evt->IsClick( BUT_LEFT ) ) { if( evt->Modifier( MD_CTRL ) ) { @@ -131,8 +120,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) if( m_selection.Empty() ) selectSingle( evt->Position() ); - if( !m_selection.Empty() ) - SetContextMenu( &m_menu, CMENU_NOW ); + generateMenu(); } // double click? Display the properties window @@ -181,6 +169,18 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) } } } + + else if( evt->IsAction( &COMMON_ACTIONS::selectionSingle ) ) + { + // GetMousePosition() is used, as it is independent of snapping settings + selectSingle( getView()->ToWorld( getViewControls()->GetMousePosition() ) ); + } + + else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO || + evt->IsAction( &COMMON_ACTIONS::selectionClear ) ) + { + clearSelection(); + } } // This tool is supposed to be active forever @@ -190,11 +190,19 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent ) } -void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction ) +void SELECTION_TOOL::AddMenuItem( const TOOL_ACTION& aAction, const SELECTION_CONDITION& aCondition ) { assert( aAction.GetId() > 0 ); // Check if the action was registered before in ACTION_MANAGER m_menu.Add( aAction ); + m_menuConditions.push_back( aCondition ); +} + + +void SELECTION_TOOL::AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel, const SELECTION_CONDITION& aCondition ) +{ + m_menu.AppendSubMenu( aMenu, aLabel ); + m_menuConditions.push_back( aCondition ); } @@ -228,14 +236,19 @@ void SELECTION_TOOL::toggleSelection( BOARD_ITEM* aItem ) bool SELECTION_TOOL::selectSingle( const VECTOR2I& aWhere, bool aAllowDisambiguation ) { - BOARD* pcb = getModel(); BOARD_ITEM* item; - GENERAL_COLLECTORS_GUIDE guide = getEditFrame()->GetCollectorsGuide(); + GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide(); GENERAL_COLLECTOR collector; - const KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_LINE_T, EOT }; // preferred types - collector.Collect( pcb, GENERAL_COLLECTOR::AllBoardItems, - wxPoint( aWhere.x, aWhere.y ), guide ); + // Preferred types (they have the priority when if they are covered by a bigger item) + const KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, PCB_LINE_T, PCB_MODULE_TEXT_T, EOT }; + + if( m_editModules ) + collector.Collect( getModel(), GENERAL_COLLECTOR::ModuleItems, + wxPoint( aWhere.x, aWhere.y ), guide ); + else + collector.Collect( getModel(), GENERAL_COLLECTOR::AllBoardItems, + wxPoint( aWhere.x, aWhere.y ), guide ); switch( collector.GetCount() ) { @@ -347,7 +360,7 @@ bool SELECTION_TOOL::selectMultiple() } // Do not display information about selected item,as there is more than one - getEditFrame()->SetCurItem( NULL ); + m_frame->SetCurItem( NULL ); if( !m_selection.Empty() ) { @@ -368,6 +381,74 @@ bool SELECTION_TOOL::selectMultiple() } +void SELECTION_TOOL::setTransitions() +{ + Go( &SELECTION_TOOL::Main, COMMON_ACTIONS::selectionActivate.MakeEvent() ); + Go( &SELECTION_TOOL::SingleSelection, COMMON_ACTIONS::selectionSingle.MakeEvent() ); + Go( &SELECTION_TOOL::ClearSelection, COMMON_ACTIONS::selectionClear.MakeEvent() ); +} + + +bool SELECTION_TOOL::CheckLock() +{ + if( !m_locked ) + return false; + + bool containsLocked = false; + + // Check if the selection contains locked items + for( int i = 0; i < m_selection.Size(); ++i ) + { + BOARD_ITEM* item = m_selection.Item( i ); + + switch( item->Type() ) + { + case PCB_MODULE_T: + if( static_cast( item )->IsLocked() ) + containsLocked = true; + break; + + case PCB_MODULE_EDGE_T: + case PCB_MODULE_TEXT_T: + if( static_cast( item->GetParent() )->IsLocked() ) + containsLocked = true; + break; + + default: // suppress warnings + break; + } + } + + if( containsLocked && + !IsOK( m_frame, _( "Selection contains locked items. Do you want to continue?" ) ) ) + { + return true; + } + + m_locked = false; + + return false; +} + + +int SELECTION_TOOL::SingleSelection( TOOL_EVENT& aEvent ) +{ + selectSingle( getView()->ToWorld( getViewControls()->GetMousePosition() ) ); + setTransitions(); + + return 0; +} + + +int SELECTION_TOOL::ClearSelection( TOOL_EVENT& aEvent ) +{ + clearSelection(); + setTransitions(); + + return 0; +} + + void SELECTION_TOOL::clearSelection() { if( m_selection.Empty() ) @@ -385,14 +466,14 @@ void SELECTION_TOOL::clearSelection() } m_selection.clear(); - getEditFrame()->SetCurItem( NULL ); - - // Do not show the context menu when there is nothing selected - SetContextMenu( &m_menu, CMENU_OFF ); + m_frame->SetCurItem( NULL ); + m_locked = true; // Inform other potentially interested tools TOOL_EVENT clearEvent( ClearedEvent ); m_toolMgr->ProcessEvent( clearEvent ); + + return; } @@ -437,7 +518,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) } else if( evt->Action() == TA_CONTEXT_MENU_CHOICE ) { - optional id = evt->GetCommandId(); + boost::optional id = evt->GetCommandId(); // User has selected an item, so this one will be returned if( id && ( *id >= 0 ) ) @@ -541,23 +622,25 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const case PCB_MODULE_T: if( aItem->IsOnLayer( F_Cu ) && board->IsElementVisible( MOD_FR_VISIBLE ) ) - return true; + return !m_editModules; if( aItem->IsOnLayer( B_Cu ) && board->IsElementVisible( MOD_BK_VISIBLE ) ) - return true; + return !m_editModules; return false; break; case PCB_MODULE_TEXT_T: - if( m_multiple ) + if( m_multiple && !m_editModules ) return false; break; // These are not selectable case PCB_MODULE_EDGE_T: case PCB_PAD_T: + return m_editModules; + case NOT_USED: case TYPE_NOT_INIT: return false; @@ -585,19 +668,15 @@ void SELECTION_TOOL::select( BOARD_ITEM* aItem ) ITEM_PICKER picker( aItem ); m_selection.items.PushItem( picker ); - // It is enough to do it only for the first selected item if( m_selection.Size() == 1 ) { // Set as the current item, so the information about selection is displayed - getEditFrame()->SetCurItem( aItem, true ); - - // Now the context menu should be enabled - SetContextMenu( &m_menu, CMENU_BUTTON ); + m_frame->SetCurItem( aItem, true ); } else if( m_selection.Size() == 2 ) // Check only for 2, so it will not be { // called for every next selected item // If multiple items are selected, do not show the information about the selected item - getEditFrame()->SetCurItem( NULL, true ); + m_frame->SetCurItem( NULL, true ); } } @@ -618,11 +697,10 @@ void SELECTION_TOOL::deselect( BOARD_ITEM* aItem ) if( itemIdx >= 0 ) m_selection.items.RemovePicker( itemIdx ); - // If there is nothing selected, disable the context menu if( m_selection.Empty() ) { - SetContextMenu( &m_menu, CMENU_OFF ); - getEditFrame()->SetCurItem( NULL ); + m_frame->SetCurItem( NULL ); + m_locked = true; } // Inform other potentially interested tools @@ -674,7 +752,7 @@ bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const void SELECTION_TOOL::highlightNet( const VECTOR2I& aPoint ) { KIGFX::RENDER_SETTINGS* render = getView()->GetPainter()->GetSettings(); - GENERAL_COLLECTORS_GUIDE guide = getEditFrame()->GetCollectorsGuide(); + GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide(); GENERAL_COLLECTOR collector; int net = -1; @@ -727,7 +805,29 @@ BOARD_ITEM* SELECTION_TOOL::prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T } -void SELECTION_TOOL::SELECTION::clear() +void SELECTION_TOOL::generateMenu() +{ + // Create a copy of the master context menu + m_menuCopy = m_menu; + + assert( m_menuCopy.GetMenuItemCount() == m_menuConditions.size() ); + + // Filter out entries that does not apply to the current selection + for( int i = m_menuCopy.GetMenuItemCount() - 1; i >= 0; --i ) + { + if( !m_menuConditions[i]( m_selection ) ) + { + wxMenuItem* item = m_menuCopy.FindItemByPosition( i ); + m_menuCopy.Destroy( item ); + } + } + + if( m_menuCopy.GetMenuItemCount() > 0 ) + SetContextMenu( &m_menuCopy, CMENU_NOW ); +} + + +void SELECTION::clear() { items.ClearItemsList(); group->Clear(); diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 9fe3d32b53..beceefee5d 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -31,6 +31,9 @@ #include #include +#include "selection_conditions.h" + +class PCB_BASE_FRAME; class SELECTION_AREA; class BOARD_ITEM; class GENERAL_COLLECTOR; @@ -40,6 +43,41 @@ namespace KIGFX class VIEW_GROUP; } +struct SELECTION +{ + /// Set of selected items + PICKED_ITEMS_LIST items; + + /// VIEW_GROUP that holds currently selected items + KIGFX::VIEW_GROUP* group; + + /// Checks if there is anything selected + bool Empty() const + { + return ( items.GetCount() == 0 ); + } + + /// Returns the number of selected parts + int Size() const + { + return items.GetCount(); + } + + /// Alias to make code shorter and clearer + template + T* Item( unsigned int aIndex ) const + { + return static_cast( items.GetPickedItem( aIndex ) ); + } + +private: + /// Clears both the VIEW_GROUP and set of selected items. Please note that it does not + /// change properties of selected items (e.g. selection flag). + void clear(); + + friend class SELECTION_TOOL; +}; + /** * Class SELECTION_TOOL * @@ -47,52 +85,16 @@ class VIEW_GROUP; * - pick single objects (click LMB) * - add objects to existing selection (Shift+LMB) * - draw selection box (drag LMB) - * - handles MODULEs properly (ie. selects either MODULE or its PADs, TEXTs, etc.) + * - handles MODULEs properly (i.e. selects either MODULE or its PADs, TEXTs, etc.) * - takes into account high-contrast & layer visibility settings * - invokes InteractiveEdit tool when user starts to drag selected items */ - class SELECTION_TOOL : public TOOL_INTERACTIVE { public: SELECTION_TOOL(); ~SELECTION_TOOL(); - struct SELECTION - { - /// Set of selected items - PICKED_ITEMS_LIST items; - - /// VIEW_GROUP that holds currently selected items - KIGFX::VIEW_GROUP* group; - - /// Checks if there is anything selected - bool Empty() const - { - return ( items.GetCount() == 0 ); - } - - /// Returns the number of selected parts - int Size() const - { - return items.GetCount(); - } - - /// Alias to make code shorter and clearer - template - T* Item( unsigned int aIndex ) const - { - return static_cast( items.GetPickedItem( aIndex ) ); - } - - private: - /// Clears both the VIEW_GROUP and set of selected items. Please note that it does not - /// change properties of selected items (e.g. selection flag). - void clear(); - - friend class SELECTION_TOOL; - }; - /// @copydoc TOOL_INTERACTIVE::Reset() void Reset( RESET_REASON aReason ); @@ -118,8 +120,42 @@ public: * * Adds a menu entry to run a TOOL_ACTION on selected items. * @param aAction is a menu entry to be added. + * @param aCondition is a condition that has to be fulfilled to enable the menu entry. */ - void AddMenuItem( const TOOL_ACTION& aAction ); + void AddMenuItem( const TOOL_ACTION& aAction, + const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways ); + + /** + * Function AddSubMenu() + * + * Adds a submenu to the selection tool right-click context menu. + * @param aMenu is the submenu to be added. + * @param aLabel is the label of added submenu. + * @param aCondition is a condition that has to be fulfilled to enable the submenu entry. + */ + void AddSubMenu( CONTEXT_MENU* aMenu, const wxString& aLabel, + const SELECTION_CONDITION& aCondition = SELECTION_CONDITIONS::ShowAlways ); + + /** + * Function EditModules() + * + * Toggles edit module mode. When enabled, one may select parts of modules individually + * (graphics, pads, etc.), so they can be modified. + * @param aEnabled decides if the mode should be enabled. + */ + void EditModules( bool aEnabled ) + { + m_editModules = aEnabled; + } + + ///> Checks if the user has agreed to modify locked items for the given selection. + bool CheckLock(); + + ///> Select single item event handler. + int SingleSelection( TOOL_EVENT& aEvent ); + + ///> Clear current selection event handler. + int ClearSelection( TOOL_EVENT& aEvent ); ///> Event sent after an item is selected. const TOOL_EVENT SelectedEvent; @@ -147,10 +183,13 @@ private: * Function selectMultiple() * Handles drawing a selection box that allows to select many items at the same time. * - * @return true if the function was cancelled (ie. CancelEvent was received). + * @return true if the function was cancelled (i.e. CancelEvent was received). */ bool selectMultiple(); + ///> Sets up handlers for various events. + void setTransitions(); + /** * Function ClearSelection() * Clears the current selection. @@ -246,20 +285,42 @@ private: */ BOARD_ITEM* prefer( GENERAL_COLLECTOR& aCollector, const KICAD_T aTypes[] ) const; - /// Visual representation of selection box + /** + * Function generateMenu() + * Creates a copy of context menu that is filtered by menu conditions and displayed to + * the user. + */ + void generateMenu(); + + /// Pointer to the parent frame. + PCB_BASE_FRAME* m_frame; + + /// Visual representation of selection box. SELECTION_AREA* m_selArea; - /// Current state of selection + /// Current state of selection. SELECTION m_selection; - /// Flag saying if items should be added to the current selection or rather replace it + /// Flag saying if items should be added to the current selection or rather replace it. bool m_additive; - /// Flag saying if multiple selection mode is active + /// Flag saying if multiple selection mode is active. bool m_multiple; - /// Right click popup menu + /// Right click popup menu (master instance). CONTEXT_MENU m_menu; + + /// Copy of the context menu that is filtered by menu conditions and displayed to the user. + CONTEXT_MENU m_menuCopy; + + /// Edit module mode flag. + bool m_editModules; + + /// Can other tools modify locked items. + bool m_locked; + + /// Conditions for specific context menu entries. + std::deque m_menuConditions; }; #endif diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index 13b1203b66..4d2117592e 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -297,13 +297,13 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList( BOARD* aPcb ) /* Add module edge items that are on copper layers * Pcbnew allows these items to be on copper layers in microwave applictions - * This is a bad thing, but must be handle here, until a better way is found + * This is a bad thing, but must be handled here, until a better way is found */ for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { - if( !item->IsOnLayer( GetLayer() ) ) + if( !item->IsOnLayer( GetLayer() ) && !item->IsOnLayer( Edge_Cuts ) ) continue; if( item->Type() != PCB_MODULE_EDGE_T )