Commit 009d28d4 authored by Maciej Suminski's avatar Maciej Suminski

Merged lp:~cern-kicad/kicad/drawing_tool branch.

parents 402c7d21 2ed804b8
......@@ -477,6 +477,8 @@ if( KICAD_SKIP_BOOST )
message( FATAL_ERROR "Boost 1.54+ libraries are required." )
endif()
add_custom_target( boost ) # it is required to meet some further dependencies
message( WARNING "
WARNING: You decided to skip building boost library.
KiCad developers strongly advise you to build the bundled boost library, as it is known to work with KiCad.
......
......@@ -29,7 +29,7 @@ add_custom_target(
set( GAL_SRCS
# Common part
drawpanel_gal.cpp
draw_panel_gal.cpp
painter.cpp
worksheet_viewitem.cpp
gal/graphics_abstraction_layer.cpp
......
......@@ -175,13 +175,6 @@ void BASE_SCREEN::SetGridList( GRIDS& gridlist )
}
void BASE_SCREEN::GetGrids( GRIDS& aList )
{
for( size_t i = 0; i < m_grids.size(); i++ )
aList.push_back( m_grids[ i ] );
}
int BASE_SCREEN::SetGrid( const wxRealPoint& size )
{
wxASSERT( !m_grids.empty() );
......
......@@ -19,8 +19,8 @@
// Default marquer shape:
#define M_SHAPE_SCALE 6 // default scaling factor for MarkerShapeCorners coordinates
#define CORNERS_COUNT 8
const int M_SHAPE_SCALE = 6; // default scaling factor for MarkerShapeCorners coordinates
const int CORNERS_COUNT = 8;
/* corners of the default shape
* actual coordinates are these values * .m_ScalingFactor
*/
......@@ -46,10 +46,10 @@ void MARKER_BASE::init()
m_Color = RED;
wxPoint start = MarkerShapeCorners[0];
wxPoint end = MarkerShapeCorners[0];
for( unsigned ii = 0; ii < CORNERS_COUNT; ii++ )
{
wxPoint corner = MarkerShapeCorners[ii];
m_Corners.push_back( corner );
start.x = std::min( start.x, corner.x);
start.y = std::min( start.y, corner.y);
end.x = std::max( end.x, corner.x);
......@@ -64,7 +64,6 @@ void MARKER_BASE::init()
MARKER_BASE::MARKER_BASE( const MARKER_BASE& aMarker )
{
m_Pos = aMarker.m_Pos;
m_Corners = aMarker.m_Corners;
m_MarkerType = aMarker.m_MarkerType;
m_Color = aMarker.m_Color;
m_ShapeBoundingBox = aMarker.m_ShapeBoundingBox;
......@@ -154,9 +153,9 @@ void MARKER_BASE::DrawMarker( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDr
GRSetDrawMode( aDC, aDrawMode );
for( unsigned ii = 0; ii < m_Corners.size(); ii++ )
for( unsigned ii = 0; ii < CORNERS_COUNT; ii++ )
{
corners[ii] = m_Corners[ii];
corners[ii] = MarkerShapeCorners[ii];
corners[ii].x *= m_ScalingFactor;
corners[ii].y *= m_ScalingFactor;
corners[ii] += m_Pos + aOffset;
......
......@@ -36,7 +36,7 @@
#include <macros.h>
#include <id.h>
#include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <class_base_screen.h>
#include <msgpanel.h>
#include <draw_frame.h>
......@@ -48,6 +48,7 @@
#include <wx/fontdlg.h>
#include <view/view.h>
#include <view/view_controls.h>
#include <gal/graphics_abstraction_layer.h>
/**
......@@ -395,7 +396,7 @@ void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event )
if( IsGalCanvasActive() )
{
GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x,
screen->GetGrid().m_Size.y ) );
screen->GetGrid().m_Size.y ) );
GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
}
......@@ -532,6 +533,38 @@ wxPoint EDA_DRAW_FRAME::GetGridPosition( const wxPoint& aPosition ) const
}
void EDA_DRAW_FRAME::SetNextGrid()
{
if( m_gridSelectBox )
{
m_gridSelectBox->SetSelection( ( m_gridSelectBox->GetSelection() + 1 ) %
m_gridSelectBox->GetCount() );
wxCommandEvent cmd( wxEVT_COMMAND_COMBOBOX_SELECTED );
// cmd.SetEventObject( this );
OnSelectGrid( cmd );
}
}
void EDA_DRAW_FRAME::SetPrevGrid()
{
if( m_gridSelectBox )
{
int cnt = m_gridSelectBox->GetSelection();
if( --cnt < 0 )
cnt = m_gridSelectBox->GetCount() - 1;
m_gridSelectBox->SetSelection( cnt );
wxCommandEvent cmd( wxEVT_COMMAND_COMBOBOX_SELECTED );
// cmd.SetEventObject( this );
OnSelectGrid( cmd );
}
}
int EDA_DRAW_FRAME::BlockCommand( int key )
{
return 0;
......@@ -1007,9 +1040,17 @@ void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
wxPoint EDA_DRAW_FRAME::GetCrossHairPosition( bool aInvertY ) const
{
// subject to change, borrow from old BASE_SCREEN for now.
if( IsGalCanvasActive() )
{
VECTOR2I cursor = GetGalCanvas()->GetViewControls()->GetCursorPosition();
BASE_SCREEN* screen = GetScreen(); // virtual call
return screen->getCrossHairPosition( aInvertY );
return wxPoint( cursor.x, cursor.y );
}
else
{
BASE_SCREEN* screen = GetScreen(); // virtual call
return screen->getCrossHairPosition( aInvertY );
}
}
......
......@@ -35,7 +35,7 @@
#include <macros.h>
#include <id.h>
#include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <class_base_screen.h>
#include <draw_frame.h>
......
......@@ -29,7 +29,7 @@
#include <wx/colour.h>
#include <wx/filename.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <pcb_painter.h>
......@@ -45,8 +45,6 @@
#include <profile.h>
#endif /* __WXDEBUG__ */
#define METRIC_UNIT_LENGTH (1e9)
EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindowId,
const wxPoint& aPosition, const wxSize& aSize,
GalType aGalType ) :
......@@ -61,11 +59,6 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
SwitchBackend( aGalType );
SetBackgroundStyle( wxBG_STYLE_CUSTOM );
// Initial display settings
m_gal->SetLookAtPoint( VECTOR2D( 0, 0 ) );
m_gal->SetZoomFactor( 1.0 );
m_gal->ComputeWorldScreenMatrix();
m_painter = new KIGFX::PCB_PAINTER( m_gal );
m_view = new KIGFX::VIEW( true );
......@@ -90,8 +83,7 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
Connect( wxEVT_MIDDLE_DCLICK, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) );
Connect( wxEVT_KEY_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_KEY_DOWN, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_CHAR, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this );
Connect( KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE,
wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
......@@ -131,17 +123,22 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
{
m_drawing = true;
m_view->UpdateItems();
m_gal->BeginDrawing();
m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
m_gal->ClearScreen();
m_view->ClearTargets();
// Grid has to be redrawn only when the NONCACHED target is redrawn
if( m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) )
m_gal->DrawGrid();
m_view->Redraw();
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
if( m_view->IsDirty() )
{
m_view->ClearTargets();
// Grid has to be redrawn only when the NONCACHED target is redrawn
if( m_view->IsTargetDirty( KIGFX::TARGET_NONCACHED ) )
m_gal->DrawGrid();
m_view->Redraw();
}
m_gal->DrawCursor( m_viewControls->GetCursorPosition() );
m_gal->EndDrawing();
m_drawing = false;
......@@ -196,14 +193,14 @@ void EDA_DRAW_PANEL_GAL::StopDrawing()
void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
{
// Protect from refreshing during backend switch
m_pendingRefresh = true;
m_refreshTimer.Stop();
// Do not do anything if the currently used GAL is correct
if( aGalType == m_currentGal && m_gal != NULL )
return;
// Prevent refreshing canvas during backend switch
m_pendingRefresh = true;
m_refreshTimer.Stop();
delete m_gal;
switch( aGalType )
......@@ -220,21 +217,15 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
return;
}
m_gal->SetWorldUnitLength( 1.0 / METRIC_UNIT_LENGTH * 2.54 ); // 1 inch in nanometers
m_gal->SetScreenDPI( 106 ); // Display resolution setting
m_gal->ComputeWorldScreenMatrix();
wxSize size = GetClientSize();
m_gal->ResizeScreen( size.GetX(), size.GetY() );
m_gal->SetBackgroundColor( KIGFX::COLOR4D( 0.0, 0.0, 0.0, 1.0 ) );
if( m_painter )
m_painter->SetGAL( m_gal );
if( m_view )
{
m_view->SetGAL( m_gal );
m_view->RecacheAllItems( true );
}
m_currentGal = aGalType;
m_pendingRefresh = false;
......
......@@ -35,9 +35,6 @@
using namespace KIGFX;
///> Opacity of a single layer
const float LAYER_ALPHA = 0.8;
CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
wxEvtHandler* aPaintListener, const wxString& aName ) :
wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
......@@ -73,14 +70,16 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
#endif
SetSize( aParent->GetSize() );
screenSize = VECTOR2D( aParent->GetSize() );
initCursor( 20 );
screenSize = VECTOR2I( aParent->GetSize() );
initCursor();
// Grid color settings are different in Cairo and OpenGL
SetGridColor( COLOR4D( 0.1, 0.1, 0.1, 0.8 ) );
// Allocate memory for pixel storage
allocateBitmaps();
initSurface();
}
......@@ -139,7 +138,7 @@ void CAIRO_GAL::EndDrawing()
*wxOutputPtr++ = value & 0xff; // Blue pixel
}
wxImage img( (int) screenSize.x, (int) screenSize.y, (unsigned char*) wxOutput, true );
wxImage img( screenSize.x, screenSize.y, (unsigned char*) wxOutput, true );
wxBitmap bmp( img );
wxClientDC client_dc( this );
wxBufferedDC dc;
......@@ -284,7 +283,7 @@ void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControl
void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
{
screenSize = VECTOR2D( aWidth, aHeight );
screenSize = VECTOR2I( aWidth, aHeight );
// Recreate the bitmaps
deleteBitmaps();
......@@ -431,7 +430,7 @@ void CAIRO_GAL::SetLayerDepth( double aLayerDepth )
}
void CAIRO_GAL::Transform( MATRIX3x3D aTransformation )
void CAIRO_GAL::Transform( const MATRIX3x3D& aTransformation )
{
cairo_matrix_t cairoTransformation;
......@@ -885,11 +884,10 @@ void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
}
void CAIRO_GAL::initCursor( int aCursorSize )
void CAIRO_GAL::initCursor()
{
cursorPixels = new wxBitmap( aCursorSize, aCursorSize );
cursorPixelsSaved = new wxBitmap( aCursorSize, aCursorSize );
cursorSize = aCursorSize;
cursorPixels = new wxBitmap( cursorSize, cursorSize );
cursorPixelsSaved = new wxBitmap( cursorSize, cursorSize );
wxMemoryDC cursorShape( *cursorPixels );
......@@ -900,8 +898,8 @@ void CAIRO_GAL::initCursor( int aCursorSize )
cursorShape.SetPen( pen );
cursorShape.Clear();
cursorShape.DrawLine( 0, aCursorSize / 2, aCursorSize, aCursorSize / 2 );
cursorShape.DrawLine( aCursorSize / 2, 0, aCursorSize / 2, aCursorSize );
cursorShape.DrawLine( 0, cursorSize / 2, cursorSize, cursorSize / 2 );
cursorShape.DrawLine( cursorSize / 2, 0, cursorSize / 2, cursorSize );
}
......@@ -925,14 +923,15 @@ void CAIRO_GAL::blitCursor( wxBufferedDC& clientDC )
}
// Store pixels that are going to be overpainted
cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, cursorPosition.x, cursorPosition.y );
VECTOR2D cursorScreen = ToScreen( cursorPosition ) - cursorSize / 2;
cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, cursorScreen.x, cursorScreen.y );
// Draw the cursor
clientDC.Blit( cursorPosition.x, cursorPosition.y, cursorSize, cursorSize,
clientDC.Blit( cursorScreen.x, cursorScreen.y, cursorSize, cursorSize,
&cursorShape, 0, 0, wxOR );
savedCursorPosition.x = (wxCoord) cursorPosition.x;
savedCursorPosition.y = (wxCoord) cursorPosition.y;
savedCursorPosition.x = (wxCoord) cursorScreen.x;
savedCursorPosition.y = (wxCoord) cursorScreen.y;
}
......@@ -958,7 +957,8 @@ void CAIRO_GAL::deleteBitmaps()
void CAIRO_GAL::initSurface()
{
wxASSERT( !isInitialized );
if( isInitialized )
return;
// Create the Cairo surface
surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
......
......@@ -39,7 +39,10 @@ GAL::GAL() :
SetIsStroke( true );
SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
SetLookAtPoint( VECTOR2D( 0, 0 ) );
SetZoomFactor( 1.0 );
SetWorldUnitLength( 1.0 / METRIC_UNIT_LENGTH * 2.54 ); // 1 inch in nanometers
SetScreenDPI( 106 ); // Display resolution setting
SetDepthRange( VECTOR2D( GAL::MIN_DEPTH, GAL::MAX_DEPTH ) );
SetFlip( false, false );
SetLineWidth( 1.0 );
......@@ -85,7 +88,7 @@ void GAL::ComputeWorldScreenMatrix()
MATRIX3x3D translation;
translation.SetIdentity();
translation.SetTranslation( 0.5 * screenSize );
translation.SetTranslation( 0.5 * VECTOR2D( screenSize ) );
MATRIX3x3D scale;
scale.SetIdentity();
......@@ -112,23 +115,23 @@ void GAL::DrawGrid()
SetTarget( TARGET_NONCACHED );
// Draw the origin marker
double origSize = static_cast<double>( gridOriginMarkerSize ) / worldScale;
double originSize = gridOriginMarkerSize / worldScale;
SetLayerDepth( GAL::GRID_DEPTH );
SetIsFill( false );
SetIsStroke( true );
SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
SetLineWidth( gridLineWidth / worldScale );
DrawLine( gridOrigin + VECTOR2D( -origSize, -origSize ),
gridOrigin + VECTOR2D( origSize, origSize ) );
DrawLine( gridOrigin + VECTOR2D( -origSize, origSize ),
gridOrigin + VECTOR2D( origSize, -origSize ) );
DrawCircle( gridOrigin, origSize * 0.7 );
DrawLine( gridOrigin + VECTOR2D( -originSize, -originSize ),
gridOrigin + VECTOR2D( originSize, originSize ) );
DrawLine( gridOrigin + VECTOR2D( -originSize, originSize ),
gridOrigin + VECTOR2D( originSize, -originSize ) );
DrawCircle( gridOrigin, originSize * 0.7 );
// Draw the grid
// For the drawing the start points, end points and increments have
// to be calculated in world coordinates
VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
VECTOR2D worldEndPoint = screenWorldMatrix * screenSize;
VECTOR2D worldEndPoint = screenWorldMatrix * VECTOR2D( screenSize );
int gridScreenSizeDense = round( gridSize.x * worldScale );
int gridScreenSizeCoarse = round( gridSize.x * static_cast<double>( gridTick ) * worldScale );
......@@ -232,12 +235,12 @@ void GAL::DrawGrid()
}
VECTOR2D GAL::GetGridPoint( VECTOR2D aPoint ) const
VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
{
VECTOR2D pointWorld = ToWorld( aPoint );
VECTOR2D gridPoint;
pointWorld.x = round( pointWorld.x / gridSize.x ) * gridSize.x;
pointWorld.y = round( pointWorld.y / gridSize.y ) * gridSize.y;
gridPoint.x = round( aPoint.x / gridSize.x ) * gridSize.x;
gridPoint.y = round( aPoint.y / gridSize.y ) * gridSize.y;
return ToScreen( pointWorld );
return gridPoint;
}
......@@ -17,7 +17,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http:O//www.gnu.org website for the version 2 license,
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
......
......@@ -86,8 +86,7 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
#endif
SetSize( aParent->GetSize() );
screenSize = VECTOR2D( aParent->GetSize() );
initCursor( 80 );
screenSize = VECTOR2I( aParent->GetSize() );
// Grid color settings are different in Cairo and OpenGL
SetGridColor( COLOR4D( 0.8, 0.8, 0.8, 0.1 ) );
......@@ -103,6 +102,8 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
}
gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
currentManager = &nonCachedManager;
}
......@@ -250,6 +251,8 @@ void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoin
const VECTOR2D startEndVector = aEndPoint - aStartPoint;
double lineAngle = startEndVector.Angle();
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
drawLineQuad( aStartPoint, aEndPoint );
// Line caps
......@@ -467,10 +470,15 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
{
if( aPointList.empty() )
return;
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
// Start from the second point
for( it++; it != aPointList.end(); it++ )
for( ++it; it != aPointList.end(); ++it )
{
const VECTOR2D startEndVector = ( *it - *( it - 1 ) );
double lineAngle = startEndVector.Angle();
......@@ -554,7 +562,7 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro
void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight )
{
screenSize = VECTOR2D( aWidth, aHeight );
screenSize = VECTOR2I( aWidth, aHeight );
// Resize framebuffers
compositor.Resize( aWidth, aHeight );
......@@ -589,16 +597,7 @@ void OPENGL_GAL::ClearScreen()
}
void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor )
{
strokeColor = aColor;
// This is the default drawing color
currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a );
}
void OPENGL_GAL::Transform( MATRIX3x3D aTransformation )
void OPENGL_GAL::Transform( const MATRIX3x3D& aTransformation )
{
GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
......@@ -767,8 +766,8 @@ void OPENGL_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,
screenSize.y - aCursorPosition.y ); // invert Y axis
VECTOR2D screenCursor = worldScreenMatrix * aCursorPosition;
cursorPosition = screenWorldMatrix * VECTOR2D( screenCursor.x, screenSize.y - screenCursor.y );
}
......@@ -778,13 +777,9 @@ void OPENGL_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
// We do not need a very precise comparison here (the lineWidth is set by GAL::DrawGrid())
if( fabs( lineWidth - 2.0 * gridLineWidth / worldScale ) < 0.1 )
{
glLineWidth( 1.0 );
}
else
{
glLineWidth( 2.0 );
}
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
......@@ -798,8 +793,23 @@ void OPENGL_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
}
inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{
/* Helper drawing: ____--- v3 ^
* ____---- ... \ \
* ____---- ... \ end \
* v1 ____---- ... ____---- \ width
* ---- ...___---- \ \
* \ ___...-- \ v
* \ ____----... ____---- v2
* ---- ... ____----
* start \ ... ____----
* \... ____----
* ----
* v0
* dots mark triangles' hypotenuses
*/
VECTOR2D startEndVector = aEndPoint - aStartPoint;
double lineLength = startEndVector.EuclideanNorm();
double scale = 0.5 * lineWidth / lineLength;
......@@ -857,8 +867,8 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]).
* Shader uses this coordinates to determine if fragments are inside the semicircle or not.
* (if you want to understand more, check the vertex shader source [shader.vert]).
* Shader uses these coordinates to determine if fragments are inside the semicircle or not.
* v2
* /\
* /__\
......@@ -888,9 +898,9 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]), the
* radius and the line width. Shader uses this coordinates to determine if fragments are
* inside the semicircle or not.
* (if you want to understand more, check the vertex shader source [shader.vert]), the
* radius and the line width. Shader uses these coordinates to determine if fragments are
* inside the semicircle or not.
* v2
* /\
* /__\
......@@ -968,12 +978,6 @@ void OPENGL_GAL::initGlew()
}
void OPENGL_GAL::initCursor( int aCursorSize )
{
cursorSize = aCursorSize;
}
void OPENGL_GAL::blitCursor()
{
if( !isCursorEnabled )
......@@ -981,11 +985,9 @@ void OPENGL_GAL::blitCursor()
compositor.SetBuffer( OPENGL_COMPOSITOR::DIRECT_RENDERING );
VECTOR2D cursorBegin = ToWorld( cursorPosition -
VECTOR2D( cursorSize / 2, cursorSize / 2 ) );
VECTOR2D cursorEnd = ToWorld( cursorPosition +
VECTOR2D( cursorSize / 2, cursorSize / 2 ) );
VECTOR2D cursorCenter = ( cursorBegin + cursorEnd ) / 2.0;
VECTOR2D cursorBegin = cursorPosition - cursorSize / ( 2 * worldScale );
VECTOR2D cursorEnd = cursorPosition + cursorSize / ( 2 * worldScale );
VECTOR2D cursorCenter = ( cursorBegin + cursorEnd ) / 2;
glDisable( GL_TEXTURE_2D );
glLineWidth( 1.0 );
......
This diff is collapsed.
......@@ -59,7 +59,7 @@ RENDER_SETTINGS::~RENDER_SETTINGS()
void RENDER_SETTINGS::update()
{
m_hiContrastColor = COLOR4D( m_hiContrastFactor, m_hiContrastFactor, m_highlightFactor,
m_hiContrastColor = COLOR4D( m_hiContrastFactor, m_hiContrastFactor, m_hiContrastFactor,
m_layerOpacity );
}
......
......@@ -26,6 +26,7 @@
#include <tool/tool_manager.h>
#include <tool/tool_event.h>
#include <tool/tool_action.h>
#include <boost/foreach.hpp>
#include <cassert>
ACTION_MANAGER::ACTION_MANAGER( TOOL_MANAGER* aToolManager ) :
......@@ -43,7 +44,12 @@ ACTION_MANAGER::~ACTION_MANAGER()
void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
{
assert( aAction->GetId() == -1 ); // Check if the TOOL_ACTION was not registered before
// Check if the TOOL_ACTION was not registered before
assert( aAction->GetId() == -1 );
// TOOL_ACTIONs are supposed to be named [appName.]toolName.actionName (with dots between)
// action name without specifying at least toolName is not valid
assert( aAction->GetName().find( '.', 0 ) != std::string::npos );
assert( m_actionNameIndex.find( aAction->m_name ) == m_actionNameIndex.end() );
assert( m_actionIdIndex.find( aAction->m_id ) == m_actionIdIndex.end() );
......@@ -53,15 +59,7 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
m_actionIdIndex[aAction->m_id] = aAction;
if( aAction->HasHotKey() )
{
// Duplication of hot keys leads to unexpected behaviour
// The right way to change a hotkey is to use ACTION_MANAGER::ClearHotKey() first
assert( m_actionHotKeys.find( aAction->m_currentHotKey ) == m_actionHotKeys.end() );
m_actionHotKeys[aAction->m_currentHotKey] = aAction;
}
aAction->setActionMgr( this );
m_actionHotKeys[aAction->m_currentHotKey].push_back( aAction );
}
......@@ -71,11 +69,18 @@ void ACTION_MANAGER::UnregisterAction( TOOL_ACTION* aAction )
m_actionIdIndex.erase( aAction->m_id );
// Indicate that the ACTION_MANAGER no longer care about the object
aAction->setActionMgr( NULL );
aAction->setId( -1 );
if( aAction->HasHotKey() )
m_actionHotKeys.erase( aAction->m_currentHotKey );
{
std::list<TOOL_ACTION*>& actions = m_actionHotKeys[aAction->m_currentHotKey];
std::list<TOOL_ACTION*>::iterator action = std::find( actions.begin(), actions.end(), aAction );
if( action != actions.end() )
actions.erase( action );
else
assert( false );
}
}
......@@ -94,34 +99,80 @@ bool ACTION_MANAGER::RunAction( const std::string& aActionName ) const
if( it == m_actionNameIndex.end() )
return false; // no action with given name found
runAction( it->second );
RunAction( it->second );
return true;
}
void ACTION_MANAGER::RunAction( const TOOL_ACTION* aAction ) const
{
TOOL_EVENT event = aAction->MakeEvent();
m_toolMgr->ProcessEvent( event );
}
bool ACTION_MANAGER::RunHotKey( int aHotKey ) const
{
std::map<int, TOOL_ACTION*>::const_iterator it = m_actionHotKeys.find( aHotKey );
int key = std::toupper( aHotKey & ~MD_MODIFIER_MASK );
int mod = aHotKey & MD_MODIFIER_MASK;
HOTKEY_LIST::const_iterator it = m_actionHotKeys.find( key | mod );
// If no luck, try without modifier, to handle keys that require a modifier
// e.g. to get ? you need to press Shift+/ without US keyboard layout
// Hardcoding ? as Shift+/ is a bad idea, as on another layout you may need to press a
// different combination
if( it == m_actionHotKeys.end() )
return false; // no appropriate action found for the hotkey
{
it = m_actionHotKeys.find( key );
runAction( it->second );
if( it == m_actionHotKeys.end() )
return false; // no appropriate action found for the hotkey
}
return true;
}
const std::list<TOOL_ACTION*>& actions = it->second;
// Choose the action that has the highest priority on the active tools stack
// If there is none, run the global action associated with the hot key
int highestPriority = -1, priority = -1;
const TOOL_ACTION* context = NULL; // pointer to context action of the highest priority tool
const TOOL_ACTION* global = NULL; // pointer to global action, if there is no context action
void ACTION_MANAGER::ClearHotKey( int aHotKey )
{
m_actionHotKeys.erase( aHotKey );
}
BOOST_FOREACH( const TOOL_ACTION* action, actions )
{
if( action->GetScope() == AS_GLOBAL )
{
// Store the global action for the hot key in case there was no possible
// context actions to run
assert( global == NULL ); // there should be only one global action per hot key
global = action;
continue;
}
TOOL_BASE* tool = m_toolMgr->FindTool( action->GetToolName() );
if( tool )
{
priority = m_toolMgr->GetPriority( tool->GetId() );
if( priority >= 0 && priority > highestPriority )
{
highestPriority = priority;
context = action;
}
}
}
if( !global && !context ) // currently there is no valid action to run
return false;
void ACTION_MANAGER::runAction( const TOOL_ACTION* aAction ) const
{
TOOL_EVENT event = aAction->MakeEvent();
if( context )
RunAction( context );
else if( global )
RunAction( global );
m_toolMgr->ProcessEvent( event );
return true;
}
......@@ -27,18 +27,16 @@
#include <tool/tool_manager.h>
#include <tool/tool_dispatcher.h>
#include <tools/common_actions.h>
#include <view/view.h>
#include <view/wx_view_controls.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <pcbnew_id.h>
#include <boost/optional.hpp>
#include <boost/foreach.hpp>
using boost::optional;
///> Stores information about a mouse button state
struct TOOL_DISPATCHER::BUTTON_STATE
{
......@@ -128,7 +126,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
{
BUTTON_STATE* st = m_buttons[aIndex];
wxEventType type = aEvent.GetEventType();
optional<TOOL_EVENT> evt;
boost::optional<TOOL_EVENT> evt;
bool isClick = false;
bool up = type == st->upEvent;
......@@ -207,7 +205,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
{
bool motion = false, buttonEvents = false;
optional<TOOL_EVENT> evt;
boost::optional<TOOL_EVENT> evt;
int type = aEvent.GetEventType();
......@@ -221,6 +219,9 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
// but changes in world coordinates (e.g. autopanning)
type == KIGFX::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
{
wxMouseEvent* me = static_cast<wxMouseEvent*>( &aEvent );
int mods = decodeModifiers<wxMouseEvent>( me );
VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetMousePosition();
VECTOR2D pos = getView()->ToWorld( screenPos );
......@@ -228,6 +229,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
{
motion = true;
m_lastMousePos = pos;
m_editFrame->UpdateStatusBar();
}
for( unsigned int i = 0; i < m_buttons.size(); i++ )
......@@ -235,29 +237,38 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
if( !buttonEvents && motion )
{
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION );
evt = TOOL_EVENT( TC_MOUSE, TA_MOUSE_MOTION, mods );
evt->SetMousePosition( pos );
}
}
// Keyboard handling
else if( type == wxEVT_KEY_UP || type == wxEVT_KEY_DOWN )
else if( type == wxEVT_CHAR )
{
wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
int key = ke->GetKeyCode();
int mods = decodeModifiers<wxKeyEvent>( ke );
if( type == wxEVT_KEY_UP )
if( mods & MD_CTRL )
{
if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL );
else
evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_UP, key | mods );
#if !wxCHECK_VERSION( 2, 9, 0 )
// I really look forward to the day when we will use only one version of wxWidgets..
const int WXK_CONTROL_A = 1;
const int WXK_CONTROL_Z = 26;
#endif
// wxWidgets have a quirk related to Ctrl+letter hot keys handled by CHAR_EVT
// http://docs.wxwidgets.org/trunk/classwx_key_event.html:
// "char events for ASCII letters in this case carry codes corresponding to the ASCII
// value of Ctrl-Latter, i.e. 1 for Ctrl-A, 2 for Ctrl-B and so on until 26 for Ctrl-Z."
if( key >= WXK_CONTROL_A && key <= WXK_CONTROL_Z )
key += 'A' - 1;
}
if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
evt = TOOL_EVENT( TC_COMMAND, TA_CANCEL_TOOL );
else
{
evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_DOWN, key | mods );
}
evt = TOOL_EVENT( TC_KEYBOARD, TA_KEY_PRESSED, key | mods );
}
if( evt )
......@@ -268,21 +279,29 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
}
void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent )
void TOOL_DISPATCHER::DispatchWxCommand( wxCommandEvent& aEvent )
{
bool activateTool = false;
std::string toolName;
boost::optional<TOOL_EVENT> evt;
// fixme: use TOOL_ACTIONs here
switch( aEvent.GetId() )
{
case ID_PNS_ROUTER_TOOL:
toolName = "pcbnew.InteractiveRouter";
activateTool = true;
case ID_ZOOM_IN: // toolbar button "Zoom In"
evt = COMMON_ACTIONS::zoomInCenter.MakeEvent();
break;
case ID_ZOOM_OUT: // toolbar button "Zoom In"
evt = COMMON_ACTIONS::zoomOutCenter.MakeEvent();
break;
case ID_ZOOM_PAGE: // toolbar button "Fit on Screen"
evt = COMMON_ACTIONS::zoomFitScreen.MakeEvent();
break;
default:
aEvent.Skip();
break;
}
// do nothing if the legacy view is active
if( activateTool && m_editFrame->IsGalCanvasActive() )
m_toolMgr->InvokeTool( toolName );
if( evt )
m_toolMgr->ProcessEvent( *evt );
}
......@@ -81,8 +81,7 @@ const std::string TOOL_EVENT::Format() const
{ TA_MOUSE_DRAG, "drag" },
{ TA_MOUSE_MOTION, "motion" },
{ TA_MOUSE_WHEEL, "wheel" },
{ TA_KEY_UP, "key-up" },
{ TA_KEY_DOWN, "key-down" },
{ TA_KEY_PRESSED, "key-pressed" },
{ TA_VIEW_REFRESH, "view-refresh" },
{ TA_VIEW_ZOOM, "view-zoom" },
{ TA_VIEW_PAN, "view-pan" },
......
......@@ -46,6 +46,12 @@ TOOL_INTERACTIVE::~TOOL_INTERACTIVE()
}
void TOOL_INTERACTIVE::Activate()
{
m_toolMgr->InvokeTool( m_toolId );
}
OPT_TOOL_EVENT TOOL_INTERACTIVE::Wait( const TOOL_EVENT_LIST& aEventList )
{
return m_toolMgr->ScheduleWait( this, aEventList );
......
......@@ -44,7 +44,7 @@
#include <wxPcbStruct.h>
#include <confirm.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
using boost::optional;
......@@ -103,6 +103,14 @@ TOOL_MANAGER::TOOL_MANAGER() :
TOOL_MANAGER::~TOOL_MANAGER()
{
DeleteAll();
delete m_actionMgr;
}
void TOOL_MANAGER::DeleteAll()
{
std::map<TOOL_BASE*, TOOL_STATE*>::iterator it, it_end;
......@@ -113,7 +121,7 @@ TOOL_MANAGER::~TOOL_MANAGER()
delete it->first; // delete the tool itself
}
delete m_actionMgr;
m_toolState.clear();
}
......@@ -196,6 +204,12 @@ bool TOOL_MANAGER::RunAction( const std::string& aActionName )
}
void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction )
{
m_actionMgr->RunAction( &aAction );
}
bool TOOL_MANAGER::invokeTool( TOOL_BASE* aTool )
{
wxASSERT( aTool != NULL );
......@@ -239,9 +253,15 @@ bool TOOL_MANAGER::runTool( TOOL_BASE* aTool )
return false;
}
// If the tool is already active, do not invoke it again
// If the tool is already active, bring it to the top of the active tools stack
if( isActive( aTool ) )
{
m_activeTools.erase( std::find( m_activeTools.begin(), m_activeTools.end(),
aTool->GetId() ) );
m_activeTools.push_front( aTool->GetId() );
return false;
}
aTool->Reset( TOOL_INTERACTIVE::RUN );
......@@ -281,6 +301,25 @@ void TOOL_MANAGER::ResetTools( TOOL_BASE::RESET_REASON aReason )
}
int TOOL_MANAGER::GetPriority( int aToolId ) const
{
int priority = 0;
for( std::deque<int>::const_iterator it = m_activeTools.begin(),
itEnd = m_activeTools.end(); it != itEnd; ++it )
{
std::cout << FindTool( *it )->GetName() << std::endl;
if( *it == aToolId )
return priority;
++priority;
}
return -1;
}
void TOOL_MANAGER::ScheduleNextState( TOOL_BASE* aTool, TOOL_STATE_FUNC& aHandler,
const TOOL_EVENT_LIST& aConditions )
{
......@@ -378,7 +417,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent )
{
if( aEvent.Action() == TA_KEY_UP )
if( aEvent.Action() == TA_KEY_PRESSED )
{
// Check if there is a hotkey associated
if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
......
This diff is collapsed.
......@@ -31,25 +31,12 @@ using namespace KIGFX;
void VIEW_ITEM::ViewSetVisible( bool aIsVisible )
{
bool update = false;
if( m_visible != aIsVisible )
update = true;
m_visible = aIsVisible;
// update only if the visibility has really changed
if( update )
if( m_visible != aIsVisible )
{
m_visible = aIsVisible;
ViewUpdate( APPEARANCE );
}
void VIEW_ITEM::ViewUpdate( int aUpdateFlags )
{
if( !m_view )
return;
m_view->InvalidateItem( this, aUpdateFlags );
}
}
......
......@@ -35,9 +35,7 @@ using namespace KIGFX;
const wxEventType WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE = wxNewEventType();
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxWindow* aParentPanel ) :
VIEW_CONTROLS( aView ),
m_state( IDLE ),
m_parentPanel( aParentPanel )
VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel )
{
m_parentPanel->Connect( wxEVT_MOTION,
wxMouseEventHandler( WX_VIEW_CONTROLS::onMotion ), NULL, this );
......@@ -68,13 +66,44 @@ void VIEW_CONTROLS::ShowCursor( bool aEnabled )
}
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
void VIEW_CONTROLS::setCenter( const VECTOR2D& aCenter )
{
m_mousePosition.x = aEvent.GetX();
m_mousePosition.y = aEvent.GetY();
if( !m_panBoundary.Contains( aCenter ) )
{
VECTOR2D newCenter( aCenter );
if( aCenter.x < m_panBoundary.GetLeft() )
newCenter.x = m_panBoundary.GetLeft();
else if( aCenter.x > m_panBoundary.GetRight() )
newCenter.x = m_panBoundary.GetRight();
if( aCenter.y < m_panBoundary.GetTop() )
newCenter.y = m_panBoundary.GetTop();
else if( aCenter.y > m_panBoundary.GetBottom() )
newCenter.y = m_panBoundary.GetBottom();
m_view->SetCenter( newCenter );
}
else
{
m_view->SetCenter( aCenter );
}
}
updateCursor();
void VIEW_CONTROLS::setScale( double aScale, const VECTOR2D& aAnchor )
{
if( aScale < m_minScale )
aScale = m_minScale;
else if( aScale > m_maxScale )
aScale = m_maxScale;
m_view->SetScale( aScale, aAnchor );
}
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
bool isAutoPanning = false;
if( m_autoPanEnabled )
......@@ -84,10 +113,10 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
if( m_state == DRAG_PANNING )
{
VECTOR2D d = m_dragStartPoint - m_mousePosition;
VECTOR2D d = m_dragStartPoint - VECTOR2D( aEvent.GetX(), aEvent.GetY() );
VECTOR2D delta = m_view->ToWorld( d, false );
m_view->SetCenter( m_lookStartPoint + delta );
setCenter( m_lookStartPoint + delta );
aEvent.StopPropagation();
}
else
......@@ -117,7 +146,7 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
VECTOR2D delta( aEvent.ControlDown() ? -scrollSpeed : 0.0,
aEvent.ShiftDown() ? -scrollSpeed : 0.0 );
m_view->SetCenter( m_view->GetCenter() + delta );
setCenter( m_view->GetCenter() + delta );
}
else
{
......@@ -140,7 +169,7 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
}
VECTOR2D anchor = m_view->ToWorld( VECTOR2D( aEvent.GetX(), aEvent.GetY() ) );
m_view->SetScale( m_view->GetScale() * zoomScale, anchor );
setScale( m_view->GetScale() * zoomScale, anchor );
}
aEvent.Skip();
......@@ -197,9 +226,7 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
dir = dir.Resize( borderSize );
dir = m_view->ToWorld( dir, false );
m_view->SetCenter( m_view->GetCenter() + dir * m_autoPanSpeed );
updateCursor();
setCenter( m_view->GetCenter() + dir * m_autoPanSpeed );
// Notify tools that the cursor position has changed in the world coordinates
wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
......@@ -238,7 +265,7 @@ void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
}
const VECTOR2D WX_VIEW_CONTROLS::GetMousePosition() const
VECTOR2D WX_VIEW_CONTROLS::GetMousePosition() const
{
wxPoint msp = wxGetMousePosition();
wxPoint winp = m_parentPanel->GetScreenPosition();
......@@ -247,6 +274,22 @@ const VECTOR2D WX_VIEW_CONTROLS::GetMousePosition() const
}
VECTOR2D WX_VIEW_CONTROLS::GetCursorPosition() const
{
if( m_forceCursorPosition )
return m_forcedPosition;
else
{
VECTOR2D mousePosition = GetMousePosition();
if( m_snappingEnabled )
return m_view->GetGAL()->GetGridPoint( m_view->ToWorld( mousePosition ) );
else
return m_view->ToWorld( mousePosition );
}
}
bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
{
VECTOR2D p( aEvent.GetX(), aEvent.GetY() );
......@@ -257,17 +300,19 @@ bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
double borderEndX = m_view->GetScreenPixelSize().x - borderStart;
double borderEndY = m_view->GetScreenPixelSize().y - borderStart;
m_panDirection = VECTOR2D();
if( p.x < borderStart )
m_panDirection.x = -( borderStart - p.x );
else if( p.x > borderEndX )
m_panDirection.x = ( p.x - borderEndX );
else
m_panDirection.x = 0;
if( p.y < borderStart )
m_panDirection.y = -( borderStart - p.y );
else if( p.y > borderEndY )
m_panDirection.y = ( p.y - borderEndY );
else
m_panDirection.y = 0;
bool borderHit = ( m_panDirection.x != 0 || m_panDirection.y != 0 );
......@@ -304,14 +349,3 @@ bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
wxASSERT_MSG( false, wxT( "This line should never be reached" ) );
return false; // Should not be reached, just avoid the compiler warnings..
}
void WX_VIEW_CONTROLS::updateCursor()
{
if( m_forceCursorPosition )
m_cursorPosition = m_view->ToScreen( m_forcedPosition );
else if( m_snappingEnabled )
m_cursorPosition = m_view->GetGAL()->GetGridPoint( m_mousePosition );
else
m_cursorPosition = m_mousePosition;
}
......@@ -189,7 +189,7 @@ void WORKSHEET_VIEWITEM::draw( const WS_DRAW_ITEM_TEXT* aItem, GAL* aGal ) const
aGal->SetStrokeColor( COLOR4D( aItem->GetColor() ) );
aGal->SetLineWidth( aItem->GetThickness() );
aGal->SetTextAttributes( aItem );
aGal->StrokeText( std::wstring( aItem->GetText().wc_str() ), position, 0.0 );
aGal->StrokeText( aItem->GetText(), position, 0.0 );
}
......
......@@ -33,7 +33,7 @@
#include <fctsys.h>
#include <id.h>
#include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <gal/graphics_abstraction_layer.h>
#include <view/view.h>
#include <class_base_screen.h>
......@@ -194,21 +194,19 @@ void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event )
RedrawScreen( center, true );
}
if( IsGalCanvasActive() )
{
// Apply computed view settings to GAL
KIGFX::VIEW* view = GetGalCanvas()->GetView();
KIGFX::GAL* gal = GetGalCanvas()->GetGAL();
UpdateStatusBar();
}
double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor();
double zoom = 1.0 / ( zoomFactor * GetZoom() );
view->SetScale( zoom );
view->SetCenter( VECTOR2D( center ) );
GetGalCanvas()->Refresh();
}
void EDA_DRAW_FRAME::SetNextZoom()
{
GetScreen()->SetNextZoom();
}
UpdateStatusBar();
void EDA_DRAW_FRAME::SetPrevZoom()
{
GetScreen()->SetPreviousZoom();
}
......
......@@ -31,7 +31,7 @@
#include <pgm_base.h>
#include <common.h>
#include <class_drawpanel.h>
#include <class_drawpanel_gal.h>
#include <class_draw_panel_gal.h>
#include <confirm.h>
#include <macros.h>
#include <bitmaps.h>
......
......@@ -271,9 +271,7 @@ void SCH_EDIT_FRAME::Process_Config( wxCommandEvent& event )
void SCH_EDIT_FRAME::OnSetOptions( wxCommandEvent& event )
{
wxArrayString units;
GRIDS grid_list;
GetScreen()->GetGrids( grid_list );
GRIDS grid_list = GetScreen()->GetGrids();
DIALOG_EESCHEMA_OPTIONS dlg( this );
......
......@@ -65,7 +65,7 @@ public:
};
typedef std::vector< GRID_TYPE > GRIDS;
typedef std::vector<GRID_TYPE> GRIDS;
/**
......@@ -445,11 +445,12 @@ public:
/**
* Function GetGrids().
* Copy the grid list to \a aList.
*
* @param aList - List to copy to.
* Returns the current list of grids.
*/
void GetGrids( GRIDS& aList );
const GRIDS& GetGrids() const
{
return m_grids;
}
/**
* Function GetClass
......
......@@ -33,8 +33,6 @@
#include <base_struct.h>
#include <gr_basic.h>
#include <boost/ptr_container/ptr_vector.hpp>
#include <gr_basic.h>
#include <layers_id_colors_and_visibility.h>
/// Abbrevation for fomatting internal units to a string.
......
......@@ -23,7 +23,7 @@
*/
/**
* @file class_drawpanel_gal.h:
* @file class_draw_panel_gal.h:
* @brief EDA_DRAW_PANEL_GAL class definition.
*/
......
......@@ -13,7 +13,6 @@ class MARKER_BASE
public:
wxPoint m_Pos; ///< position of the marker
protected:
std::vector <wxPoint> m_Corners; ///< Corner list for shape definition (a polygon)
int m_MarkerType; ///< Can be used as a flag
EDA_COLOR_T m_Color; ///< color
EDA_RECT m_ShapeBoundingBox; ///< Bounding box of the graphic symbol, relative
......
......@@ -353,6 +353,18 @@ public:
*/
wxPoint GetGridPosition( const wxPoint& aPosition ) const;
/**
* Function SetNextGrid()
* changes the grid size settings to the next one available.
*/
virtual void SetNextGrid();
/**
* Function SetPrevGrid()
* changes the grid size settings to the previous one available.
*/
virtual void SetPrevGrid();
/**
* Command event handler for selecting grid sizes.
*
......@@ -410,6 +422,18 @@ public:
virtual void OnZoom( wxCommandEvent& event );
/**
* Function SetNextZoom()
* changes the zoom to the next one available.
*/
void SetNextZoom();
/**
* Function SetPrevZoom()
* changes the zoom to the previous one available.
*/
void SetPrevZoom();
/**
* Function RedrawScreen
* redraws the entire screen area by updating the scroll bars and mouse pointer in
......
......@@ -164,7 +164,7 @@ public:
// --------------
/// @copydoc GAL::Transform()
virtual void Transform( MATRIX3x3D aTransformation );
virtual void Transform( const MATRIX3x3D& aTransformation );
/// @copydoc GAL::Rotate()
virtual void Rotate( double aAngle );
......@@ -283,8 +283,6 @@ private:
wxPoint savedCursorPosition; ///< The last cursor position
wxBitmap* cursorPixels; ///< Cursor pixels
wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels
int cursorSize; ///< Cursor size
VECTOR2D cursorPosition; ///< Current cursor position
/// Maximum number of arguments for one command
static const int MAX_CAIRO_ARGUMENTS = 6;
......@@ -354,8 +352,10 @@ private:
*/
void skipMouseEvent( wxMouseEvent& aEvent );
/// @copydoc GAL::initCursor()
virtual void initCursor( int aCursorSize );
/**
* @brief Prepares cursor bitmap.
*/
virtual void initCursor();
/**
* @brief Blits cursor into the current screen.
......@@ -386,6 +386,9 @@ private:
/// Format used to store pixels
static const cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
///> Opacity of a single layer
static const float LAYER_ALPHA = 0.8;
};
} // namespace KIGFX
......
......@@ -31,8 +31,6 @@
#include <stack>
#include <limits>
#include <wx/event.h>
#include <math/matrix3x3.h>
#include <gal/color4d.h>
......@@ -162,7 +160,7 @@ public:
virtual bool Show( bool aShow ) = 0;
/// @brief Returns GAL canvas size in pixels
VECTOR2D GetScreenPixelSize() const
const VECTOR2I& GetScreenPixelSize() const
{
return screenSize;
}
......@@ -222,7 +220,7 @@ public:
*
* @return the color for stroking the outline.
*/
inline COLOR4D GetStrokeColor()
inline const COLOR4D& GetStrokeColor() const
{
return strokeColor;
}
......@@ -252,7 +250,7 @@ public:
*
* @return the actual line width.
*/
inline double GetLineWidth()
inline double GetLineWidth() const
{
return lineWidth;
}
......@@ -335,7 +333,7 @@ public:
*
* @param aTransformation is the ransformation matrix.
*/
virtual void Transform( MATRIX3x3D aTransformation ) = 0;
virtual void Transform( const MATRIX3x3D& aTransformation ) = 0;
/**
* @brief Rotate the context.
......@@ -428,11 +426,21 @@ public:
*
* @return the transformation matrix.
*/
MATRIX3x3D GetWorldScreenMatrix()
const MATRIX3x3D& GetWorldScreenMatrix() const
{
return worldScreenMatrix;
}
/**
* @brief Get the screen <-> world transformation matrix.
*
* @return the transformation matrix.
*/
const MATRIX3x3D& GetScreenWorldMatrix() const
{
return screenWorldMatrix;
}
/**
* @brief Set the world <-> screen transformation matrix.
*
......@@ -487,7 +495,7 @@ public:
*
* @return the look at point.
*/
inline VECTOR2D GetLookAtPoint()
inline const VECTOR2D& GetLookAtPoint() const
{
return lookAtPoint;
}
......@@ -507,7 +515,7 @@ public:
*
* @return the zoom factor.
*/
inline double GetZoomFactor()
inline double GetZoomFactor() const
{
return zoomFactor;
}
......@@ -528,7 +536,7 @@ public:
/**
* @brief Returns the minimum depth in the currently used range (the top).
*/
inline double GetMinDepth()
inline double GetMinDepth() const
{
return depthRange.x;
}
......@@ -536,7 +544,7 @@ public:
/**
* @brief Returns the maximum depth in the currently used range (the bottom).
*/
inline double GetMaxDepth()
inline double GetMaxDepth() const
{
return depthRange.y;
}
......@@ -546,7 +554,7 @@ public:
*
* @return the actual world scale factor.
*/
inline double GetWorldScale()
inline double GetWorldScale() const
{
return worldScale;
}
......@@ -694,7 +702,7 @@ public:
*
* @return the grid line width
*/
inline double GetGridLineWidth()
inline double GetGridLineWidth() const
{
return gridLineWidth;
}
......@@ -709,19 +717,17 @@ public:
gridLineWidth = aGridLineWidth;
}
/// @brief Draw the grid
///> @brief Draw the grid
void DrawGrid();
/**
* Function GetGridPoint()
* For a given point it returns the nearest point belonging to the grid.
* For a given point it returns the nearest point belonging to the grid in world coordinates.
*
* @param aPoint is the point for which the grid point is searched.
* @return The nearest grid point.
* @return The nearest grid point in world coordinates.
*/
VECTOR2D GetGridPoint( VECTOR2D aPoint ) const;
VECTOR2D GetGridPoint( const VECTOR2D& aPoint ) const;
/**
* @brief Change the grid display style.
......@@ -739,7 +745,7 @@ public:
* @param aPoint the pointposition in screen coordinates.
* @return the point position in world coordinates.
*/
inline virtual VECTOR2D ToWorld( const VECTOR2D& aPoint ) const
inline VECTOR2D ToWorld( const VECTOR2D& aPoint ) const
{
return VECTOR2D( screenWorldMatrix * aPoint );
}
......@@ -750,15 +756,15 @@ public:
* @param aPoint the pointposition in world coordinates.
* @return the point position in screen coordinates.
*/
inline virtual VECTOR2D ToScreen( const VECTOR2D& aPoint ) const
inline VECTOR2D ToScreen( const VECTOR2D& aPoint ) const
{
return VECTOR2D( worldScreenMatrix * aPoint );
}
/**
* @brief Enable/Disable cursor.
* @brief Enable/disable cursor.
*
* @param aIsCursorEnabled is true if the cursor should be enabled, else false.
* @param aCursorEnabled is true if the cursor should be drawn, else false.
*/
inline void SetCursorEnabled( bool aCursorEnabled )
{
......@@ -778,7 +784,7 @@ public:
/**
* @brief Set the cursor size.
*
* @param aCursorSize is the size of the cursor.
* @param aCursorSize is the size of the cursor expressed in pixels.
*/
inline void SetCursorSize( unsigned int aCursorSize )
{
......@@ -821,9 +827,11 @@ public:
/// Depth level on which the grid is drawn
static const int GRID_DEPTH = 1024;
static const double METRIC_UNIT_LENGTH = 1e9;
protected:
std::stack<double> depthStack; ///< Stored depth values
VECTOR2D screenSize; ///< Screen size in screen coordinates
VECTOR2I screenSize; ///< Screen size in screen coordinates
double worldUnitLength; ///< The unit length of the world coordinates [inch]
double screenDPI; ///< The dots per inch of the screen
......@@ -862,7 +870,8 @@ protected:
bool isCursorEnabled; ///< Is the cursor enabled?
COLOR4D cursorColor; ///< Cursor color
int cursorSize; ///< Size of the cursor in pixels
unsigned int cursorSize; ///< Size of the cursor in pixels
VECTOR2D cursorPosition; ///< Current cursor position (world coordinates)
/// Instance of object that stores information about how to draw texts
STROKE_FONT strokeFont;
......@@ -881,13 +890,6 @@ protected:
*/
virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0;
/**
* @brief Initialize the cursor.
*
* @param aCursorSize is the size of the cursor.
*/
virtual void initCursor( int aCursorSize ) = 0;
static const int MIN_DEPTH = -2048;
static const int MAX_DEPTH = 2047;
};
......
......@@ -145,19 +145,12 @@ public:
/// @copydoc GAL::ClearScreen()
virtual void ClearScreen();
// -----------------
// Attribute setting
// -----------------
/// @copydoc GAL::SetStrokeColor()
virtual void SetStrokeColor( const COLOR4D& aColor );
// --------------
// Transformation
// --------------
/// @copydoc GAL::Transform()
virtual void Transform( MATRIX3x3D aTransformation );
virtual void Transform( const MATRIX3x3D& aTransformation );
/// @copydoc GAL::Rotate()
virtual void Rotate( double aAngle );
......@@ -299,8 +292,6 @@ private:
bool isShaderInitialized; ///< Was the shader initialized?
bool isGrouping; ///< Was a group started?
VECTOR2D cursorPosition; ///< Current cursor position
// Polygon tesselation
/// The tessellator
GLUtesselator* tesselator;
......@@ -313,7 +304,7 @@ private:
* @param aStartPoint is the start point of the line.
* @param aEndPoint is the end point of the line.
*/
inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/**
* @brief Draw a semicircle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs
......@@ -364,9 +355,6 @@ private:
/// Initialize GLEW
void initGlew();
/// @copydoc GAL::initCursor()
virtual void initCursor( int aCursorSize );
/**
* @brief Blits cursor into the current screen.
*/
......
......@@ -46,7 +46,8 @@ public:
* to an object the segment belongs to (e.g. a line chain) or references to locally stored
* points (m_a, m_b).
*/
VECTOR2I& A, B;
VECTOR2I& A;
VECTOR2I& B;
/** Default constructor
* Creates an empty (0, 0) segment, locally-referenced
......@@ -203,6 +204,8 @@ public:
bool Collide( const SEG& aSeg, int aClearance ) const;
ecoord SquaredDistance( const SEG& aSeg ) const;
/**
* Function Distance()
*
......@@ -210,14 +213,16 @@ public:
* @param aSeg other segment
* @return minimum distance
*/
ecoord SquaredDistance( const SEG& aSeg ) const;
int Distance( const SEG& aSeg ) const
{
return sqrt( SquaredDistance( aSeg ) );
}
ecoord SquaredDistance( const VECTOR2I& aP ) const
{
return ( NearestPoint( aP ) - aP ).SquaredEuclideanNorm();
}
/**
* Function Distance()
*
......@@ -225,11 +230,6 @@ public:
* @param aP the point
* @return minimum distance
*/
ecoord SquaredDistance( const VECTOR2I& aP ) const
{
return ( NearestPoint( aP ) - aP ).SquaredEuclideanNorm();
}
int Distance( const VECTOR2I& aP ) const
{
return sqrt( SquaredDistance( aP ) );
......@@ -244,14 +244,14 @@ public:
*/
bool Collinear( const SEG& aSeg ) const
{
ecoord qa1 = A.y - B.y;
ecoord qb1 = B.x - A.x;
ecoord qc1 = -qa1 * A.x - qb1 * A.y;
ecoord qa2 = aSeg.A.y - aSeg.B.y;
ecoord qb2 = aSeg.B.x - aSeg.A.x;
ecoord qc2 = -qa2 * aSeg.A.x - qb2 * aSeg.A.y;
return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 );
ecoord qa = A.y - B.y;
ecoord qb = B.x - A.x;
ecoord qc = -qa * A.x - qb * A.y;
ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc );
ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc );
return ( d1 <= 1 && d2 <= 1 );
}
/**
......
......@@ -415,7 +415,7 @@ public:
* @param aP the point to be looked for
* @return index of the correspoinding point in the line chain or negative when not found.
*/
int Find ( const VECTOR2I& aP ) const;
int Find( const VECTOR2I& aP ) const;
/**
* Function Slice()
......
......@@ -246,6 +246,7 @@ enum PCB_VISIBLE
PADS_HOLES_VISIBLE,
VIAS_HOLES_VISIBLE,
DRC_VISIBLE, ///< drc markers
WORKSHEET, ///< worksheet frame
GP_OVERLAY, ///< general purpose overlay
......
......@@ -28,24 +28,9 @@
#define __BOX2_H
#include <math/vector2d.h>
#include <limits>
template <class Vec>
class BOX2_TRAITS
{
};
template <>
class BOX2_TRAITS<VECTOR2I>
{
public:
enum
{
c_max_size = INT_MAX - 1,
c_min_coord_value = INT_MIN / 2 + 1
};
};
/**
* Class BOX2
* handles a 2-D bounding box, built on top of an origin point
......@@ -59,8 +44,9 @@ private:
Vec m_Size; // Rectangle Size
public:
typedef typename Vec::coord_type coord_type;
typedef typename Vec::extended_type ecoord_type;
typedef typename Vec::coord_type coord_type;
typedef typename Vec::extended_type ecoord_type;
typedef typename std::numeric_limits<coord_type> coord_limits;
BOX2() {};
......@@ -73,8 +59,8 @@ public:
void SetMaximum()
{
m_Pos.x = m_Pos.y = BOX2_TRAITS<Vec>().c_min_coord_value;
m_Size.x = m_Size.y = BOX2_TRAITS<Vec>().c_max_size;
m_Pos.x = m_Pos.y = coord_limits::min() / 2 + coord_limits::epsilon();
m_Size.x = m_Size.y = coord_limits::max() - coord_limits::epsilon();
}
Vec Centre() const
......
......@@ -109,6 +109,26 @@ public:
return ( m_activeLayers.count( aLayerId ) > 0 );
}
/**
* Function GetHighlight
* Returns current highlight setting.
* @return True if highlight is enabled, false otherwise.
*/
bool GetHighlight() const
{
return m_highlightEnabled;
}
/**
* Function GetHighlightNetCode
* Returns netcode of currently highlighted net.
* @return Netcode of currently highlighted net.
*/
int GetHighlightNetCode() const
{
return m_highlightNetcode;
}
/**
* Function SetHighlight
* Turns on/off highlighting - it may be done for the active layer or the specified net.
......@@ -119,9 +139,7 @@ public:
inline void SetHighlight( bool aEnabled, int aNetcode = -1 )
{
m_highlightEnabled = aEnabled;
if( aNetcode > 0 )
m_highlightNetcode = aNetcode;
m_highlightNetcode = aNetcode;
}
/**
......
......@@ -25,6 +25,7 @@
#ifndef ACTION_MANAGER_H_
#define ACTION_MANAGER_H_
#include <list>
#include <map>
#include <string>
......@@ -81,6 +82,14 @@ public:
*/
bool RunAction( const std::string& aActionName ) const;
/**
* Function RunAction()
* Prepares an appropriate event and sends it to the destination specified in a TOOL_ACTION
* object.
* @param aAction is the action to be run.
*/
void RunAction( const TOOL_ACTION* aAction ) const;
/**
* Function RunHotKey()
* Runs an action associated with a hotkey (if there is one available).
......@@ -89,13 +98,6 @@ public:
*/
bool RunHotKey( int aHotKey ) const;
/**
* Function ClearHotKey()
* Removes an action associated with a hotkey.
* @param aHotKey is the hotkey to be cleared.
*/
void ClearHotKey( int aHotKey );
private:
///> Tool manager needed to run actions
TOOL_MANAGER* m_toolMgr;
......@@ -107,15 +109,8 @@ private:
std::map<std::string, TOOL_ACTION*> m_actionNameIndex;
///> Map for indexing actions by their hotkeys
std::map<int, TOOL_ACTION*> m_actionHotKeys;
/**
* Function runAction()
* Prepares an appropriate event and sends it to the destination specified in a TOOL_ACTION
* object.
* @param aAction is the action to be run.
*/
void runAction( const TOOL_ACTION* aAction ) const;
typedef std::map<int, std::list<TOOL_ACTION*> > HOTKEY_LIST;
HOTKEY_LIST m_actionHotKeys;
};
#endif /* ACTION_MANAGER_H_ */
......@@ -30,7 +30,7 @@
#include <cassert>
#include <tool/tool_base.h>
#include <tool/action_manager.h>
#include <tool/tool_manager.h>
/**
* Class TOOL_ACTION
......@@ -50,14 +50,14 @@ public:
const std::string& aMenuDesc = std::string( "" ) ) :
m_name( aName ), m_scope( aScope ), m_defaultHotKey( aDefaultHotKey ),
m_currentHotKey( aDefaultHotKey ), m_menuItem( aMenuItem ),
m_menuDescription( aMenuDesc ), m_id( -1 ), m_actionMgr( NULL )
m_menuDescription( aMenuDesc ), m_id( -1 )
{
TOOL_MANAGER::Instance().RegisterAction( this );
}
~TOOL_ACTION()
{
if( m_actionMgr )
m_actionMgr->UnregisterAction( this );
TOOL_MANAGER::Instance().UnregisterAction( this );
}
bool operator==( const TOOL_ACTION& aRhs ) const
......@@ -171,6 +171,21 @@ public:
m_menuDescription = aDescription;
}
TOOL_ACTION_SCOPE GetScope() const
{
return m_scope;
}
/**
* Returns name of the tool associated with the action. It is basically the action name
* stripped of the last part (e.g. for "pcbnew.InteractiveDrawing.drawCircle" it is
* "pcbnew.InteractiveDrawing").
*/
std::string GetToolName() const
{
return m_name.substr( 0, m_name.rfind( '.' ) );
}
private:
friend class ACTION_MANAGER;
......@@ -180,12 +195,6 @@ private:
m_id = aId;
}
/// Assigns ACTION_MANAGER object that handles the TOOL_ACTION.
void setActionMgr( ACTION_MANAGER* aManager )
{
m_actionMgr = aManager;
}
/// Name of the action (convention is: app.[tool.]action.name)
std::string m_name;
......@@ -210,9 +219,6 @@ private:
/// Unique ID for fast matching. Assigned by ACTION_MANAGER.
int m_id;
/// Action manager that handles this TOOL_ACTION.
ACTION_MANAGER* m_actionMgr;
/// Origin of the action
// const TOOL_BASE* m_origin;
......
......@@ -79,7 +79,7 @@ public:
* specified tool).
* @param aEvent is the wxCommandEvent to be processed.
*/
virtual void DispatchWxCommand( const wxCommandEvent& aEvent );
virtual void DispatchWxCommand( wxCommandEvent& aEvent );
private:
///> Number of mouse buttons that is handled in events.
......
......@@ -64,36 +64,35 @@ enum TOOL_ACTIONS
TA_MOUSE_WHEEL = 0x0040,
TA_MOUSE = 0x007f,
TA_KEY_UP = 0x0080,
TA_KEY_DOWN = 0x0100,
TA_KEYBOARD = TA_KEY_UP | TA_KEY_DOWN,
TA_KEY_PRESSED = 0x0080,
TA_KEYBOARD = TA_KEY_PRESSED,
// View related events
TA_VIEW_REFRESH = 0x0200,
TA_VIEW_ZOOM = 0x0400,
TA_VIEW_PAN = 0x0800,
TA_VIEW_DIRTY = 0x1000,
TA_VIEW = 0x1e00,
TA_VIEW_REFRESH = 0x0100,
TA_VIEW_ZOOM = 0x0200,
TA_VIEW_PAN = 0x0400,
TA_VIEW_DIRTY = 0x0800,
TA_VIEW = 0x0f00,
TA_CHANGE_LAYER = 0x2000,
TA_CHANGE_LAYER = 0x1000,
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
// the context menu.
TA_CANCEL_TOOL = 0x4000,
TA_CANCEL_TOOL = 0x2000,
// Context menu update. Issued whenever context menu is open and the user hovers the mouse
// over one of choices. Used in dynamic highligting in disambiguation menu
TA_CONTEXT_MENU_UPDATE = 0x8000,
TA_CONTEXT_MENU_UPDATE = 0x4000,
// Context menu choice. Sent if the user picked something from the context menu or
// closed it without selecting anything.
TA_CONTEXT_MENU_CHOICE = 0x10000,
TA_CONTEXT_MENU_CHOICE = 0x8000,
// This event is sent *before* undo/redo command is performed.
TA_UNDO_REDO = 0x20000,
TA_UNDO_REDO = 0x10000,
// Tool action (allows to control tools)
TA_ACTION = 0x40000,
TA_ACTION = 0x20000,
TA_ANY = 0xffffffff
};
......@@ -189,7 +188,7 @@ public:
m_scope( aScope ),
m_mouseButtons( 0 )
{
if( aCategory == TC_COMMAND )
if( aCategory == TC_COMMAND || aCategory == TC_MESSAGE )
m_commandStr = aExtraParam;
}
......@@ -207,7 +206,7 @@ public:
///> Returns information about difference between current mouse cursor position and the place
///> where dragging has started.
const VECTOR2D Delta() const
const VECTOR2D& Delta() const
{
assert( m_category == TC_MOUSE ); // this should be used only with mouse events
return m_mouseDelta;
......@@ -277,14 +276,9 @@ public:
return m_keyCode;
}
bool IsKeyUp() const
bool IsKeyPressed() const
{
return m_actions == TA_KEY_UP;
}
bool IsKeyDown() const
{
return m_actions == TA_KEY_DOWN;
return m_actions == TA_KEY_PRESSED;
}
void SetMouseDragOrigin( const VECTOR2D& aP )
......@@ -317,7 +311,7 @@ public:
if( !( m_actions & aEvent.m_actions ) )
return false;
if( m_category == TC_COMMAND )
if( m_category == TC_COMMAND || m_category == TC_MESSAGE )
{
if( m_commandStr && aEvent.m_commandStr )
return *m_commandStr == *aEvent.m_commandStr;
......
......@@ -48,6 +48,12 @@ public:
TOOL_INTERACTIVE( const std::string& aName );
virtual ~TOOL_INTERACTIVE();
/**
* Function Activate()
* Runs the tool. After activation, the tool starts receiving events until it is finished.
*/
void Activate();
/**
* Function SetContextMenu()
*
......
......@@ -48,9 +48,20 @@ class wxWindow;
class TOOL_MANAGER
{
public:
TOOL_MANAGER();
static TOOL_MANAGER& Instance()
{
static TOOL_MANAGER manager;
return manager;
}
~TOOL_MANAGER();
/**
* Deletes all the tools that were registered in the TOOL_MANAGER.
*/
void DeleteAll();
/**
* Generates an unique ID from for a tool with given name.
*/
......@@ -101,13 +112,21 @@ public:
/**
* Function RunAction()
* Runs the specified action. The common format is "application.ToolName.Action".
* Runs the specified action. The common format for action names is "application.ToolName.Action".
*
* @param aActionName is the name of action to be invoked.
* @return True if the action finished successfully, false otherwise.
*/
bool RunAction( const std::string& aActionName );
/**
* Function RunAction()
* Runs the specified action.
*
* @param aAction is the action to be invoked.
*/
void RunAction( const TOOL_ACTION& aAction );
/**
* Function FindTool()
* Searches for a tool with given ID.
......@@ -167,6 +186,36 @@ public:
return m_editFrame;
}
/**
* Returns id of the tool that is on the top of the active tools stack
* (was invoked the most recently).
* @return Id of the currently used tool.
*/
int GetCurrentToolId() const
{
return m_activeTools.front();
}
/**
* Returns the tool that is on the top of the active tools stack
* (was invoked the most recently).
* @return Pointer to the currently used tool.
*/
TOOL_BASE* GetCurrentTool() const
{
return FindTool( GetCurrentToolId() );
}
/**
* Returns priority of a given tool. Higher number means that the tool is closer to the
* beginning of the active tools queue (i.e. receives events earlier, tools with lower
* priority receive events later).
* @param aToolId is the id of queried tool.
* @return The priority of a given tool. If returned number is negative, then it means that
* the tool id is invalid or the tool is not active.
*/
int GetPriority( int aToolId ) const;
/**
* Defines a state transition - the events that cause a given handler method in the tool
* to be called. Called by TOOL_INTERACTIVE::Go(). May be called from a coroutine context.
......@@ -203,6 +252,8 @@ public:
}
private:
TOOL_MANAGER();
struct TOOL_STATE;
typedef std::pair<TOOL_EVENT_LIST, TOOL_STATE_FUNC> TRANSITION;
......
......@@ -40,111 +40,152 @@
#ifndef _HALF_EDGE_DART_
#define _HALF_EDGE_DART_
#include <ttl/halfedge/hetriang.h>
namespace hed
{
/**
* \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class DART
{
EDGE_PTR m_edge;
namespace hed {
//------------------------------------------------------------------------------------------------
// Dart class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \class Dart
* \brief \b %Dart class for the half-edge data structure.
*
* See \ref api for a detailed description of how the member functions
* should be implemented.
*/
class Dart {
EdgePtr edge_;
bool dir_; // true if dart is counterclockwise in face
/// Dart direction: true if dart is counterclockwise in face
bool m_dir;
public:
public:
/// Default constructor
Dart() { dir_ = true; }
DART()
{
m_dir = true;
}
/// Constructor
Dart(const EdgePtr& edge, bool dir = true) { edge_ = edge; dir_ = dir; }
DART( const EDGE_PTR& aEdge, bool aDir = true )
{
m_edge = aEdge;
m_dir = aDir;
}
/// Copy constructor
Dart(const Dart& dart) { edge_ = dart.edge_; dir_ = dart.dir_; }
DART( const DART& aDart )
{
m_edge = aDart.m_edge;
m_dir = aDart.m_dir;
}
/// Destructor
~Dart() {}
~DART()
{
}
/// Assignment operator
Dart& operator = (const Dart& dart) {
if (this == &dart)
DART& operator=( const DART& aDart )
{
if( this == &aDart )
return *this;
m_edge = aDart.m_edge;
m_dir = aDart.m_dir;
return *this;
edge_ = dart.edge_;
dir_ = dart.dir_;
return *this;
}
/// Comparing dart objects
bool operator==(const Dart& dart) const {
if (dart.edge_ == edge_ && dart.dir_ == dir_)
return true;
return false;
bool operator==( const DART& aDart ) const
{
return ( aDart.m_edge == m_edge && aDart.m_dir == m_dir );
}
/// Comparing dart objects
bool operator!=(const Dart& dart) const {
return !(dart==*this);
bool operator!=( const DART& aDart ) const
{
return !( aDart == *this );
}
/// Maps the dart to a different node
Dart& alpha0() { dir_ = !dir_; return *this; }
DART& Alpha0()
{
m_dir = !m_dir;
return *this;
}
/// Maps the dart to a different edge
Dart& alpha1() {
if (dir_) {
edge_ = edge_->getNextEdgeInFace()->getNextEdgeInFace();
dir_ = false;
}
else {
edge_ = edge_->getNextEdgeInFace();
dir_ = true;
}
return *this;
DART& Alpha1()
{
if( m_dir )
{
m_edge = m_edge->GetNextEdgeInFace()->GetNextEdgeInFace();
m_dir = false;
}
else
{
m_edge = m_edge->GetNextEdgeInFace();
m_dir = true;
}
return *this;
}
/// Maps the dart to a different triangle. \b Note: the dart is not changed if it is at the boundary!
Dart& alpha2() {
if (edge_->getTwinEdge()) {
edge_ = edge_->getTwinEdge();
dir_ = !dir_;
}
// else, the dart is at the boundary and should not be changed
return *this;
DART& Alpha2()
{
if( m_edge->GetTwinEdge() )
{
m_edge = m_edge->GetTwinEdge();
m_dir = !m_dir;
}
// else, the dart is at the boundary and should not be changed
return *this;
}
// Utilities not required by TTL
// -----------------------------
/** @name Utilities not required by TTL */
//@{
void Init( const EDGE_PTR& aEdge, bool aDir = true )
{
m_edge = aEdge;
m_dir = aDir;
}
void init(const EdgePtr& edge, bool dir = true) { edge_ = edge; dir_ = dir; }
double X() const
{
return GetNode()->GetX();
}
double x() const { return getNode()->GetX(); } // x-coordinate of source node
double y() const { return getNode()->GetY(); } // y-coordinate of source node
double Y() const
{
return GetNode()->GetY();
}
bool isCounterClockWise() const { return dir_; }
bool IsCCW() const
{
return m_dir;
}
const NodePtr& getNode() const { return dir_ ? edge_->getSourceNode() : edge_->getTargetNode(); }
const NodePtr& getOppositeNode() const { return dir_ ? edge_->getTargetNode() : edge_->getSourceNode(); }
EdgePtr& getEdge() { return edge_; }
const NODE_PTR& GetNode() const
{
return m_dir ? m_edge->GetSourceNode() : m_edge->GetTargetNode();
}
//@} // End of Utilities not required by TTL
const NODE_PTR& GetOppositeNode() const
{
return m_dir ? m_edge->GetTargetNode() : m_edge->GetSourceNode();
}
};
EDGE_PTR& GetEdge()
{
return m_edge;
}
//@} // End of Utilities not required by TTL
};
}; // End of hed namespace
} // End of hed namespace
#endif
......@@ -40,136 +40,149 @@
#ifndef _HALF_EDGE_TRAITS_
#define _HALF_EDGE_TRAITS_
#include <ttl/halfedge/hetriang.h>
#include <ttl/halfedge/hedart.h>
namespace hed {
//------------------------------------------------------------------------------------------------
// Traits class for the half-edge data structure
//------------------------------------------------------------------------------------------------
/** \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure.
*
* The member functions are those required by different function templates
* in the TTL. Documentation is given here to explain what actions
* should be carried out on the actual data structure as required by the functions
* in the \ref ttl namespace.
*
* The source code of \c %HeTraits.h shows how the traits class is implemented for the
* half-edge data structure.
*
* \see \ref api
*
*/
struct TTLtraits {
namespace hed
{
/**
* \struct TTLtraits
* \brief \b Traits class (static struct) for the half-edge data structure.
*
* The member functions are those required by different function templates
* in the TTL. Documentation is given here to explain what actions
* should be carried out on the actual data structure as required by the functions
* in the \ref ttl namespace.
*
* The source code of \c %HeTraits.h shows how the traits class is implemented for the
* half-edge data structure.
*
* \see \ref api
*/
struct TTLtraits
{
/**
* The floating point type used in calculations involving scalar products and cross products.
*/
typedef double REAL_TYPE;
/** The floating point type used in calculations
* involving scalar products and cross products.
*/
typedef double real_type;
//----------------------------------------------------------------------------------------------
// ------------------------------- Geometric Predicates Group ---------------------------------
//----------------------------------------------------------------------------------------------
/** @name Geometric Predicates */
//@{
//----------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors represented as darts.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static real_type scalarProduct2d(const Dart& v1, const Dart& v2) {
Dart v10 = v1; v10.alpha0();
Dart v20 = v2; v20.alpha0();
return ttl_util::scalarProduct2d(v10.x()-v1.x(), v10.y()-v1.y(),
v20.x()-v2.x(), v20.y()-v2.y());
/**
* Scalar product between two 2D vectors represented as darts.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static REAL_TYPE ScalarProduct2D( const DART& aV1, const DART& aV2 )
{
DART v10 = aV1;
v10.Alpha0();
DART v20 = aV2;
v20.Alpha0();
return ttl_util::ScalarProduct2D( v10.X() - aV1.X(), v10.Y() - aV1.Y(),
v20.X() - aV2.X(), v20.Y() - aV2.Y() );
}
//----------------------------------------------------------------------------------------------
/** Scalar product between two 2D vectors.
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.\n
*
* ttl_util::scalarProduct2d can be used.
*/
static real_type scalarProduct2d(const Dart& v, const NodePtr& p) {
Dart d0 = v; d0.alpha0();
return ttl_util::scalarProduct2d(d0.x() - v.x(), d0.y() - v.y(),
p->GetX() - v.x(), p->GetY() - v.y());
/**
* Scalar product between two 2D vectors.
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.\n
*
* ttl_util::ScalarProduct2D can be used.
*/
static REAL_TYPE ScalarProduct2D( const DART& aV, const NODE_PTR& aP )
{
DART d0 = aV;
d0.Alpha0();
return ttl_util::ScalarProduct2D( d0.X() - aV.X(), d0.Y() - aV.Y(),
aP->GetX() - aV.X(), aP->GetY() - aV.Y() );
}
//----------------------------------------------------------------------------------------------
/** Cross product between two vectors in the plane represented as darts.
* The z-component of the cross product is returned.\n
*
* ttl_util::crossProduct2d can be used.
*/
static real_type crossProduct2d(const Dart& v1, const Dart& v2) {
Dart v10 = v1; v10.alpha0();
Dart v20 = v2; v20.alpha0();
return ttl_util::crossProduct2d(v10.x()-v1.x(), v10.y()-v1.y(),
v20.x()-v2.x(), v20.y()-v2.y());
/**
* Cross product between two vectors in the plane represented as darts.
* The z-component of the cross product is returned.\n
*
* ttl_util::CrossProduct2D can be used.
*/
static REAL_TYPE CrossProduct2D( const DART& aV1, const DART& aV2 )
{
DART v10 = aV1;
v10.Alpha0();
DART v20 = aV2;
v20.Alpha0();
return ttl_util::CrossProduct2D( v10.X() - aV1.X(), v10.Y() - aV1.Y(),
v20.X() - aV2.X(), v20.Y() - aV2.Y() );
}
//----------------------------------------------------------------------------------------------
/** Cross product between two vectors in the plane.
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.
* The z-component of the cross product is returned.\n
*
* ttl_util::crossProduct2d can be used.
*/
static real_type crossProduct2d(const Dart& v, const NodePtr& p) {
Dart d0 = v; d0.alpha0();
return ttl_util::crossProduct2d(d0.x() - v.x(), d0.y() - v.y(),
p->GetX() - v.x(), p->GetY() - v.y());
/**
* Cross product between two vectors in the plane.
* The first vector is represented by a dart \e v, and the second
* vector has direction from the source node of \e v to the point \e p.
* The z-component of the cross product is returned.\n
*
* ttl_util::CrossProduct2d can be used.
*/
static REAL_TYPE CrossProduct2D( const DART& aV, const NODE_PTR& aP )
{
DART d0 = aV;
d0.Alpha0();
return ttl_util::CrossProduct2D( d0.X() - aV.X(), d0.Y() - aV.Y(),
aP->GetX() - aV.X(), aP->GetY() - aV.Y() );
}
//----------------------------------------------------------------------------------------------
/** Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p
* be a point in the plane. Return a positive value if \e n1, \e n2,
* and \e p occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*/
static real_type orient2d(const Dart& n1, const Dart& n2, const NodePtr& p) {
real_type pa[2]; real_type pb[2]; real_type pc[2];
pa[0] = n1.x(); pa[1] = n1.y();
pb[0] = n2.x(); pb[1] = n2.y();
pc[0] = p->GetX(); pc[1] = p->GetY();
return ttl_util::orient2dfast(pa, pb, pc);
/**
* Let \e n1 and \e n2 be the nodes associated with two darts, and let \e p
* be a point in the plane. Return a positive value if \e n1, \e n2,
* and \e p occur in counterclockwise order; a negative value if they occur
* in clockwise order; and zero if they are collinear.
*/
static REAL_TYPE Orient2D( const DART& aN1, const DART& aN2, const NODE_PTR& aP )
{
REAL_TYPE pa[2];
REAL_TYPE pb[2];
REAL_TYPE pc[2];
pa[0] = aN1.X();
pa[1] = aN1.Y();
pb[0] = aN2.X();
pb[1] = aN2.Y();
pc[0] = aP->GetX();
pc[1] = aP->GetY();
return ttl_util::Orient2DFast( pa, pb, pc );
}
//----------------------------------------------------------------------------------------------
/** This is the same predicate as represented with the function above,
* but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart
* represents a point in the plane.
* This function is required for constrained triangulation.
*/
static real_type orient2d(const Dart& n1, const Dart& n2, const Dart& p) {
real_type pa[2]; real_type pb[2]; real_type pc[2];
pa[0] = n1.x(); pa[1] = n1.y();
pb[0] = n2.x(); pb[1] = n2.y();
pc[0] = p.x(); pc[1] = p.y();
return ttl_util::orient2dfast(pa, pb, pc);
/**
* This is the same predicate as represented with the function above,
* but with a slighty different interface:
* The last parameter is given as a dart where the source node of the dart
* represents a point in the plane.
* This function is required for constrained triangulation.
*/
static REAL_TYPE Orient2D( const DART& aN1, const DART& aN2, const DART& aP )
{
REAL_TYPE pa[2];
REAL_TYPE pb[2];
REAL_TYPE pc[2];
pa[0] = aN1.X();
pa[1] = aN1.Y();
pb[0] = aN2.X();
pb[1] = aN2.Y();
pc[0] = aP.X();
pc[1] = aP.Y();
return ttl_util::Orient2DFast( pa, pb, pc );
}
//@} // End of Geometric Predicates Group
};
};
}; // End of hed namespace
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -34,6 +34,7 @@
#include <PolyLine.h>
#include <math_for_graphics.h>
#include <trigo.h>
#include <common.h>
class LINE_READER;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment