diff --git a/CMakeLists.txt b/CMakeLists.txt index 42afeabcb1..8d71af2c60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -531,6 +531,7 @@ endif() # Find Cairo library, required # find_package( Cairo 1.8.8 REQUIRED ) +find_package( Pixman 1.0 REQUIRED ) # # Find Boost library, required. diff --git a/CMakeModules/FindPixman.cmake b/CMakeModules/FindPixman.cmake new file mode 100644 index 0000000000..18e0c399eb --- /dev/null +++ b/CMakeModules/FindPixman.cmake @@ -0,0 +1,40 @@ +# - Find Pixman +# Find the Pixman libraries +# +# This module defines the following variables: +# PIXMAN_FOUND - true if PIXMAN_INCLUDE_DIR & PIXMAN_LIBRARY are found +# PIXMAN_LIBRARIES - Set when PIXMAN_LIBRARY is found +# PIXMAN_INCLUDE_DIRS - Set when PIXMAN_INCLUDE_DIR is found +# +# PIXMAN_INCLUDE_DIR - where to find pixman.h, etc. +# PIXMAN_LIBRARY - the Pixman library +# + +#============================================================================= +# Copyright 2013 Marc-Andre Moreau +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +find_path(PIXMAN_INCLUDE_DIR NAMES pixman.h PATH_SUFFIXES pixman-1) + +find_library(PIXMAN_LIBRARY NAMES pixman-1) + +find_package_handle_standard_args(pixman-1 DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR) + +if(PIXMAN-1_FOUND) + set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY}) + set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR}) +endif() + +mark_as_advanced(PIXMAN_INCLUDE_DIR PIXMAN_LIBRARY) \ No newline at end of file diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index c89470c55a..034fa552dd 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ./widgets ./dialog_about ${CAIRO_INCLUDE_DIR} + ${PIXMAN_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} ${GLM_INCLUDE_DIR} ${CURL_INCLUDE_DIRS} diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp index f81cb5a0bd..813c554c76 100644 --- a/common/gal/cairo/cairo_compositor.cpp +++ b/common/gal/cairo/cairo_compositor.cpp @@ -89,7 +89,7 @@ unsigned int CAIRO_COMPOSITOR::CreateBuffer() #endif /* __WXDEBUG__ */ // Set default settings for the buffer - cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); + cairo_set_antialias( context, CAIRO_ANTIALIAS_NONE ); cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND ); cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND ); diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 0328eccb82..d9c765b355 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -33,11 +33,11 @@ #include +#include + using namespace KIGFX; -const float CAIRO_GAL::LAYER_ALPHA = 0.8; - CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener, const wxString& aName ) : @@ -109,9 +109,6 @@ void CAIRO_GAL::BeginDrawing() compositor->SetMainContext( context ); compositor->SetBuffer( mainBuffer ); - - // Cairo grouping prevents display of overlapping items on the same layer in the lighter color - cairo_push_group( currentContext ); } @@ -120,37 +117,32 @@ void CAIRO_GAL::EndDrawing() // Force remaining objects to be drawn Flush(); - // Cairo grouping prevents display of overlapping items on the same layer in the lighter color - cairo_pop_group_to_source( currentContext ); - cairo_paint_with_alpha( currentContext, LAYER_ALPHA ); - // Merge buffers on the screen compositor->DrawBuffer( mainBuffer ); compositor->DrawBuffer( overlayBuffer ); - // This code was taken from the wxCairo example - it's not the most efficient one - // Here is a good place for optimizations - // Now translate the raw context data from the format stored // by cairo into a format understood by wxImage. - unsigned char* wxOutputPtr = wxOutput; + pixman_image_t* dstImg = pixman_image_create_bits(PIXMAN_r8g8b8, + screenSize.x, screenSize.y, (uint32_t*)wxOutput, wxBufferWidth * 3 ); + pixman_image_t* srcImg = pixman_image_create_bits(PIXMAN_a8b8g8r8, + screenSize.x, screenSize.y, (uint32_t*)bitmapBuffer, wxBufferWidth * 4 ); - for( size_t count = 0; count < bufferSize; count++ ) - { - unsigned int value = bitmapBuffer[count]; - *wxOutputPtr++ = ( value >> 16 ) & 0xff; // Red pixel - *wxOutputPtr++ = ( value >> 8 ) & 0xff; // Green pixel - *wxOutputPtr++ = value & 0xff; // Blue pixel - } + pixman_image_composite (PIXMAN_OP_SRC, srcImg, NULL, dstImg, + 0, 0, 0, 0, 0, 0, screenSize.x, screenSize.y ); - wxImage img( screenSize.x, screenSize.y, (unsigned char*) wxOutput, true ); - wxBitmap bmp( img ); - wxClientDC client_dc( this ); - wxBufferedDC dc; - dc.Init( &client_dc, bmp ); + // Free allocated memory + pixman_image_unref( srcImg ); + pixman_image_unref( dstImg ); + + wxImage img( wxBufferWidth, screenSize.y, (unsigned char*) wxOutput, true ); + wxBitmap bmp( img ); + wxMemoryDC mdc( bmp ); + wxClientDC clientDC( this ); // Now it is the time to blit the mouse cursor - blitCursor( dc ); + blitCursor( mdc ); + clientDC.Blit( 0, 0, screenSize.x, screenSize.y, &mdc, 0, 0, wxCOPY ); deinitSurface(); } @@ -160,6 +152,7 @@ void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint { cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); + flushPath(); isElementAdded = true; } @@ -174,6 +167,8 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo cairo_move_to( currentContext, (double) aStartPoint.x, (double) aStartPoint.y ); cairo_line_to( currentContext, (double) aEndPoint.x, (double) aEndPoint.y ); + cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a ); + cairo_stroke( currentContext ); } else { @@ -197,6 +192,7 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo cairo_line_to( currentContext, lineLength, -aWidth / 2.0 ); cairo_restore( currentContext ); + flushPath(); } isElementAdded = true; @@ -205,10 +201,9 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo void CAIRO_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) { - // A circle is drawn using an arc cairo_new_sub_path( currentContext ); cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI ); - + flushPath(); isElementAdded = true; } @@ -234,6 +229,8 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS cairo_close_path( currentContext ); } + flushPath(); + isElementAdded = true; } @@ -250,6 +247,7 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y ); cairo_close_path( currentContext ); + flushPath(); isElementAdded = true; } @@ -263,6 +261,7 @@ void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControl aControlPointB.y, aEndPoint.x, aEndPoint.y ); cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); + flushPath(); isElementAdded = true; } @@ -319,7 +318,7 @@ void CAIRO_GAL::SetIsFill( bool aIsFillEnabled ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SET_FILL; - groupElement.boolArgument = aIsFillEnabled; + groupElement.argument.boolArg = aIsFillEnabled; currentGroup->push_back( groupElement ); } } @@ -334,7 +333,7 @@ void CAIRO_GAL::SetIsStroke( bool aIsStrokeEnabled ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SET_STROKE; - groupElement.boolArgument = aIsStrokeEnabled; + groupElement.argument.boolArg = aIsStrokeEnabled; currentGroup->push_back( groupElement ); } } @@ -349,10 +348,10 @@ void CAIRO_GAL::SetStrokeColor( const COLOR4D& aColor ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SET_STROKECOLOR; - groupElement.arguments[0] = strokeColor.r; - groupElement.arguments[1] = strokeColor.g; - groupElement.arguments[2] = strokeColor.b; - groupElement.arguments[3] = strokeColor.a; + groupElement.argument.dblArg[0] = strokeColor.r; + groupElement.argument.dblArg[1] = strokeColor.g; + groupElement.argument.dblArg[2] = strokeColor.b; + groupElement.argument.dblArg[3] = strokeColor.a; currentGroup->push_back( groupElement ); } } @@ -367,10 +366,10 @@ void CAIRO_GAL::SetFillColor( const COLOR4D& aColor ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SET_FILLCOLOR; - groupElement.arguments[0] = fillColor.r; - groupElement.arguments[1] = fillColor.g; - groupElement.arguments[2] = fillColor.b; - groupElement.arguments[3] = fillColor.a; + groupElement.argument.dblArg[0] = fillColor.r; + groupElement.argument.dblArg[1] = fillColor.g; + groupElement.argument.dblArg[2] = fillColor.b; + groupElement.argument.dblArg[3] = fillColor.a; currentGroup->push_back( groupElement ); } } @@ -386,7 +385,7 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SET_LINE_WIDTH; - groupElement.arguments[0] = aLineWidth; + groupElement.argument.dblArg[0] = aLineWidth; currentGroup->push_back( groupElement ); } else @@ -405,14 +404,7 @@ void CAIRO_GAL::SetLayerDepth( double aLayerDepth ) super::SetLayerDepth( aLayerDepth ); if( isInitialized ) - { storePath(); - - cairo_pop_group_to_source( currentContext ); - cairo_paint_with_alpha( currentContext, LAYER_ALPHA ); - - cairo_push_group( currentContext ); - } } @@ -440,7 +432,7 @@ void CAIRO_GAL::Rotate( double aAngle ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_ROTATE; - groupElement.arguments[0] = aAngle; + groupElement.argument.dblArg[0] = aAngle; currentGroup->push_back( groupElement ); } else @@ -458,8 +450,8 @@ void CAIRO_GAL::Translate( const VECTOR2D& aTranslation ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_TRANSLATE; - groupElement.arguments[0] = aTranslation.x; - groupElement.arguments[1] = aTranslation.y; + groupElement.argument.dblArg[0] = aTranslation.x; + groupElement.argument.dblArg[1] = aTranslation.y; currentGroup->push_back( groupElement ); } else @@ -477,8 +469,8 @@ void CAIRO_GAL::Scale( const VECTOR2D& aScale ) { GROUP_ELEMENT groupElement; groupElement.command = CMD_SCALE; - groupElement.arguments[0] = aScale.x; - groupElement.arguments[1] = aScale.y; + groupElement.argument.dblArg[0] = aScale.x; + groupElement.argument.dblArg[1] = aScale.y; currentGroup->push_back( groupElement ); } else @@ -562,21 +554,21 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) switch( it->command ) { case CMD_SET_FILL: - isFillEnabled = it->boolArgument; + isFillEnabled = it->argument.boolArg; break; case CMD_SET_STROKE: - isStrokeEnabled = it->boolArgument; + isStrokeEnabled = it->argument.boolArg; break; case CMD_SET_FILLCOLOR: - fillColor = COLOR4D( it->arguments[0], it->arguments[1], it->arguments[2], - it->arguments[3] ); + fillColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2], + it->argument.dblArg[3] ); break; case CMD_SET_STROKECOLOR: - strokeColor = COLOR4D( it->arguments[0], it->arguments[1], it->arguments[2], - it->arguments[3] ); + strokeColor = COLOR4D( it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2], + it->argument.dblArg[3] ); break; case CMD_SET_LINE_WIDTH: @@ -585,7 +577,7 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) double x = 1.0, y = 1.0; cairo_device_to_user_distance( currentContext, &x, &y ); double minWidth = std::min( fabs( x ), fabs( y ) ); - cairo_set_line_width( currentContext, std::max( it->arguments[0], minWidth ) ); + cairo_set_line_width( currentContext, std::max( it->argument.dblArg[0], minWidth ) ); } break; @@ -602,23 +594,25 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) cairo_fill( currentContext ); break; + /* case CMD_TRANSFORM: cairo_matrix_t matrix; - cairo_matrix_init( &matrix, it->arguments[0], it->arguments[1], it->arguments[2], - it->arguments[3], it->arguments[4], it->arguments[5] ); + cairo_matrix_init( &matrix, it->argument.dblArg[0], it->argument.dblArg[1], it->argument.dblArg[2], + it->argument.dblArg[3], it->argument.dblArg[4], it->argument.dblArg[5] ); cairo_transform( currentContext, &matrix ); break; + */ case CMD_ROTATE: - cairo_rotate( currentContext, it->arguments[0] ); + cairo_rotate( currentContext, it->argument.dblArg[0] ); break; case CMD_TRANSLATE: - cairo_translate( currentContext, it->arguments[0], it->arguments[1] ); + cairo_translate( currentContext, it->argument.dblArg[0], it->argument.dblArg[1] ); break; case CMD_SCALE: - cairo_scale( currentContext, it->arguments[0], it->arguments[1] ); + cairo_scale( currentContext, it->argument.dblArg[0], it->argument.dblArg[1] ); break; case CMD_SAVE: @@ -630,7 +624,7 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) break; case CMD_CALL_GROUP: - DrawGroup( it->intArgument ); + DrawGroup( it->argument.intArg ); break; } } @@ -646,10 +640,10 @@ void CAIRO_GAL::ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor ) { if( it->command == CMD_SET_FILLCOLOR || it->command == CMD_SET_STROKECOLOR ) { - it->arguments[0] = aNewColor.r; - it->arguments[1] = aNewColor.g; - it->arguments[2] = aNewColor.b; - it->arguments[3] = aNewColor.a; + it->argument.dblArg[0] = aNewColor.r; + it->argument.dblArg[1] = aNewColor.g; + it->argument.dblArg[2] = aNewColor.b; + it->argument.dblArg[3] = aNewColor.a; } } } @@ -731,13 +725,8 @@ void CAIRO_GAL::SetTarget( RENDER_TARGET aTarget ) // Cairo grouping prevents display of overlapping items on the same layer in the lighter color if( isInitialized ) - { storePath(); - cairo_pop_group_to_source( currentContext ); - cairo_paint_with_alpha( currentContext, LAYER_ALPHA ); - } - switch( aTarget ) { default: @@ -751,9 +740,6 @@ void CAIRO_GAL::SetTarget( RENDER_TARGET aTarget ) break; } - if( isInitialized ) - cairo_push_group( currentContext ); - currentTarget = aTarget; } @@ -799,10 +785,7 @@ void CAIRO_GAL::SetCursorSize( unsigned int aCursorSize ) void CAIRO_GAL::DrawCursor( const VECTOR2D& aCursorPosition ) { - // Now we should only store the position of the mouse cursor - // The real drawing routines are in blitCursor() - cursorPosition = VECTOR2D( aCursorPosition.x - cursorSize / 2, - aCursorPosition.y - cursorSize / 2 ); + cursorPosition = aCursorPosition; } @@ -810,11 +793,33 @@ void CAIRO_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP { cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); - cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b ); + cairo_set_source_rgba( currentContext, gridColor.r, gridColor.g, gridColor.b, strokeColor.a ); cairo_stroke( currentContext ); } +void CAIRO_GAL::flushPath() +{ + if( isFillEnabled ) + { + cairo_set_source_rgba( currentContext, + fillColor.r, fillColor.g, fillColor.b, fillColor.a ); + + if( isStrokeEnabled ) + cairo_fill_preserve( currentContext ); + else + cairo_fill( currentContext ); + } + + if( isStrokeEnabled ) + { + cairo_set_source_rgba( currentContext, + strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); + cairo_stroke( currentContext ); + } +} + + void CAIRO_GAL::storePath() { if( isElementAdded ) @@ -902,47 +907,32 @@ void CAIRO_GAL::initCursor() } -void CAIRO_GAL::blitCursor( wxBufferedDC& clientDC ) +void CAIRO_GAL::blitCursor( wxMemoryDC& clientDC ) { if( !isCursorEnabled ) return; - wxMemoryDC cursorSave( *cursorPixelsSaved ); - wxMemoryDC cursorShape( *cursorPixels ); + auto p = ToScreen( cursorPosition ); - if( !isDeleteSavedPixels ) - { - // Restore pixels that were overpainted by the previous cursor - clientDC.Blit( savedCursorPosition.x, savedCursorPosition.y, - cursorSize, cursorSize, &cursorSave, 0, 0 ); - } - else - { - isDeleteSavedPixels = false; - } + clientDC.SetPen( *wxWHITE_PEN ); + clientDC.DrawLine( p.x - cursorSize / 2, p.y, p.x + cursorSize / 2, p.y ); + clientDC.DrawLine( p.x, p.y - cursorSize / 2, p.x, p.y + cursorSize / 2 ); - // Store pixels that are going to be overpainted - VECTOR2D cursorScreen = ToScreen( cursorPosition ) - cursorSize / 2.0f; - cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, cursorScreen.x, cursorScreen.y ); - - // Draw the cursor - clientDC.Blit( cursorScreen.x, cursorScreen.y, cursorSize, cursorSize, - &cursorShape, 0, 0, wxOR ); - - savedCursorPosition.x = (wxCoord) cursorScreen.x; - savedCursorPosition.y = (wxCoord) cursorScreen.y; } void CAIRO_GAL::allocateBitmaps() { + wxBufferWidth = screenSize.x; + while( ( ( wxBufferWidth * 3 ) % 4 ) != 0 ) wxBufferWidth++; + // Create buffer, use the system independent Cairo context backend - stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x ); + stride = cairo_format_stride_for_width( GAL_FORMAT, wxBufferWidth ); bufferSize = stride * screenSize.y; bitmapBuffer = new unsigned int[bufferSize]; bitmapBufferBackup = new unsigned int[bufferSize]; - wxOutput = new unsigned char[bufferSize * 3]; + wxOutput = new unsigned char[wxBufferWidth * 3 * screenSize.y]; } @@ -961,7 +951,7 @@ void CAIRO_GAL::initSurface() // Create the Cairo surface surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT, - screenSize.x, screenSize.y, stride ); + wxBufferWidth, screenSize.y, stride ); context = cairo_create( surface ); #ifdef __WXDEBUG__ cairo_status_t status = cairo_status( context ); @@ -969,7 +959,7 @@ void CAIRO_GAL::initSurface() #endif /* __WXDEBUG__ */ currentContext = context; - cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL ); + cairo_set_antialias( context, CAIRO_ANTIALIAS_NONE ); // Clear the screen ClearScreen( backgroundColor ); @@ -1037,6 +1027,7 @@ void CAIRO_GAL::drawPoly( const std::deque& aPointList ) cairo_line_to( currentContext, it->x, it->y ); } + flushPath(); isElementAdded = true; } @@ -1054,6 +1045,7 @@ void CAIRO_GAL::drawPoly( const VECTOR2D aPointList[], int aListSize ) cairo_line_to( currentContext, ptr->x, ptr->y ); } + flushPath(); isElementAdded = true; } @@ -1064,9 +1056,7 @@ unsigned int CAIRO_GAL::getNewGroupNumber() wxT( "There are no free slots to store a group" ) ); while( groups.find( groupCounter ) != groups.end() ) - { groupCounter++; - } return groupCounter++; } diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index b5847fc707..113690fda6 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -110,8 +110,9 @@ void GAL::ComputeWorldScreenMatrix() scale.SetScale( VECTOR2D( worldScale, worldScale ) ); MATRIX3x3D flip; + flip.SetIdentity(); - flip.SetScale( VECTOR2D( flipX, flipY ) ); + flip.SetScale( VECTOR2D( globalFlipX ? -1.0 : 1.0, globalFlipY ? -1.0 : 1.0 ) ); MATRIX3x3D lookat; lookat.SetIdentity(); @@ -151,15 +152,25 @@ void GAL::DrawGrid() int gridStartY = KiROUND( worldStartPoint.y / gridSize.y ); int gridEndY = KiROUND( worldEndPoint.y / gridSize.y ); - assert( gridEndX >= gridStartX ); - assert( gridEndY >= gridStartY ); - // Correct the index, else some lines are not correctly painted - gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; + gridStartY -= std::abs( gridOrigin.y / gridSize.y ) + 1; - gridEndX += std::abs( gridOrigin.x / gridSize.x ) + 1; gridEndY += std::abs( gridOrigin.y / gridSize.y ) + 1; + if ( gridStartX <= gridEndX ) + { + gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; + gridEndX += std::abs( gridOrigin.x / gridSize.x ) + 1; + } + else + { + gridStartX += std::abs( gridOrigin.x / gridSize.x ) + 1; + gridEndX -= std::abs( gridOrigin.x / gridSize.x ) + 1; + } + + int dirX = gridEndX >= gridStartX ? 1 : -1; + int dirY = gridEndY >= gridStartY ? 1 : -1; + // Draw the grid behind all other layers SetLayerDepth( depthRange.y * 0.75 ); @@ -172,7 +183,7 @@ void GAL::DrawGrid() // Now draw the grid, every coarse grid line gets the double width // Vertical lines - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) SetLineWidth( doubleMarker ); @@ -188,7 +199,7 @@ void GAL::DrawGrid() } // Horizontal lines - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) SetLineWidth( doubleMarker ); @@ -210,14 +221,14 @@ void GAL::DrawGrid() SetIsStroke( false ); SetFillColor( gridColor ); - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) tickY = true; else tickY = false; - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) tickX = true; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index c94bc4f94b..3c4cfe2c50 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -766,7 +766,11 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2D& aPosition, currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); currentManager->Translate( aPosition.x, aPosition.y, layerDepth ); currentManager->Rotate( aRotationAngle, 0.0f, 0.0f, -1.0f ); - currentManager->Scale( SCALE, SCALE, 0 ); + + double sx = SCALE * ( globalFlipX ? -1.0 : 1.0 ); + double sy = SCALE * ( globalFlipY ? -1.0 : 1.0 ); + + currentManager->Scale( sx, sy, 0 ); currentManager->Translate( 0, -commonOffset, 0 ); switch( GetHorizontalJustify() ) @@ -875,15 +879,24 @@ void OPENGL_GAL::DrawGrid() int gridStartY = KiROUND( worldStartPoint.y / gridSize.y ); int gridEndY = KiROUND( worldEndPoint.y / gridSize.y ); - assert( gridEndX >= gridStartX ); - assert( gridEndY >= gridStartY ); - // Correct the index, else some lines are not correctly painted - gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; gridStartY -= std::abs( gridOrigin.y / gridSize.y ) + 1; - gridEndX += std::abs( gridOrigin.x / gridSize.x ) + 1; gridEndY += std::abs( gridOrigin.y / gridSize.y ) + 1; + if ( gridStartX <= gridEndX ) + { + gridStartX -= std::abs( gridOrigin.x / gridSize.x ) + 1; + gridEndX += std::abs( gridOrigin.x / gridSize.x ) + 1; + } + else + { + gridStartX += std::abs( gridOrigin.x / gridSize.x ) + 1; + gridEndX -= std::abs( gridOrigin.x / gridSize.x ) + 1; + } + + int dirX = gridStartX >= gridEndX ? -1 : 1; + int dirY = gridStartY >= gridEndY ? -1 : 1; + glDisable( GL_DEPTH_TEST ); glDisable( GL_TEXTURE_2D ); @@ -900,7 +913,7 @@ void OPENGL_GAL::DrawGrid() } // Vertical lines - for( int j = gridStartY; j < gridEndY; j += 1 ) + for( int j = gridStartY; j != gridEndY; j += dirY ) { if( j % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) glLineWidth( 2.0 ); @@ -924,7 +937,7 @@ void OPENGL_GAL::DrawGrid() } // Horizontal lines - for( int i = gridStartX; i < gridEndX; i += 1 ) + for( int i = gridStartX; i != gridEndX; i += dirX ) { if( i % gridTick == 0 && gridScreenSizeDense > gridDrawThreshold ) glLineWidth( 2.0 ); diff --git a/common/gal/opengl/shader.vert b/common/gal/opengl/shader.vert index a937ff1d28..dfc1105768 100644 --- a/common/gal/opengl/shader.vert +++ b/common/gal/opengl/shader.vert @@ -47,7 +47,7 @@ void main() if( shaderParams[0] == SHADER_LINE ) { float lineWidth = shaderParams[3]; - float worldScale = gl_ModelViewMatrix[0][0]; + float worldScale = abs( gl_ModelViewMatrix[0][0] ); // Make lines appear to be at least 1 pixel wide if( worldScale * lineWidth < MIN_WIDTH ) @@ -79,7 +79,7 @@ void main() // Make the line appear to be at least 1 pixel wide float lineWidth = shaderParams[3]; - float worldScale = gl_ModelViewMatrix[0][0]; + float worldScale = abs( gl_ModelViewMatrix[0][0] ); if( worldScale * lineWidth < MIN_WIDTH ) shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth ); diff --git a/common/origin_viewitem.cpp b/common/origin_viewitem.cpp index 64548160fd..08e5e66633 100644 --- a/common/origin_viewitem.cpp +++ b/common/origin_viewitem.cpp @@ -43,22 +43,23 @@ const BOX2I ORIGIN_VIEWITEM::ViewBBox() const } -void ORIGIN_VIEWITEM::ViewDraw( int, GAL* aGal ) const +void ORIGIN_VIEWITEM::ViewDraw( int, VIEW* aView ) const { + auto gal = aView->GetGAL(); // Nothing to do if the target shouldn't be drawn at 0,0 and that's where the target is. This // mimics the Legacy canvas that doesn't display most targets at 0,0 if( !m_drawAtZero && ( m_position.x == 0 ) && ( m_position.y == 0 ) ) return; - aGal->SetIsStroke( true ); - aGal->SetIsFill( false ); - aGal->SetLineWidth( 1 ); - aGal->SetStrokeColor( m_color ); - VECTOR2D scaledSize = m_view->ToWorld( VECTOR2D( m_size, m_size ), false ); + gal->SetIsStroke( true ); + gal->SetIsFill( false ); + gal->SetLineWidth( 1 ); + gal->SetStrokeColor( m_color ); + VECTOR2D scaledSize = aView->ToWorld( VECTOR2D( m_size, m_size ), false ); // Draw a circle around the marker's centre point if the style demands it if( ( m_style == CIRCLE_CROSS ) || ( m_style == CIRCLE_DOT ) || ( m_style == CIRCLE_X ) ) - aGal->DrawCircle( m_position, scaledSize.x ); + gal->DrawCircle( m_position, fabs( scaledSize.x ) ); switch( m_style ) { @@ -67,22 +68,22 @@ void ORIGIN_VIEWITEM::ViewDraw( int, GAL* aGal ) const case CROSS: case CIRCLE_CROSS: - aGal->DrawLine( m_position - VECTOR2D( scaledSize.x, 0 ), + gal->DrawLine( m_position - VECTOR2D( scaledSize.x, 0 ), m_position + VECTOR2D( scaledSize.x, 0 ) ); - aGal->DrawLine( m_position - VECTOR2D( 0, scaledSize.y ), + gal->DrawLine( m_position - VECTOR2D( 0, scaledSize.y ), m_position + VECTOR2D( 0, scaledSize.y ) ); break; case X: case CIRCLE_X: - aGal->DrawLine( m_position - scaledSize, m_position + scaledSize ); + gal->DrawLine( m_position - scaledSize, m_position + scaledSize ); scaledSize.y = -scaledSize.y; - aGal->DrawLine( m_position - scaledSize, m_position + scaledSize ); + gal->DrawLine( m_position - scaledSize, m_position + scaledSize ); break; case DOT: case CIRCLE_DOT: - aGal->DrawCircle( m_position, scaledSize.x / 4 ); + gal->DrawCircle( m_position, scaledSize.x / 4 ); break; } } diff --git a/common/view/view.cpp b/common/view/view.cpp index c58193b5b5..2f09553fa6 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -38,18 +39,230 @@ #include #endif /* __WXDEBUG__ */ -using namespace KIGFX; +namespace KIGFX { + +class VIEW; + +class VIEW_ITEM_DATA +{ +public: + VIEW_ITEM_DATA() : + m_flags( KIGFX::VISIBLE ), + m_requiredUpdate( KIGFX::NONE ), + m_groups( nullptr ), + m_groupsSize( 0 ) {} + + ~VIEW_ITEM_DATA() + { + delete[] m_groups; + } + + int getFlags() const + { + return m_flags; + } + +private: + friend class VIEW; + + /** + * Function getLayers() + * Returns layer numbers used by the item. + * + * @param aLayers[]: output layer index array + * @param aCount: number of layer indices in aLayers[] + */ + void getLayers( int* aLayers, int& aCount ) const + { + int* layersPtr = aLayers; + + for( unsigned int i = 0; i < m_layers.size(); ++i ) + { + if( m_layers[i] ) + *layersPtr++ = i; + } + + aCount = m_layers.count(); + } + + VIEW* m_view; ///< Current dynamic view the item is assigned to. + int m_flags; ///< Visibility flags + int m_requiredUpdate; ///< Flag required for updating + + ///> Helper for storing cached items group ids + typedef std::pair GroupPair; + + ///> Indexes of cached GAL display lists corresponding to the item (for every layer it occupies). + ///> (in the std::pair "first" stores layer number, "second" stores group id). + GroupPair* m_groups; + int m_groupsSize; + + /** + * Function getGroup() + * Returns number of the group id for the given layer, or -1 in case it was not cached before. + * + * @param aLayer is the layer number for which group id is queried. + * @return group id or -1 in case there is no group id (ie. item is not cached). + */ + int getGroup( int aLayer ) const + { + for( int i = 0; i < m_groupsSize; ++i ) + { + if( m_groups[i].first == aLayer ) + return m_groups[i].second; + } + + return -1; + } + + /** + * Function getAllGroups() + * Returns all group ids for the item (collected from all layers the item occupies). + * + * @return vector of group ids. + */ + std::vector getAllGroups() const + { + std::vector groups( m_groupsSize ); + + for( int i = 0; i < m_groupsSize; ++i ) + { + groups[i] = m_groups[i].second; + } + + return groups; + } + + /** + * Function setGroup() + * Sets a group id for the item and the layer combination. + * + * @param aLayer is the layer numbe. + * @param aGroup is the group id. + */ + void setGroup( int aLayer, int aGroup ) + { + // Look if there is already an entry for the layer + for( int i = 0; i < m_groupsSize; ++i ) + { + if( m_groups[i].first == aLayer ) + { + m_groups[i].second = aGroup; + return; + } + } + + // If there was no entry for the given layer - create one + GroupPair* newGroups = new GroupPair[m_groupsSize + 1]; + + if( m_groupsSize > 0 ) + { + std::copy( m_groups, m_groups + m_groupsSize, newGroups ); + delete[] m_groups; + } + + m_groups = newGroups; + newGroups[m_groupsSize++] = GroupPair( aLayer, aGroup ); + } + + + /** + * Function deleteGroups() + * Removes all of the stored group ids. Forces recaching of the item. + */ + void deleteGroups() + { + delete[] m_groups; + m_groups = NULL; + m_groupsSize = 0; + } + + + /** + * Function storesGroups() + * Returns information if the item uses at least one group id (ie. if it is cached at all). + * + * @returns true in case it is cached at least for one layer. + */ + inline bool storesGroups() const + { + return m_groupsSize > 0; + } + + /// Stores layer numbers used by the item. + std::bitset m_layers; + + /** + * Function saveLayers() + * Saves layers used by the item. + * + * @param aLayers is an array containing layer numbers to be saved. + * @param aCount is the size of the array. + */ + void saveLayers( int* aLayers, int aCount ) + { + m_layers.reset(); + + for( int i = 0; i < aCount; ++i ) + { + // this fires on some eagle board after EAGLE_PLUGIN::Load() + wxASSERT( unsigned( aLayers[i] ) <= unsigned( VIEW::VIEW_MAX_LAYERS ) ); + + m_layers.set( aLayers[i] ); + } + } + + /** + * Function viewRequiredUpdate() + * Returns current update flag for an item. + */ + int requiredUpdate() const + { + return m_requiredUpdate; + } + + /** + * Function clearUpdateFlags() + * Marks an item as already updated, so it is not going to be redrawn. + */ + void clearUpdateFlags() + { + m_requiredUpdate = NONE; + } + + /** + * Function isRenderable() + * Returns if the item should be drawn or not. + */ + bool isRenderable() const + { + return m_flags == VISIBLE; + } +}; + + +void VIEW::OnDestroy( VIEW_ITEM* aItem ) +{ + auto data = aItem->viewPrivData(); + + if(!data) + return; + + data->m_view->Remove( aItem ); +} + VIEW::VIEW( bool aIsDynamic ) : m_enableOrderModifier( true ), m_scale( 4.0 ), m_minScale( 4.0 ), m_maxScale( 15000 ), + m_mirrorX( false ), m_mirrorY( false ), m_painter( NULL ), m_gal( NULL ), m_dynamic( aIsDynamic ) { m_boundary.SetMaximum(); - m_needsUpdate.reserve( 32768 ); + m_allItems.reserve( 32768 ); // Redraw everything at the beginning MarkDirty(); @@ -91,11 +304,13 @@ void VIEW::Add( VIEW_ITEM* aItem ) { int layers[VIEW_MAX_LAYERS], layers_count; - aItem->ViewGetLayers( layers, layers_count ); - aItem->saveLayers( layers, layers_count ); + aItem->m_viewPrivData = new VIEW_ITEM_DATA; + aItem->m_viewPrivData->m_view = this; - if( m_dynamic ) - aItem->viewAssign( this ); + aItem->ViewGetLayers( layers, layers_count ); + aItem->viewPrivData()->saveLayers( layers, layers_count ); + + m_allItems.push_back(aItem); for( int i = 0; i < layers_count; ++i ) { @@ -104,29 +319,31 @@ void VIEW::Add( VIEW_ITEM* aItem ) MarkTargetDirty( l.target ); } - aItem->ViewUpdate( VIEW_ITEM::ALL ); + SetVisible( aItem, true ); + Update( aItem, KIGFX::ALL ); } void VIEW::Remove( VIEW_ITEM* aItem ) { - if( m_dynamic ) - aItem->m_view = NULL; + if( !aItem ) + return; - if( aItem->viewRequiredUpdate() != VIEW_ITEM::NONE ) // prevent from updating a removed item + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return; + + auto item = std::find( m_allItems.begin(), m_allItems.end(), aItem ); + + if( item != m_allItems.end() ) { - std::vector::iterator item = std::find( m_needsUpdate.begin(), - m_needsUpdate.end(), aItem ); - - if( item != m_needsUpdate.end() ) - { - m_needsUpdate.erase( item ); - aItem->clearUpdateFlags(); - } + m_allItems.erase( item ); + viewData->clearUpdateFlags(); } int layers[VIEW::VIEW_MAX_LAYERS], layers_count; - aItem->getLayers( layers, layers_count ); + viewData->getLayers( layers, layers_count ); for( int i = 0; i < layers_count; ++i ) { @@ -135,13 +352,14 @@ void VIEW::Remove( VIEW_ITEM* aItem ) MarkTargetDirty( l.target ); // Clear the GAL cache - int prevGroup = aItem->getGroup( layers[i] ); + int prevGroup = viewData->getGroup( layers[i] ); if( prevGroup >= 0 ) m_gal->DeleteGroup( prevGroup ); } - aItem->deleteGroups(); + viewData->deleteGroups(); + aItem->m_viewPrivData = nullptr; } @@ -170,7 +388,7 @@ struct queryVisitor bool operator()( VIEW_ITEM* aItem ) { - if( aItem->ViewIsVisible() ) + if( aItem->viewPrivData()->getFlags() & VISIBLE ) m_cont.push_back( VIEW::LAYER_ITEM_PAIR( aItem, m_layer ) ); return true; @@ -261,6 +479,7 @@ void VIEW::SetGAL( GAL* aGal ) // force the new GAL to display the current viewport. SetCenter( m_center ); SetScale( m_scale ); + SetMirror( m_mirrorX, m_mirrorY ); } @@ -293,7 +512,14 @@ void VIEW::SetViewport( const BOX2D& aViewport ) void VIEW::SetMirror( bool aMirrorX, bool aMirrorY ) { + wxASSERT_MSG( !aMirrorY, _( "Mirroring for Y axis is not supported yet" ) ); + + m_mirrorX = aMirrorX; + m_mirrorY = aMirrorY; m_gal->SetFlip( aMirrorX, aMirrorY ); + + // Redraw everything + MarkDirty(); } @@ -398,7 +624,7 @@ struct VIEW::updateItemsColor { // Obtain the color that should be used for coloring the item const COLOR4D color = painter->GetSettings()->GetColor( aItem, layer ); - int group = aItem->getGroup( layer ); + int group = aItem->viewPrivData()->getGroup( layer ); if( group >= 0 ) gal->ChangeGroupColor( group, color ); @@ -463,7 +689,7 @@ struct VIEW::changeItemsDepth bool operator()( VIEW_ITEM* aItem ) { - int group = aItem->getGroup( layer ); + int group = aItem->viewPrivData()->getGroup( layer ); if( group >= 0 ) gal->ChangeGroupDepth( group, depth ); @@ -593,9 +819,11 @@ struct VIEW::drawItem bool operator()( VIEW_ITEM* aItem ) { + + assert( aItem->viewPrivData() ); // Conditions that have te be fulfilled for an item to be drawn - bool drawCondition = aItem->isRenderable() && - aItem->ViewGetLOD( layer ) < view->m_scale; + bool drawCondition = aItem->viewPrivData()->isRenderable() && + aItem->ViewGetLOD( layer, view ) < view->m_scale; if( !drawCondition ) return true; @@ -627,10 +855,15 @@ void VIEW::redrawRect( const BOX2I& aRect ) void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) { + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return; + if( IsCached( aLayer ) && !aImmediate ) { // Draw using cached information or create one - int group = aItem->getGroup( aLayer ); + int group = viewData->getGroup( aLayer ); if( group >= 0 ) { @@ -639,10 +872,10 @@ void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) else { group = m_gal->BeginGroup(); - aItem->setGroup( aLayer, group ); + viewData->setGroup( aLayer, group ); if( !m_painter->Draw( aItem, aLayer ) ) - aItem->ViewDraw( aLayer, m_gal ); // Alternative drawing method + aItem->ViewDraw( aLayer, this ); // Alternative drawing method m_gal->EndGroup(); } @@ -651,7 +884,7 @@ void VIEW::draw( VIEW_ITEM* aItem, int aLayer, bool aImmediate ) { // Immediate mode if( !m_painter->Draw( aItem, aLayer ) ) - aItem->ViewDraw( aLayer, m_gal ); // Alternative drawing method + aItem->ViewDraw( aLayer, this ); // Alternative drawing method } } @@ -672,22 +905,18 @@ void VIEW::draw( VIEW_ITEM* aItem, bool aImmediate ) } } - void VIEW::draw( VIEW_GROUP* aGroup, bool aImmediate ) { - std::set::const_iterator it; - - for( it = aGroup->Begin(); it != aGroup->End(); ++it ) - draw( *it, aImmediate ); + for( unsigned int i = 0; i < aGroup->GetSize(); i++) + draw( aGroup->GetItem(i), aImmediate ); } - struct VIEW::unlinkItem { bool operator()( VIEW_ITEM* aItem ) { - aItem->m_view = NULL; - + delete aItem->m_viewPrivData; + aItem->m_viewPrivData = nullptr; return true; } }; @@ -702,14 +931,19 @@ struct VIEW::recacheItem bool operator()( VIEW_ITEM* aItem ) { + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return false; + // Remove previously cached group - int group = aItem->getGroup( layer ); + int group = viewData->getGroup( layer ); if( group >= 0 ) gal->DeleteGroup( group ); - aItem->setGroup( layer, -1 ); - aItem->ViewUpdate( VIEW_ITEM::ALL ); + viewData->setGroup( layer, -1 ); + view->Update( aItem ); return true; } @@ -726,10 +960,7 @@ void VIEW::Clear() r.SetMaximum(); - for( VIEW_ITEM* item : m_needsUpdate ) - item->clearUpdateFlags(); - - m_needsUpdate.clear(); + m_allItems.clear(); for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i ) { @@ -806,7 +1037,7 @@ struct VIEW::clearLayerCache bool operator()( VIEW_ITEM* aItem ) { - aItem->deleteGroups(); + aItem->viewPrivData()->deleteGroups(); return true; } @@ -833,9 +1064,9 @@ void VIEW::clearGroupCache() void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) { // updateLayers updates geometry too, so we do not have to update both of them at the same time - if( aUpdateFlags & VIEW_ITEM::LAYERS ) + if( aUpdateFlags & LAYERS ) updateLayers( aItem ); - else if( aUpdateFlags & VIEW_ITEM::GEOMETRY ) + else if( aUpdateFlags & GEOMETRY ) updateBbox( aItem ); int layers[VIEW_MAX_LAYERS], layers_count; @@ -848,9 +1079,9 @@ void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) if( IsCached( layerId ) ) { - if( aUpdateFlags & ( VIEW_ITEM::GEOMETRY | VIEW_ITEM::LAYERS ) ) + if( aUpdateFlags & ( GEOMETRY | LAYERS ) ) updateItemGeometry( aItem, layerId ); - else if( aUpdateFlags & VIEW_ITEM::COLOR ) + else if( aUpdateFlags & COLOR ) updateItemColor( aItem, layerId ); } @@ -858,7 +1089,7 @@ void VIEW::invalidateItem( VIEW_ITEM* aItem, int aUpdateFlags ) MarkTargetDirty( m_layers[layerId].target ); } - aItem->clearUpdateFlags(); + aItem->viewPrivData()->clearUpdateFlags(); } @@ -879,12 +1110,16 @@ void VIEW::sortLayers() void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer ) { + auto viewData = aItem->viewPrivData(); wxASSERT( (unsigned) aLayer < m_layers.size() ); wxASSERT( IsCached( aLayer ) ); + if( !viewData ) + return; + // Obtain the color that should be used for coloring the item on the specific layerId const COLOR4D color = m_painter->GetSettings()->GetColor( aItem, aLayer ); - int group = aItem->getGroup( aLayer ); + int group = viewData->getGroup( aLayer ); // Change the color, only if it has group assigned if( group >= 0 ) @@ -894,25 +1129,29 @@ void VIEW::updateItemColor( VIEW_ITEM* aItem, int aLayer ) void VIEW::updateItemGeometry( VIEW_ITEM* aItem, int aLayer ) { + auto viewData = aItem->viewPrivData(); wxASSERT( (unsigned) aLayer < m_layers.size() ); wxASSERT( IsCached( aLayer ) ); + if( !viewData ) + return; + VIEW_LAYER& l = m_layers.at( aLayer ); m_gal->SetTarget( l.target ); m_gal->SetLayerDepth( l.renderingOrder ); // Redraw the item from scratch - int group = aItem->getGroup( aLayer ); + int group = viewData->getGroup( aLayer ); if( group >= 0 ) m_gal->DeleteGroup( group ); group = m_gal->BeginGroup(); - aItem->setGroup( aLayer, group ); + viewData->setGroup( aLayer, group ); if( !m_painter->Draw( static_cast( aItem ), aLayer ) ) - aItem->ViewDraw( aLayer, m_gal ); // Alternative drawing method + aItem->ViewDraw( aLayer, this ); // Alternative drawing method m_gal->EndGroup(); } @@ -936,10 +1175,14 @@ void VIEW::updateBbox( VIEW_ITEM* aItem ) void VIEW::updateLayers( VIEW_ITEM* aItem ) { + auto viewData = aItem->viewPrivData(); int layers[VIEW_MAX_LAYERS], layers_count; + if( !viewData ) + return; + // Remove the item from previous layer set - aItem->getLayers( layers, layers_count ); + viewData->getLayers( layers, layers_count ); for( int i = 0; i < layers_count; ++i ) { @@ -950,19 +1193,19 @@ void VIEW::updateLayers( VIEW_ITEM* aItem ) if( IsCached( l.id ) ) { // Redraw the item from scratch - int prevGroup = aItem->getGroup( layers[i] ); + int prevGroup = viewData->getGroup( layers[i] ); if( prevGroup >= 0 ) { m_gal->DeleteGroup( prevGroup ); - aItem->setGroup( l.id, -1 ); + viewData->setGroup( l.id, -1 ); } } } // Add the item to new layer set aItem->ViewGetLayers( layers, layers_count ); - aItem->saveLayers( layers, layers_count ); + viewData->saveLayers( layers, layers_count ); for( int i = 0; i < layers_count; i++ ) { @@ -1014,15 +1257,20 @@ void VIEW::UpdateItems() { m_gal->BeginUpdate(); - for( VIEW_ITEM* item : m_needsUpdate ) + for( VIEW_ITEM* item : m_allItems ) { - assert( item->viewRequiredUpdate() != VIEW_ITEM::NONE ); + auto viewData = item->viewPrivData(); - invalidateItem( item, item->viewRequiredUpdate() ); + if( !viewData ) + continue; + + if( viewData->m_requiredUpdate != NONE ) + invalidateItem( item, viewData->m_requiredUpdate ); + + viewData->m_requiredUpdate = NONE; } m_gal->EndUpdate(); - m_needsUpdate.clear(); } @@ -1041,7 +1289,8 @@ struct VIEW::extentsVisitor if( first ) extents = aItem->ViewBBox(); else - extents.Merge ( aItem->ViewBBox() ); + extents.Merge( aItem->ViewBBox() ); + return false; } }; @@ -1062,4 +1311,73 @@ const BOX2I VIEW::CalculateExtents() } +void VIEW::SetVisible( VIEW_ITEM* aItem, bool aIsVisible ) +{ + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return; + + bool cur_visible = viewData->m_flags & VISIBLE; + + if( cur_visible != aIsVisible ) + { + if( aIsVisible ) + viewData->m_flags |= VISIBLE; + else + viewData->m_flags &= ~VISIBLE; + + Update( aItem, APPEARANCE | COLOR ); + } +} + + +void VIEW::Hide( VIEW_ITEM* aItem, bool aHide ) +{ + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return; + + if( !( viewData->m_flags & VISIBLE ) ) + return; + + if( aHide ) + viewData->m_flags |= HIDDEN; + else + viewData->m_flags &= ~HIDDEN; + + Update( aItem, APPEARANCE ); +} + + +bool VIEW::IsVisible( const VIEW_ITEM* aItem ) const +{ + const auto viewData = aItem->viewPrivData(); + + return viewData->m_flags & VISIBLE; +} + + +void VIEW::Update( VIEW_ITEM *aItem ) +{ + Update( aItem, ALL ); +} + + +void VIEW::Update( VIEW_ITEM* aItem, int aUpdateFlags ) +{ + auto viewData = aItem->viewPrivData(); + + if( !viewData ) + return; + + assert( aUpdateFlags != NONE ); + + viewData->m_requiredUpdate |= aUpdateFlags; + +} + const int VIEW::TOP_LAYER_MODIFIER = -VIEW_MAX_LAYERS; + +}; diff --git a/common/view/view_group.cpp b/common/view/view_group.cpp index 94123f1b28..a5ce10cab3 100644 --- a/common/view/view_group.cpp +++ b/common/view/view_group.cpp @@ -41,43 +41,54 @@ using namespace KIGFX; VIEW_GROUP::VIEW_GROUP( VIEW* aView ) : - m_layer( ITEM_GAL_LAYER( GP_OVERLAY ) ) + m_layer( ITEM_GAL_LAYER( GP_OVERLAY ) ), + m_view( aView ) { - m_view = aView; + } VIEW_GROUP::~VIEW_GROUP() { + if( m_view && viewPrivData() ) + m_view->Remove( this ); } void VIEW_GROUP::Add( VIEW_ITEM* aItem ) { - m_items.insert( aItem ); - ViewUpdate(); + m_groupItems.push_back( aItem ); } void VIEW_GROUP::Remove( VIEW_ITEM* aItem ) { - m_items.erase( aItem ); - ViewUpdate(); + for( auto iter = m_groupItems.begin(); iter != m_groupItems.end(); ++iter) + { + if( aItem == *iter ) + { + m_groupItems.erase( iter); + break; + } + } } void VIEW_GROUP::Clear() { - m_items.clear(); - ViewUpdate(); + m_groupItems.clear(); } unsigned int VIEW_GROUP::GetSize() const { - return m_items.size(); + return m_groupItems.size(); } +VIEW_ITEM *VIEW_GROUP::GetItem(unsigned int idx) const +{ + return m_groupItems[idx]; +} const BOX2I VIEW_GROUP::ViewBBox() const { @@ -88,31 +99,34 @@ const BOX2I VIEW_GROUP::ViewBBox() const } -void VIEW_GROUP::ViewDraw( int aLayer, GAL* aGal ) const +void VIEW_GROUP::ViewDraw( int aLayer, VIEW* aView ) const { - PAINTER* painter = m_view->GetPainter(); + auto gal = aView->GetGAL(); + PAINTER* painter = aView->GetPainter(); + + const auto drawList = updateDrawList(); // Draw all items immediately (without caching) - for( VIEW_ITEM* item : m_items ) + for( auto item : drawList ) { - aGal->PushDepth(); + gal->PushDepth(); int layers[VIEW::VIEW_MAX_LAYERS], layers_count; item->ViewGetLayers( layers, layers_count ); - m_view->SortLayers( layers, layers_count ); + aView->SortLayers( layers, layers_count ); for( int i = 0; i < layers_count; i++ ) { - if( m_view->IsCached( layers[i] ) && m_view->IsLayerVisible( layers[i] ) ) + if( aView->IsLayerVisible( layers[i] ) ) { - aGal->AdvanceDepth(); + gal->AdvanceDepth(); if( !painter->Draw( item, layers[i] ) ) - item->ViewDraw( layers[i], aGal ); // Alternative drawing method + item->ViewDraw( layers[i], aView ); // Alternative drawing method } } - aGal->PopDepth(); + gal->PopDepth(); } } @@ -127,8 +141,9 @@ void VIEW_GROUP::ViewGetLayers( int aLayers[], int& aCount ) const void VIEW_GROUP::FreeItems() { - for( VIEW_ITEM* item : m_items ) + for(unsigned int i = 0 ; i < GetSize(); i++) { + VIEW_ITEM* item = GetItem(i); delete item; } @@ -136,30 +151,27 @@ void VIEW_GROUP::FreeItems() } -void VIEW_GROUP::ItemsSetVisibility( bool aVisible ) +const VIEW_GROUP::ITEMS VIEW_GROUP::updateDrawList() const { - std::set::const_iterator it, it_end; + return m_groupItems; +} - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->ViewSetVisible( aVisible ); + +/*void VIEW_GROUP::ItemsSetVisibility( bool aVisible ) +{ + for(unsigned int i = 0 ; i < GetSize(); i++) + GetItem(i)->ViewSetVisible( aVisible ); } void VIEW_GROUP::ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags ) { - std::set::const_iterator it, it_end; - - for( it = m_items.begin(), it_end = m_items.end(); it != it_end; ++it ) - (*it)->ViewUpdate( aFlags ); -} + for(unsigned int i = 0 ; i < GetSize(); i++) + GetItem(i)->ViewUpdate( aFlags ); +}*/ void VIEW_GROUP::updateBbox() { - // Save the used VIEW, as it used nulled during Remove() - VIEW* view = m_view; - // Reinsert the group, so the bounding box can be updated - view->Remove( this ); - view->Add( this ); } diff --git a/common/view/view_item.cpp b/common/view/view_item.cpp index f1713f3f0f..a543e31649 100644 --- a/common/view/view_item.cpp +++ b/common/view/view_item.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2016 CERN * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -29,81 +29,8 @@ using namespace KIGFX; -void VIEW_ITEM::ViewRelease() +VIEW_ITEM::~VIEW_ITEM() { - if( m_view && m_view->IsDynamic() ) - m_view->Remove( this ); -} - - -void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const -{ - int* layersPtr = aLayers; - - for( unsigned int i = 0; i < m_layers.size(); ++i ) - { - if( m_layers[i] ) - *layersPtr++ = i; - } - - aCount = m_layers.count(); -} - - -int VIEW_ITEM::getGroup( int aLayer ) const -{ - for( int i = 0; i < m_groupsSize; ++i ) - { - if( m_groups[i].first == aLayer ) - return m_groups[i].second; - } - - return -1; -} - - -std::vector VIEW_ITEM::getAllGroups() const -{ - std::vector groups( m_groupsSize ); - - for( int i = 0; i < m_groupsSize; ++i ) - { - groups[i] = m_groups[i].second; - } - - return groups; -} - - -void VIEW_ITEM::setGroup( int aLayer, int aId ) -{ - // Look if there is already an entry for the layer - for( int i = 0; i < m_groupsSize; ++i ) - { - if( m_groups[i].first == aLayer ) - { - m_groups[i].second = aId; - return; - } - } - - // If there was no entry for the given layer - create one - GroupPair* newGroups = new GroupPair[m_groupsSize + 1]; - - if( m_groupsSize > 0 ) - { - std::copy( m_groups, m_groups + m_groupsSize, newGroups ); - delete[] m_groups; - } - - m_groups = newGroups; - newGroups[m_groupsSize++] = GroupPair( aLayer, aId ); -} - - -void VIEW_ITEM::deleteGroups() -{ - delete[] m_groups; - m_groups = NULL; - m_groupsSize = 0; + VIEW::OnDestroy( this ); + m_viewPrivData = nullptr; } diff --git a/common/worksheet_viewitem.cpp b/common/worksheet_viewitem.cpp index 9c09a24ddf..2a2af1bf6b 100644 --- a/common/worksheet_viewitem.cpp +++ b/common/worksheet_viewitem.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace KIGFX; @@ -44,14 +45,12 @@ WORKSHEET_VIEWITEM::WORKSHEET_VIEWITEM( const PAGE_INFO* aPageInfo, const TITLE_ void WORKSHEET_VIEWITEM::SetPageInfo( const PAGE_INFO* aPageInfo ) { m_pageInfo = aPageInfo; - ViewUpdate( GEOMETRY ); } void WORKSHEET_VIEWITEM::SetTitleBlock( const TITLE_BLOCK* aTitleBlock ) { m_titleBlock = aTitleBlock; - ViewUpdate( GEOMETRY ); } @@ -74,9 +73,10 @@ const BOX2I WORKSHEET_VIEWITEM::ViewBBox() const } -void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const +void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, VIEW* aView ) const { - RENDER_SETTINGS* settings = m_view->GetPainter()->GetSettings(); + auto gal = aView->GetGAL(); + auto settings = aView->GetPainter()->GetSettings(); wxString fileName( m_fileName.c_str(), wxConvUTF8 ); wxString sheetName( m_sheetName.c_str(), wxConvUTF8 ); WS_DRAW_ITEM_LIST drawList; @@ -102,19 +102,19 @@ void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const switch( item->GetType() ) { case WS_DRAW_ITEM_BASE::wsg_line: - draw( static_cast( item ), aGal ); + draw( static_cast( item ), gal ); break; case WS_DRAW_ITEM_BASE::wsg_rect: - draw( static_cast( item ), aGal ); + draw( static_cast( item ), gal ); break; case WS_DRAW_ITEM_BASE::wsg_poly: - draw( static_cast( item ), aGal ); + draw( static_cast( item ), gal ); break; case WS_DRAW_ITEM_BASE::wsg_text: - draw( static_cast( item ), aGal ); + draw( static_cast( item ), gal ); break; case WS_DRAW_ITEM_BASE::wsg_bitmap: @@ -125,7 +125,7 @@ void WORKSHEET_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const } // Draw gray line that outlines the sheet size - drawBorder( aGal ); + drawBorder( gal ); } diff --git a/include/base_struct.h b/include/base_struct.h index 7f57f58cf2..61205b0bd8 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -229,12 +229,12 @@ public: inline bool IsBrightened() const { return m_Flags & BRIGHTENED; } inline void SetWireImage() { SetFlags( IS_WIRE_IMAGE ); } - inline void SetSelected() { SetFlags( SELECTED ); ViewUpdate( COLOR ); } - inline void SetHighlighted() { SetFlags( HIGHLIGHTED ); ViewUpdate( COLOR ); } + inline void SetSelected() { SetFlags( SELECTED ); } + inline void SetHighlighted() { SetFlags( HIGHLIGHTED ); } inline void SetBrightened() { SetFlags( BRIGHTENED ); } - inline void ClearSelected() { ClearFlags( SELECTED ); ViewUpdate( COLOR ); } - inline void ClearHighlighted() { ClearFlags( HIGHLIGHTED ); ViewUpdate( COLOR ); } + inline void ClearSelected() { ClearFlags( SELECTED ); } + inline void ClearHighlighted() { ClearFlags( HIGHLIGHTED ); } inline void ClearBrightened() { ClearFlags( BRIGHTENED ); } void SetModified(); diff --git a/include/class_draw_panel_gal.h b/include/class_draw_panel_gal.h index 77133d9fcf..d7f026fd6c 100644 --- a/include/class_draw_panel_gal.h +++ b/include/class_draw_panel_gal.h @@ -72,7 +72,7 @@ public: * Switches method of rendering graphics. * @param aGalType is a type of rendering engine that you want to use. */ - bool SwitchBackend( GAL_TYPE aGalType ); + virtual bool SwitchBackend( GAL_TYPE aGalType ); /** * Function GetBackend diff --git a/include/commit.h b/include/commit.h index 646e991a4b..243f2e360b 100644 --- a/include/commit.h +++ b/include/commit.h @@ -109,6 +109,16 @@ public: ///> before the modification. COMMIT& Modified( EDA_ITEM* aItem, EDA_ITEM* aCopy ); + template + COMMIT& StageItems( const Range& aRange, CHANGE_TYPE aChangeType ) + { + for( const auto& item : aRange ) + Stage( item, aChangeType ); + + return *this; + } + + ///> Adds a change of the item aItem of type aChangeType to the change list. COMMIT& Stage( EDA_ITEM* aItem, CHANGE_TYPE aChangeType ); @@ -117,7 +127,7 @@ public: COMMIT& Stage( const PICKED_ITEMS_LIST& aItems, UNDO_REDO_T aModFlag = UR_UNSPECIFIED ); ///> Executes the changes. - virtual void Push( const wxString& aMessage ) = 0; + virtual void Push( const wxString& aMessage = wxT( "A commit" ) ) = 0; ///> Revertes the commit by restoring the modifed items state. virtual void Revert() = 0; diff --git a/include/convert_to_biu.h b/include/convert_to_biu.h index 5d6d0f9c30..795f79d48a 100644 --- a/include/convert_to_biu.h +++ b/include/convert_to_biu.h @@ -29,23 +29,21 @@ * @file convert_to_biu.h */ - /** * @brief some define and functions to convert a value in mils, decimils or mm * to the internal unit used in pcbnew, cvpcb or gerbview (nanometer or deci-mil) * depending on compile time option */ - - /// Scaling factor to convert mils to internal units. #if defined(PCBNEW) || defined(CVPCB) || defined(GERBVIEW) #if defined(GERBVIEW) - #define IU_PER_MM 1e5 // Gerbview IU is 10 nanometers. + constexpr double IU_PER_MM = 1e5; // Gerbview IU is 10 nanometers. #else - #define IU_PER_MM 1e6 // Pcbnew IU is 1 nanometer. + constexpr double IU_PER_MM = 1e6; // Pcbnew IU is 1 nanometer. #endif - #define IU_PER_MILS (IU_PER_MM * 0.0254) + +constexpr double IU_PER_MILS = IU_PER_MM * 0.0254; /// Convert mils to PCBNEW internal units (iu). inline int Mils2iu( int mils ) @@ -55,8 +53,9 @@ inline int Mils2iu( int mils ) } #elif defined (PL_EDITOR) -#define IU_PER_MM 1e3 // internal units in micron (should be enough) -#define IU_PER_MILS (IU_PER_MM * 0.0254) +constexpr double IU_PER_MM = 1e3; // internal units in micron (should be enough) +constexpr double IU_PER_MILS = (IU_PER_MM * 0.0254); + /// Convert mils to page layout editor internal units (iu). inline int Mils2iu( int mils ) { @@ -65,37 +64,37 @@ inline int Mils2iu( int mils ) } #elif defined (EESCHEMA) // Eeschema -#define IU_PER_MILS 1.0 -#define IU_PER_MM (IU_PER_MILS / 0.0254) +constexpr double IU_PER_MILS = 1.0; +constexpr double IU_PER_MM = ( IU_PER_MILS / 0.0254 ); -inline int Mils2iu( int mils ) +constexpr inline int Mils2iu( int mils ) { return mils; } #else // Here, we do not know the value of internal units: do not define -// conversion functions (They do not have meaning +// conversion functions (They do not have meaning) #define UNKNOWN_IU #endif #ifndef UNKNOWN_IU // Other definitions used in a few files -#define MM_PER_IU (1/IU_PER_MM) +constexpr double MM_PER_IU = ( 1 / IU_PER_MM ); /// Convert mm to internal units (iu). -inline int Millimeter2iu( double mm ) +constexpr inline int Millimeter2iu( double mm ) { - return (int) ( mm < 0 ? mm * IU_PER_MM - 0.5 : mm * IU_PER_MM + 0.5); + return (int) ( mm < 0 ? mm * IU_PER_MM - 0.5 : mm * IU_PER_MM + 0.5 ); } /// Convert mm to internal units (iu). -inline double Iu2Millimeter( int iu ) +constexpr inline double Iu2Millimeter( int iu ) { return iu / IU_PER_MM; } /// Convert mm to internal units (iu). -inline double Iu2Mils( int iu ) +constexpr inline double Iu2Mils( int iu ) { return iu / IU_PER_MILS; } diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 9e5f249f32..74e5227052 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -296,7 +296,7 @@ private: wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels /// Maximum number of arguments for one command - static const int MAX_CAIRO_ARGUMENTS = 6; + static const int MAX_CAIRO_ARGUMENTS = 4; /// Definitions for the command recorder enum GRAPHICS_COMMAND @@ -308,7 +308,7 @@ private: CMD_SET_LINE_WIDTH, ///< Set the line width CMD_STROKE_PATH, ///< Set the stroke path CMD_FILL_PATH, ///< Set the fill path - CMD_TRANSFORM, ///< Transform the actual context + //CMD_TRANSFORM, ///< Transform the actual context CMD_ROTATE, ///< Rotate the context CMD_TRANSLATE, ///< Translate the context CMD_SCALE, ///< Scale the context @@ -321,9 +321,11 @@ private: typedef struct { GRAPHICS_COMMAND command; ///< Command to execute - double arguments[MAX_CAIRO_ARGUMENTS]; ///< Arguments for Cairo commands - bool boolArgument; ///< A bool argument - int intArgument; ///< An int argument + union { + double dblArg[MAX_CAIRO_ARGUMENTS]; ///< Arguments for Cairo commands + bool boolArg; ///< A bool argument + int intArg; ///< An int argument + } argument; cairo_path_t* cairoPath; ///< Pointer to a Cairo path } GROUP_ELEMENT; @@ -346,6 +348,9 @@ private: bool isInitialized; ///< Are Cairo image & surface ready to use COLOR4D backgroundColor; ///< Background color + int wxBufferWidth; + + void flushPath(); // Methods void storePath(); ///< Store the actual path @@ -372,7 +377,7 @@ private: /** * @brief Blits cursor into the current screen. */ - virtual void blitCursor( wxBufferedDC& clientDC ); + virtual void blitCursor( wxMemoryDC& clientDC ); /// Prepare Cairo surfaces for drawing void initSurface(); diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 20f8130ba6..c6bc0643a4 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -49,6 +49,7 @@ enum GRID_STYLE GRID_STYLE_DOTS ///< Use dots for the grid }; + /** * @brief Class GAL is the abstract interface for drawing on a 2D-surface. * @@ -309,7 +310,15 @@ public: double aRotationAngle ) { // Fallback: use stroke font + + // Handle flipped view + if( globalFlipX ) + textProperties.m_mirrored = !textProperties.m_mirrored; + StrokeText( aText, aPosition, aRotationAngle ); + + if( globalFlipX ) + textProperties.m_mirrored = !textProperties.m_mirrored; } /** @@ -690,17 +699,11 @@ public: */ inline void SetFlip( bool xAxis, bool yAxis ) { - if( xAxis ) - flipX = -1.0; // flipped - else - flipX = 1.0; // regular - - if( yAxis ) - flipY = -1.0; // flipped - else - flipY = 1.0; // regular + globalFlipX = xAxis; + globalFlipY = yAxis; } + // --------------------------- // Buffer manipulation methods // --------------------------- @@ -978,8 +981,9 @@ protected: MATRIX3x3D worldScreenMatrix; ///< World transformation MATRIX3x3D screenWorldMatrix; ///< Screen transformation double worldScale; ///< The scale factor world->screen - double flipX; ///< Flag for X axis flipping - double flipY; ///< Flag for Y axis flipping + + bool globalFlipX; ///< Flag for X axis flipping + bool globalFlipY; ///< Flag for Y axis flipping double lineWidth; ///< The line width diff --git a/include/origin_viewitem.h b/include/origin_viewitem.h index a00fd44d4f..1e55611245 100644 --- a/include/origin_viewitem.h +++ b/include/origin_viewitem.h @@ -50,7 +50,7 @@ public: const BOX2I ViewBBox() const override; - void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const override; + void ViewDraw( int aLayer, VIEW* aView ) const override; void ViewGetLayers( int aLayers[], int& aCount ) const override { @@ -86,7 +86,6 @@ public: inline void SetPosition( const VECTOR2D& aPosition ) { m_position = aPosition; - ViewUpdate(); } inline const VECTOR2D& GetPosition() const diff --git a/include/profile.h b/include/profile.h index acf9166bbb..d3cb30bd29 100644 --- a/include/profile.h +++ b/include/profile.h @@ -33,6 +33,9 @@ #include #include +#include +#include + /** * Function get_tics * Returns the number of microseconds that have elapsed since the system was started. @@ -87,4 +90,50 @@ static inline void prof_end( prof_counter* aCnt ) aCnt->end = get_tics(); } +class PROF_COUNTER +{ +public: + PROF_COUNTER( const std::string& name, bool autostart = true ) + { + m_name = name; + m_running = false; + + if( autostart ) + start(); + } + + void start() + { + m_running = true; + prof_start( &m_cnt ); + } + + void stop() + { + if( !m_running ) + return; + + m_running = false; + prof_end( &m_cnt ); + } + + void show() + { + stop(); + fprintf( stderr, "%s took %.1f milliseconds.\n", m_name.c_str(), (double)m_cnt.msecs() ); + start(); + } + + double msecs() const + { + return m_cnt.msecs(); + } + +private: + std::string m_name; + prof_counter m_cnt; + bool m_running; +}; + + #endif diff --git a/include/view/view.h b/include/view/view.h index ca8f4122fb..4f7014345f 100644 --- a/include/view/view.h +++ b/include/view/view.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2016 CERN * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -70,6 +70,12 @@ public: ~VIEW(); + // nasty hack, invoked by the destructor of VIEW_ITEM to auto-remove the item + // from the owning VIEW if there is any. Kicad relies too much on this mechanism. + // this is the only linking dependency now between EDA_ITEM and VIEW class. In near future + // I'll replace it with observers. + static void OnDestroy( VIEW_ITEM* aItem ); + /** * Function Add() * Adds a VIEW_ITEM to the view. @@ -84,6 +90,7 @@ public: */ void Remove( VIEW_ITEM* aItem ); + /** * Function Query() * Finds all visible items that touch or are within the rectangle aRect. @@ -95,6 +102,41 @@ public: */ int Query( const BOX2I& aRect, std::vector& aResult ) const; + /** + * Function SetVisible() + * Sets the item visibility. + * + * @param aIsVisible: whether the item is visible (on all layers), or not. + */ + void SetVisible( VIEW_ITEM* aItem, bool aIsVisible = true ); + + /** + * Function Hide() + * Temporarily hides the item in the view (e.g. for overlaying) + * + * @param aHide: whether the item is hidden (on all layers), or not. + */ + void Hide( VIEW_ITEM* aItem, bool aHide = true ); + + /** + * Function IsVisible() + * Returns information if the item is visible (or not). + * + * @return when true, the item is visible (i.e. to be displayed, not visible in the + * *current* viewport) + */ + bool IsVisible( const VIEW_ITEM* aItem ) const; + + /** + * Function ViewUpdate() + * For dynamic VIEWs, informs the associated VIEW that the graphical representation of + * this item has changed. For static views calling has no effect. + * + * @param aUpdateFlags: how much the object has changed. + */ + void Update( VIEW_ITEM* aItem ); + void Update( VIEW_ITEM* aItem, int aUpdateFlags ); + /** * Function SetRequired() * Marks the aRequiredId layer as required for the aLayerId layer. In order to display the @@ -176,6 +218,24 @@ public: */ void SetMirror( bool aMirrorX, bool aMirrorY ); + /** + * Function IsMirroredX() + * Returns true if view is flipped across the X axis. + */ + bool IsMirroredX() const + { + return m_mirrorX; + } + + /** + * Function IsMirroredX() + * Returns true if view is flipped across the Y axis. + */ + bool IsMirroredY() const + { + return m_mirrorY; + } + /** * Function SetScale() * Sets the scaling factor. Scale = 1 corresponds to the real world size of the objects @@ -547,10 +607,7 @@ public: * Adds an item to a list of items that are going to be refreshed upon the next frame rendering. * @param aItem is the item to be refreshed. */ - void MarkForUpdate( VIEW_ITEM* aItem ) - { - m_needsUpdate.push_back( aItem ); - } + void MarkForUpdate( VIEW_ITEM* aItem ); /** * Function UpdateItems() @@ -695,6 +752,12 @@ private: /// Scale upper limit double m_maxScale; + ///> Horizontal flip flag + bool m_mirrorX; + + ///> Vertical flip flag + bool m_mirrorY; + /// PAINTER contains information how do draw items PAINTER* m_painter; @@ -711,8 +774,8 @@ private: /// Rendering order modifier for layers that are marked as top layers static const int TOP_LAYER_MODIFIER; - /// Items to be updated - std::vector m_needsUpdate; + /// Flat list of all items + std::vector m_allItems; }; } // namespace KIGFX diff --git a/include/view/view_group.h b/include/view/view_group.h index 57c972ec2f..31c2d9bedb 100644 --- a/include/view/view_group.h +++ b/include/view/view_group.h @@ -38,15 +38,23 @@ namespace KIGFX { + class VIEW_GROUP : public VIEW_ITEM { +protected: + typedef std::vector ITEMS; + public: VIEW_GROUP( VIEW* aView = NULL ); virtual ~VIEW_GROUP(); - /// Helper typedefs - typedef std::set::const_iterator const_iter; - typedef std::set::iterator iter; + /** + * Function GetSize() + * Returns the number of stored items. + * + * @return Number of stored items. + */ + virtual unsigned int GetSize() const; /** * Function Add() @@ -70,31 +78,7 @@ public: */ virtual void Clear(); - /** - * Function Begin() - * Returns iterator to beginning. - */ - inline const_iter Begin() const - { - return m_items.begin(); - } - - /** - * Function End() - * Returns iterator to end. - */ - inline const_iter End() const - { - return m_items.end(); - } - - /** - * Function GetSize() - * Returns the number of stored items. - * - * @return Number of stored items. - */ - virtual unsigned int GetSize() const; + virtual VIEW_ITEM* GetItem( unsigned int aIdx ) const; /** * Function ViewBBox() @@ -111,7 +95,7 @@ public: * @param aLayer is the layer which should be drawn. * @param aGal is the GAL that should be used for drawing. */ - virtual void ViewDraw( int aLayer, GAL* aGal ) const override; + virtual void ViewDraw( int aLayer, VIEW* aView ) const override; /** * Function ViewGetLayers() @@ -131,7 +115,6 @@ public: inline virtual void SetLayer( int aLayer ) { m_layer = aLayer; - ViewUpdate(); } /** @@ -140,67 +123,23 @@ public: */ void FreeItems(); - /** - * Function GetView() - * Returns pointer to the VIEW instance used by items. - * - * @return Pointer to the VIEW instance. - */ - KIGFX::VIEW* GetView() const - { - return m_view; - } - - /** - * Function ItemsSetVisibility() - * Sets visibility of items stored in the VIEW_GROUP. - * - * @param aVisible decides if items should be visible or not. - */ - virtual void ItemsSetVisibility( bool aVisible ); - - /** - * Function ItemsViewUpdate() - * Updates items stored in the VIEW_GROUP. - * - * @param aFlags determines the way in which items will be updated. - */ - virtual void ItemsViewUpdate( VIEW_ITEM::VIEW_UPDATE_FLAGS aFlags ); - protected: - /// These functions cannot be used with VIEW_GROUP as they are intended only to work with - /// singular VIEW_ITEMs (there is only one-to-one relation between item/layer combination and - /// its group). - int getGroup( int aLayer ) const override - { - return -1; - } - std::vector getAllGroups() const override - { - return std::vector(); - } - - void setGroup( int aLayer, int aGroup ) override - {} - - void deleteGroups() override - {} - - bool storesGroups() const override - { - return false; - } + virtual const ITEMS updateDrawList() const; /// Layer on which the group is drawn int m_layer; +protected: + /// Container for storing VIEW_ITEMs + ITEMS m_groupItems; + private: void updateBbox(); - /// Container for storing VIEW_ITEMs - std::set m_items; + VIEW* m_view; }; + } // namespace KIGFX #endif // VIEW_GROUP_H_ diff --git a/include/view/view_item.h b/include/view/view_item.h index 878c8e7001..293b0e675b 100644 --- a/include/view/view_item.h +++ b/include/view/view_item.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2013 CERN + * Copyright (C) 2013-2016 CERN * @author Tomasz Wlostowski * * This program is free software; you can redistribute it and/or @@ -33,15 +33,40 @@ #include #include #include -#include -#include - namespace KIGFX { // Forward declarations -class GAL; -class PAINTER; +class VIEW; +class VIEW_ITEM_DATA; + + /** + * Enum VIEW_UPDATE_FLAGS. + * Defines the how severely the shape/appearance of the item has been changed: + * - NONE: TODO + * - APPEARANCE: shape or layer set of the item have not been affected, + * only colors or visibility. + * - COLOR: + * - GEOMETRY: shape or layer set of the item have changed, VIEW may need to reindex it. + * - LAYERS: TODO + * - ALL: all the flags above */ +enum VIEW_UPDATE_FLAGS { + NONE = 0x00, /// No updates are required + APPEARANCE = 0x01, /// Visibility flag has changed + COLOR = 0x02, /// Color has changed + GEOMETRY = 0x04, /// Position or shape has changed + LAYERS = 0x08, /// Layers have changed + ALL = 0xff +}; + +/** + * Enum VIEW_VISIBILITY_FLAGS. + * Defines the visibility of the item (temporarily hidden, invisible, etc). + */ +enum VIEW_VISIBILITY_FLAGS { + VISIBLE = 0x01, /// Item is visible (in general) + HIDDEN = 0x02 /// Item is temporarily hidden (e.g. being used by a tool). Overrides VISIBLE flag. +}; /** * Class VIEW_ITEM - @@ -53,50 +78,17 @@ class PAINTER; * VIEW_ITEM objects are never owned by a VIEW. A single VIEW_ITEM can belong to any number of * static VIEWs, but only one dynamic VIEW due to storage of only one VIEW reference. */ + class VIEW_ITEM { public: - /** - * Enum VIEW_UPDATE_FLAGS. - * Defines the how severely the shape/appearance of the item has been changed: - * - NONE: TODO - * - APPEARANCE: shape or layer set of the item have not been affected, - * only colors or visibility. - * - COLOR: - * - GEOMETRY: shape or layer set of the item have changed, VIEW may need to reindex it. - * - LAYERS: TODO - * - ALL: all the flags above */ - - enum VIEW_UPDATE_FLAGS { - NONE = 0x00, /// No updates are required - APPEARANCE = 0x01, /// Visibility flag has changed - COLOR = 0x02, /// Color has changed - GEOMETRY = 0x04, /// Position or shape has changed - LAYERS = 0x08, /// Layers have changed - ALL = 0xff - }; - - /** - * Enum VIEW_VISIBILITY_FLAGS. - * Defines the visibility of the item (temporarily hidden, invisible, etc). - */ - enum VIEW_VISIBILITY_FLAGS { - VISIBLE = 0x01, /// Item is visible (in general) - HIDDEN = 0x02 /// Item is temporarily hidden (e.g. being used by a tool). Overrides VISIBLE flag. - }; - - VIEW_ITEM() : m_view( NULL ), m_flags( VISIBLE ), m_requiredUpdate( NONE ), - m_groups( NULL ), m_groupsSize( 0 ) {} - - /** - * Destructor. For dynamic views, removes the item from the view. - */ - virtual ~VIEW_ITEM() + VIEW_ITEM() : m_viewPrivData( nullptr ) { - ViewRelease(); - delete[] m_groups; + } + virtual ~VIEW_ITEM(); + /** * Function ViewBBox() * returns the bounding box of the item covering all its layers. @@ -117,7 +109,7 @@ public: * @param aLayer: current drawing layer * @param aGal: pointer to the GAL device we are drawing on */ - virtual void ViewDraw( int aLayer, GAL* aGal ) const + virtual void ViewDraw( int aLayer, VIEW* aView ) const {} /** @@ -131,226 +123,30 @@ public: */ virtual void ViewGetLayers( int aLayers[], int& aCount ) const = 0; - /** - * Function ViewSetVisible() - * Sets the item visibility. - * - * @param aIsVisible: whether the item is visible (on all layers), or not. - */ - void ViewSetVisible( bool aIsVisible = true ) - { - bool cur_visible = m_flags & VISIBLE; - - if( cur_visible != aIsVisible ) - { - if( aIsVisible ) - m_flags |= VISIBLE; - else - m_flags &= ~VISIBLE; - - ViewUpdate( APPEARANCE | COLOR ); - } - } - - /** - * Function ViewHide() - * Temporarily hides the item in the view (e.g. for overlaying) - * - * @param aHide: whether the item is hidden (on all layers), or not. - */ - void ViewHide( bool aHide = true ) - { - if( !( m_flags & VISIBLE ) ) - return; - - if( aHide ) - m_flags |= HIDDEN; - else - m_flags &= ~HIDDEN; - - ViewUpdate( APPEARANCE ); - } - - /** - * Function ViewIsVisible() - * Returns information if the item is visible (or not). - * - * @return when true, the item is visible (i.e. to be displayed, not visible in the - * *current* viewport) - */ - bool ViewIsVisible() const - { - return m_flags & VISIBLE; - } - /** * Function ViewGetLOD() * Returns the level of detail of the item. A level of detail is the minimal VIEW scale that * is sufficient for an item to be shown on a given layer. */ - virtual unsigned int ViewGetLOD( int aLayer ) const + virtual unsigned int ViewGetLOD( int aLayer, VIEW* aView ) const { // By default always show the item return 0; } - /** - * Function ViewUpdate() - * For dynamic VIEWs, informs the associated VIEW that the graphical representation of - * this item has changed. For static views calling has no effect. - * - * @param aUpdateFlags: how much the object has changed. - */ - virtual void ViewUpdate( int aUpdateFlags = ALL ) +public: + + VIEW_ITEM_DATA* viewPrivData() const { - if( m_view ) - { - assert( aUpdateFlags != NONE ); - - if( m_requiredUpdate == NONE ) - m_view->MarkForUpdate( this ); - - m_requiredUpdate |= aUpdateFlags; - } + return m_viewPrivData; } - /** - * Function ViewRelease() - * Releases the item from an associated dynamic VIEW. For static views calling has no effect. - */ - virtual void ViewRelease(); - -protected: +private: friend class VIEW; - /** - * Function getLayers() - * Returns layer numbers used by the item. - * - * @param aLayers[]: output layer index array - * @param aCount: number of layer indices in aLayers[] - */ - virtual void getLayers( int* aLayers, int& aCount ) const; - - /** - * Function viewAssign() - * Assigns the item to a given dynamic VIEW. Called internally by the VIEW. - * - * @param aView[]: dynamic VIEW instance the item is being added to. - */ - virtual void viewAssign( VIEW* aView ) - { - // release the item from a previously assigned dynamic view (if there is any) - ViewRelease(); - m_view = aView; - deleteGroups(); - } - - VIEW* m_view; ///< Current dynamic view the item is assigned to. - int m_flags; ///< Visibility flags - int m_requiredUpdate; ///< Flag required for updating - - ///* Helper for storing cached items group ids - typedef std::pair GroupPair; - - ///* Indexes of cached GAL display lists corresponding to the item (for every layer it occupies). - ///* (in the std::pair "first" stores layer number, "second" stores group id). - GroupPair* m_groups; - int m_groupsSize; - - /** - * Function getGroup() - * Returns number of the group id for the given layer, or -1 in case it was not cached before. - * - * @param aLayer is the layer number for which group id is queried. - * @return group id or -1 in case there is no group id (ie. item is not cached). - */ - virtual int getGroup( int aLayer ) const; - - /** - * Function getAllGroups() - * Returns all group ids for the item (collected from all layers the item occupies). - * - * @return vector of group ids. - */ - virtual std::vector getAllGroups() const; - - /** - * Function setGroup() - * Sets a group id for the item and the layer combination. - * - * @param aLayer is the layer numbe. - * @param aGroup is the group id. - */ - virtual void setGroup( int aLayer, int aGroup ); - - /** - * Function deleteGroups() - * Removes all of the stored group ids. Forces recaching of the item. - */ - virtual void deleteGroups(); - - /** - * Function storesGroups() - * Returns information if the item uses at least one group id (ie. if it is cached at all). - * - * @returns true in case it is cached at least for one layer. - */ - inline virtual bool storesGroups() const - { - return m_groupsSize > 0; - } - - /// Stores layer numbers used by the item. - std::bitset m_layers; - - /** - * Function saveLayers() - * Saves layers used by the item. - * - * @param aLayers is an array containing layer numbers to be saved. - * @param aCount is the size of the array. - */ - virtual void saveLayers( int* aLayers, int aCount ) - { - m_layers.reset(); - - for( int i = 0; i < aCount; ++i ) - { - // this fires on some eagle board after EAGLE_PLUGIN::Load() - wxASSERT( unsigned( aLayers[i] ) <= unsigned( VIEW::VIEW_MAX_LAYERS ) ); - - m_layers.set( aLayers[i] ); - } - } - - /** - * Function viewRequiredUpdate() - * Returns current update flag for an item. - */ - virtual int viewRequiredUpdate() const - { - return m_requiredUpdate; - } - - /** - * Function clearUpdateFlags() - * Marks an item as already updated, so it is not going to be redrawn. - */ - void clearUpdateFlags() - { - m_requiredUpdate = NONE; - } - - /** - * Function isRenderable() - * Returns if the item should be drawn or not. - */ - bool isRenderable() const - { - return m_flags == VISIBLE; - } + VIEW_ITEM_DATA* m_viewPrivData; }; + } // namespace KIGFX #endif diff --git a/include/worksheet_viewitem.h b/include/worksheet_viewitem.h index cf193a51c7..efbb6d0133 100644 --- a/include/worksheet_viewitem.h +++ b/include/worksheet_viewitem.h @@ -42,6 +42,7 @@ class WS_DRAW_ITEM_TEXT; namespace KIGFX { +class VIEW; class GAL; class WORKSHEET_VIEWITEM : public EDA_ITEM @@ -58,7 +59,6 @@ public: void SetFileName( const std::string& aFileName ) { m_fileName = aFileName; - ViewUpdate( GEOMETRY ); } /** @@ -70,7 +70,6 @@ public: void SetSheetName( const std::string& aSheetName ) { m_sheetName = aSheetName; - ViewUpdate( GEOMETRY ); } /** @@ -98,8 +97,6 @@ public: void SetSheetNumber( int aSheetNumber ) { m_sheetNumber = aSheetNumber; - ViewUpdate( GEOMETRY ); - } /** @@ -111,14 +108,13 @@ public: void SetSheetCount( int aSheetCount ) { m_sheetCount = aSheetCount; - ViewUpdate( GEOMETRY ); } /// @copydoc VIEW_ITEM::ViewBBox() const BOX2I ViewBBox() const override; /// @copydoc VIEW_ITEM::ViewDraw() - void ViewDraw( int aLayer, GAL* aGal ) const override; + void ViewDraw( int aLayer, VIEW* aView ) const override; /// @copydoc VIEW_ITEM::ViewGetLayers() void ViewGetLayers( int aLayers[], int& aCount ) const override; diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 55f8da62a7..296861474e 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -637,6 +637,7 @@ public: bool OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu ) override; void OnSelectOptionToolbar( wxCommandEvent& event ); + void OnFlipPcbView( wxCommandEvent& event ); void ToolOnRightClick( wxCommandEvent& event ) override; /* Block operations: */ diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index bbe77563aa..aef2c92f2d 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -442,10 +442,9 @@ void PCB_BASE_FRAME::OnTogglePadDrawMode( wxCommandEvent& aEvent ) if( gal ) { // Apply new display options to the GAL canvas - KIGFX::PCB_PAINTER* painter = - static_cast ( gal->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + auto view = gal->GetView(); + auto painter = static_cast ( view->GetPainter() ); + auto settings = static_cast ( painter->GetSettings() ); settings->LoadDisplayOptions( displ_opts ); // Update pads @@ -453,7 +452,7 @@ void PCB_BASE_FRAME::OnTogglePadDrawMode( wxCommandEvent& aEvent ) for( MODULE* module = board->m_Modules; module; module = module->Next() ) { for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) - pad->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( pad, KIGFX::GEOMETRY ); } } diff --git a/pcbnew/board_commit.cpp b/pcbnew/board_commit.cpp index b5b23b9cae..2b39111d17 100644 --- a/pcbnew/board_commit.cpp +++ b/pcbnew/board_commit.cpp @@ -70,7 +70,6 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { int changeType = ent.m_type & CHT_TYPE; int changeFlags = ent.m_type & CHT_FLAGS; - bool done = changeFlags & CHT_DONE; BOARD_ITEM* boardItem = static_cast( ent.m_item ); // Module items need to be saved in the undo buffer before modification @@ -110,7 +109,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { undoList.PushItem( ITEM_PICKER( boardItem, UR_NEW ) ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Add( boardItem ); //ratsnest->Add( boardItem ); // TODO currently done by BOARD::Add() @@ -126,7 +125,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) // modules inside modules are not supported yet assert( boardItem->Type() != PCB_MODULE_T ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->m_Modules->Add( boardItem ); } @@ -137,7 +136,9 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case CHT_REMOVE: { if( !m_editModules ) + { undoList.PushItem( ITEM_PICKER( boardItem, UR_DELETED ) ); + } switch( boardItem->Type() ) { @@ -181,7 +182,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) { view->Remove( boardItem ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) { MODULE* module = static_cast( boardItem->GetParent() ); assert( module && module->Type() == PCB_MODULE_T ); @@ -206,7 +207,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) case PCB_ZONE_AREA_T: view->Remove( boardItem ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Remove( boardItem ); //ratsnest->Remove( boardItem ); // currently done by BOARD::Remove() @@ -223,7 +224,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) view->Remove( module ); - if( !done ) + if( !( changeFlags & CHT_DONE ) ) board->Remove( module ); // Clear flags to indicate, that the ratsnest, list of nets & pads are not valid anymore @@ -248,7 +249,13 @@ void BOARD_COMMIT::Push( const wxString& aMessage ) undoList.PushItem( itemWrapper ); } - boardItem->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + if ( boardItem->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( boardItem ); + module->RunOnChildren( [&view] ( BOARD_ITEM *aItem ){ view->Update( aItem ); } ); + } + + view->Update ( boardItem ); ratsnest->Update( boardItem ); break; } diff --git a/pcbnew/board_commit.h b/pcbnew/board_commit.h index 2dbcddf5a0..c1c3e38b5b 100644 --- a/pcbnew/board_commit.h +++ b/pcbnew/board_commit.h @@ -40,7 +40,7 @@ public: BOARD_COMMIT( PCB_BASE_FRAME* aFrame ); virtual ~BOARD_COMMIT(); - virtual void Push( const wxString& aMessage ) override; + virtual void Push( const wxString& aMessage = wxT( "A commit" ) ) override; virtual void Revert() override; private: diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index ebeee9d698..ff914e8d62 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -48,6 +48,7 @@ #include #include +#include MODULE::MODULE( BOARD* parent ) : BOARD_ITEM_CONTAINER( (BOARD_ITEM*) parent, PCB_MODULE_T ), @@ -825,29 +826,6 @@ void MODULE::RunOnChildren( std::function aFunction ) } } - -void MODULE::ViewUpdate( int aUpdateFlags ) -{ - if( !m_view ) - return; - - // Update the module itself - VIEW_ITEM::ViewUpdate( aUpdateFlags ); - - // Update pads - for( D_PAD* pad = m_Pads.GetFirst(); pad; pad = pad->Next() ) - pad->ViewUpdate( aUpdateFlags ); - - // Update module's drawing (mostly silkscreen) - for( BOARD_ITEM* drawing = m_Drawings.GetFirst(); drawing; drawing = drawing->Next() ) - drawing->ViewUpdate( aUpdateFlags ); - - // Update module's texts - m_Reference->ViewUpdate( aUpdateFlags ); - m_Value->ViewUpdate( aUpdateFlags ); -} - - void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const { aCount = 2; @@ -870,13 +848,13 @@ void MODULE::ViewGetLayers( int aLayers[], int& aCount ) const } -unsigned int MODULE::ViewGetLOD( int aLayer ) const +unsigned int MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { int layer = ( m_Layer == F_Cu ) ? MOD_FR_VISIBLE : ( m_Layer == B_Cu ) ? MOD_BK_VISIBLE : ANCHOR_VISIBLE; // Currently it is only for anchor layer - if( m_view->IsLayerVisible( ITEM_GAL_LAYER( layer ) ) ) + if( aView->IsLayerVisible( ITEM_GAL_LAYER( layer ) ) ) return 30; return std::numeric_limits::max(); diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index b536e4dd06..63a549a863 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -53,6 +53,10 @@ class D_PAD; class BOARD; class MSG_PANEL_ITEM; +namespace KIGFX +{ + class VIEW; +}; enum INCLUDE_NPTH_T { @@ -557,14 +561,12 @@ public: */ void RunOnChildren( std::function aFunction ); - /// @copydoc VIEW_ITEM::ViewUpdate() - void ViewUpdate( int aUpdateFlags = KIGFX::VIEW_ITEM::ALL ) override; /// @copydoc VIEW_ITEM::ViewGetLayers() virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; /// @copydoc VIEW_ITEM::ViewGetLOD() - virtual unsigned int ViewGetLOD( int aLayer ) const override; + virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override; /// @copydoc VIEW_ITEM::ViewBBox() virtual const BOX2I ViewBBox() const override; diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 67cd26162e..081e020a46 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -959,7 +959,7 @@ void D_PAD::ViewGetLayers( int aLayers[], int& aCount ) const } -unsigned int D_PAD::ViewGetLOD( int aLayer ) const +unsigned int D_PAD::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { // Netnames will be shown only if zoom is appropriate if( IsNetnameLayer( aLayer ) ) diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 63798d66d2..c4689630fb 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -46,6 +46,10 @@ class MODULE; class TRACK; class MSG_PANEL_INFO; +namespace KIGFX +{ + class VIEW; +}; // Helper class to store parameters used to draw a pad class PAD_DRAWINFO @@ -540,7 +544,7 @@ public: virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; /// @copydoc VIEW_ITEM::ViewGetLOD() - virtual unsigned int ViewGetLOD( int aLayer ) const override; + virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override; /// @copydoc VIEW_ITEM::ViewBBox() virtual const BOX2I ViewBBox() const override; diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 8f1672143e..d069bedf96 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -45,6 +45,8 @@ #include #include +#include + #include @@ -419,25 +421,25 @@ void TEXTE_MODULE::ViewGetLayers( int aLayers[], int& aCount ) const } -unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer ) const +unsigned int TEXTE_MODULE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { const int MAX = std::numeric_limits::max(); - if( !m_view ) + if( !aView ) return 0; - if( m_Type == TEXT_is_VALUE && !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ) ) ) + if( m_Type == TEXT_is_VALUE && !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_VALUES_VISIBLE ) ) ) return MAX; - if( m_Type == TEXT_is_REFERENCE && !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE ) ) ) + if( m_Type == TEXT_is_REFERENCE && !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_REFERENCES_VISIBLE ) ) ) return MAX; - if( IsFrontLayer( m_Layer ) && ( !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ) ) || - !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_FR_VISIBLE ) ) ) ) + if( IsFrontLayer( m_Layer ) && ( !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_FR_VISIBLE ) ) || + !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_FR_VISIBLE ) ) ) ) return MAX; - if( IsBackLayer( m_Layer ) && ( !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ) ) || - !m_view->IsLayerVisible( ITEM_GAL_LAYER( MOD_BK_VISIBLE ) ) ) ) + if( IsBackLayer( m_Layer ) && ( !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_TEXT_BK_VISIBLE ) ) || + !aView->IsLayerVisible( ITEM_GAL_LAYER( MOD_BK_VISIBLE ) ) ) ) return MAX; return 0; diff --git a/pcbnew/class_text_mod.h b/pcbnew/class_text_mod.h index 42b35030a5..76d56fb541 100644 --- a/pcbnew/class_text_mod.h +++ b/pcbnew/class_text_mod.h @@ -184,7 +184,7 @@ public: virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; /// @copydoc VIEW_ITEM::ViewGetLOD() - virtual unsigned int ViewGetLOD( int aLayer ) const override; + virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override; #if defined(DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index a85c4cfb14..27a622fc0e 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -757,7 +757,7 @@ void TRACK::ViewGetLayers( int aLayers[], int& aCount ) const } -unsigned int TRACK::ViewGetLOD( int aLayer ) const +unsigned int TRACK::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const { // Netnames will be shown only if zoom is appropriate if( IsNetnameLayer( aLayer ) ) diff --git a/pcbnew/class_track.h b/pcbnew/class_track.h index e1f782d866..e18517942a 100644 --- a/pcbnew/class_track.h +++ b/pcbnew/class_track.h @@ -302,7 +302,7 @@ public: virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; /// @copydoc VIEW_ITEM::ViewGetLOD() - virtual unsigned int ViewGetLOD( int aLayer ) const override; + virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override; #if defined (DEBUG) virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } diff --git a/pcbnew/clean.cpp b/pcbnew/clean.cpp index e9b705b984..cd75aecd88 100644 --- a/pcbnew/clean.cpp +++ b/pcbnew/clean.cpp @@ -742,7 +742,6 @@ TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aTrackRef->SetStart( aCandidate->GetEnd() ); aTrackRef->start = aCandidate->end; aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( END_ON_PAD ) ); - aTrackRef->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); return aCandidate; } else @@ -750,7 +749,6 @@ TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aTrackRef->SetStart( aCandidate->GetStart() ); aTrackRef->start = aCandidate->start; aTrackRef->SetState( START_ON_PAD, aCandidate->GetState( START_ON_PAD ) ); - aTrackRef->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); return aCandidate; } } @@ -767,7 +765,6 @@ TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aTrackRef->SetEnd( aCandidate->GetEnd() ); aTrackRef->end = aCandidate->end; aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( END_ON_PAD ) ); - aTrackRef->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); return aCandidate; } else @@ -775,7 +772,6 @@ TRACK* TRACKS_CLEANER::mergeCollinearSegmentIfPossible( TRACK* aTrackRef, TRACK* aTrackRef->SetEnd( aCandidate->GetStart() ); aTrackRef->end = aCandidate->start; aTrackRef->SetState( END_ON_PAD, aCandidate->GetState( START_ON_PAD ) ); - aTrackRef->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); return aCandidate; } } diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index 50c3805cf9..99e6eb953f 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -942,9 +943,12 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() } } + if( IsGalCanvasActive() ) + { /// @todo LEGACY tracks might have changed their nets, so we need to refresh labels in GAL - for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) - track->ViewUpdate(); + for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() ) + GetGalCanvas()->GetView()->Update( track ); + } // Sort the track list by net codes: RebuildTrackChain( m_Pcb ); diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index d766deb03c..5ddf4db130 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -124,7 +124,6 @@ TRACK* PCB_EDIT_FRAME::Delete_Segment( wxDC* DC, TRACK* aTrack ) GetBoard()->Remove( aTrack ); GetBoard()->GetRatsnest()->Remove( aTrack ); - aTrack->ViewRelease(); // redraw the area where the track was m_canvas->RefreshDrawingRect( aTrack->GetBoundingBox() ); @@ -175,7 +174,6 @@ void PCB_EDIT_FRAME::Delete_net( wxDC* DC, TRACK* aTrack ) break; GetBoard()->GetRatsnest()->Remove( segm ); - segm->ViewRelease(); GetBoard()->m_Track.Remove( segm ); // redraw the area where the track was @@ -222,7 +220,6 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm ) << std::endl; ) GetBoard()->GetRatsnest()->Remove( tracksegment ); - tracksegment->ViewRelease(); GetBoard()->m_Track.Remove( tracksegment ); // redraw the area where the track was diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp index 80c26e2cdf..029cf8a166 100644 --- a/pcbnew/dialogs/dialog_drc.cpp +++ b/pcbnew/dialogs/dialog_drc.cpp @@ -36,6 +36,7 @@ #include #include #include +#include /* class DIALOG_DRC_CONTROL: a dialog to set DRC parameters (clearance, min cooper size) * and run DRC tests @@ -672,4 +673,3 @@ void DIALOG_DRC_CONTROL::UpdateDisplayedCounts() m_MarkerCount->SetLabelText( wxString::Format( "%d", marker_count ) ); m_UnconnectedCount->SetLabelText( wxString::Format( "%d", unconnected_count ) ); } - diff --git a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp index 8ba9521d63..c597c09179 100644 --- a/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp +++ b/pcbnew/dialogs/dialog_global_edit_tracks_and_vias.cpp @@ -33,6 +33,7 @@ #include +#include /** * DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS, derived from DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS_BASE_BASE @@ -260,7 +261,7 @@ void DIALOG_GLOBAL_EDIT_TRACKS_AND_VIAS::OnOkClick( wxCommandEvent& event ) if( m_parent->IsGalCanvasActive() ) { for( TRACK* track = m_parent->GetBoard()->m_Track; track != NULL; track = track->Next() ) - track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_parent->GetGalCanvas()->GetView()->Update( track, KIGFX::GEOMETRY ); } else m_parent->GetCanvas()->Refresh(); diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp index a56522e261..a73eaeb783 100644 --- a/pcbnew/dialogs/dialog_pad_properties.cpp +++ b/pcbnew/dialogs/dialog_pad_properties.cpp @@ -877,7 +877,7 @@ void DIALOG_PAD_PROPERTIES::redraw() { if( m_parent->IsGalCanvasActive() ) { - m_dummyPad->ViewUpdate(); + m_parent->GetGalCanvas()->GetView()->Update( m_dummyPad ); BOX2I bbox = m_dummyPad->ViewBBox(); diff --git a/pcbnew/dialogs/dialog_track_via_properties.cpp b/pcbnew/dialogs/dialog_track_via_properties.cpp index 78ca781e44..b53c1db055 100644 --- a/pcbnew/dialogs/dialog_track_via_properties.cpp +++ b/pcbnew/dialogs/dialog_track_via_properties.cpp @@ -52,12 +52,9 @@ DIALOG_TRACK_VIA_PROPERTIES::DIALOG_TRACK_VIA_PROPERTIES( PCB_BASE_FRAME* aParen bool hasLocked = false; bool hasUnlocked = false; - // Look for values that are common for every item that is selected - for( int i = 0; i < m_items.Size(); ++i ) + for( auto& item : m_items ) { - const BOARD_ITEM* item = m_items.Item( i ); - switch( item->Type() ) { case PCB_TRACE_T: @@ -212,10 +209,8 @@ bool DIALOG_TRACK_VIA_PROPERTIES::Apply( COMMIT& aCommit ) bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED; bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED; - - for( int i = 0; i < m_items.Size(); ++i ) + for( auto item : m_items ) { - BOARD_ITEM* item = m_items.Item( i ); aCommit.Modify( item ); switch( item->Type() ) diff --git a/pcbnew/edit_track_width.cpp b/pcbnew/edit_track_width.cpp index 756f0bedc6..8441c93b8f 100644 --- a/pcbnew/edit_track_width.cpp +++ b/pcbnew/edit_track_width.cpp @@ -239,7 +239,8 @@ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment ) segm = (TRACK*) itemsListPicker.GetPickedItem( ii ); segm->Draw( m_canvas, aDC, GR_OR ); // Display new track shape - segm->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); +// fixme: commit! +// segm->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } m_canvas->CrossHairOn( aDC ); // Display cursor shape diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index b787dd7e60..69cebdc803 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -366,6 +366,10 @@ void PCB_EDIT_FRAME::ReCreateMenuBar() _( "&List Nets" ), _( "View a list of nets with names and id's" ), KiBitmap( list_nets_xpm ) ); + AddMenuItem( viewMenu, ID_MENU_PCB_FLIP_VIEW, + _( "&Flip View" ), _( "Flips (mirrors) the board view." ), + KiBitmap( three_d_xpm ), wxITEM_CHECK ); + viewMenu->AppendSeparator(); text = AddHotkeyName( _( "&Switch Canvas to Legacy" ), g_Pcbnew_Editor_Hokeys_Descr, diff --git a/pcbnew/modedit.cpp b/pcbnew/modedit.cpp index c4db2911f8..ca1e563e5c 100644 --- a/pcbnew/modedit.cpp +++ b/pcbnew/modedit.cpp @@ -582,7 +582,6 @@ void FOOTPRINT_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) int ret = dialog.ShowModal(); GetScreen()->GetCurItem()->ClearFlags(); - GetBoard()->m_Modules.GetFirst()->ViewUpdate(); if( ret > 0 ) m_canvas->Refresh(); @@ -988,4 +987,3 @@ void FOOTPRINT_EDIT_FRAME::SetActiveLayer( LAYER_ID aLayer ) if( IsGalCanvasActive() ) GetGalCanvas()->Refresh(); } - diff --git a/pcbnew/netlist.cpp b/pcbnew/netlist.cpp index 88f03b9c82..af06f69b81 100644 --- a/pcbnew/netlist.cpp +++ b/pcbnew/netlist.cpp @@ -52,6 +52,7 @@ using namespace std::placeholders; #include #include +#include void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName, @@ -159,7 +160,6 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName, { module->RunOnChildren( std::bind( &KIGFX::VIEW::Add, view, _1 ) ); view->Add( module ); - module->ViewUpdate(); } if( aDeleteUnconnectedTracks && board->m_Track ) diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp index 81b28c6934..3383c5388e 100644 --- a/pcbnew/pcb_base_edit_frame.cpp +++ b/pcbnew/pcb_base_edit_frame.cpp @@ -27,6 +27,8 @@ #include #include #include +#include + void PCB_BASE_EDIT_FRAME::SetRotationAngle( int aRotationAngle ) { diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp index c7b37a0245..55c1bd7261 100644 --- a/pcbnew/pcb_draw_panel_gal.cpp +++ b/pcbnew/pcb_draw_panel_gal.cpp @@ -380,6 +380,14 @@ void PCB_DRAW_PANEL_GAL::setDefaultLayerOrder() } +bool PCB_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType ) +{ + bool rv = EDA_DRAW_PANEL_GAL::SwitchBackend( aGalType ); + setDefaultLayerDeps(); + return rv; +} + + void PCB_DRAW_PANEL_GAL::setDefaultLayerDeps() { for( LAYER_NUM i = 0; (unsigned) i < sizeof( GAL_LAYER_ORDER ) / sizeof( LAYER_NUM ); ++i ) @@ -400,6 +408,13 @@ void PCB_DRAW_PANEL_GAL::setDefaultLayerDeps() } } + // caching makes no sense for Cairo and other software renderers + if ( m_backend != GAL_TYPE_OPENGL ) + { + for( int i = 0; i < KIGFX::VIEW::VIEW_MAX_LAYERS; i++ ) + m_view->SetLayerTarget( i, KIGFX::TARGET_NONCACHED ); + } + m_view->SetLayerTarget( ITEM_GAL_LAYER( ANCHOR_VISIBLE ), KIGFX::TARGET_NONCACHED ); m_view->SetLayerDisplayOnly( ITEM_GAL_LAYER( ANCHOR_VISIBLE ) ); diff --git a/pcbnew/pcb_draw_panel_gal.h b/pcbnew/pcb_draw_panel_gal.h index f4e397dc15..7911919ebe 100644 --- a/pcbnew/pcb_draw_panel_gal.h +++ b/pcbnew/pcb_draw_panel_gal.h @@ -83,6 +83,8 @@ public: ///> @copydoc EDA_DRAW_PANEL_GAL::OnShow() void OnShow() override; + bool SwitchBackend( GAL_TYPE aGalType ) override; + protected: ///> Reassigns layer order to the initial settings. void setDefaultLayerOrder(); diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h index 2099f78a17..e6582860c8 100644 --- a/pcbnew/pcb_painter.h +++ b/pcbnew/pcb_painter.h @@ -191,7 +191,7 @@ public: } /// @copydoc PAINTER::GetSettings() - virtual RENDER_SETTINGS* GetSettings() override + virtual PCB_RENDER_SETTINGS* GetSettings() override { return &m_pcbSettings; } diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp index 18f69a9ae6..91a04986d6 100644 --- a/pcbnew/pcbframe.cpp +++ b/pcbnew/pcbframe.cpp @@ -115,6 +115,7 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME ) // Menu Files: EVT_MENU( ID_MAIN_MENUBAR, PCB_EDIT_FRAME::Process_Special_Functions ) + EVT_MENU( ID_MENU_PCB_FLIP_VIEW, PCB_EDIT_FRAME::OnFlipPcbView ) EVT_MENU( ID_APPEND_FILE, PCB_EDIT_FRAME::Files_io ) EVT_MENU( ID_SAVE_BOARD_AS, PCB_EDIT_FRAME::Files_io ) @@ -1131,3 +1132,12 @@ void PCB_EDIT_FRAME::OnUpdatePCBFromSch( wxCommandEvent& event ) Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_PCB_UPDATE_REQUEST, "", this ); } } + + +void PCB_EDIT_FRAME::OnFlipPcbView( wxCommandEvent& evt ) +{ + auto view = GetGalCanvas()->GetView(); + view->SetMirror( evt.IsChecked(), false ); + view->RecacheAllItems(); + Refresh(); +} diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index f1e31b51e0..e7333d296b 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -60,6 +60,7 @@ #include #include #include +#include void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) @@ -186,7 +187,7 @@ void PCB_EDIT_FRAME::Process_Config( wxCommandEvent& event ) if( dlg.ShowModal() == 1 && IsGalCanvasActive() ) { for( MODULE* module = GetBoard()->m_Modules; module; module = module->Next() ) - module->ViewUpdate(); + GetGalCanvas()->GetView()->Update( module ); GetGalCanvas()->Refresh(); } diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index e5a6e90cbb..801a4e021c 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -52,6 +52,7 @@ enum pcbnew_ids ID_PCB_MASK_CLEARANCE, ID_PCB_LAYERS_SETUP, + ID_MENU_PCB_FLIP_VIEW, ID_POPUP_PCB_START_RANGE, ID_POPUP_PCB_MOVE_MODULE_REQUEST, diff --git a/pcbnew/ratsnest_viewitem.cpp b/pcbnew/ratsnest_viewitem.cpp index 9561b2e6c4..cdeba78e09 100644 --- a/pcbnew/ratsnest_viewitem.cpp +++ b/pcbnew/ratsnest_viewitem.cpp @@ -33,6 +33,7 @@ #include #include +#include namespace KIGFX { @@ -52,13 +53,14 @@ const BOX2I RATSNEST_VIEWITEM::ViewBBox() const } -void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const +void RATSNEST_VIEWITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { - aGal->SetIsStroke( true ); - aGal->SetIsFill( false ); - aGal->SetLineWidth( 1.0 ); - RENDER_SETTINGS* rs = m_view->GetPainter()->GetSettings(); - COLOR4D color = rs->GetColor( NULL, ITEM_GAL_LAYER( RATSNEST_VISIBLE ) ); + auto gal = aView->GetGAL(); + gal->SetIsStroke( true ); + gal->SetIsFill( false ); + gal->SetLineWidth( 1.0 ); + auto rs = aView->GetPainter()->GetSettings(); + auto color = rs->GetColor( NULL, ITEM_GAL_LAYER( RATSNEST_VISIBLE ) ); int highlightedNet = rs->GetHighlightNetCode(); // Dynamic ratsnest (for e.g. dragged items) @@ -70,7 +72,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const continue; // Set brighter color for the temporary ratsnest - aGal->SetStrokeColor( color.Brightened( 0.8 ) ); + gal->SetStrokeColor( color.Brightened( 0.8 ) ); // Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved) for( const RN_NODE_PTR& node : net.GetSimpleNodes() ) @@ -86,13 +88,13 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const VECTOR2D origin( node->GetX(), node->GetY() ); VECTOR2D end( dest->GetX(), dest->GetY() ); - aGal->DrawLine( origin, end ); + gal->DrawLine( origin, end ); } } // Draw the "static" ratsnest if( i != highlightedNet ) - aGal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted + gal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted const std::vector* edges = net.GetUnconnected(); @@ -106,7 +108,7 @@ void RATSNEST_VIEWITEM::ViewDraw( int aLayer, GAL* aGal ) const VECTOR2D source( sourceNode->GetX(), sourceNode->GetY() ); VECTOR2D target( targetNode->GetX(), targetNode->GetY() ); - aGal->DrawLine( source, target ); + gal->DrawLine( source, target ); } } } diff --git a/pcbnew/ratsnest_viewitem.h b/pcbnew/ratsnest_viewitem.h index 516c4cae90..7573e59ce4 100644 --- a/pcbnew/ratsnest_viewitem.h +++ b/pcbnew/ratsnest_viewitem.h @@ -47,7 +47,7 @@ public: const BOX2I ViewBBox() const override; /// @copydoc VIEW_ITEM::ViewDraw() - void ViewDraw( int aLayer, GAL* aGal ) const override; + void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; /// @copydoc VIEW_ITEM::ViewGetLayers() void ViewGetLayers( int aLayers[], int& aCount ) const override; diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 5cf4151387..3a69890782 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -326,6 +326,7 @@ public: ~PNS_PCBNEW_DEBUG_DECORATOR() { Clear(); + m_view->Remove( m_items ); delete m_items; } @@ -342,7 +343,6 @@ public: m_items = new KIGFX::VIEW_GROUP( m_view ); m_items->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) ); m_view->Add( m_items ); - m_items->ViewSetVisible( true ); } void AddPoint( VECTOR2I aP, int aColor ) override @@ -404,12 +404,11 @@ public: void AddLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) override { - ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_items ); + ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_view ); pitem->Line( aLine, aWidth, aType ); m_items->Add( pitem ); // Should not be needed, as m_items has been passed as a parent group in alloc; - pitem->ViewSetVisible( true ); - m_items->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); + m_view->Update( m_items ); } void Clear() override @@ -417,7 +416,7 @@ public: if( m_view && m_items ) { m_items->FreeItems(); - m_items->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( m_items ); } } @@ -518,7 +517,7 @@ std::unique_ptr< PNS::SOLID > PNS_KICAD_IFACE::syncPad( D_PAD* aPad ) RotatePoint( &offset, aPad->GetOrientation() ); solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); - solid->SetOffset ( VECTOR2I ( offset.x, offset.y ) ); + solid->SetOffset( VECTOR2I( offset.x, offset.y ) ); double orient = aPad->GetOrientation() / 10.0; @@ -795,14 +794,14 @@ void PNS_KICAD_IFACE::SyncWorld( PNS::NODE *aWorld ) void PNS_KICAD_IFACE::EraseView() { for( auto item : m_hiddenItems ) - item->ViewSetVisible( true ); + m_view->SetVisible( item, true ); m_hiddenItems.clear(); if( m_previewItems ) { m_previewItems->FreeItems(); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( m_previewItems ); } if( m_debugDecorator ) @@ -814,7 +813,7 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aColor, int aClea { wxLogTrace( "PNS", "DisplayItem %p", aItem ); - ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); + ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view ); if( aColor >= 0 ) pitem->SetColor( KIGFX::COLOR4D( aColor ) ); @@ -824,8 +823,7 @@ void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aColor, int aClea m_previewItems->Add( pitem ); - pitem->ViewSetVisible( true ); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); + m_view->Update( m_previewItems ); } @@ -835,11 +833,11 @@ void PNS_KICAD_IFACE::HideItem( PNS::ITEM* aItem ) if( parent ) { - if( parent->ViewIsVisible() ) + if( m_view->IsVisible( parent ) ) m_hiddenItems.insert( parent ); - parent->ViewSetVisible( false ); - parent->ViewUpdate( KIGFX::VIEW_ITEM::APPEARANCE ); + m_view->SetVisible( parent, false ); + m_view->Update( parent, KIGFX::APPEARANCE ); } } @@ -906,8 +904,9 @@ void PNS_KICAD_IFACE::AddItem( PNS::ITEM* aItem ) void PNS_KICAD_IFACE::Commit() { + EraseView(); m_commit->Push( wxT( "Added a track" ) ); - m_commit.reset( new BOARD_COMMIT ( m_frame ) ); + m_commit.reset( new BOARD_COMMIT( m_frame ) ); } @@ -925,7 +924,6 @@ void PNS_KICAD_IFACE::SetView( KIGFX::VIEW *aView ) m_previewItems = new KIGFX::VIEW_GROUP( m_view ); m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) ); m_view->Add( m_previewItems ); - m_previewItems->ViewSetVisible( true ); delete m_debugDecorator; m_debugDecorator = new PNS_PCBNEW_DEBUG_DECORATOR(); @@ -938,11 +936,13 @@ void PNS_KICAD_IFACE::UpdateNet( int aNetCode ) wxLogTrace( "PNS", "Update-net %d", aNetCode ); } + PNS::RULE_RESOLVER* PNS_KICAD_IFACE::GetRuleResolver() { return m_ruleResolver; } + void PNS_KICAD_IFACE::SetRouter( PNS::ROUTER* aRouter ) { m_router = aRouter; @@ -953,5 +953,5 @@ void PNS_KICAD_IFACE::SetHostFrame( PCB_EDIT_FRAME* aFrame ) { m_frame = aFrame; - m_commit.reset( new BOARD_COMMIT ( m_frame ) ); + m_commit.reset( new BOARD_COMMIT( m_frame ) ); } diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp index 32a3715d0b..b4aafec5ae 100644 --- a/pcbnew/router/pns_tool_base.cpp +++ b/pcbnew/router/pns_tool_base.cpp @@ -56,6 +56,8 @@ using namespace std::placeholders; #include "pns_tune_status_popup.h" #include "pns_topology.h" +#include + using namespace KIGFX; namespace PNS { diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index 239985ef6b..5b0c27352d 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -37,10 +37,10 @@ using namespace KIGFX; -ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, VIEW_GROUP* aParent ) : +ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView ) : EDA_ITEM( NOT_USED ) { - m_parent = aParent; + m_view = aView; m_shape = NULL; m_clearance = -1; @@ -118,8 +118,6 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem ) if( aItem->Marker() & PNS::MK_VIOLATION ) m_color = COLOR4D( 0, 1, 0, 1 ); - - ViewSetVisible( true ); } @@ -146,52 +144,53 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const } -void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL* aGal ) const +void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL* gal ) const { for( int s = 0; s < aL.SegmentCount(); s++ ) - aGal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B ); + gal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B ); if( aL.IsClosed() ) - aGal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A ); + gal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A ); } -void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const +void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { + auto gal = aView->GetGAL(); //col.Brighten(0.7); - aGal->SetLayerDepth( m_depth ); + gal->SetLayerDepth( m_depth ); if( m_type == PR_SHAPE ) { if( !m_shape ) return; - aGal->SetLineWidth( m_width ); - aGal->SetStrokeColor( m_color ); - aGal->SetFillColor( m_color ); - aGal->SetIsStroke( m_width ? true : false ); - aGal->SetIsFill( true ); + gal->SetLineWidth( m_width ); + gal->SetStrokeColor( m_color ); + gal->SetFillColor( m_color ); + gal->SetIsStroke( m_width ? true : false ); + gal->SetIsFill( true ); switch( m_shape->Type() ) { case SH_LINE_CHAIN: { const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) m_shape; - drawLineChain( *l, aGal ); + drawLineChain( *l, gal ); break; } case SH_SEGMENT: { const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) m_shape; - aGal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() ); + gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() ); if( m_clearance > 0 ) { - aGal->SetLayerDepth( ClearanceOverlayDepth ); - aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); - aGal->SetFillColor( COLOR4D( DARKDARKGRAY ) ); - aGal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance ); + gal->SetLayerDepth( ClearanceOverlayDepth ); + gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); + gal->SetFillColor( COLOR4D( DARKDARKGRAY ) ); + gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance ); } break; @@ -200,14 +199,14 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const case SH_CIRCLE: { const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) m_shape; - aGal->DrawCircle( c->GetCenter(), c->GetRadius() ); + gal->DrawCircle( c->GetCenter(), c->GetRadius() ); if( m_clearance > 0 ) { - aGal->SetLayerDepth( ClearanceOverlayDepth ); - aGal->SetFillColor( COLOR4D( DARKDARKGRAY ) ); - aGal->SetIsStroke( false ); - aGal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); + gal->SetLayerDepth( ClearanceOverlayDepth ); + gal->SetFillColor( COLOR4D( DARKDARKGRAY ) ); + gal->SetIsStroke( false ); + gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance ); } break; @@ -216,19 +215,19 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const case SH_RECT: { const SHAPE_RECT* r = (const SHAPE_RECT*) m_shape; - aGal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() ); + gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() ); if( m_clearance > 0 ) { - aGal->SetLayerDepth( ClearanceOverlayDepth ); + gal->SetLayerDepth( ClearanceOverlayDepth ); VECTOR2I p0( r->GetPosition() ), s( r->GetSize() ); - aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); - aGal->SetIsStroke( true ); - aGal->SetLineWidth( 2 * m_clearance ); - aGal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) ); - aGal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) ); - aGal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) ); - aGal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) ); + gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); + gal->SetIsStroke( true ); + gal->SetLineWidth( 2 * m_clearance ); + gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) ); + gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) ); + gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) ); + gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) ); } break; @@ -242,17 +241,17 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const { polygon.push_back( c->CDPoint( i ) ); } - aGal->DrawPolygon( polygon ); + gal->DrawPolygon( polygon ); if( m_clearance > 0 ) { - aGal->SetLayerDepth( ClearanceOverlayDepth ); - aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); - aGal->SetIsStroke( true ); - aGal->SetLineWidth( 2 * m_clearance ); + gal->SetLayerDepth( ClearanceOverlayDepth ); + gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) ); + gal->SetIsStroke( true ); + gal->SetLineWidth( 2 * m_clearance ); // need the implicit last segment to be explicit for DrawPolyline polygon.push_back( c->CDPoint( 0 ) ); - aGal->DrawPolyline( polygon ); + gal->DrawPolyline( polygon ); } break; } @@ -273,8 +272,6 @@ void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int a m_type = PR_SHAPE; m_depth = -1024; // TODO gal->GetMinDepth() m_shape = aLine.Clone(); - - ViewSetVisible( true ); } @@ -290,8 +287,7 @@ void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle ) const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const { - PCB_RENDER_SETTINGS* settings = - static_cast( m_parent->GetView()->GetPainter()->GetSettings() ); + auto settings = static_cast( m_view->GetPainter()->GetSettings() ); return settings->GetLayerColor( aLayer ); } diff --git a/pcbnew/router/router_preview_item.h b/pcbnew/router/router_preview_item.h index 3dd6da9b94..094e7ddcdb 100644 --- a/pcbnew/router/router_preview_item.h +++ b/pcbnew/router/router_preview_item.h @@ -56,7 +56,7 @@ public: PR_SHAPE }; - ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = NULL, KIGFX::VIEW_GROUP* aParent = NULL ); + ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem = NULL, KIGFX::VIEW* aView = NULL); ~ROUTER_PREVIEW_ITEM(); void Update( const PNS::ITEM* aItem ); @@ -91,7 +91,7 @@ public: const BOX2I ViewBBox() const override; - virtual void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const override; + virtual void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; virtual void ViewGetLayers( int aLayers[], int& aCount ) const override { @@ -105,7 +105,7 @@ private: const KIGFX::COLOR4D assignColor( int aStyle ) const; const KIGFX::COLOR4D getLayerColor( int aLayer ) const; - KIGFX::VIEW_GROUP* m_parent; + KIGFX::VIEW* m_view; PNS::ROUTER* m_router; SHAPE* m_shape; diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 72defe9797..f3c37b5966 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -32,6 +32,7 @@ using namespace std::placeholders; #include #include #include +#include #include #include #include diff --git a/pcbnew/tools/bright_box.cpp b/pcbnew/tools/bright_box.cpp index 7901de2995..2e52634fdf 100644 --- a/pcbnew/tools/bright_box.cpp +++ b/pcbnew/tools/bright_box.cpp @@ -31,31 +31,42 @@ using namespace KIGFX; const double BRIGHT_BOX::LINE_WIDTH = 100000.0; const COLOR4D BRIGHT_BOX::BOX_COLOR = KIGFX::COLOR4D( 0.0, 1.0, 0.0, 1.0 ); -BRIGHT_BOX::BRIGHT_BOX( BOARD_ITEM* aItem ) : +BRIGHT_BOX::BRIGHT_BOX() : EDA_ITEM( NOT_USED ), // this item is never added to a BOARD so it needs no type - m_item( aItem ) + m_item( nullptr ) { } -void BRIGHT_BOX::ViewDraw( int aLayer, GAL* aGal ) const +void BRIGHT_BOX::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { - aGal->SetIsStroke( true ); - aGal->SetIsFill( false ); - aGal->SetLineWidth( LINE_WIDTH ); - aGal->SetStrokeColor( BOX_COLOR ); + if( !m_item ) + return; + + auto gal = aView->GetGAL(); + + gal->SetIsStroke( true ); + gal->SetIsFill( false ); + gal->SetLineWidth( LINE_WIDTH ); + gal->SetStrokeColor( BOX_COLOR ); + if( m_item->Type() == PCB_TRACE_T ) { const TRACK* track = static_cast( m_item ); - aGal->DrawSegment( track->GetStart(), track->GetEnd(), track->GetWidth() ); + gal->DrawSegment( track->GetStart(), track->GetEnd(), track->GetWidth() ); } else { BOX2I box = m_item->ViewBBox(); - aGal->DrawRectangle( box.GetOrigin(), box.GetOrigin() + box.GetSize() ); + gal->DrawRectangle( box.GetOrigin(), box.GetOrigin() + box.GetSize() ); } } + +void BRIGHT_BOX::SetItem( BOARD_ITEM* aItem ) +{ + m_item = aItem; +} diff --git a/pcbnew/tools/bright_box.h b/pcbnew/tools/bright_box.h index 035c46b6e5..c4e2a19a5e 100644 --- a/pcbnew/tools/bright_box.h +++ b/pcbnew/tools/bright_box.h @@ -39,15 +39,21 @@ class BRIGHT_BOX : public EDA_ITEM { public: - BRIGHT_BOX( BOARD_ITEM* aItem ); - ~BRIGHT_BOX() {}; + BRIGHT_BOX(); + ~BRIGHT_BOX() {} virtual const BOX2I ViewBBox() const override { + BOX2I bb; bb.SetMaximum(); + return bb; + + if( !m_item ) + return BOX2I(); + return m_item->ViewBBox(); } - void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const override; + void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; void ViewGetLayers( int aLayers[], int& aCount ) const override { @@ -69,6 +75,8 @@ public: return wxT( "BRIGHT_BOX" ); } + void SetItem( BOARD_ITEM* aItem ); + private: static const KIGFX::COLOR4D BOX_COLOR; static const double LINE_WIDTH; diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index b9a9fdac4f..efc54ded40 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,8 @@ #include #include +#include + DRAWING_TOOL::DRAWING_TOOL() : PCB_TOOL( "pcbnew.InteractiveDrawing" ), m_view( NULL ), m_controls( NULL ), m_board( NULL ), m_frame( NULL ), m_lineWidth( 1 ) @@ -163,7 +166,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -206,13 +209,13 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); - preview.ViewUpdate(); + m_view->Update( &preview ); } // TODO rotate CCW else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { text->Flip( text->GetPosition() ); - preview.ViewUpdate(); + m_view->Update( &preview ); } } @@ -302,7 +305,7 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item - preview.ViewUpdate(); + m_view->Update( &preview ); } } @@ -326,7 +329,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) int maxThickness; // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -369,7 +372,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) else if( evt->IsAction( &COMMON_ACTIONS::incWidth ) && step != SET_ORIGIN ) { dimension->SetWidth( dimension->GetWidth() + WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::decWidth ) && step != SET_ORIGIN ) @@ -379,7 +382,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) if( width > WIDTH_STEP ) { dimension->SetWidth( width - WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } } @@ -478,7 +481,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) } // Show a preview of the item - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } } @@ -527,23 +530,21 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); - VECTOR2I delta = cursorPos - (*list.begin())->GetPosition(); + VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view - for( auto it = list.begin(), itEnd = list.end(); it != itEnd; ++it ) + for( auto item : list ) { - KICAD_T type = (*it)->Type(); - assert( type == PCB_LINE_T || type == PCB_TEXT_T ); + assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); - if( type == PCB_LINE_T || type == PCB_TEXT_T ) - preview.Add( *it ); + preview.Add( item ); } - BOARD_ITEM* firstItem = static_cast( *preview.Begin() ); + BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -561,10 +562,10 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { delta = cursorPos - firstItem->GetPosition(); - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Move( wxPoint( delta.x, delta.y ) ); + for( auto item : preview ) + item->Move( wxPoint( delta.x, delta.y ) ); - preview.ViewUpdate(); + m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) @@ -572,18 +573,18 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Rotate( wxPoint( cursorPos.x, cursorPos.y ), - m_frame->GetRotationAngle() ); + for( auto item : preview ) + item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), + m_frame->GetRotationAngle() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(), end = preview.End(); it != end; ++it ) - static_cast( *it )->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); + for( auto item : preview ) + item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { @@ -595,13 +596,10 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing - PICKED_ITEMS_LIST picklist; BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); - for( KIGFX::VIEW_GROUP::const_iter it = preview.Begin(); it != preview.End(); ++it ) + for( auto item : preview ) { - BOARD_ITEM* item = static_cast( *it ); - if( m_editModules ) { // Modules use different types for the same things, @@ -745,7 +743,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, DRAWSEGMENT line45; // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -903,7 +901,7 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic, } if( updatePreview ) - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } m_controls->ShowCursor( false ); @@ -928,7 +926,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) helperLine.SetWidth( 1 ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -1014,7 +1012,6 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) assert( aGraphic->GetWidth() > 0 ); m_view->Add( aGraphic ); - aGraphic->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); preview.Remove( aGraphic ); preview.Remove( &helperLine ); @@ -1055,13 +1052,13 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) } // Show a preview of the item - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::incWidth ) ) { aGraphic->SetWidth( aGraphic->GetWidth() + WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::decWidth ) ) @@ -1071,7 +1068,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) if( width > WIDTH_STEP ) { aGraphic->SetWidth( width - WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } } @@ -1083,7 +1080,7 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic ) aGraphic->SetAngle( aGraphic->GetAngle() + 3600.0 ); clockwise = !clockwise; - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } } @@ -1105,7 +1102,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item - KIGFX::VIEW_GROUP preview( m_view ); + SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -1293,7 +1290,7 @@ int DRAWING_TOOL::drawZone( bool aKeepout ) } if( updatePreview ) - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } m_controls->ShowCursor( false ); diff --git a/pcbnew/tools/edit_points.cpp b/pcbnew/tools/edit_points.cpp index 1ee9d64f5f..6acabb1913 100644 --- a/pcbnew/tools/edit_points.cpp +++ b/pcbnew/tools/edit_points.cpp @@ -42,9 +42,9 @@ EDIT_POINTS::EDIT_POINTS( EDA_ITEM* aParent ) : } -EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation ) +EDIT_POINT* EDIT_POINTS::FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ) // fixme: ugly { - float size = m_view->ToWorld( EDIT_POINT::POINT_SIZE ); + float size = aView->ToWorld( EDIT_POINT::POINT_SIZE ); std::deque::iterator pit, pitEnd; for( pit = m_points.begin(), pitEnd = m_points.end(); pit != pitEnd; ++pit ) @@ -203,23 +203,25 @@ EDIT_LINE* EDIT_POINTS::Next( const EDIT_LINE& aLine ) } -void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const +void EDIT_POINTS::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { - aGal->SetFillColor( KIGFX::COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); - aGal->SetIsFill( true ); - aGal->SetIsStroke( false ); - aGal->PushDepth(); - aGal->SetLayerDepth( aGal->GetMinDepth() ); + auto gal = aView->GetGAL(); - float size = m_view->ToWorld( EDIT_POINT::POINT_SIZE ); + gal->SetFillColor( KIGFX::COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); + gal->SetIsFill( true ); + gal->SetIsStroke( false ); + gal->PushDepth(); + gal->SetLayerDepth( gal->GetMinDepth() ); + + float size = aView->ToWorld( EDIT_POINT::POINT_SIZE ); for( const EDIT_POINT& point : m_points ) - aGal->DrawRectangle( point.GetPosition() - size / 2, point.GetPosition() + size / 2 ); + gal->DrawRectangle( point.GetPosition() - size / 2, point.GetPosition() + size / 2 ); for( const EDIT_LINE& line : m_lines ) { - aGal->DrawCircle( line.GetPosition(), size / 2 ); + gal->DrawCircle( line.GetPosition(), size / 2 ); } - aGal->PopDepth(); + gal->PopDepth(); } diff --git a/pcbnew/tools/edit_points.h b/pcbnew/tools/edit_points.h index ec134d1e95..43dc46a1cb 100644 --- a/pcbnew/tools/edit_points.h +++ b/pcbnew/tools/edit_points.h @@ -35,6 +35,7 @@ #include +#include /** * Class EDIT_POINT @@ -317,7 +318,7 @@ public: * Returns a point that is at given coordinates or NULL if there is no such point. * @param aLocation is the location for searched point. */ - EDIT_POINT* FindPoint( const VECTOR2I& aLocation ); + EDIT_POINT* FindPoint( const VECTOR2I& aLocation, KIGFX::VIEW *aView ); /** * Function GetParent() @@ -498,7 +499,7 @@ public: } ///> @copydoc VIEW_ITEM::ViewDraw() - virtual void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const override; + virtual void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; ///> @copydoc VIEW_ITEM::ViewGetLayers() virtual void ViewGetLayers( int aLayers[], int& aCount ) const override diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp index f6b552f9fa..dbe1585dac 100644 --- a/pcbnew/tools/edit_tool.cpp +++ b/pcbnew/tools/edit_tool.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -60,7 +61,7 @@ using namespace std::placeholders; EDIT_TOOL::EDIT_TOOL() : PCB_TOOL( "pcbnew.InteractiveEdit" ), m_selectionTool( NULL ), - m_dragging( false ), m_updateFlag( KIGFX::VIEW_ITEM::NONE ) + m_dragging( false ) { } @@ -68,7 +69,6 @@ EDIT_TOOL::EDIT_TOOL() : void EDIT_TOOL::Reset( RESET_REASON aReason ) { m_dragging = false; - m_updateFlag = KIGFX::VIEW_ITEM::NONE; if( aReason != RUN ) m_commit.reset( new BOARD_COMMIT( this ) ); @@ -137,7 +137,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); VECTOR2I originalCursorPos = controls->GetCursorPosition(); - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); // Shall the selection be cleared at the end? bool unselect = selection.Empty(); @@ -153,9 +153,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) bool restore = false; // Should items' state be restored when finishing the tool? bool lockOverride = false; - // By default, modified items need to update their geometry - m_updateFlag = KIGFX::VIEW_ITEM::GEOMETRY; - controls->ShowCursor( true ); // cumulative translation @@ -182,7 +179,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) else if( evt->IsAction( &COMMON_ACTIONS::editActivate ) || evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) { - BOARD_ITEM* item = selection.Item( 0 ); + BOARD_ITEM* item = selection.Front(); if( m_dragging && evt->Category() == TC_MOUSE ) { @@ -193,8 +190,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) totalMovement += movement; // Drag items to the current cursor position - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) - selection.Item( i )->Move( movement + m_offset ); + for( auto item : selection ) + item->Move( movement + m_offset ); updateRatsnest( true ); } @@ -216,10 +213,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) lockOverride = true; // Save items, so changes can be undone - selection.ForAll( [&](BOARD_ITEM* brd_item) - { - m_commit->Modify( brd_item ); - } ); + for( auto item : selection ) + m_commit->Modify( item ); m_cursor = controls->GetCursorPosition(); @@ -247,7 +242,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) } } - selection.group->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( &selection ); m_toolMgr->RunAction( COMMON_ACTIONS::editModifiedSelection, true ); } @@ -263,9 +258,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { Flip( aEvent ); - - // Flip causes change of layers - enableUpdateFlag( KIGFX::VIEW_ITEM::LAYERS ); } else if( evt->IsAction( &COMMON_ACTIONS::remove ) ) { @@ -287,9 +279,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) //editFrame->RestoreCopyFromUndoList( dummy ); // // So, instead, reset the position manually - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); item->SetPosition( item->GetPosition() - totalMovement ); // And what about flipping and rotation? @@ -307,8 +298,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) if( m_dragging ) { // Update dragging offset (distance between cursor and the first dragged item) - m_offset = selection.Item( 0 )->GetPosition() - modPoint; - selection.group->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + m_offset = selection.Front()->GetPosition() - modPoint; + getView()->Update( &selection ); updateRatsnest( true ); } } @@ -343,7 +334,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent ) int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); // Shall the selection be cleared at the end? @@ -366,7 +357,7 @@ int EDIT_TOOL::Properties( const TOOL_EVENT& aEvent ) else if( selection.Size() == 1 ) // Properties are displayed when there is only one item selected { // Display properties dialog - BOARD_ITEM* item = selection.Item( 0 ); + BOARD_ITEM* item = selection.Front(); // Some of properties dialogs alter pointers, so we should deselect them m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); @@ -403,9 +394,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent ) wxPoint rotatePoint = getModificationPoint( selection ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Rotate( rotatePoint, editFrame->GetRotationAngle() ); } @@ -435,9 +425,8 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent ) wxPoint flipPoint = getModificationPoint( selection ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Flip( flipPoint ); } @@ -465,9 +454,8 @@ int EDIT_TOOL::Remove( const TOOL_EVENT& aEvent ) // As we are about to remove items, they have to be removed from the selection first m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Remove( item ); } @@ -500,16 +488,15 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent ) VECTOR2I rp = selection.GetCenter(); wxPoint rotPoint( rp.x, rp.y ); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); m_commit->Modify( item ); item->Move( translation ); item->Rotate( rotPoint, rotation ); if( !m_dragging ) - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( item, KIGFX::GEOMETRY ); } m_commit->Push( _( "Move exact" ) ); @@ -532,7 +519,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + SELECTION& selection = selTool->GetSelection(); // Be sure that there is at least one item that we can modify if( !hoverSelection() ) @@ -543,10 +530,8 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) std::vector old_items; - for( int i = 0; i < selection.Size(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); - if( item ) old_items.push_back( item ); } @@ -563,7 +548,9 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent ) BOARD_ITEM* new_item = NULL; if( m_editModules ) + { new_item = editFrame->GetBoard()->m_Modules->Duplicate( item, increment ); + } else { #if 0 @@ -621,7 +608,7 @@ private: BOARD_ITEM* getNthItemToArray( int n ) const override { - return m_selection.Item( n ); + return m_selection[n]; } BOARD* getBoard() const override @@ -665,7 +652,7 @@ int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent ) { // first, check if we have a selection, or try to get one SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + SELECTION& selection = selTool->GetSelection(); // pick up items under the cursor if needed if( !hoverSelection() ) @@ -697,15 +684,13 @@ void EDIT_TOOL::SetTransitions() void EDIT_TOOL::updateRatsnest( bool aRedraw ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); ratsnest->ClearSimple(); - for( unsigned int i = 0; i < selection.items.GetCount(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); - ratsnest->Update( item ); if( aRedraw ) @@ -718,7 +703,7 @@ wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection ) { if( aSelection.Size() == 1 ) { - return aSelection.Item( 0 )->GetPosition() - m_offset; + return aSelection.Front()->GetPosition() - m_offset; } else { @@ -759,7 +744,7 @@ bool EDIT_TOOL::hoverSelection( bool aSanitize ) int EDIT_TOOL::editFootprintInFpEditor( const TOOL_EVENT& aEvent ) { - const SELECTION& selection = m_selectionTool->GetSelection(); + SELECTION& selection = m_selectionTool->GetSelection(); bool unselect = selection.Empty(); if( !hoverSelection() ) diff --git a/pcbnew/tools/edit_tool.h b/pcbnew/tools/edit_tool.h index 0a4ca6e442..0f9b509db8 100644 --- a/pcbnew/tools/edit_tool.h +++ b/pcbnew/tools/edit_tool.h @@ -28,17 +28,11 @@ #include #include -#include class BOARD_COMMIT; class BOARD_ITEM; class SELECTION_TOOL; -namespace KIGFX -{ -class VIEW_GROUP; -} - /** * Class EDIT_TOOL * @@ -133,16 +127,6 @@ private: ///> of edit reference point). VECTOR2I m_cursor; - ///> The required update flag for modified items - KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS m_updateFlag; - - ///> Enables higher order update flag - void enableUpdateFlag( KIGFX::VIEW_ITEM::VIEW_UPDATE_FLAGS aFlag ) - { - if( m_updateFlag < aFlag ) - m_updateFlag = aFlag; - } - ///> Updates ratsnest for selected items. ///> @param aRedraw says if selected items should be drawn using the simple mode (e.g. one line ///> per item). @@ -164,10 +148,10 @@ private: { const SELECTION& selection = m_selectionTool->GetSelection(); - if( selection.items.GetCount() != 1 ) - return NULL; + if( selection.Size() != 1 ) + return nullptr; - BOARD_ITEM* item = selection.Item( 0 ); + auto item = selection[0]; return dyn_cast( item ); } diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp index ac94c2eace..2ae97e0348 100644 --- a/pcbnew/tools/grid_helper.cpp +++ b/pcbnew/tools/grid_helper.cpp @@ -33,6 +33,7 @@ using namespace std::placeholders; #include #include +#include #include #include @@ -196,12 +197,14 @@ std::set GRID_HELPER::queryVisible( const BOX2I& aArea ) const std::vector selectedItems; std::vector::iterator it, it_end; - m_frame->GetGalCanvas()->GetView()->Query( aArea, selectedItems ); // Get the list of selected items + auto view = m_frame->GetGalCanvas()->GetView(); + view->Query( aArea, selectedItems ); // Get the list of selected items for( it = selectedItems.begin(), it_end = selectedItems.end(); it != it_end; ++it ) { BOARD_ITEM* item = static_cast( it->first ); - if( item->ViewIsVisible() ) + + if( view->IsVisible( item ) ) items.insert ( item ); } diff --git a/pcbnew/tools/module_tools.cpp b/pcbnew/tools/module_tools.cpp index d41f6e55f8..2cc251ad89 100644 --- a/pcbnew/tools/module_tools.cpp +++ b/pcbnew/tools/module_tools.cpp @@ -133,7 +133,7 @@ int MODULE_TOOLS::PlacePad( const TOOL_EVENT& aEvent ) if( evt->IsMotion() ) { pad->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.ViewUpdate(); + m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) @@ -141,12 +141,12 @@ int MODULE_TOOLS::PlacePad( const TOOL_EVENT& aEvent ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { pad->Rotate( pad->GetPosition(), m_frame->GetRotationAngle() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { pad->Flip( pad->GetPosition() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { @@ -370,9 +370,9 @@ int MODULE_TOOLS::CopyItems( const TOOL_EVENT& aEvent ) // Create a temporary module that contains selected items to ease serialization MODULE module( m_board ); - for( int i = 0; i < selection.Size(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* clone = static_cast( selection.Item( i )->Clone() ); + auto clone = static_cast( item->Clone() ); // Do not add reference/value - convert them to the common type if( TEXTE_MODULE* text = dyn_cast( clone ) ) @@ -426,7 +426,7 @@ int MODULE_TOOLS::PasteItems( const TOOL_EVENT& aEvent ) KIGFX::VIEW_GROUP preview( m_view ); pastedModule->SetParent( m_board ); pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - pastedModule->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, + pastedModule->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, std::ref( preview ), _1 ) ); preview.Add( pastedModule ); m_view->Add( &preview ); @@ -446,7 +446,7 @@ int MODULE_TOOLS::PasteItems( const TOOL_EVENT& aEvent ) if( evt->IsMotion() ) { pastedModule->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.ViewUpdate(); + m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) @@ -454,12 +454,12 @@ int MODULE_TOOLS::PasteItems( const TOOL_EVENT& aEvent ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { pastedModule->Rotate( pastedModule->GetPosition(), m_frame->GetRotationAngle() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { pastedModule->Flip( pastedModule->GetPosition() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { @@ -542,11 +542,11 @@ int MODULE_TOOLS::ModuleTextOutlines( const TOOL_EVENT& aEvent ) for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item ->Next() ) { if( item->Type() == PCB_MODULE_TEXT_T ) - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( item, KIGFX::GEOMETRY ); } - module->Reference().ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - module->Value().ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( &module->Reference(), KIGFX::GEOMETRY ); + getView()->Update( &module->Value(), KIGFX::GEOMETRY ); } m_frame->GetGalCanvas()->Refresh(); @@ -576,7 +576,7 @@ int MODULE_TOOLS::ModuleEdgeOutlines( const TOOL_EVENT& aEvent ) for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item ->Next() ) { if( item->Type() == PCB_MODULE_EDGE_T ) - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( item, KIGFX::GEOMETRY ); } } diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp index 8c94e0b40a..74e2761eaa 100644 --- a/pcbnew/tools/pcb_editor_control.cpp +++ b/pcbnew/tools/pcb_editor_control.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,8 @@ PCB_EDITOR_CONTROL::PCB_EDITOR_CONTROL() : PCB_EDITOR_CONTROL::~PCB_EDITOR_CONTROL() { + getView()->Remove( m_placeOrigin ); + delete m_placeOrigin; delete m_zoneMenu; delete m_lockMenu; @@ -269,12 +272,12 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent ) if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { module->Rotate( module->GetPosition(), m_frame->GetRotationAngle() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { module->Flip( module->GetPosition() ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } } @@ -321,7 +324,7 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent ) else if( module && evt->IsMotion() ) { module->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } } @@ -365,9 +368,8 @@ int PCB_EDITOR_CONTROL::modifyLockSelected( MODIFY_MODE aMode ) bool modified = false; - for( int i = 0; i < selection.Size(); ++i ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); bool prevState = item->IsLocked(); switch( aMode ) @@ -433,7 +435,7 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) else if( evt->IsAction( &COMMON_ACTIONS::incWidth ) ) { target->SetWidth( target->GetWidth() + WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::decWidth ) ) @@ -443,7 +445,7 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) if( width > WIDTH_STEP ) { target->SetWidth( width - WIDTH_STEP ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } } @@ -466,7 +468,7 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) else if( evt->IsMotion() ) { target->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); - preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( &preview ); } } @@ -484,19 +486,19 @@ int PCB_EDITOR_CONTROL::PlaceTarget( const TOOL_EVENT& aEvent ) // Zone actions int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent ) { - SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + auto selTool = m_toolMgr->GetTool(); + const auto& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); - for( int i = 0; i < selection.Size(); ++i ) + for( auto item : selection ) { - assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + assert( item->Type() == PCB_ZONE_AREA_T ); - ZONE_CONTAINER* zone = selection.Item( i ); + ZONE_CONTAINER* zone = static_cast ( item ); m_frame->Fill_Zone( zone ); zone->SetIsFilled( true ); ratsnest->Update( zone ); - zone->ViewUpdate(); + getView()->Update( zone ); } ratsnest->Recalculate(); @@ -516,7 +518,7 @@ int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent ) m_frame->Fill_Zone( zone ); zone->SetIsFilled( true ); ratsnest->Update( zone ); - zone->ViewUpdate(); + getView()->Update( zone ); } ratsnest->Recalculate(); @@ -527,19 +529,19 @@ int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent ) int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent ) { - SELECTION_TOOL* selTool = m_toolMgr->GetTool(); - const SELECTION& selection = selTool->GetSelection(); + auto selTool = m_toolMgr->GetTool(); + const auto& selection = selTool->GetSelection(); RN_DATA* ratsnest = getModel()->GetRatsnest(); - for( int i = 0; i < selection.Size(); ++i ) + for( auto item : selection ) { - assert( selection.Item( i )->Type() == PCB_ZONE_AREA_T ); + assert( item->Type() == PCB_ZONE_AREA_T ); - ZONE_CONTAINER* zone = selection.Item( i ); + ZONE_CONTAINER* zone = static_cast( item ); zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); - zone->ViewUpdate(); + getView()->Update( zone ); } ratsnest->Recalculate(); @@ -559,7 +561,7 @@ int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) zone->SetIsFilled( false ); zone->ClearFilledPolysList(); ratsnest->Update( zone ); - zone->ViewUpdate(); + getView()->Update( zone ); } ratsnest->Recalculate(); @@ -568,101 +570,106 @@ int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent ) } +static bool mergeZones( BOARD_COMMIT& aCommit, std::vector& aOriginZones, + std::vector& aMergedZones ) +{ + SHAPE_POLY_SET mergedOutlines = ConvertPolyListToPolySet( aOriginZones[0]->Outline()->m_CornersList ); + + for( unsigned int i = 1; i < aOriginZones.size(); i++ ) + { + SHAPE_POLY_SET areaToMergePoly = ConvertPolyListToPolySet( aOriginZones[i]->Outline()->m_CornersList ); + + mergedOutlines.BooleanAdd( areaToMergePoly, SHAPE_POLY_SET::PM_FAST ); + } + + mergedOutlines.Simplify( SHAPE_POLY_SET::PM_FAST ); + + // We should have one polygon with hole + // We can have 2 polygons with hole, if the 2 initial polygons have only one common corner + // and therefore cannot be merged (they are dectected as intersecting) + // but we should never have more than 2 polys + if( mergedOutlines.OutlineCount() > 1 ) + { + wxLogMessage( wxT( "BOARD::CombineAreas error: more than 2 polys after merging" ) ); + return false; + } + + for( unsigned int i = 1; i < aOriginZones.size(); i++ ) + { + aCommit.Remove( aOriginZones[i] ); + } + + aCommit.Modify( aOriginZones[0] ); + aMergedZones.push_back( aOriginZones[0] ); + + aOriginZones[0]->Outline()->m_CornersList = ConvertPolySetToPolyList( mergedOutlines ); + aOriginZones[0]->SetLocalFlags( 1 ); + aOriginZones[0]->Outline()->Hatch(); + + return true; +} + int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent ) { - SELECTION selection = m_toolMgr->GetTool()->GetSelection(); + SELECTION& selection = m_toolMgr->GetTool()->GetSelection(); BOARD* board = getModel(); - RN_DATA* ratsnest = board->GetRatsnest(); - KIGFX::VIEW* view = getView(); BOARD_COMMIT commit( m_frame ); if( selection.Size() < 2 ) return 0; - PICKED_ITEMS_LIST changes; int netcode = -1; - // Loop through all combinations - for( int ia1 = 0; ia1 < selection.Size() - 1; ++ia1 ) + ZONE_CONTAINER* firstZone = nullptr; + std::vector toMerge, merged; + + for( auto item : selection ) { - ZONE_CONTAINER* curr_area = dynamic_cast( selection.Item( ia1 ) ); + auto curr_area = dynamic_cast( item ); if( !curr_area ) continue; + if( !firstZone ) + firstZone = curr_area; + netcode = curr_area->GetNetCode(); - EDA_RECT b1 = curr_area->Outline()->GetBoundingBox(); - bool mod_ia1 = false; - - for( int ia2 = selection.Size() - 1; ia2 > ia1; --ia2 ) + if( firstZone ) { - ZONE_CONTAINER* area2 = dynamic_cast( selection.Item( ia2 ) ); - - if( !area2 ) + if( firstZone->GetNetCode() != netcode ) continue; - if( area2->GetNetCode() != netcode ) + if( curr_area->GetPriority() != firstZone->GetPriority() ) continue; - if( curr_area->GetPriority() != area2->GetPriority() ) + if( curr_area->GetIsKeepout() != firstZone->GetIsKeepout() ) continue; - if( curr_area->GetIsKeepout() != area2->GetIsKeepout() ) + if( curr_area->GetLayer() != firstZone->GetLayer() ) continue; - if( curr_area->GetLayer() != area2->GetLayer() ) + if( !board->TestAreaIntersection( curr_area, firstZone ) ) continue; - EDA_RECT b2 = area2->Outline()->GetBoundingBox(); - - if( b1.Intersects( b2 ) ) - { - EDA_ITEM* backup = curr_area->Clone(); - bool ret = board->TestAreaIntersection( curr_area, area2 ); - - if( ret && board->CombineAreas( &changes, curr_area, area2 ) ) - { - mod_ia1 = true; - selection.items.RemovePicker( ia2 ); - - ITEM_PICKER picker( curr_area, UR_CHANGED ); - picker.SetLink( backup ); - changes.PushItem( picker ); - } - else - { - delete backup; - } - } + toMerge.push_back( curr_area ); + } + else + { + toMerge.push_back( curr_area ); } - - if( mod_ia1 ) - --ia1; // if modified, we need to check it again } m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); - commit.Stage( changes ); - - for( unsigned i = 0; i < changes.GetCount(); ++i ) + if( mergeZones( commit, toMerge, merged ) ) { - ITEM_PICKER picker = changes.GetItemWrapper( i ); - BOARD_ITEM* item = static_cast( picker.GetItem() ); + commit.Push( _( "Merge zones" ) ); - if( picker.GetStatus() == UR_DELETED ) - { - view->Remove( item ); - ratsnest->Remove( item ); - } - else if( picker.GetStatus() == UR_CHANGED ) - { + for( auto item : merged ) m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); - } } - commit.Push( _( "Merge zones" ) ); - return 0; } @@ -679,7 +686,7 @@ int PCB_EDITOR_CONTROL::CrossProbePcbToSch( const TOOL_EVENT& aEvent ) const SELECTION& selection = selTool->GetSelection(); if( selection.Size() == 1 ) - m_frame->SendMessageToEESCHEMA( selection.Item( 0 ) ); + m_frame->SendMessageToEESCHEMA( selection.Front() ); return 0; } diff --git a/pcbnew/tools/pcb_tool.h b/pcbnew/tools/pcb_tool.h index f235945512..accc8f0d32 100644 --- a/pcbnew/tools/pcb_tool.h +++ b/pcbnew/tools/pcb_tool.h @@ -31,6 +31,7 @@ #include #include #include +#include /** * Class PCB_TOOL diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp index 823dc617a1..c6cd77fb4e 100644 --- a/pcbnew/tools/pcbnew_control.cpp +++ b/pcbnew/tools/pcbnew_control.cpp @@ -71,6 +71,7 @@ PCBNEW_CONTROL::PCBNEW_CONTROL() : PCBNEW_CONTROL::~PCBNEW_CONTROL() { + getView()->Remove( m_gridOrigin ); delete m_gridOrigin; } @@ -203,10 +204,8 @@ int PCBNEW_CONTROL::ZoomPreset( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::TrackDisplayMode( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); // Apply new display options to the GAL canvas DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); @@ -216,7 +215,7 @@ int PCBNEW_CONTROL::TrackDisplayMode( const TOOL_EVENT& aEvent ) for( TRACK* track = getModel()->m_Track; track; track = track->Next() ) { if( track->Type() == PCB_TRACE_T ) - track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( track, KIGFX::GEOMETRY ); } m_frame->GetGalCanvas()->Refresh(); @@ -227,10 +226,9 @@ int PCBNEW_CONTROL::TrackDisplayMode( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::PadDisplayMode( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); + DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); // Apply new display options to the GAL canvas @@ -240,7 +238,7 @@ int PCBNEW_CONTROL::PadDisplayMode( const TOOL_EVENT& aEvent ) 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 ); + getView()->Update( pad, KIGFX::GEOMETRY ); } m_frame->GetGalCanvas()->Refresh(); @@ -251,10 +249,8 @@ int PCBNEW_CONTROL::PadDisplayMode( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::ViaDisplayMode( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); // Apply new display options to the GAL canvas @@ -263,8 +259,8 @@ int PCBNEW_CONTROL::ViaDisplayMode( const TOOL_EVENT& aEvent ) for( TRACK* track = getModel()->m_Track; track; track = track->Next() ) { - if( track->Type() == PCB_VIA_T ) - track->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + if( track->Type() == PCB_TRACE_T ) + getView()->Update( track, KIGFX::GEOMETRY ); } m_frame->GetGalCanvas()->Refresh(); @@ -275,10 +271,8 @@ int PCBNEW_CONTROL::ViaDisplayMode( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::ZoneDisplayMode( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); // Apply new display options to the GAL canvas @@ -295,7 +289,7 @@ int PCBNEW_CONTROL::ZoneDisplayMode( const TOOL_EVENT& aEvent ) BOARD* board = getModel(); for( int i = 0; i < board->GetAreaCount(); ++i ) - board->GetArea( i )->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + getView()->Update( board->GetArea( i ), KIGFX::GEOMETRY ); m_frame->GetGalCanvas()->Refresh(); @@ -305,10 +299,8 @@ int PCBNEW_CONTROL::ZoneDisplayMode( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::HighContrastMode( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); displ_opts->m_ContrastModeDisplay = !displ_opts->m_ContrastModeDisplay; @@ -404,10 +396,8 @@ int PCBNEW_CONTROL::LayerToggle( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::LayerAlphaInc( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); LAYER_NUM currentLayer = m_frame->GetActiveLayer(); KIGFX::COLOR4D currentColor = settings->GetLayerColor( currentLayer ); @@ -425,10 +415,8 @@ int PCBNEW_CONTROL::LayerAlphaInc( const TOOL_EVENT& aEvent ) int PCBNEW_CONTROL::LayerAlphaDec( const TOOL_EVENT& aEvent ) { - KIGFX::PCB_PAINTER* painter = - static_cast( m_frame->GetGalCanvas()->GetView()->GetPainter() ); - KIGFX::PCB_RENDER_SETTINGS* settings = - static_cast ( painter->GetSettings() ); + auto painter = static_cast( getView()->GetPainter() ); + auto settings = painter->GetSettings(); LAYER_NUM currentLayer = m_frame->GetActiveLayer(); KIGFX::COLOR4D currentColor = settings->GetLayerColor( currentLayer ); @@ -450,6 +438,7 @@ int PCBNEW_CONTROL::CursorControl( const TOOL_EVENT& aEvent ) long type = aEvent.Parameter(); bool fastMove = type & COMMON_ACTIONS::CURSOR_FAST_MOVE; type &= ~COMMON_ACTIONS::CURSOR_FAST_MOVE; + bool mirroredX = getView()->IsMirroredX(); GRID_HELPER gridHelper( m_frame ); VECTOR2D cursor = getViewControls()->GetCursorPosition(); @@ -470,11 +459,11 @@ int PCBNEW_CONTROL::CursorControl( const TOOL_EVENT& aEvent ) break; case COMMON_ACTIONS::CURSOR_LEFT: - newCursor -= VECTOR2D( gridSize.x, 0 ); + newCursor -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_RIGHT: - newCursor += VECTOR2D( gridSize.x, 0 ); + newCursor += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_CLICK: // fall through @@ -559,6 +548,7 @@ int PCBNEW_CONTROL::PanControl( const TOOL_EVENT& aEvent ) GRID_HELPER gridHelper( m_frame ); VECTOR2D center = view->GetCenter(); VECTOR2I gridSize = gridHelper.GetGrid() * 10; + bool mirroredX = view->IsMirroredX(); switch( type ) { @@ -571,11 +561,11 @@ int PCBNEW_CONTROL::PanControl( const TOOL_EVENT& aEvent ) break; case COMMON_ACTIONS::CURSOR_LEFT: - center -= VECTOR2D( gridSize.x, 0 ); + center -= VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_RIGHT: - center += VECTOR2D( gridSize.x, 0 ); + center += VECTOR2D( mirroredX ? -gridSize.x : gridSize.x, 0 ); break; default: @@ -740,7 +730,7 @@ static bool deleteItem( TOOL_MANAGER* aToolMgr, const VECTOR2D& aPosition ) if( selection.Empty() ) return true; - bool canBeRemoved = ( selection.Item( 0 )->Type() != PCB_MODULE_T ); + bool canBeRemoved = ( selection.Front()->Type() != PCB_MODULE_T ); if( canBeRemoved || IsOK( aToolMgr->GetEditFrame(), _( "Are you sure you want to delete item?" ) ) ) aToolMgr->RunAction( COMMON_ACTIONS::remove, true ); @@ -792,6 +782,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) // (for undo command for instance) // Tracks are inserted, not appended, so mark the existing tracks to know what are the new tracks + // TODO legacy for( TRACK* track = board->m_Track; track; track = track->Next() ) track->SetFlags( FLAG0 ); @@ -897,7 +888,7 @@ int PCBNEW_CONTROL::AppendBoard( const TOOL_EVENT& aEvent ) // Start dragging the appended board SELECTION_TOOL* selectionTool = m_toolMgr->GetTool(); const SELECTION& selection = selectionTool->GetSelection(); - VECTOR2D v( selection.Item( 0 )->GetPosition() ); + VECTOR2D v( selection.Front()->GetPosition() ); getViewControls()->WarpCursor( v, true, true ); m_toolMgr->InvokeTool( "pcbnew.InteractiveEdit" ); diff --git a/pcbnew/tools/placement_tool.cpp b/pcbnew/tools/placement_tool.cpp index c5c6a5d723..78f8cdbcd1 100644 --- a/pcbnew/tools/placement_tool.cpp +++ b/pcbnew/tools/placement_tool.cpp @@ -80,23 +80,22 @@ int PLACEMENT_TOOL::AlignTop( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the highest point of selection - it will be the edge of alignment - int top = selection.Item( 0 )->GetBoundingBox().GetY(); + int top = selection.Front()->GetBoundingBox().GetY(); for( int i = 1; i < selection.Size(); ++i ) { - int currentTop = selection.Item( i )->GetBoundingBox().GetY(); + int currentTop = selection[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 ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = top - item->GetBoundingBox().GetY(); item->Move( wxPoint( 0, difference ) ); @@ -116,23 +115,22 @@ int PLACEMENT_TOOL::AlignBottom( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the lowest point of selection - it will be the edge of alignment - int bottom = selection.Item( 0 )->GetBoundingBox().GetBottom(); + int bottom = selection.Front()->GetBoundingBox().GetBottom(); for( int i = 1; i < selection.Size(); ++i ) { - int currentBottom = selection.Item( i )->GetBoundingBox().GetBottom(); + int currentBottom = selection[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 ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = bottom - item->GetBoundingBox().GetBottom(); item->Move( wxPoint( 0, difference ) ); @@ -152,23 +150,22 @@ int PLACEMENT_TOOL::AlignLeft( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the leftmost point of selection - it will be the edge of alignment - int left = selection.Item( 0 )->GetBoundingBox().GetX(); + int left = selection.Front()->GetBoundingBox().GetX(); for( int i = 1; i < selection.Size(); ++i ) { - int currentLeft = selection.Item( i )->GetBoundingBox().GetX(); + int currentLeft = selection[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 ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = left - item->GetBoundingBox().GetX(); item->Move( wxPoint( difference, 0 ) ); @@ -188,23 +185,22 @@ int PLACEMENT_TOOL::AlignRight( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // Compute the rightmost point of selection - it will be the edge of alignment - int right = selection.Item( 0 )->GetBoundingBox().GetRight(); + int right = selection.Front()->GetBoundingBox().GetRight(); for( int i = 1; i < selection.Size(); ++i ) { - int currentRight = selection.Item( i )->GetBoundingBox().GetRight(); + int currentRight = selection[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 ) + for( auto item : selection ) { - BOARD_ITEM* item = selection.Item( i ); int difference = right - item->GetBoundingBox().GetRight(); item->Move( wxPoint( difference, 0 ) ); @@ -236,26 +232,27 @@ int PLACEMENT_TOOL::DistributeHorizontally( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // 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 ) ); + std::vector itemsList; + + for( auto item : selection ) + itemsList.push_back( item ); // Sort items by X coordinate - itemsList.sort( compareX ); + std::sort(itemsList.begin(), itemsList.end(), compareX ); // Expected X coordinate for the next item (=minX) - int position = (*itemsList.begin())->GetBoundingBox().Centre().x; + int position = itemsList.front()->GetBoundingBox().Centre().x; // X coordinate for the last item - const int maxX = (*itemsList.rbegin())->GetBoundingBox().Centre().x; + const int maxX = itemsList.back()->GetBoundingBox().Centre().x; // Distance between items const int distance = ( maxX - position ) / ( itemsList.size() - 1 ); - for( BOARD_ITEM* item : itemsList ) + for( auto item : itemsList ) { int difference = position - item->GetBoundingBox().Centre().x; @@ -278,15 +275,16 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent ) return 0; BOARD_COMMIT commit( getEditFrame() ); - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); // 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 ) ); + std::vector itemsList; + + for( auto item : selection ) + itemsList.push_back( item ); // Sort items by Y coordinate - itemsList.sort( compareY ); + std::sort( itemsList.begin(), itemsList.end(), compareY ); // Expected Y coordinate for the next item (=minY) int position = (*itemsList.begin())->GetBoundingBox().Centre().y; @@ -297,7 +295,7 @@ int PLACEMENT_TOOL::DistributeVertically( const TOOL_EVENT& aEvent ) // Distance between items const int distance = ( maxY - position ) / ( itemsList.size() - 1 ); - for( BOARD_ITEM* item : itemsList ) + for( auto item : itemsList ) { int difference = position - item->GetBoundingBox().Centre().y; diff --git a/pcbnew/tools/point_editor.cpp b/pcbnew/tools/point_editor.cpp index 025d531b41..38b570b582 100644 --- a/pcbnew/tools/point_editor.cpp +++ b/pcbnew/tools/point_editor.cpp @@ -226,11 +226,11 @@ void POINT_EDITOR::updateEditedPoint( const TOOL_EVENT& aEvent ) if( aEvent.IsMotion() ) { - point = m_editPoints->FindPoint( aEvent.Position() ); + point = m_editPoints->FindPoint( aEvent.Position(), getView() ); } else if( aEvent.IsDrag( BUT_LEFT ) ) { - point = m_editPoints->FindPoint( aEvent.DragOrigin() ); + point = m_editPoints->FindPoint( aEvent.DragOrigin(), getView() ); } if( m_editedPoint != point ) @@ -249,7 +249,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) KIGFX::VIEW_CONTROLS* controls = getViewControls(); KIGFX::VIEW* view = getView(); PCB_BASE_EDIT_FRAME* editFrame = getEditFrame(); - EDA_ITEM* item = selection.items.GetPickedItem( 0 ); + auto item = selection.Front(); m_editPoints = EDIT_POINTS_FACTORY::Make( item, getView()->GetGAL() ); @@ -295,7 +295,7 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent ) { if( !modified ) { - commit.Stage( selection.items, UR_CHANGED ); + commit.StageItems( selection, CHT_MODIFY ); controls->ForceCursorPosition( false ); m_original = *m_editedPoint; // Save the original position @@ -620,7 +620,7 @@ void POINT_EDITOR::updatePoints() break; } - m_editPoints->ViewUpdate(); + getView()->Update( m_editPoints.get() ); } @@ -851,7 +851,7 @@ bool POINT_EDITOR::addCornerCondition( const SELECTION& aSelection ) if( aSelection.Size() != 1 ) return false; - BOARD_ITEM* item = aSelection.Item( 0 ); + auto item = aSelection.Front(); // Works only for zones and line segments return item->Type() == PCB_ZONE_AREA_T || diff --git a/pcbnew/tools/selection_area.cpp b/pcbnew/tools/selection_area.cpp index 8bfdcec020..7e4e900a8a 100644 --- a/pcbnew/tools/selection_area.cpp +++ b/pcbnew/tools/selection_area.cpp @@ -26,6 +26,8 @@ #include #include +#include + using namespace KIGFX; const BOX2I SELECTION_AREA::ViewBBox() const @@ -46,14 +48,15 @@ void SELECTION_AREA::ViewGetLayers( int aLayers[], int& aCount ) const } -void SELECTION_AREA::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const +void SELECTION_AREA::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const { - aGal->SetLineWidth( 1.0 ); - aGal->SetStrokeColor( COLOR4D( 1.0, 1.0, 0.4, 1.0 ) ); - aGal->SetFillColor( COLOR4D( 0.3, 0.3, 0.5, 0.3 ) ); - aGal->SetIsStroke( true ); - aGal->SetIsFill( true ); - aGal->DrawRectangle( m_origin, m_end ); + auto gal = aView->GetGAL(); + gal->SetLineWidth( 1.0 ); + gal->SetStrokeColor( COLOR4D( 1.0, 1.0, 0.4, 1.0 ) ); + gal->SetFillColor( COLOR4D( 0.3, 0.3, 0.5, 0.3 ) ); + gal->SetIsStroke( true ); + gal->SetIsFill( true ); + gal->DrawRectangle( m_origin, m_end ); } diff --git a/pcbnew/tools/selection_area.h b/pcbnew/tools/selection_area.h index be84537f77..97fb0ab021 100644 --- a/pcbnew/tools/selection_area.h +++ b/pcbnew/tools/selection_area.h @@ -49,7 +49,7 @@ public: virtual const BOX2I ViewBBox() const override; - void ViewDraw( int aLayer, KIGFX::GAL* aGal ) const override; + void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override; void ViewGetLayers( int aLayers[], int& aCount ) const override; diff --git a/pcbnew/tools/selection_conditions.cpp b/pcbnew/tools/selection_conditions.cpp index c9b58b7d6f..7187a71090 100644 --- a/pcbnew/tools/selection_conditions.cpp +++ b/pcbnew/tools/selection_conditions.cpp @@ -41,9 +41,9 @@ bool SELECTION_CONDITIONS::OnlyConnectedItems( const SELECTION& aSelection ) if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto &item : aSelection ) { - KICAD_T type = aSelection.Item( i )->Type(); + auto type = item->Type(); if( type != PCB_PAD_T && type != PCB_VIA_T && type != PCB_TRACE_T && type != PCB_ZONE_T ) return false; @@ -114,12 +114,12 @@ bool SELECTION_CONDITIONS::sameNetFunc( const SELECTION& aSelection, bool aAllow int netcode = -1; // -1 stands for 'net code is not yet determined' - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& aitem : aSelection ) { int current_netcode = -1; const BOARD_CONNECTED_ITEM* item = - dynamic_cast( aSelection.Item( i ) ); + dynamic_cast( aitem ); if( item ) { @@ -161,13 +161,8 @@ bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection ) LSET layerSet; layerSet.set(); - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& item : aSelection ) { - const BOARD_ITEM* item = dynamic_cast( aSelection.Item( i ) ); - - if( !item ) - return false; - layerSet &= item->GetLayerSet(); if( !layerSet.any() ) // there are no common layers left @@ -180,9 +175,9 @@ bool SELECTION_CONDITIONS::sameLayerFunc( const SELECTION& aSelection ) bool SELECTION_CONDITIONS::hasTypeFunc( const SELECTION& aSelection, KICAD_T aType ) { - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& item : aSelection ) { - if( aSelection.Item( i )->Type() == aType ) + if( item->Type() == aType ) return true; } @@ -195,9 +190,9 @@ bool SELECTION_CONDITIONS::onlyTypeFunc( const SELECTION& aSelection, KICAD_T aT if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& item : aSelection ) { - if( aSelection.Item( i )->Type() != aType ) + if( item->Type() != aType ) return false; } @@ -210,13 +205,13 @@ bool SELECTION_CONDITIONS::onlyTypesFunc( const SELECTION& aSelection, const std if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& item : aSelection ) { bool valid = false; for( std::vector::const_iterator it = aTypes.begin(); it != aTypes.end(); ++it ) { - if( aSelection.Item( i )->Type() == *it ) + if( item->Type() == *it ) { valid = true; break; @@ -236,14 +231,14 @@ bool SELECTION_CONDITIONS::onlyTypesFuncArr( const SELECTION& aSelection, const if( aSelection.Empty() ) return false; - for( int i = 0; i < aSelection.Size(); ++i ) + for( const auto& item : aSelection ) { bool valid = false; const KICAD_T* type = aTypes; while( *type != EOT ) { - if( aSelection.Item( i )->Type() == *type ) + if( item->Type() == *type ) { valid = true; break; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index ba0b3585a0..d5950f8420 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -80,7 +80,8 @@ SELECTION_TOOL::SELECTION_TOOL() : SELECTION_TOOL::~SELECTION_TOOL() { - delete m_selection.group; + getView()->Remove( &m_selection ); + delete m_contextMenu; delete m_selectMenu; delete m_zoomMenu; @@ -90,8 +91,6 @@ SELECTION_TOOL::~SELECTION_TOOL() bool SELECTION_TOOL::Init() { - m_selection.group = new KIGFX::VIEW_GROUP; - m_selectMenu = new SELECT_MENU; m_selectMenu->SetTool( this ); @@ -129,7 +128,7 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) // Remove pointers to the selected items from containers // without changing their properties (as they are already deleted // while a new board is loaded) - m_selection.clear(); + m_selection.Clear(); getView()->GetPainter()->GetSettings()->SetHighlight( false ); } else @@ -137,8 +136,8 @@ void SELECTION_TOOL::Reset( RESET_REASON aReason ) clearSelection(); // Reinsert the VIEW_GROUP, in case it was removed from the VIEW - getView()->Remove( m_selection.group ); - getView()->Add( m_selection.group ); + getView()->Remove( &m_selection ); + getView()->Add( &m_selection ); } @@ -301,24 +300,19 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) } -const SELECTION& SELECTION_TOOL::GetSelection() +SELECTION& SELECTION_TOOL::GetSelection() { // The selected items list has been requested, so it is no longer preliminary m_preliminary = false; - // Filter out not modifiable items - for( int i = 0; i < m_selection.Size(); ) - { - BOARD_ITEM* item = m_selection.Item( i ); + auto items = m_selection.GetItems(); + // Filter out not modifiable items + for( auto item : items ) + { if( !modifiable( item ) ) { - m_selection.items.RemovePicker( i ); - m_selection.group->Remove( item ); - } - else - { - ++i; + m_selection.Remove( item ); } } @@ -360,7 +354,7 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag ) GENERAL_COLLECTORS_GUIDE guide = m_frame->GetCollectorsGuide(); GENERAL_COLLECTOR collector; - collector.Collect( getModel(), + collector.Collect( board(), m_editModules ? GENERAL_COLLECTOR::ModuleItems : GENERAL_COLLECTOR::AllBoardItems, wxPoint( aWhere.x, aWhere.y ), guide ); @@ -456,14 +450,14 @@ bool SELECTION_TOOL::selectMultiple() // Start drawing a selection box area.SetOrigin( evt->DragOrigin() ); area.SetEnd( evt->Position() ); - area.ViewSetVisible( true ); - area.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->SetVisible( &area, true ); + view->Update( &area ); } if( evt->IsMouseUp( BUT_LEFT ) ) { // End drawing the selection box - area.ViewSetVisible( false ); + view->SetVisible( &area, false ); // Mark items within the selection box as selected std::vector selectedItems; @@ -485,7 +479,7 @@ bool SELECTION_TOOL::selectMultiple() } if( m_selection.Size() == 1 ) - m_frame->SetCurItem( m_selection.Item( 0 ) ); + m_frame->SetCurItem( m_selection.Front() ); else m_frame->SetCurItem( NULL ); @@ -498,7 +492,6 @@ bool SELECTION_TOOL::selectMultiple() } // Stop drawing the selection box - area.ViewSetVisible( false ); view->Remove( &area ); m_multiple = false; // Multiple selection mode is inactive getViewControls()->SetAutoPan( false ); @@ -530,10 +523,8 @@ SELECTION_LOCK_FLAGS SELECTION_TOOL::CheckLock() bool containsLocked = false; // Check if the selection contains locked items - for( int i = 0; i < m_selection.Size(); ++i ) + for( const auto& item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); - switch( item->Type() ) { case PCB_MODULE_T: @@ -624,14 +615,14 @@ int SELECTION_TOOL::selectConnection( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = m_selection.Front(); clearSelection(); if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) return 0; int segmentCount; - TRACK* trackList = getModel()->MarkTrace( static_cast( item ), &segmentCount, + TRACK* trackList = board()->MarkTrace( static_cast( item ), &segmentCount, NULL, NULL, true ); if( segmentCount == 0 ) @@ -655,7 +646,7 @@ int SELECTION_TOOL::selectCopper( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = static_cast ( m_selection.Front() ); clearSelection(); if( item->Type() != PCB_TRACE_T && item->Type() != PCB_VIA_T ) @@ -682,7 +673,10 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent ) if( !selectCursor( true ) ) return 0; - BOARD_CONNECTED_ITEM* item = m_selection.Item( 0 ); + auto item = dynamic_cast ( m_selection.Front() ); + + if( !item ) + return 0; std::list itemsList; RN_DATA* ratsnest = getModel()->GetRatsnest(); @@ -752,19 +746,10 @@ void SELECTION_TOOL::clearSelection() if( m_selection.Empty() ) return; - KIGFX::VIEW_GROUP::const_iter it, it_end; + for( auto item : m_selection ) + unselectVisually( item ); - // Restore the initial properties - for( it = m_selection.group->Begin(), it_end = m_selection.group->End(); it != it_end; ++it ) - { - BOARD_ITEM* item = static_cast( *it ); - - item->ViewHide( false ); - item->ClearSelected(); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ) ; - } - - m_selection.clear(); + m_selection.Clear(); m_frame->SetCurItem( NULL ); m_locked = true; @@ -777,9 +762,11 @@ void SELECTION_TOOL::clearSelection() BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) { BOARD_ITEM* current = NULL; - std::shared_ptr brightBox; + BRIGHT_BOX brightBox; CONTEXT_MENU menu; + getView()->Add( &brightBox ); + int limit = std::min( 10, aCollector->GetCount() ); for( int i = 0; i < limit; ++i ) @@ -829,12 +816,17 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector ) // Draw a mark to show which item is available to be selected if( current && current->IsBrightened() ) { - brightBox.reset( new BRIGHT_BOX( current ) ); - getView()->Add( brightBox.get() ); - // BRIGHT_BOX is removed from view on destruction + brightBox.SetItem( current ); + getView()->SetVisible( &brightBox, true ); +// getView()->Hide( &brightBox, false ); + getView()->Update( &brightBox, KIGFX::GEOMETRY ); + getView()->MarkTargetDirty( KIGFX::TARGET_OVERLAY ); } } + getView()->Remove( &brightBox ); + + return current; } @@ -904,8 +896,6 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const return false; } - BOARD* board = getModel(); - switch( aItem->Type() ) { case PCB_VIA_T: @@ -915,15 +905,15 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const static_cast( aItem )->LayerPair( &top, &bottom ); - return board->IsLayerVisible( top ) || board->IsLayerVisible( bottom ); + return board()->IsLayerVisible( top ) || board()->IsLayerVisible( bottom ); } break; case PCB_MODULE_T: - if( aItem->IsOnLayer( F_Cu ) && board->IsElementVisible( MOD_FR_VISIBLE ) ) + if( aItem->IsOnLayer( F_Cu ) && board()->IsElementVisible( MOD_FR_VISIBLE ) ) return !m_editModules; - if( aItem->IsOnLayer( B_Cu ) && board->IsElementVisible( MOD_BK_VISIBLE ) ) + if( aItem->IsOnLayer( B_Cu ) && board()->IsElementVisible( MOD_BK_VISIBLE ) ) return !m_editModules; return false; @@ -934,7 +924,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const if( m_multiple && !m_editModules ) return false; - return aItem->ViewIsVisible() && board->IsLayerVisible( aItem->GetLayer() ); + return view()->IsVisible( aItem ) && board()->IsLayerVisible( aItem->GetLayer() ); case PCB_MODULE_EDGE_T: case PCB_PAD_T: @@ -959,7 +949,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const } // All other items are selected only if the layer on which they exist is visible - return board->IsLayerVisible( aItem->GetLayer() ); + return board()->IsLayerVisible( aItem->GetLayer() ); } @@ -975,27 +965,20 @@ bool SELECTION_TOOL::modifiable( const BOARD_ITEM* aItem ) const void SELECTION_TOOL::select( BOARD_ITEM* aItem ) { if( aItem->IsSelected() ) - return; - - // Modules are treated in a special way - when they are selected, we have to mark - // all the parts that make the module as selected - if( aItem->Type() == PCB_MODULE_T ) { - MODULE* module = static_cast( aItem ); - module->RunOnChildren( std::bind( &SELECTION_TOOL::selectVisually, this, _1 ) ); + return; } if( aItem->Type() == PCB_PAD_T ) { MODULE* module = static_cast( aItem->GetParent() ); - if( m_selection.items.FindItem( module ) >= 0 ) + if( m_selection.Contains( module ) ) return; } selectVisually( aItem ); - ITEM_PICKER picker( aItem ); - m_selection.items.PushItem( picker ); + m_selection.Add( aItem ); if( m_selection.Size() == 1 ) { @@ -1015,19 +998,8 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem ) if( !aItem->IsSelected() ) return; - // Modules are treated in a special way - when they are selected, we have to - // unselect all the parts that make the module, not the module itself - if( aItem->Type() == PCB_MODULE_T ) - { - MODULE* module = static_cast( aItem ); - module->RunOnChildren( std::bind( &SELECTION_TOOL::unselectVisually, this, _1 ) ); - } - unselectVisually( aItem ); - - int itemIdx = m_selection.items.FindItem( aItem ); - if( itemIdx >= 0 ) - m_selection.items.RemovePicker( itemIdx ); + m_selection.Remove( aItem ); if( m_selection.Empty() ) { @@ -1039,22 +1011,45 @@ void SELECTION_TOOL::unselect( BOARD_ITEM* aItem ) void SELECTION_TOOL::selectVisually( BOARD_ITEM* aItem ) const { - m_selection.group->Add( aItem ); - // Hide the original item, so it is shown only on overlay - aItem->ViewHide( true ); aItem->SetSelected(); + view()->Hide( aItem, true ); + view()->Update( aItem, KIGFX::GEOMETRY ); + + // Modules are treated in a special way - when they are selected, we have to + // unselect all the parts that make the module, not the module itself + + if( aItem->Type() == PCB_MODULE_T ) + { + static_cast( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item ) + { + item->SetSelected(); + view()->Hide( item, true ); + view()->Update( item, KIGFX::GEOMETRY ); + } ); + } } void SELECTION_TOOL::unselectVisually( BOARD_ITEM* aItem ) const { - m_selection.group->Remove( aItem ); - // Restore original item visibility - aItem->ViewHide( false ); aItem->ClearSelected(); - aItem->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view()->Hide( aItem, false ); + view()->Update( aItem, KIGFX::ALL ); + + // Modules are treated in a special way - when they are selected, we have to + // unselect all the parts that make the module, not the module itself + + if( aItem->Type() == PCB_MODULE_T ) + { + static_cast( aItem )->RunOnChildren( [&] ( BOARD_ITEM* item ) + { + item->ClearSelected(); + view()->Hide( item, false ); + view()->Update( item, KIGFX::ALL ); + }); + } } @@ -1064,9 +1059,8 @@ bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false ); // Check if the point is located within any of the currently selected items bounding boxes - for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) + for( auto item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); BOX2I itemBox = item->ViewBBox(); itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item @@ -1382,10 +1376,8 @@ bool SELECTION_TOOL::SanitizeSelection() if( !m_editModules ) { - for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) + for( auto item : m_selection ) { - BOARD_ITEM* item = m_selection.Item( i ); - if( item->Type() == PCB_PAD_T ) { MODULE* mod = static_cast( item->GetParent() ); @@ -1400,7 +1392,7 @@ bool SELECTION_TOOL::SanitizeSelection() } // case 2: multi-item selection contains both the module and its pads - remove the pads - if( mod && m_selection.items.FindItem( mod ) >= 0 ) + if( mod && m_selection.Contains( mod ) ) rejected.insert( item ); } } @@ -1428,10 +1420,14 @@ bool SELECTION_TOOL::SanitizeSelection() } +SELECTION::SELECTION( KIGFX::VIEW* aView ) : + KIGFX::VIEW_GROUP( aView ) +{} + + void SELECTION::clear() { - items.ClearItemsList(); - group->Clear(); + m_items.clear(); } @@ -1441,15 +1437,17 @@ VECTOR2I SELECTION::GetCenter() const if( Size() == 1 ) { - centre = Item( 0 )->GetCenter(); + centre = Front()->GetCenter(); } else { - EDA_RECT bbox = Item( 0 )->GetBoundingBox(); - for( unsigned int i = 1; i < items.GetCount(); ++i ) + EDA_RECT bbox = Front()->GetBoundingBox(); + auto i = m_items.begin(); + ++i; + + for( ; i != m_items.end(); ++i ) { - BOARD_ITEM* item = Item( i ); - bbox.Merge( item->GetBoundingBox() ); + bbox.Merge( (*i)->GetBoundingBox() ); } centre = bbox.Centre(); @@ -1459,6 +1457,25 @@ VECTOR2I SELECTION::GetCenter() const } +const KIGFX::VIEW_GROUP::ITEMS SELECTION::updateDrawList() const +{ + std::vector items; + + for( auto item : m_items ) + { + items.push_back( item ); + + if( item->Type() == PCB_MODULE_T ) + { + MODULE* module = static_cast( item ); + module->RunOnChildren( [&] ( BOARD_ITEM* bitem ) { items.push_back( bitem ); } ); + } + } + + return items; +} + + const TOOL_EVENT SELECTION_TOOL::SelectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.selected" ); const TOOL_EVENT SELECTION_TOOL::UnselectedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.unselected" ); const TOOL_EVENT SELECTION_TOOL::ClearedEvent( TC_MESSAGE, TA_ACTION, "pcbnew.InteractiveSelection.cleared" ); diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index da3b9c61c1..a0110a3372 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -26,10 +26,11 @@ #ifndef __SELECTION_TOOL_H #define __SELECTION_TOOL_H +#include + #include #include #include -#include #include "selection_conditions.h" #include "conditional_menu.h" @@ -44,53 +45,110 @@ class GRID_MENU; namespace KIGFX { -class VIEW_GROUP; + class GAL; } -struct SELECTION +struct SELECTION : public KIGFX::VIEW_GROUP { +private: /// Set of selected items - PICKED_ITEMS_LIST items; + std::set m_items; - /// VIEW_GROUP that holds currently selected items - KIGFX::VIEW_GROUP* group; +public: + using ITER = std::set::iterator; + using CITER = std::set::const_iterator; + + SELECTION( KIGFX::VIEW* aView = nullptr ); + + ITER begin() { return m_items.begin(); } + ITER end() { return m_items.end(); } + CITER begin() const { return m_items.cbegin(); } + CITER end() const { return m_items.cend(); } + + virtual void Add( BOARD_ITEM* aItem ) + { + m_items.insert( aItem ); + } + + virtual void Remove( BOARD_ITEM *aItem ) + { + m_items.erase( aItem ); + } + + virtual void Clear() override + { + m_items.clear(); + } + + virtual unsigned int GetSize() const override + { + return m_items.size(); + } + + virtual KIGFX::VIEW_ITEM* GetItem( unsigned int idx ) const override + { + auto iter = m_items.begin(); + + while( idx-- ) + ++iter; + + return *iter; + } + + bool Contains( BOARD_ITEM* aItem ) const + { + return m_items.find( aItem ) != m_items.end(); + } /// Checks if there is anything selected bool Empty() const { - return ( items.GetCount() == 0 ); + return ( m_items.size() == 0 ); } /// Returns the number of selected parts int Size() const { - return items.GetCount(); + return m_items.size(); } - /// Alias to make code shorter and clearer - template - T* Item( unsigned int aIndex ) const + const std::set GetItems() const { - return static_cast( items.GetPickedItem( aIndex ) ); + return m_items; } /// Returns the center point of the selection area bounding box. VECTOR2I GetCenter() const; - /// Runs a function on all selected items. - template - void ForAll( std::function aFunction ) const + BOARD_ITEM *operator[] ( const int index ) const { - for( unsigned int i = 0; i < items.GetCount(); ++i ) - aFunction( Item( i ) ); + if ( index < 0 || (unsigned int) index >= m_items.size() ) + return nullptr; + + return (* m_items.begin() + index ); } + BOARD_ITEM* Front() const + { + if ( !m_items.size() ) + return nullptr; + + return *m_items.begin(); + } + + std::set& Items() + { + return m_items; + } + + virtual const VIEW_GROUP::ITEMS updateDrawList() const override; + 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; }; enum SELECTION_LOCK_FLAGS @@ -135,7 +193,7 @@ public: * * Returns the set of currently selected items. */ - const SELECTION& GetSelection(); + SELECTION& GetSelection(); inline CONDITIONAL_MENU& GetMenu() { diff --git a/pcbnew/tools/zoom_tool.cpp b/pcbnew/tools/zoom_tool.cpp index 9a3a082e10..a86ef11956 100644 --- a/pcbnew/tools/zoom_tool.cpp +++ b/pcbnew/tools/zoom_tool.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "zoom_tool.h" @@ -90,13 +91,13 @@ bool ZOOM_TOOL::selectRegion() { area.SetOrigin( evt->DragOrigin() ); area.SetEnd( evt->Position() ); - area.ViewSetVisible( true ); - area.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->SetVisible( &area, true ); + view->Update( &area, KIGFX::GEOMETRY ); } if( evt->IsMouseUp( BUT_LEFT ) ) { - area.ViewSetVisible( false ); + view->SetVisible( &area, false ); auto selectionBox = area.ViewBBox(); VECTOR2D screenSize = view->ToWorld( canvas->GetClientSize(), false ); @@ -118,7 +119,7 @@ bool ZOOM_TOOL::selectRegion() } } - area.ViewSetVisible( false ); + view->SetVisible( &area, false ); view->Remove( &area ); getViewControls()->SetAutoPan( false ); diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp index 6551518cac..f0ee448bc6 100644 --- a/pcbnew/undo_redo.cpp +++ b/pcbnew/undo_redo.cpp @@ -50,6 +50,8 @@ using namespace std::placeholders; #include #include +#include + /* Functions to undo and redo edit commands. * commands to undo are stored in CurrentScreen->m_UndoList * commands to redo are stored in CurrentScreen->m_RedoList @@ -482,7 +484,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool view->Add( item ); ratsnest->Add( item ); item->ClearFlags(); - item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); + } break; @@ -497,7 +499,6 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool } view->Remove( item ); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); break; case UR_DELETED: /* deleted items are put in List, as new items */ @@ -511,33 +512,32 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool } view->Add( item ); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); build_item_list = true; break; case UR_MOVED: item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint ); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( item, KIGFX::GEOMETRY ); ratsnest->Update( item ); break; case UR_ROTATED: item->Rotate( aList->m_TransformPoint, aRedoCommand ? m_rotationAngle : -m_rotationAngle ); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( item, KIGFX::GEOMETRY ); ratsnest->Update( item ); break; case UR_ROTATED_CLOCKWISE: item->Rotate( aList->m_TransformPoint, aRedoCommand ? -m_rotationAngle : m_rotationAngle ); - item->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + view->Update( item, KIGFX::GEOMETRY ); ratsnest->Update( item ); break; case UR_FLIPPED: item->Flip( aList->m_TransformPoint ); - item->ViewUpdate( KIGFX::VIEW_ITEM::LAYERS ); + view->Update( item, KIGFX::LAYERS ); ratsnest->Update( item ); break; @@ -663,4 +663,3 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount delete curr_cmd; // Delete command } } - diff --git a/pcbnew/zones_by_polygon_fill_functions.cpp b/pcbnew/zones_by_polygon_fill_functions.cpp index 16e2088d53..ebe2964ff6 100644 --- a/pcbnew/zones_by_polygon_fill_functions.cpp +++ b/pcbnew/zones_by_polygon_fill_functions.cpp @@ -43,6 +43,8 @@ #include #include +#include + #define FORMAT_STRING _( "Filling zone %d out of %d (net %s)..." ) @@ -115,7 +117,7 @@ int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone ) wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor) aZone->BuildFilledSolidAreasPolygons( GetBoard() ); - aZone->ViewUpdate( KIGFX::VIEW_ITEM::ALL ); + GetGalCanvas()->GetView()->Update( aZone, KIGFX::ALL ); GetBoard()->GetRatsnest()->Update( aZone ); OnModify();