diff --git a/common/base_screen.cpp b/common/base_screen.cpp index 0592888c0f..98d502f083 100644 --- a/common/base_screen.cpp +++ b/common/base_screen.cpp @@ -423,6 +423,18 @@ wxPoint BASE_SCREEN::GetCursorPosition( bool aOnGrid, wxRealPoint* aGridSize ) } +wxPoint BASE_SCREEN::GetCrossHairScreenPosition() const +{ + wxPoint pos = m_Curseur - m_DrawOrg; + double scalar = GetScalingFactor(); + + pos.x = wxRound( (double) pos.x * scalar ); + pos.y = wxRound( (double) pos.y * scalar ); + + return pos; +} + + /* free the undo and the redo lists */ void BASE_SCREEN::ClearUndoRedoList() diff --git a/common/drawframe.cpp b/common/drawframe.cpp index 91f3670927..2319857c08 100644 --- a/common/drawframe.cpp +++ b/common/drawframe.cpp @@ -727,12 +727,12 @@ void EDA_DRAW_FRAME::LoadSettings() bool btmp; if ( cfg->Read( m_FrameName + ShowGridEntryKeyword, &btmp ) ) - SetGridVisibility( btmp); + SetGridVisibility( btmp ); int itmp; if( cfg->Read( m_FrameName + GridColorEntryKeyword, &itmp ) ) - SetGridColor(itmp); + SetGridColor( itmp ); cfg->Read( m_FrameName + LastGridSizeId, &m_LastGridSizeId, 0L ); } diff --git a/common/drawpanel.cpp b/common/drawpanel.cpp index 935aa4ec37..631c134c0e 100644 --- a/common/drawpanel.cpp +++ b/common/drawpanel.cpp @@ -16,17 +16,20 @@ #define CURSOR_SIZE 12 // Cursor size in pixels -#define CLIP_BOX_PADDING 12 - +#define CLIP_BOX_PADDING 1 /* Definitions for enabling and disabling debugging features in drawpanel.cpp. * Please don't forget to turn these off before making any commits to Launchpad. */ - #define DEBUG_SHOW_CLIP_RECT 0 // Set to 1 to draw clipping rectangle. -#define DEBUG_DUMP_CLIP_COORDS 0 // Set to 1 to dump clipping rectangle coordinates. -#define DEBUG_DUMP_SCROLL_SETTINGS 0 // Set to 1 to dump scroll settings. -#define KICAD_TRACE_COORDS wxT( "kicad_dump_coords" ) + +/** + * Trace mask used to enable or disable the trace output of coordinates during drawing + * functions. The coordinate dumping can be turned on by setting the WXTRACE environment + * variable to "kicad_dump_coords". See the wxWidgets documentation on wxLogTrace for + * more information. + */ +#define KICAD_TRACE_COORDS wxT( "kicad_dump_coords" ) /* Used to inhibit a response to a mouse left button release, after a @@ -60,15 +63,12 @@ EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, const wxPoint& pos, const wxSize& size ) : wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL ) { - m_Parent = parent; - wxASSERT( m_Parent ); + wxASSERT( parent ); m_scrollIncrementX = MIN( size.x / 8, 10 ); m_scrollIncrementY = MIN( size.y / 8, 10 ); - SetBackgroundColour( wxColour( ColorRefs[g_DrawBgColor].m_Red, - ColorRefs[g_DrawBgColor].m_Green, - ColorRefs[g_DrawBgColor].m_Blue ) ); + SetBackgroundColour( MakeColour( g_DrawBgColor ) ); #if KICAD_USE_BUFFERED_DC || KICAD_USE_BUFFERED_PAINTDC SetBackgroundStyle( wxBG_STYLE_CUSTOM ); @@ -79,7 +79,7 @@ EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, m_ClipBox.SetY( 0 ); m_CanStartBlock = -1; // Command block can start if >= 0 m_AbortEnable = m_AbortRequest = false; - m_AutoPAN_Enable = TRUE; + m_AutoPAN_Enable = true; m_IgnoreMouseEvents = 0; ManageCurseur = NULL; @@ -90,11 +90,17 @@ EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, m_AutoPAN_Request = false; m_Block_Enable = false; - m_defaultCursor = m_cursor = wxCURSOR_ARROW; - m_CursorLevel = 0; - m_PrintIsMirrored = false; -// wxLog::AddTraceMask( KICAD_TRACE_COORDS ); +#ifdef __WXMAC__ + m_defaultCursor = m_cursor = wxCURSOR_CROSS; + m_showCrossHair = false; +#else + m_defaultCursor = m_cursor = wxCURSOR_ARROW; + m_showCrossHair = true; +#endif + + m_cursorLevel = 0; + m_PrintIsMirrored = false; } @@ -104,32 +110,30 @@ EDA_DRAW_PANEL::~EDA_DRAW_PANEL() } +EDA_DRAW_FRAME* EDA_DRAW_PANEL::GetParent() +{ + return ( EDA_DRAW_FRAME* ) wxWindow::GetParent(); +} + + BASE_SCREEN* EDA_DRAW_PANEL::GetScreen() { - EDA_DRAW_FRAME* parentFrame = m_Parent; + EDA_DRAW_FRAME* parentFrame = GetParent(); return parentFrame->GetScreen(); } -/* - * Draw the schematic cursor which is usually on grid - */ void EDA_DRAW_PANEL::DrawCursor( wxDC* aDC, int aColor ) { - if( m_CursorLevel != 0 || aDC == NULL ) + if( m_cursorLevel != 0 || aDC == NULL || !m_showCrossHair ) return; -#ifdef __WXMAC__ - SetCursor( *wxCROSS_CURSOR ); - return; -#endif - wxPoint Cursor = GetScreen()->m_Curseur; GRSetDrawMode( aDC, GR_XOR ); - if( m_Parent->m_CursorShape == 1 ) /* Draws a crosshair. */ + if( GetParent()->m_CursorShape == 1 ) /* Draws a crosshair. */ { wxSize clientSize = GetClientSize(); wxPoint lineStart = wxPoint( Cursor.x, aDC->DeviceToLogicalY( 0 ) ); @@ -151,27 +155,20 @@ void EDA_DRAW_PANEL::DrawCursor( wxDC* aDC, int aColor ) } -/* - * Remove the grid cursor from the display in preparation for other drawing - * operations - */ void EDA_DRAW_PANEL::CursorOff( wxDC* DC ) { DrawCursor( DC ); - --m_CursorLevel; + --m_cursorLevel; } -/* - * Display the grid cursor - */ void EDA_DRAW_PANEL::CursorOn( wxDC* DC ) { - ++m_CursorLevel; + ++m_cursorLevel; DrawCursor( DC ); - if( m_CursorLevel > 0 ) // Shouldn't happen, but just in case .. - m_CursorLevel = 0; + if( m_cursorLevel > 0 ) // Shouldn't happen, but just in case .. + m_cursorLevel = 0; } @@ -193,35 +190,12 @@ wxRealPoint EDA_DRAW_PANEL::GetGrid() } -/** - * Convert a coordinate position in device (screen) units to logical (drawing) units. - * - * @param aPosition = position in device (screen) units. - * @return position in logical (drawing) units. - */ -wxPoint EDA_DRAW_PANEL::CursorRealPosition( const wxPoint& aPosition ) -{ - double scalar = GetScreen()->GetScalingFactor(); - wxPoint pos; - pos.x = wxRound( (double) aPosition.x / scalar ); - pos.y = wxRound( (double) aPosition.y / scalar ); - pos += GetScreen()->m_DrawOrg; - return pos; -} - - -/** - * Function IsPointOnDisplay - * @param ref_pos is the position to test in pixels, relative to the panel. - * @return TRUE if ref_pos is a point currently visible on screen - * false if ref_pos is out of screen - */ -bool EDA_DRAW_PANEL::IsPointOnDisplay( wxPoint ref_pos ) +bool EDA_DRAW_PANEL::IsPointOnDisplay( const wxPoint& aPosition ) { wxPoint pos; EDA_Rect display_rect; - INSTALL_UNBUFFERED_DC( dc, this ); // Refresh the boundary box. + INSTALL_UNBUFFERED_DC( dc, this ); // Refresh the clip box to the entire screen size. SetClipBox( dc ); display_rect = m_ClipBox; @@ -230,7 +204,7 @@ bool EDA_DRAW_PANEL::IsPointOnDisplay( wxPoint ref_pos ) #define PIXEL_MARGIN 8 display_rect.Inflate( -PIXEL_MARGIN ); - return display_rect.Contains( ref_pos ); + return display_rect.Contains( aPosition ); } @@ -254,22 +228,6 @@ void EDA_DRAW_PANEL::RefreshDrawingRect( const EDA_Rect& aRect, bool aEraseBackg } -/** - * Function CursorScreenPosition - * @return the cursor current position in pixels in the screen draw area - */ -wxPoint EDA_DRAW_PANEL::CursorScreenPosition() -{ - wxPoint pos = GetScreen()->m_Curseur - GetScreen()->m_DrawOrg; - double scalar = GetScreen()->GetScalingFactor(); - - pos.x = wxRound( (double) pos.x * scalar ); - pos.y = wxRound( (double) pos.y * scalar ); - - return pos; -} - - wxPoint EDA_DRAW_PANEL::GetScreenCenterLogicalPosition() { wxSize size = GetClientSize() / 2; @@ -279,8 +237,6 @@ wxPoint EDA_DRAW_PANEL::GetScreenCenterLogicalPosition() } -/* Move the mouse cursor to the current schematic cursor - */ void EDA_DRAW_PANEL::MouseToCursorSchema() { MoveCursor( GetScreen()->m_Curseur ); @@ -329,13 +285,6 @@ void EDA_DRAW_PANEL::MoveCursor( const wxPoint& aPosition ) } -/** - * Called on window activation. - * init the member m_CanStartBlock to avoid a block start command - * on activation (because a left mouse button can be pressed and no block - * command wanted. - * This happens when enter on a hierarchy sheet on double click - */ void EDA_DRAW_PANEL::OnActivate( wxActivateEvent& event ) { m_CanStartBlock = -1; // Block Command can't start @@ -409,10 +358,9 @@ void EDA_DRAW_PANEL::OnScroll( wxScrollWinEvent& event ) return; } -#if DEBUG_DUMP_SCROLL_SETTINGS - wxLogDebug( wxT( "Setting scroll bars ppuX=%d, ppuY=%d, unitsX=%d, unitsY=%d," \ + wxLogTrace( KICAD_TRACE_COORDS, + wxT( "Setting scroll bars ppuX=%d, ppuY=%d, unitsX=%d, unitsY=%d," \ "posX=%d, posY=%d" ), ppux, ppuy, unitsX, unitsY, x, y ); -#endif Scroll( x/ppux, y/ppuy ); event.Skip(); @@ -459,11 +407,10 @@ void EDA_DRAW_PANEL::SetClipBox( wxDC& aDC, const wxRect* aRect ) m_ClipBox.m_Size = wxSize( aDC.DeviceToLogicalXRel( clipBox.width ), aDC.DeviceToLogicalYRel( clipBox.height ) ); -#if DEBUG_DUMP_CLIP_COORDS - wxLogDebug( wxT( "Device clip box=(%d, %d, %d, %d), Logical clip box=(%d, %d, %d, %d)" ), + wxLogTrace( KICAD_TRACE_COORDS, + wxT( "Device clip box=(%d, %d, %d, %d), Logical clip box=(%d, %d, %d, %d)" ), clipBox.x, clipBox.y, clipBox.width, clipBox.height, m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y, m_ClipBox.m_Size.x, m_ClipBox.m_Size.y ); -#endif } @@ -547,7 +494,7 @@ void EDA_DRAW_PANEL::ReDraw( wxDC* DC, bool erasebg ) DC->SetBackground( *wxBLACK_BRUSH ); DC->SetBackgroundMode( wxSOLID ); - m_Parent->RedrawActiveWindow( DC, erasebg ); + GetParent()->RedrawActiveWindow( DC, erasebg ); // Verfies that the clipping is working correctly. If these two sets of numbers are // not the same or really close. The clipping algorithms are broken. @@ -558,14 +505,6 @@ void EDA_DRAW_PANEL::ReDraw( wxDC* DC, bool erasebg ) } -/** - * Function DrawBackGround - * @param DC = current Device Context - * Draws (if allowed) : - * the grid - * X and Y axis - * X and Y auxiliary axis - */ void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC ) { int axis_color = BLUE; @@ -573,11 +512,11 @@ void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC ) GRSetDrawMode( DC, GR_COPY ); - if( m_Parent->IsGridVisible() ) + if( GetParent()->IsGridVisible() ) DrawGrid( DC ); /* Draw axis */ - if( m_Parent->m_Draw_Axis ) + if( GetParent()->m_Draw_Axis ) { /* Draw the Y axis */ GRDashedLine( &m_ClipBox, DC, 0, -screen->ReturnPageSize().y, @@ -588,22 +527,15 @@ void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC ) screen->ReturnPageSize().x, 0, 0, axis_color ); } - if( m_Parent->m_Draw_Auxiliary_Axis ) + if( GetParent()->m_Draw_Auxiliary_Axis ) DrawAuxiliaryAxis( DC, GR_COPY ); - if( m_Parent->m_Draw_Grid_Axis ) + if( GetParent()->m_Draw_Grid_Axis ) DrawGridAxis( DC, GR_COPY ); } -/** - * Function DrawGrid - * @param DC = current Device Context - * draws the grid - * - the grid is drawn only if the zoom level allows a good visibility - * - the grid is always centered on the screen center - */ -void EDA_DRAW_PANEL::DrawGrid( wxDC* DC ) +void EDA_DRAW_PANEL::DrawGrid( wxDC* aDC ) { #define MIN_GRID_SIZE 10 // min grid size in pixels to allow drawing BASE_SCREEN* screen = GetScreen(); @@ -619,8 +551,8 @@ void EDA_DRAW_PANEL::DrawGrid( wxDC* DC ) screen->m_StartVisu = CalcUnscrolledPosition( wxPoint( 0, 0 ) ); screenSize = GetClientSize(); - screenGridSize.x = DC->LogicalToDeviceXRel( wxRound( gridSize.x ) ); - screenGridSize.y = DC->LogicalToDeviceXRel( wxRound( gridSize.y ) ); + screenGridSize.x = aDC->LogicalToDeviceXRel( wxRound( gridSize.x ) ); + screenGridSize.y = aDC->LogicalToDeviceYRel( wxRound( gridSize.y ) ); org = m_ClipBox.m_Pos; @@ -635,7 +567,7 @@ void EDA_DRAW_PANEL::DrawGrid( wxDC* DC ) if( screenGridSize.x < MIN_GRID_SIZE || screenGridSize.y < MIN_GRID_SIZE ) return; - m_Parent->PutOnGrid( &org, &gridSize ); + GetParent()->PutOnGrid( &org, &gridSize ); // Setting the nearest grid position can select grid points outside the clip box. // Incrementing the start point by one grid step should prevent drawing grid points @@ -646,11 +578,11 @@ void EDA_DRAW_PANEL::DrawGrid( wxDC* DC ) if( org.y < m_ClipBox.GetY() ) org.y += wxRound( gridSize.y ); -#if ( defined( __WXMAC__ ) || defined( __WXGTK__ ) || 1 ) - // Use a pixel based draw to display grid. There are a lot of calls, so the cost is high - // and grid is slowly drawn on some platforms. Please note that this should always be - // enabled until the bitmap based solution below is fixed. - GRSetColorPen( DC, m_Parent->GetGridColor() ); +#if ( defined( __WXMAC__ ) || 0 ) + // Use a pixel based draw to display grid. There are a lot of calls, so the cost is + // high and grid is slowly drawn on some platforms. Please note that this should + // always be enabled until the bitmap based solution below is fixed. + GRSetColorPen( aDC, GetParent()->GetGridColor() ); int xpos; double right = ( double ) m_ClipBox.GetRight(); @@ -662,63 +594,70 @@ void EDA_DRAW_PANEL::DrawGrid( wxDC* DC ) for( double y = (double) org.y; y <= bottom; y += gridSize.y ) { - DC->DrawPoint( xpos, wxRound( y ) ); + aDC->DrawPoint( xpos, wxRound( y ) ); } } #else - /* Currently under development: use a bitmap to draw the grid. This is fast only if the - * Blit function is fast. Not true on all platforms. - * - * A single grid column is drawn to a bitmap and then copied to each column. This is - * possible because the grid is drawn only after clearing the screen. + /* This is fast only if the Blit function is fast. Not true on all platforms. * * A first grid column is drawn in a temporary bitmap, and after is duplicated using * the Blit function (copy from a screen area to an other screen area). */ wxMemoryDC tmpDC; - wxBitmap tmpBM( 1, m_ClipBox.GetHeight() ); - tmpDC.SelectObjectAsSource( tmpBM ); - GRSetColorPen( &tmpDC, g_DrawBgColor ); - tmpDC.DrawLine( 0, 0, 0, m_ClipBox.GetHeight() - 1 ); // init background - GRSetColorPen( &tmpDC, m_Parent->GetGridColor() ); + wxBitmap tmpBM( 1, aDC->LogicalToDeviceYRel( m_ClipBox.GetHeight() ) ); + tmpDC.SelectObject( tmpBM ); + tmpDC.SetLogicalFunction( wxCOPY ); + tmpDC.SetBackground( wxBrush( GetBackgroundColour() ) ); + tmpDC.Clear(); + tmpDC.SetPen( MakeColour( GetParent()->GetGridColor() ) ); + + double usx, usy; + int lox, loy, dox, doy; + + aDC->GetUserScale( &usx, &usy ); + aDC->GetLogicalOrigin( &lox, &loy ); + aDC->GetDeviceOrigin( &dox, &doy ); + + // Create a dummy DC for coordinate translation because the actual DC scale and origin + // must be reset in order to work correctly. + wxBitmap tmpBitmap( 1, 1 ); + wxMemoryDC scaleDC( tmpBitmap ); + scaleDC.SetUserScale( usx, usy ); + scaleDC.SetLogicalOrigin( lox, loy ); + scaleDC.SetDeviceOrigin( dox, doy ); double bottom = ( double ) m_ClipBox.GetBottom(); - for( double y = (double) org.y; y <= bottom; y += gridSize.y ) // draw grid points + // Draw a column of grid points. + for( double y = (double) org.y; y <= bottom; y += gridSize.y ) { - if( y > bottom ) - break; - - tmpDC.DrawPoint( 0, wxRound( y ) ); + tmpDC.DrawPoint( 0, scaleDC.LogicalToDeviceY( wxRound( y ) ) ); } - // Use the layer bitmap itself as a mask when blitting. - // The bitmap cannot be referenced by a device context - // when setting the mask. + // Reset the device context scale and origin and restore on exit. + EDA_BLIT_NORMALIZER blitNorm( aDC ); + + // Mask of everything but the grid points. tmpDC.SelectObject( wxNullBitmap ); - tmpBM.SetMask( new wxMask( tmpBM, MakeColour( g_DrawBgColor ) ) ); + tmpBM.SetMask( new wxMask( tmpBM, GetBackgroundColour() ) ); tmpDC.SelectObject( tmpBM ); double right = m_ClipBox.GetRight(); + // Blit the column for each row of the damaged region. for( double x = (double) org.x; x <= right; x += gridSize.x ) { - DC->Blit( wxRound( x ), org.y, 1, m_ClipBox.GetHeight(), &tmpDC, 0, 0, wxCOPY, true ); + aDC->Blit( scaleDC.LogicalToDeviceX( wxRound( x ) ), + scaleDC.LogicalToDeviceY( m_ClipBox.m_Pos.y ), + 1, tmpBM.GetHeight(), &tmpDC, 0, 0, wxCOPY, true ); } #endif } -/** - * Function DrawAuxiliaryAxis - * Draw the Auxiliary Axis, used in pcbnew which as origin coordinates - * for gerber and excellon files - * @param aDC = current Device Context - * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) - */ void EDA_DRAW_PANEL::DrawAuxiliaryAxis( wxDC* aDC, int aDrawMode ) { - if( m_Parent->m_Auxiliary_Axis_Position == wxPoint( 0, 0 ) ) + if( GetParent()->m_Auxiliary_Axis_Position == wxPoint( 0, 0 ) ) return; int Color = DARKRED; @@ -728,18 +667,18 @@ void EDA_DRAW_PANEL::DrawAuxiliaryAxis( wxDC* aDC, int aDrawMode ) /* Draw the Y axis */ GRDashedLine( &m_ClipBox, aDC, - m_Parent->m_Auxiliary_Axis_Position.x, + GetParent()->m_Auxiliary_Axis_Position.x, -screen->ReturnPageSize().y, - m_Parent->m_Auxiliary_Axis_Position.x, + GetParent()->m_Auxiliary_Axis_Position.x, screen->ReturnPageSize().y, 0, Color ); /* Draw the X axis */ GRDashedLine( &m_ClipBox, aDC, -screen->ReturnPageSize().x, - m_Parent->m_Auxiliary_Axis_Position.y, + GetParent()->m_Auxiliary_Axis_Position.y, screen->ReturnPageSize().x, - m_Parent->m_Auxiliary_Axis_Position.y, + GetParent()->m_Auxiliary_Axis_Position.y, 0, Color ); } @@ -748,11 +687,11 @@ void EDA_DRAW_PANEL::DrawGridAxis( wxDC* aDC, int aDrawMode ) { BASE_SCREEN* screen = GetScreen(); - if( !m_Parent->m_Draw_Grid_Axis + if( !GetParent()->m_Draw_Grid_Axis || ( screen->m_GridOrigin.x == 0 && screen->m_GridOrigin.y == 0 ) ) return; - int Color = m_Parent->GetGridColor(); + int Color = GetParent()->GetGridColor(); GRSetDrawMode( aDC, aDrawMode ); @@ -774,9 +713,6 @@ void EDA_DRAW_PANEL::DrawGridAxis( wxDC* aDC, int aDrawMode ) } -/** Build and display a Popup menu on a right mouse button click - * @return true if a popup menu is shown, or false - */ bool EDA_DRAW_PANEL::OnRightClick( wxMouseEvent& event ) { wxPoint pos; @@ -786,10 +722,10 @@ bool EDA_DRAW_PANEL::OnRightClick( wxMouseEvent& event ) pos = event.GetLogicalPosition( dc ); - if( !m_Parent->OnRightClick( pos, &MasterMenu ) ) + if( !GetParent()->OnRightClick( pos, &MasterMenu ) ) return false; - m_Parent->AddMenuZoomAndGrid( &MasterMenu ); + GetParent()->AddMenuZoomAndGrid( &MasterMenu ); pos = event.GetPosition(); m_IgnoreMouseEvents = true; @@ -801,7 +737,6 @@ bool EDA_DRAW_PANEL::OnRightClick( wxMouseEvent& event ) } -// Called when the canvas receives a mouse event leaving frame. void EDA_DRAW_PANEL::OnMouseLeaving( wxMouseEvent& event ) { if( ManageCurseur == NULL ) // No command in progress. @@ -823,13 +758,6 @@ void EDA_DRAW_PANEL::OnMouseLeaving( wxMouseEvent& event ) } -/* - * Handle mouse wheel events. - * - * The mouse wheel is used to provide support for zooming and panning. This - * is accomplished by converting mouse wheel events in pseudo menu command - * events. - */ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event ) { if( m_IgnoreMouseEvents ) @@ -841,16 +769,16 @@ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event ) if( event.GetWheelRotation() == 0 || !GetParent()->IsEnabled() || !rect.Contains( event.GetPosition() ) ) { -#if 0 - wxLogDebug( wxT( "OnMouseWheel() position(%d, %d) rectangle(%d, %d, %d, %d)" ), + wxLogTrace( KICAD_TRACE_COORDS, + wxT( "OnMouseWheel() position(%d, %d) rectangle(%d, %d, %d, %d)" ), event.GetPosition().x, event.GetPosition().y, rect.x, rect.y, rect.width, rect.height ); -#endif event.Skip(); return; } - GetScreen()->m_Curseur = CursorRealPosition( CalcUnscrolledPosition( event.GetPosition() ) ); + INSTALL_UNBUFFERED_DC( dc, this ); + GetScreen()->m_Curseur = event.GetLogicalPosition( dc ); wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED ); cmd.SetEventObject( this ); @@ -880,7 +808,6 @@ void EDA_DRAW_PANEL::OnMouseWheel( wxMouseEvent& event ) } -// Called when the canvas receives a mouse event. void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) { int localrealbutt = 0, localbutt = 0, localkey = 0; @@ -911,7 +838,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) if( ManageCurseur == NULL ) // No command in progress m_AutoPAN_Request = false; - if( m_Parent->m_FrameIsActive ) + if( GetParent()->m_FrameIsActive ) SetFocus(); else return; @@ -974,7 +901,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) // Calling Double Click and Click functions : if( localbutt == (int) ( GR_M_LEFT_DOWN | GR_M_DCLICK ) ) { - m_Parent->OnLeftDClick( &DC, screen->m_MousePosition ); + GetParent()->OnLeftDClick( &DC, screen->m_MousePosition ); // inhibit a response to the mouse left button release, // because we have a double click, and we do not want a new @@ -986,7 +913,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) // A block command is in progress: a left up is the end of block // or this is the end of a double click, already seen if( screen->m_BlockLocate.m_State==STATE_NO_BLOCK && !s_IgnoreNextLeftButtonRelease ) - m_Parent->OnLeftClick( &DC, screen->m_MousePosition ); + GetParent()->OnLeftClick( &DC, screen->m_MousePosition ); s_IgnoreNextLeftButtonRelease = false; } @@ -1011,7 +938,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) } /* Calling the general function on mouse changes (and pseudo key commands) */ - m_Parent->GeneralControle( &DC, event.GetLogicalPosition( DC ) ); + GetParent()->GeneralControle( &DC, event.GetLogicalPosition( DC ) ); /*******************************/ /* Control of block commands : */ @@ -1057,7 +984,7 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) if( screen->m_BlockLocate.m_State == STATE_BLOCK_MOVE ) { m_AutoPAN_Request = false; - m_Parent->HandleBlockPlace( &DC ); + GetParent()->HandleBlockPlace( &DC ); s_IgnoreNextLeftButtonRelease = true; } } @@ -1083,15 +1010,15 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) MinDragEventCount++; else { - if( !m_Parent->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) ) + if( !GetParent()->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) ) { // should not occurs: error - m_Parent->DisplayToolMsg( + GetParent()->DisplayToolMsg( wxT( "EDA_DRAW_PANEL::OnMouseEvent() Block Error" ) ); } else { - m_AutoPAN_Request = TRUE; + m_AutoPAN_Request = true; SetCursor( m_cursor = wxCURSOR_SIZING ); } } @@ -1125,12 +1052,12 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) else if( screen->m_BlockLocate.m_State == STATE_BLOCK_END ) { m_AutoPAN_Request = false; - m_Parent->HandleBlockEnd( &DC ); + GetParent()->HandleBlockEnd( &DC ); SetCursor( m_cursor = m_defaultCursor ); if( screen->m_BlockLocate.m_State == STATE_BLOCK_MOVE ) { - m_AutoPAN_Request = TRUE; + m_AutoPAN_Request = true; SetCursor( wxCURSOR_HAND ); } } @@ -1151,13 +1078,12 @@ void EDA_DRAW_PANEL::OnMouseEvent( wxMouseEvent& event ) } } - #if 0 wxString msg_debug; msg_debug.Printf( " block state %d, cmd %d", screen->m_BlockLocate.m_State, screen->m_BlockLocate.m_Command ); - m_Parent->PrintMsg( msg_debug ); + GetParent()->PrintMsg( msg_debug ); #endif LastPanel = this; @@ -1220,7 +1146,7 @@ void EDA_DRAW_PANEL::OnKeyEvent( wxKeyEvent& event ) pos = wxPoint( DC.DeviceToLogicalX( pos.x ), DC.DeviceToLogicalY( pos.y ) ); Screen->m_MousePosition = pos; - m_Parent->GeneralControle( &DC, pos ); + GetParent()->GeneralControle( &DC, pos ); #if 0 event.Skip(); // Allow menu shortcut processing @@ -1295,6 +1221,6 @@ void EDA_DRAW_PANEL::UnManageCursor( int id, int cursor, const wxString& title ) if( id != -1 && cursor != -1 ) { wxASSERT( cursor > wxCURSOR_NONE && cursor < wxCURSOR_MAX ); - m_Parent->SetToolID( id, cursor, title ); + GetParent()->SetToolID( id, cursor, title ); } } diff --git a/eeschema/find.cpp b/eeschema/find.cpp index e030bd864c..f16b07f55a 100644 --- a/eeschema/find.cpp +++ b/eeschema/find.cpp @@ -198,7 +198,7 @@ SCH_ITEM* SCH_EDIT_FRAME::FindComponentAndItem( const wxString& component_refere wxPoint old_cursor_position = sheet->LastScreen()->m_Curseur; sheet->LastScreen()->m_Curseur = pos; - curpos = DrawPanel->CursorScreenPosition(); + curpos = GetScreen()->GetCrossHairScreenPosition(); DrawPanel->GetViewStart( &( GetScreen()->m_StartVisu.x ), &( GetScreen()->m_StartVisu.y ) ); diff --git a/gerbview/draw_gerber_screen.cpp b/gerbview/draw_gerber_screen.cpp index cc697ba77a..b6d336a27e 100644 --- a/gerbview/draw_gerber_screen.cpp +++ b/gerbview/draw_gerber_screen.cpp @@ -134,7 +134,9 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin layerBitmap = new wxBitmap( bitmapWidth, bitmapHeight ); screenBitmap = new wxBitmap( bitmapWidth, bitmapHeight ); layerDC.SelectObject( *layerBitmap ); + EDA_Rect tmpRect = aPanel->m_ClipBox; aPanel->DoPrepareDC( layerDC ); + aPanel->m_ClipBox = tmpRect; layerDC.SetBackground( bgBrush ); layerDC.SetBackgroundMode( wxSOLID ); layerDC.Clear(); diff --git a/include/class_base_screen.h b/include/class_base_screen.h index 98f645aad6..2087a951e6 100644 --- a/include/class_base_screen.h +++ b/include/class_base_screen.h @@ -244,7 +244,7 @@ public: * @return the the current scale used to draw items on screen * draw coordinates are user coordinates * GetScalingFactor( ) */ - double GetScalingFactor() + double GetScalingFactor() const { return (double) m_ZoomScalar / (double) GetZoom(); } @@ -365,6 +365,13 @@ public: */ wxPoint GetCursorPosition( bool aOnGrid, wxRealPoint* aGridSize = NULL ); + /** + * Function GetCursorScreenPosition + * returns the cross hair position in device (display) units.b + * @return The current cross hair position. + */ + wxPoint GetCrossHairScreenPosition() const; + /** * Function GetNearestGridPosition * returns the nearest \a aGridSize location to \a aPosition. diff --git a/include/class_drawpanel.h b/include/class_drawpanel.h index c6d0fde552..f884a224c0 100644 --- a/include/class_drawpanel.h +++ b/include/class_drawpanel.h @@ -18,50 +18,39 @@ class PCB_SCREEN; class EDA_DRAW_PANEL : public wxScrolledWindow { private: - EDA_DRAW_FRAME* m_Parent; - int m_cursor; ///< Current mouse cursor shape id. - int m_defaultCursor; ///< The default mouse cursor shape id. + int m_cursor; ///< Current mouse cursor shape id. + int m_defaultCursor; ///< The default mouse cursor shape id. + bool m_showCrossHair; ///< Indicate if cross hair is to be shown. + int m_cursorLevel; // Index for cursor redraw in XOR mode. public: - EDA_Rect m_ClipBox; // the clipbox used in screen - // redraw (usually gives the - // visible area in internal units) - wxPoint m_CursorStartPos; // useful in testing the cursor - // movement + EDA_Rect m_ClipBox; // the clipbox used in screen redraw (usually gives the + // visible area in internal units) + wxPoint m_CursorStartPos; // useful in testing the cursor movement + int m_scrollIncrementX; // X axis scroll increment in pixels per unit. + int m_scrollIncrementY; // Y axis scroll increment in pixels per unit. - int m_scrollIncrementX; // X axis scroll increment in pixels per unit. - int m_scrollIncrementY; // Y axis scroll increment in pixels per unit. + bool m_AbortRequest; // Flag to abort long commands + bool m_AbortEnable; // TRUE if abort button or menu to be displayed + bool m_AutoPAN_Enable; // TRUE to allow auto pan + bool m_AutoPAN_Request; // TRUE to request an auto pan (will be made only if + // m_AutoPAN_Enable = true) + int m_IgnoreMouseEvents; // when non-zero (true), then ignore mouse events + bool m_Block_Enable; // TRUE to accept Block Commands - bool m_AbortRequest; // Flag to abort long commands - bool m_AbortEnable; // TRUE if abort button or menu to - // be displayed - - bool m_AutoPAN_Enable; // TRUE to allow auto pan - bool m_AutoPAN_Request; // TRUE to request an auto pan - // (will be made only if - // m_AutoPAN_Enable = true) - - int m_IgnoreMouseEvents; // when non-zero (true), then - // ignore mouse events - - bool m_Block_Enable; // TRUE to accept Block Commands // useful to avoid false start block in certain cases // (like switch from a sheet to an other sheet - int m_CanStartBlock; // >= 0 (or >= n) if a block can - // start - bool m_PrintIsMirrored; // True when drawing in mirror - // mode. Used in draw arc function, - // because arcs are oriented, and - // in mirror mode, orientations are - // reversed - int m_CursorLevel; // Index for cursor redraw in XOR - // mode + int m_CanStartBlock; // >= 0 (or >= n) if a block can start + bool m_PrintIsMirrored; // True when drawing in mirror mode. Used in draw arc function, + // because arcs are oriented, and in mirror mode, orientations + // are reversed #ifdef USE_WX_OVERLAY // MAC Uses overlay to workaround the wxINVERT and wxXOR miss - wxOverlay m_overlay; + wxOverlay m_overlay; #endif + /* Cursor management (used in editing functions) */ /* Mouse capture move callback function prototype. */ @@ -78,12 +67,9 @@ public: BASE_SCREEN* GetScreen(); - EDA_DRAW_FRAME* GetParent() - { - return m_Parent; - } + virtual EDA_DRAW_FRAME* GetParent(); - void OnPaint( wxPaintEvent& event ); + void OnPaint( wxPaintEvent& event ); /** * Function DrawBackGround @@ -93,16 +79,17 @@ public: * X and Y axis * X and Y auxiliary axis */ - void DrawBackGround( wxDC* DC ); + void DrawBackGround( wxDC* DC ); /** * Function DrawGrid - * @param DC = current Device Context - * draws the grid - * - the grid is drawn only if the zoom level allows a good visibility - * - the grid is always centered on the screen center + * draws a grid to \a aDC. + * @see m_ClipBox to determine the damaged area of the drawing to draw the grid. + * @see EDA_DRAW_FRAME::IsGridVisible() to determine if grid is shown. + * @see EDA_DRAW_FRAME::GetGridColor() for the color of the grid. + * @param aDC The device context to draw the grid. */ - void DrawGrid( wxDC* DC ); + void DrawGrid( wxDC* DC ); /** * Function DrawAuxiliaryAxis @@ -111,7 +98,7 @@ public: * @param aDC = current Device Context * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) */ - void DrawAuxiliaryAxis( wxDC* aDC, int aDrawMode ); + void DrawAuxiliaryAxis( wxDC* aDC, int aDrawMode ); /** * Function DrawGridAxis @@ -120,29 +107,36 @@ public: * @param aDC = current Device Context * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) */ - void DrawGridAxis( wxDC* aDC, int aDrawMode ); + void DrawGridAxis( wxDC* aDC, int aDrawMode ); - void OnEraseBackground( wxEraseEvent& event ) { } - - void OnActivate( wxActivateEvent& event ); + void OnEraseBackground( wxEraseEvent& event ) { } /** - * Prepare the device context for drawing. - * - * This overrides wxScrolledWindow::DoPrepareDC() for drawing depending - * on the render mode selected a build time. If the old kicad coordinate - * scaling code is used then this code doesn't do any thing other than - * update the boundary box. If wxDC coordinate manipulation is used, then - * the scale factor and drawing logical offset is set. Then the base - * method is called to set the DC device origin and user scale. This - * connects everything together to achieve the appropriate coordinate - * manipulation using wxDC LogicalToDeviceXXX and DeviceToLogixalXXX - * methods. This gets called automatically for a paint event. If you do - * any drawing outside the paint event, you must call DoPrepareDC manually. - * - * @param dc - The device context to prepare. + * Function OnActivate + * handles window activation events. + *

+ * The member m_CanStartBlock is initialize to avoid a block start command on activation + * (because a left mouse button can be pressed and no block command wanted. This happens + * when enter on a hierarchy sheet on double click. + *

*/ - virtual void DoPrepareDC(wxDC& dc); + void OnActivate( wxActivateEvent& event ); + + /** + * Fucntion DoPrepareDC + * sets up the device context \a aDC for drawing. + *

+ * This overrides wxScrolledWindow::DoPrepareDC() for settting up the the device context + * used for drawing. The scale factor and drawing logical offset are set and the base + * method is called to set the DC device origin (scroll bar position). This connects + * everything together to achieve the appropriate coordinate manipulation using wxDC + * LogicalToDeviceXXX and DeviceToLogixalXXX methods. This gets called automatically + * for a paint event. If you do any drawing outside the paint event, you must call + * DoPrepareDC manually. + *

+ * @param aDC The device context to prepare. + */ + virtual void DoPrepareDC( wxDC& aDC ); /** * Function DeviceToLogical @@ -157,26 +151,46 @@ public: wxRect DeviceToLogical( const wxRect& aRect, wxDC& aDC ); /* Mouse and keys events */ - void OnMouseWheel( wxMouseEvent& event ); - void OnMouseEvent( wxMouseEvent& event ); - void OnMouseLeaving( wxMouseEvent& event ); - void OnKeyEvent( wxKeyEvent& event ); - void OnPan( wxCommandEvent& event ); + /** + * Funtion OnMouseWheel + * handles mouse wheel events. + *

+ * The mouse wheel is used to provide support for zooming and panning. This + * is accomplished by converting mouse wheel events in pseudo menu command + * events and sending them to the appropriate parent window event handler. + *

+ */ + void OnMouseWheel( wxMouseEvent& event ); + void OnMouseEvent( wxMouseEvent& event ); + void OnMouseLeaving( wxMouseEvent& event ); + void OnKeyEvent( wxKeyEvent& event ); - void EraseScreen( wxDC* DC ); - void OnScrollWin( wxCommandEvent& event ); - void OnScroll( wxScrollWinEvent& event ); + void OnPan( wxCommandEvent& event ); - void SetZoom( int mode ); - int GetZoom(); - void SetGrid( const wxRealPoint& size ); - wxRealPoint GetGrid(); + void EraseScreen( wxDC* DC ); + void OnScrollWin( wxCommandEvent& event ); + void OnScroll( wxScrollWinEvent& event ); - bool OnRightClick( wxMouseEvent& event ); - void Process_Special_Functions( wxCommandEvent& event ); + void SetZoom( int mode ); + int GetZoom(); + void SetGrid( const wxRealPoint& size ); + wxRealPoint GetGrid(); - bool IsPointOnDisplay( wxPoint ref_pos ); + /** + * Function OnRightClick + * builds and displays a context menu on a right mouse button click. + * @return true if the context menu is shown, or false + */ + bool OnRightClick( wxMouseEvent& event ); + + /** + * Function IsPointOnDisplay + * @param aPosition The position to test in logical (drawing) units. + * @return true if \a aPosition is visible on the screen. + * false if \a aPosition is not visiable on the screen. + */ + bool IsPointOnDisplay( const wxPoint& aPosition ); /** * Function SetClipBox @@ -194,22 +208,9 @@ public: * @param aRect The clip rectangle in device units or NULL for the entire visible area * of the screen. */ - void SetClipBox( wxDC& aDC, const wxRect* aRect = NULL ); + void SetClipBox( wxDC& aDC, const wxRect* aRect = NULL ); - void ReDraw( wxDC* DC, bool erasebg = TRUE ); - - /** - * Function CursorRealPosition - * @return the position in user units of location ScreenPos - * @param aPosition = the screen (in pixel) position to convert - */ - wxPoint CursorRealPosition( const wxPoint& aPosition ); - - /** - * Function CursorScreenPosition - * @return the cursor current position in pixels in the screen draw area - */ - wxPoint CursorScreenPosition(); + void ReDraw( wxDC* DC, bool erasebg = TRUE ); /** * Function RefreshDrawingRect @@ -218,22 +219,22 @@ public: * @param aRect The rectangle to repaint. * @param aEraseBackground Erases the background if true. */ - void RefreshDrawingRect( const EDA_Rect& aRect, bool aEraseBackground = true ); + void RefreshDrawingRect( const EDA_Rect& aRect, bool aEraseBackground = true ); /** * Function GetScreenCenterLogicalPosition * @return The current screen center position in logical (drawing) units. */ - wxPoint GetScreenCenterLogicalPosition(); + wxPoint GetScreenCenterLogicalPosition(); - void MouseToCursorSchema(); + void MouseToCursorSchema(); /** * Function MoveCursor * moves the mouse pointer to \a aPosition in logical (drawing) units. * @param aPosition The position in logical units to move the cursor. */ - void MoveCursor( const wxPoint& aPosition ); + void MoveCursor( const wxPoint& aPosition ); /* Cursor functions */ /** @@ -241,20 +242,20 @@ public: * * The user cursor is not the mouse cursor although they may be at the * same screen position. The mouse cursor is still render by the OS. - * This is a drawn cursor that is used to snap to grid when grid snapping + * This is a drawn cross hair that is used to snap to grid when grid snapping * is enabled. This is required because OSX does not allow moving the * cursor programmatically. * * @param aDC - the device context to draw the cursor * @param aColor - the color to draw the cursor */ - void DrawCursor( wxDC* aDC, int aColor = WHITE ); + void DrawCursor( wxDC* aDC, int aColor = WHITE ); // remove the grid cursor from the display - void CursorOff( wxDC* DC ); + void CursorOff( wxDC* DC ); // display the grid cursor - void CursorOn( wxDC* DC ); + void CursorOn( wxDC* DC ); /** * Release managed cursor. @@ -266,8 +267,7 @@ public: * @param aTitle The tool message to display in the status bar or wxEmptyString to clear * the message. */ - void UnManageCursor( int aId = -1, int aCursorId = -1, - const wxString& aTitle = wxEmptyString ); + void UnManageCursor( int aId = -1, int aCursorId = -1, const wxString& aTitle = wxEmptyString ); int GetDefaultCursor() const { return m_defaultCursor; } diff --git a/include/kicad_device_context.h b/include/kicad_device_context.h index 802126492a..82caee0b51 100644 --- a/include/kicad_device_context.h +++ b/include/kicad_device_context.h @@ -86,6 +86,55 @@ private: }; +/** + * Class EDA_BLIT_NORMALIZER + * is a helper class for clearing a device context scale and offset parameters before + * performing a Blit operation. + *

+ * This class keeps a temporary copy of the scale and offset parameters of a device + * context and then restores them when it goes out of scope. + *

+ */ +class EDA_BLIT_NORMALIZER +{ +public: + EDA_BLIT_NORMALIZER( wxDC* aDC ) + : m_dc( aDC ) + { + if( aDC ) + { + aDC->GetUserScale( &m_userScaleX, &m_userScaleY ); + aDC->GetLogicalOrigin( &m_logicalOriginX, &m_logicalOriginY ); + aDC->GetDeviceOrigin( &m_deviceOriginX, &m_deviceOriginY ); + aDC->SetUserScale( 1.0, 1.0 ); + aDC->SetLogicalOrigin( 0, 0 ); + aDC->SetDeviceOrigin( 0, 0 ); + } + } + + ~EDA_BLIT_NORMALIZER() + { + if( m_dc ) + { + m_dc->SetUserScale( m_userScaleX, m_userScaleY ); + m_dc->SetLogicalOrigin( m_logicalOriginX, m_logicalOriginY ); + m_dc->SetDeviceOrigin( m_deviceOriginX, m_deviceOriginY ); + } + } + +private: + wxDC* m_dc; + double m_userScaleX; + double m_userScaleY; + int m_logicalOriginX; + int m_logicalOriginY; + int m_deviceOriginX; + int m_deviceOriginY; + + DECLARE_NO_COPY_CLASS( EDA_BLIT_NORMALIZER ) +}; + + #if USE_WX_GRAPHICS_CONTEXT #include #endif