int PCBNEW_CONTROL::PanControl( const TOOL_EVENT& aEvent ) { long type = aEvent.Parameter<long>(); KIGFX::VIEW* view = getView(); GRID_HELPER gridHelper( m_frame ); VECTOR2D center = view->GetCenter(); VECTOR2I gridSize = gridHelper.GetGrid() * 10; switch( type ) { case COMMON_ACTIONS::CURSOR_UP: center -= VECTOR2D( 0, gridSize.y ); break; case COMMON_ACTIONS::CURSOR_DOWN: center += VECTOR2D( 0, gridSize.y ); break; case COMMON_ACTIONS::CURSOR_LEFT: center -= VECTOR2D( gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_RIGHT: center += VECTOR2D( gridSize.x, 0 ); break; default: assert( false ); break; } view->SetCenter( center ); return 0; }
void EDA_DRAW_FRAME::UseGalCanvas() { KIGFX::GAL* gal = GetGalCanvas()->GetGAL(); // Set up grid settings gal->SetGridVisibility( IsGridVisible() ); gal->SetGridSize( VECTOR2D( GetScreen()->GetGridSize() ) ); gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) ); // Transfer EDA_DRAW_PANEL settings KIGFX::VIEW_CONTROLS* viewControls = GetGalCanvas()->GetViewControls(); viewControls->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() ); viewControls->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() ); viewControls->EnableAutoPan( m_canvas->GetEnableAutoPan() ); m_canvas->SetEvtHandlerEnabled( false ); GetGalCanvas()->SetEvtHandlerEnabled( true ); GetGalCanvas()->StartDrawing(); // Switch panes // JEY TODO: drop down to a single pane.... m_auimgr.GetPane( "DrawFrame" ).Show( false ); m_auimgr.GetPane( "DrawFrameGal" ).Show( true ); m_auimgr.Update(); // Reset current tool on switch(); SetNoToolSelected(); }
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable ) { KIGFX::VIEW* view = GetGalCanvas()->GetView(); KIGFX::GAL* gal = GetGalCanvas()->GetGAL(); double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); // Display the same view after canvas switching if( aEnable ) { BASE_SCREEN* screen = GetScreen(); // Switch to GAL rendering if( !IsGalCanvasActive() ) { // Set up viewport double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() ); view->SetScale( zoom ); view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); } // Set up grid settings gal->SetGridVisibility( IsGridVisible() ); gal->SetGridSize( VECTOR2D( screen->GetGridSize().x, screen->GetGridSize().y ) ); gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) ); } else { // Switch to standard rendering if( IsGalCanvasActive() ) { // Change view settings only if GAL was active previously double zoom = 1.0 / ( zoomFactor * view->GetScale() ); m_canvas->SetZoom( zoom ); VECTOR2D center = view->GetCenter(); RedrawScreen( wxPoint( center.x, center.y ), false ); } } m_canvas->SetEvtHandlerEnabled( !aEnable ); GetGalCanvas()->SetEvtHandlerEnabled( aEnable ); // Switch panes m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable ); m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable ); m_auimgr.Update(); // Reset current tool on switch(); SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); m_galCanvasActive = aEnable; }
bool SHAPE_ARC::ConstructFromCorners( VECTOR2I aP0, VECTOR2I aP1, double aCenterAngle ) { VECTOR2D mid = ( VECTOR2D( aP0 ) + VECTOR2D( aP1 ) ) * 0.5; VECTOR2D chord = VECTOR2D( aP1 ) - VECTOR2D( aP0 ); double c = (aP1 - aP0).EuclideanNorm() / 2; VECTOR2D d = chord.Rotate( M_PI / 2.0 ).Resize( c ); m_pc = mid + d * ( 1.0 / tan( aCenterAngle / 2.0 * M_PI / 180.0 ) ); m_p0 = aP0; m_p1 = aP1; return true; }
void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable ) { KIGFX::VIEW* view = GetGalCanvas()->GetView(); KIGFX::GAL* gal = GetGalCanvas()->GetGAL(); // Display the same view after canvas switching if( aEnable ) { // Switch to GAL renderer from legacy if( !m_galCanvasActive ) { // Set up viewport double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() ); view->SetScale( zoom ); view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); } // Set up grid settings gal->SetGridVisibility( IsGridVisible() ); gal->SetGridSize( VECTOR2D( GetScreen()->GetGridSize() ) ); gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) ); // Transfer EDA_DRAW_PANEL settings GetGalCanvas()->GetViewControls()->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() ); GetGalCanvas()->GetViewControls()->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() ); GetGalCanvas()->GetViewControls()->EnableAutoPan( m_canvas->GetEnableAutoPan() ); } else if( m_galCanvasActive ) { // Switch to legacy renderer from GAL double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); // TODO replace it with EDA_DRAW_PANEL_GAL::GetLegacyZoom m_canvas->SetZoom( 1.0 / ( zoomFactor * view->GetScale() ) ); VECTOR2D center = view->GetCenter(); AdjustScrollBars( wxPoint( center.x, center.y ) ); } m_canvas->SetEvtHandlerEnabled( !aEnable ); GetGalCanvas()->SetEvtHandlerEnabled( aEnable ); // Switch panes m_auimgr.GetPane( wxT( "DrawFrame" ) ).Show( !aEnable ); m_auimgr.GetPane( wxT( "DrawFrameGal" ) ).Show( aEnable ); m_auimgr.Update(); // Reset current tool on switch(); SetNoToolSelected(); m_galCanvasActive = aEnable; }
void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event ) { event.Skip(); // I am assuming that the double click actually changed the selected item. // please verify this. int selection = m_ClearanceListBox->GetSelection(); if( selection != wxNOT_FOUND ) { // Find the selected MARKER in the PCB, position cursor there. // Then close the dialog. const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection ); if( item ) { /* * // after the goto, process a button OK command later. * wxCommandEvent cmd( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ); * ::wxPostEvent( GetEventHandler(), cmd ); */ m_Parent->CursorGoto( item->GetPointA() ); m_Parent->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) ); // turn control over to m_Parent, hide this DIALOG_DRC_CONTROL window, // no destruction so we can preserve listbox cursor Show( false ); // We do not want the clarification popup window. // when releasing the left button in the main window m_Parent->SkipNextLeftButtonReleaseEvent(); } } }
int PCBNEW_CONTROL::ZoomFitScreen( const TOOL_EVENT& aEvent ) { KIGFX::VIEW* view = getView(); EDA_DRAW_PANEL_GAL* galCanvas = m_frame->GetGalCanvas(); BOARD* board = getModel<BOARD>(); board->ComputeBoundingBox(); BOX2I boardBBox = board->ViewBBox(); VECTOR2D scrollbarSize = VECTOR2D( galCanvas->GetSize() - galCanvas->GetClientSize() ); VECTOR2D screenSize = view->ToWorld( galCanvas->GetClientSize(), false ); if( boardBBox.GetWidth() == 0 || boardBBox.GetHeight() == 0 ) { // Empty view view->SetScale( 17.0 ); // works fine for the standard worksheet frame view->SetCenter( screenSize / 2.0 ); } else { VECTOR2D vsize = boardBBox.GetSize(); double scale = view->GetScale() / std::max( fabs( vsize.x / screenSize.x ), fabs( vsize.y / screenSize.y ) ); view->SetScale( scale ); view->SetCenter( boardBBox.Centre() ); } // Take scrollbars into account VECTOR2D worldScrollbarSize = view->ToWorld( scrollbarSize, false ); view->SetCenter( view->GetCenter() + worldScrollbarSize / 2.0 ); return 0; }
void DIALOG_DRC_CONTROL::OnLeftDClickClearance( wxMouseEvent& event ) { event.Skip(); // I am assuming that the double click actually changed the selected item. // please verify this. int selection = m_ClearanceListBox->GetSelection(); if( selection != wxNOT_FOUND ) { // Find the selected MARKER in the PCB, position cursor there. // Then close the dialog. const DRC_ITEM* item = m_ClearanceListBox->GetItem( selection ); if( item ) { m_brdEditor->CursorGoto( item->GetPointA() ); m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) ); if( !IsModal() ) { // turn control over to m_brdEditor, hide this DIALOG_DRC_CONTROL window, // no destruction so we can preserve listbox cursor Show( false ); // We do not want the clarification popup window. // when releasing the left button in the main window m_brdEditor->SkipNextLeftButtonReleaseEvent(); } } } }
void DIALOG_DRC_CONTROL::OnLeftDClickUnconnected( wxMouseEvent& event ) { event.Skip(); // I am assuming that the double click actually changed the selected item. // please verify this. int selection = m_UnconnectedListBox->GetSelection(); if( selection != wxNOT_FOUND ) { // Find the selected DRC_ITEM in the listbox, position cursor there, // at the first of the two pads. // Then hide the dialog. const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection ); if( item ) { m_brdEditor->CursorGoto( item->GetPointA() ); m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) ); if( !IsModal() ) { Show( false ); // We do not want the clarification popup window. // when releasing the left button in the main window m_brdEditor->SkipNextLeftButtonReleaseEvent(); } } } }
int PCBNEW_CONTROL::ZoomFitScreen( const TOOL_EVENT& aEvent ) { KIGFX::VIEW* view = m_frame->GetGalCanvas()->GetView(); KIGFX::GAL* gal = m_frame->GetGalCanvas()->GetGAL(); BOARD* board = getModel<BOARD>(); board->ComputeBoundingBox(); BOX2I boardBBox = board->ViewBBox(); VECTOR2I screenSize = gal->GetScreenPixelSize(); if( boardBBox.GetSize().x == 0 || boardBBox.GetSize().y == 0 ) { // Empty view view->SetCenter( view->ToWorld( VECTOR2D( screenSize.x / 2, screenSize.y / 2 ) ) ); view->SetScale( 17.0 ); } else { // Autozoom to board double iuPerX = screenSize.x ? boardBBox.GetWidth() / screenSize.x : 1.0; double iuPerY = screenSize.y ? boardBBox.GetHeight() / screenSize.y : 1.0; double bestZoom = std::max( iuPerX, iuPerY ); double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); double zoom = 1.0 / ( zoomFactor * bestZoom ); view->SetCenter( boardBBox.Centre() ); view->SetScale( zoom ); } return 0; }
DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, D_PAD* aPad ) : DIALOG_PAD_PROPERTIES_BASE( aParent ), m_OrientValidator( 1, &m_OrientValue ) { m_canUpdate = false; m_parent = aParent; m_currentPad = aPad; // aPad can be NULL, if the dialog is called // from the footprint editor to set default pad setup m_board = m_parent->GetBoard(); m_OrientValidator.SetRange( -360.0, 360.0 ); m_PadOrientCtrl->SetValidator( m_OrientValidator ); m_OrientValidator.SetWindow( m_PadOrientCtrl ); m_padMaster = &m_parent->GetDesignSettings().m_Pad_Master; m_dummyPad = new D_PAD( (MODULE*) NULL ); if( aPad ) *m_dummyPad = *aPad; else // We are editing a "master" pad, i.e. a template to create new pads *m_dummyPad = *m_padMaster; // Show the X and Y axis. It is usefull because pad shape can have an offset // or be a complex shape. m_axisOrigin = new KIGFX::ORIGIN_VIEWITEM( KIGFX::COLOR4D(0.0, 0.0, 0.8, 1.0), KIGFX::ORIGIN_VIEWITEM::CROSS, Millimeter2iu( 0.2 ), VECTOR2D( m_dummyPad->GetPosition() ) ); m_axisOrigin->SetDrawAtZero( true ); if( m_parent->IsGalCanvasActive() ) { m_panelShowPadGal->UseColorScheme( m_board->GetColorsSettings() ); m_panelShowPadGal->SwitchBackend( m_parent->GetGalCanvas()->GetBackend() ); m_panelShowPadGal->Show(); m_panelShowPad->Hide(); m_panelShowPadGal->GetView()->Add( m_dummyPad ); m_panelShowPadGal->GetView()->Add( m_axisOrigin ); m_panelShowPadGal->StartDrawing(); Connect( wxEVT_SIZE, wxSizeEventHandler( DIALOG_PAD_PROPERTIES::OnResize ) ); } else { m_panelShowPad->Show(); m_panelShowPadGal->Hide(); } initValues(); TransferDataToWindow(); m_sdbSizerOK->SetDefault(); m_PadNumCtrl->SetFocus(); m_canUpdate = true; FixOSXCancelButtonIssue(); // Now all widgets have the size fixed, call FinishDialogSettings FinishDialogSettings(); }
void PCB_BASE_EDIT_FRAME::SetBoard( BOARD* aBoard ) { bool new_board = ( aBoard != m_Pcb ); // The active tool might store a reference to the BOARD that is about to be deleted. if( m_toolManager ) m_toolManager->DeactivateTool(); // It has to be done before the previous board is destroyed by SetBoard() if( new_board ) GetGalCanvas()->GetView()->Clear(); PCB_BASE_FRAME::SetBoard( aBoard ); GetGalCanvas()->GetGAL()->SetGridOrigin( VECTOR2D( aBoard->GetGridOrigin() ) ); // update the tool manager with the new board and its view. if( m_toolManager ) { PCB_DRAW_PANEL_GAL* drawPanel = static_cast<PCB_DRAW_PANEL_GAL*>( GetGalCanvas() ); drawPanel->DisplayBoard( aBoard ); m_toolManager->SetEnvironment( aBoard, drawPanel->GetView(), drawPanel->GetViewControls(), this ); if( new_board ) m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); } }
void PCBNEW_CONTROL::updateGrid() { BASE_SCREEN* screen = m_frame->GetScreen(); //GRID_TYPE grid = screen->GetGrid( idx ); getView()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGridSize() ) ); getView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); }
bool SHAPE_ARC::ConstructFromCornerAndAngles( VECTOR2I aP0, double aStartAngle, double aCenterAngle, double aRadius ) { m_p0 = aP0; auto d1 = VECTOR2D( 1.0, 0.0 ).Rotate( aStartAngle * M_PI / 180.0 ) * aRadius; auto d2 = VECTOR2D( 1.0, 0.0 ).Rotate( (aStartAngle + aCenterAngle) * M_PI / 180.0 ) * aRadius; m_pc = m_p0 - (VECTOR2I) d1; m_p1 = m_pc + (VECTOR2I) d2; if( aCenterAngle < 0 ) std::swap( m_p0, m_p1 ); return true; }
int GraphicTextWidth( const wxString& aText, const wxSize& aSize, bool aItalic, bool aBold ) { basic_gal.SetFontItalic( aItalic ); basic_gal.SetFontBold( aBold ); basic_gal.SetGlyphSize( VECTOR2D( aSize ) ); VECTOR2D tsize = basic_gal.GetTextLineSize( aText ); return KiROUND( tsize.x ); }
/** * Function DrawGraphicText * Draw a graphic text (like module texts) * @param aClipBox = the clipping rect, or NULL if no clipping * @param aDC = the current Device Context. NULL if draw within a 3D GL Canvas * @param aPos = text position (according to h_justify, v_justify) * @param aColor (COLOR4D) = text color * @param aText = text to draw * @param aOrient = angle in 0.1 degree * @param aSize = text size (size.x or size.y can be < 0 for mirrored texts) * @param aH_justify = horizontal justification (Left, center, right) * @param aV_justify = vertical justification (bottom, center, top) * @param aWidth = line width (pen width) (use default width if aWidth = 0) * if width < 0 : draw segments in sketch mode, width = abs(width) * Use a value min(aSize.x, aSize.y) / 5 for a bold text * @param aItalic = true to simulate an italic font * @param aBold = true to use a bold font. Useful only with default width value (aWidth = 0) * @param aCallback() = function called (if non null) to draw each segment. * used to draw 3D texts or for plotting, NULL for normal drawings * @param aPlotter = a pointer to a PLOTTER instance, when this function is used to plot * the text. NULL to draw this text. */ void DrawGraphicText( EDA_RECT* aClipBox, wxDC* aDC, const wxPoint& aPos, COLOR4D aColor, const wxString& aText, double aOrient, const wxSize& aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, void (* aCallback)( int x0, int y0, int xf, int yf ), PLOTTER* aPlotter ) { bool fill_mode = true; if( aWidth == 0 && aBold ) // Use default values if aWidth == 0 aWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) ); if( aWidth < 0 ) { aWidth = -aWidth; fill_mode = false; } basic_gal.SetIsFill( fill_mode ); basic_gal.SetLineWidth( aWidth ); EDA_TEXT dummy; dummy.SetItalic( aItalic ); dummy.SetBold( aBold ); dummy.SetHorizJustify( aH_justify ); dummy.SetVertJustify( aV_justify ); wxSize size = aSize; dummy.SetMirrored( size.x < 0 ); if( size.x < 0 ) size.x = - size.x; dummy.SetTextSize( size ); basic_gal.SetTextAttributes( &dummy ); basic_gal.SetPlotter( aPlotter ); basic_gal.SetCallback( aCallback ); basic_gal.m_DC = aDC; basic_gal.m_Color = aColor; basic_gal.SetClipBox( aClipBox ); basic_gal.StrokeText( aText, VECTOR2D( aPos ), aOrient * M_PI/1800 ); }
int PCBNEW_CONTROL::GridPreset( const TOOL_EVENT& aEvent ) { long idx = aEvent.Parameter<long>(); m_frame->SetPresetGrid( idx ); BASE_SCREEN* screen = m_frame->GetScreen(); GRID_TYPE grid = screen->GetGrid( idx ); getView()->GetGAL()->SetGridSize( VECTOR2D( grid.m_Size ) ); getView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); return 0; }
const BOX2I D_PAD::ViewBBox() const { // Bounding box includes soldermask too int solderMaskMargin = GetSolderMaskMargin(); VECTOR2I solderPasteMargin = VECTOR2D( GetSolderPasteMargin() ); EDA_RECT bbox = GetBoundingBox(); // Look for the biggest possible bounding box int xMargin = std::max( solderMaskMargin, solderPasteMargin.x ); int yMargin = std::max( solderMaskMargin, solderPasteMargin.y ); return BOX2I( VECTOR2I( bbox.GetOrigin() ) - VECTOR2I( xMargin, yMargin ), VECTOR2I( bbox.GetSize() ) + VECTOR2I( 2 * xMargin, 2 * yMargin ) ); }
int PCB_EDITOR_CONTROL::CrossProbeSchToPcb( const TOOL_EVENT& aEvent ) { BOARD_ITEM* item = aEvent.Parameter<BOARD_ITEM*>(); if( item ) { m_probingSchToPcb = true; getView()->SetCenter( VECTOR2D( item->GetPosition() ) ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_toolMgr->RunAction( COMMON_ACTIONS::selectItem, true, item ); } return 0; }
void SELECTION_TOOL::findCallback( BOARD_ITEM* aItem ) { clearSelection(); if( aItem ) { clearSelection(); select( aItem ); getView()->SetCenter( VECTOR2D( aItem->GetPosition() ) ); // Inform other potentially interested tools m_toolMgr->ProcessEvent( SelectedEvent ); } m_frame->GetGalCanvas()->ForceRefresh(); }
void DIALOG_DRC_CONTROL::OnPopupMenu( wxCommandEvent& event ) { int source = event.GetId(); const DRC_ITEM* item = 0; wxPoint pos; int selection; switch( source ) { case ID_POPUP_UNCONNECTED_A: selection = m_UnconnectedListBox->GetSelection(); item = m_UnconnectedListBox->GetItem( selection ); pos = item->GetPointA(); break; case ID_POPUP_UNCONNECTED_B: selection = m_UnconnectedListBox->GetSelection(); item = m_UnconnectedListBox->GetItem( selection ); pos = item->GetPointB(); break; case ID_POPUP_MARKERS_A: selection = m_ClearanceListBox->GetSelection(); item = m_ClearanceListBox->GetItem( selection ); pos = item->GetPointA(); break; case ID_POPUP_MARKERS_B: selection = m_ClearanceListBox->GetSelection(); item = m_ClearanceListBox->GetItem( selection ); pos = item->GetPointB(); break; } if( item ) { m_brdEditor->CursorGoto( pos ); m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) ); if( !IsModal() ) Show( false ); } }
bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const { const unsigned GRIP_MARGIN = 20; VECTOR2D margin = getView()->ToWorld( VECTOR2D( GRIP_MARGIN, GRIP_MARGIN ), false ); // Check if the point is located within any of the currently selected items bounding boxes for( unsigned int i = 0; i < m_selection.items.GetCount(); ++i ) { BOARD_ITEM* item = m_selection.Item<BOARD_ITEM>( i ); BOX2I itemBox = item->ViewBBox(); itemBox.Inflate( margin.x, margin.y ); // Give some margin for gripping an item if( itemBox.Contains( aPoint ) ) return true; } return false; }
void DIALOG_DRC_CONTROL::OnUnconnectedSelectionEvent( wxCommandEvent& event ) { int selection = event.GetSelection(); if( selection != wxNOT_FOUND ) { // until a MARKER is selected, this button is not enabled. m_DeleteCurrentMarkerButton->Enable( true ); // Find the selected DRC_ITEM in the listbox, position cursor there, // at the first of the two pads. const DRC_ITEM* item = m_UnconnectedListBox->GetItem( selection ); if( item ) { m_brdEditor->CursorGoto( item->GetPointA(), false ); m_brdEditor->GetGalCanvas()->GetView()->SetCenter( VECTOR2D( item->GetPointA() ) ); } } event.Skip(); }
bool PCB_BASE_FRAME::InvokeDialogGrid() { wxPoint grid_origin = GetGridOrigin(); DIALOG_SET_GRID dlg( this, &m_UserGridUnit, g_UserUnit, &m_UserGridSize, &grid_origin, &m_FastGrid1, &m_FastGrid2, m_gridSelectBox->GetStrings() ); int ret = dlg.ShowModal(); if( ret == wxID_OK ) { if( GetGridOrigin() != grid_origin && IsType( FRAME_PCB ) ) OnModify(); // because grid origin is saved in board, show as modified SetGridOrigin( grid_origin ); BASE_SCREEN* screen = GetScreen(); screen->AddGrid( m_UserGridSize, m_UserGridUnit, ID_POPUP_GRID_USER ); // If the user grid is the current option, recall SetGrid() // to force new values put in list as current grid value if( screen->GetGridId() == ID_POPUP_GRID_USER ) screen->SetGrid( ID_POPUP_GRID_USER ); if( IsGalCanvasActive() ) { GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x, screen->GetGrid().m_Size.y ) ); GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); } m_canvas->Refresh(); return true; } return false; }
PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) : EDA_DRAW_FRAME( aKiway, aParent, FRAME_PL_EDITOR, wxT( "PlEditorFrame" ), wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, PL_EDITOR_FRAME_NAME ) { m_UserUnits = MILLIMETRES; m_zoomLevelCoeff = 290.0; // Adjusted to roughly displays zoom level = 1 // when the screen shows a 1:1 image // obviously depends on the monitor, // but this is an acceptable value m_showAxis = false; // true to show X and Y axis on screen m_showGridAxis = true; m_showBorderAndTitleBlock = true; // true for reference drawings. m_hotkeysDescrList = PlEditorHotkeysDescr; m_originSelectChoice = 0; SetDrawBgColor( WHITE ); // default value, user option (WHITE/BLACK) WS_DATA_MODEL::GetTheInstance().m_EditMode = true; SetShowPageLimits( true ); m_AboutTitle = "PlEditor"; m_propertiesFrameWidth = 200; // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_pagelayout_editor_xpm ) ); SetIcon( icon ); // Create GAL canvas #ifdef __WXMAC__ // Cairo renderer doesn't handle Retina displays m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL; #else m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO; #endif auto* drawPanel = new PL_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, GetGalDisplayOptions(), m_canvasType ); SetGalCanvas( drawPanel ); LoadSettings( config() ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); wxSize pageSizeIU = GetPageLayout().GetPageSettings().GetSizeIU(); SetScreen( new PL_EDITOR_SCREEN( pageSizeIU ) ); if( !GetScreen()->GridExists( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 ) ) m_LastGridSizeId = ID_POPUP_GRID_LEVEL_1MM - ID_POPUP_GRID_LEVEL_1000; GetScreen()->SetGrid( m_LastGridSizeId + ID_POPUP_GRID_LEVEL_1000 ); setupTools(); ReCreateMenuBar(); ReCreateHToolbar(); ReCreateVToolbar(); wxWindow* stsbar = GetStatusBar(); int dims[] = { // balance of status bar on far left is set to a default or whatever is left over. -1, // When using GetTextSize() remember the width of '1' is not the same // as the width of '0' unless the font is fixed width, and it usually won't be. // zoom: GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10, // cursor coords GetTextSize( wxT( "X 0234.567 Y 0234.567" ), stsbar ).x + 10, // delta distances GetTextSize( wxT( "dx 0234.567 dx 0234.567" ), stsbar ).x + 10, // Coord origin (use the bigger message) GetTextSize( _( "coord origin: Right Bottom page corner" ), stsbar ).x + 10, // units display, Inches is bigger than mm GetTextSize( _( "Inches" ), stsbar ).x + 10 }; SetStatusWidths( arrayDim( dims ), dims ); m_auimgr.SetManagedWindow( this ); m_auimgr.SetArtProvider( new EDA_DOCKART( this ) ); m_propertiesPagelayout = new PROPERTIES_FRAME( this ); // Horizontal items; layers 4 - 6 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); // Vertical items; layers 1 - 3 m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_propertiesPagelayout, EDA_PANE().Palette().Name( "Props" ).Right().Layer(2) .Caption( _( "Properties" ) ).MinSize( m_propertiesPagelayout->GetMinSize() ) .BestSize( m_propertiesFrameWidth, -1 ) ); m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "DrawFrame" ).Center() ); m_auimgr.AddPane( GetGalCanvas(), EDA_PANE().Canvas().Name( "DrawFrameGal" ).Center().Hide() ); // Set up viewport KIGFX::VIEW* view = GetGalCanvas()->GetView(); view->SetScale( GetZoomLevelCoeff() / m_canvas->GetZoom() ); view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); UseGalCanvas(); m_auimgr.Update(); // Initialize the current page layout WS_DATA_MODEL& pglayout = WS_DATA_MODEL::GetTheInstance(); #if 0 //start with empty layout pglayout.AllowVoidList( true ); pglayout.ClearList(); #else // start with the default Kicad layout pglayout.SetPageLayout(); #endif OnNewPageLayout(); }
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const { // In case the item has a very tiny width defined, allow it to be selected const int MIN_HIT_TEST_RADIUS = Millimeter2iu( 0.01 ); // calculate aRefPos in XY gerber axis: wxPoint ref_pos = GetXYPosition( aRefPos ); SHAPE_POLY_SET poly; switch( m_Shape ) { case GBR_POLYGON: poly = m_Polygon; return poly.Contains( VECTOR2I( ref_pos ), 0 ); case GBR_SPOT_POLY: poly = GetDcodeDescr()->m_Polygon; poly.Move( m_Start ); return poly.Contains( VECTOR2I( ref_pos ), 0 ); case GBR_SPOT_RECT: return GetBoundingBox().Contains( aRefPos ); case GBR_ARC: { double radius = GetLineLength( m_Start, m_ArcCentre ); VECTOR2D test_radius = VECTOR2D( ref_pos ) - VECTOR2D( m_ArcCentre ); int size = ( ( m_Size.x < MIN_HIT_TEST_RADIUS ) ? MIN_HIT_TEST_RADIUS : m_Size.x ); // Are we close enough to the radius? bool radius_hit = ( std::fabs( test_radius.EuclideanNorm() - radius) < size ); if( radius_hit ) { // Now check that we are within the arc angle VECTOR2D start = VECTOR2D( m_Start ) - VECTOR2D( m_ArcCentre ); VECTOR2D end = VECTOR2D( m_End ) - VECTOR2D( m_ArcCentre ); double start_angle = NormalizeAngleRadiansPos( start.Angle() ); double end_angle = NormalizeAngleRadiansPos( end.Angle() ); if( m_Start == m_End ) { start_angle = 0; end_angle = 2 * M_PI; } else if( end_angle < start_angle ) { end_angle += 2 * M_PI; } double test_angle = NormalizeAngleRadiansPos( test_radius.Angle() ); return ( test_angle > start_angle && test_angle < end_angle ); } return false; } case GBR_SPOT_MACRO: // Aperture macro polygons are already in absolute coordinates auto p = GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start ); for( int i = 0; i < p->OutlineCount(); ++i ) { if( p->Contains( VECTOR2I( aRefPos ), i ) ) return true; } return false; } // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items) int radius = std::min( m_Size.x, m_Size.y ) >> 1; if( radius < MIN_HIT_TEST_RADIUS ) radius = MIN_HIT_TEST_RADIUS; if( m_Flashed ) return HitTestPoints( m_Start, ref_pos, radius ); else return TestSegmentHit( ref_pos, m_Start, m_End, radius ); }
void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) { for( TOOL_ID toolId : m_activeTools ) { TOOL_STATE* st = m_toolIdIndex[toolId]; // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode) // or immediately (CMENU_NOW) mode. The latter is used for clarification lists. if( st->contextMenuTrigger == CMENU_OFF ) continue; if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) ) break; st->pendingWait = true; st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY ); // Store the menu pointer in case it is changed by the TOOL when handling menu events CONTEXT_MENU* m = st->contextMenu; if( st->contextMenuTrigger == CMENU_NOW ) st->contextMenuTrigger = CMENU_OFF; // Store the cursor position, so the tools could execute actions // using the point where the user has invoked a context menu m_menuCursor = m_viewControls->GetCursorPosition(); // Save all tools cursor settings, as they will be overridden for( auto idState : m_toolIdIndex ) { TOOL_STATE* s = idState.second; const auto& vc = s->vcSettings; if( vc.m_forceCursorPosition ) m_cursorSettings[idState.first] = vc.m_forcedPosition; else m_cursorSettings[idState.first] = NULLOPT; } m_viewControls->ForceCursorPosition( true, m_menuCursor ); // Display a copy of menu std::unique_ptr<CONTEXT_MENU> menu( m->Clone() ); // Run update handlers on the created copy menu->UpdateAll(); m_menuOwner = toolId; m_menuActive = true; auto frame = dynamic_cast<wxFrame*>( m_editFrame ); if( frame ) frame->PopupMenu( menu.get() ); // Warp the cursor as long as the menu wasn't clicked out of if( menu->GetSelected() >= 0 ) m_viewControls->WarpCursor( m_menuCursor, true, false ); // Otherwise notify the tool of a cancelled menu else { TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 ); evt.SetParameter( m ); dispatchInternal( evt ); } // Notify the tools that menu has been closed TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED ); evt.SetParameter( m ); dispatchInternal( evt ); m_menuActive = false; m_menuOwner = -1; // Restore cursor settings for( auto cursorSetting : m_cursorSettings ) { auto it = m_toolIdIndex.find( cursorSetting.first ); wxASSERT( it != m_toolIdIndex.end() ); if( it == m_toolIdIndex.end() ) continue; KIGFX::VC_SETTINGS& vc = it->second->vcSettings; vc.m_forceCursorPosition = (bool) cursorSetting.second; vc.m_forcedPosition = cursorSetting.second ? *cursorSetting.second : VECTOR2D( 0, 0 ); } m_cursorSettings.clear(); break; } }
FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent, EDA_DRAW_PANEL_GAL::GAL_TYPE aBackend ) : PCB_BASE_EDIT_FRAME( aKiway, aParent, FRAME_PCB_MODULE_EDITOR, wxEmptyString, wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GetFootprintEditorFrameName() ) { m_showBorderAndTitleBlock = false; // true to show the frame references m_showAxis = true; // true to show X and Y axis on screen m_showGridAxis = true; // show the grid origin axis m_hotkeysDescrList = g_Module_Editor_Hotkeys_Descr; m_FrameSize = ConvertDialogToPixels( wxSize( 500, 350 ) ); // default in case of no prefs m_canvasType = aBackend; m_AboutTitle = "ModEdit"; // Give an icon wxIcon icon; icon.CopyFromBitmap( KiBitmap( icon_modedit_xpm ) ); SetIcon( icon ); // Create GAL canvas if( aBackend == EDA_DRAW_PANEL_GAL::GAL_TYPE_UNKNOWN ) m_canvasType = LoadCanvasTypeSetting(); else m_canvasType = aBackend; PCB_DRAW_PANEL_GAL* drawPanel = new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), m_FrameSize, GetGalDisplayOptions(), m_canvasType ); SetGalCanvas( drawPanel ); SetBoard( new BOARD() ); // In modedit, the default net clearance is not known. // (it depends on the actual board) // So we do not show the default clearance, by setting it to 0 // The footprint or pad specific clearance will be shown GetBoard()->GetDesignSettings().GetDefault()->SetClearance( 0 ); // Don't show the default board solder mask clearance in the footprint editor. Only the // footprint or pad clearance setting should be shown if it is not 0. GetBoard()->GetDesignSettings().m_SolderMaskMargin = 0; // restore the last footprint from the project, if any restoreLastFootprint(); // Ensure all layers and items are visible: // In footprint editor, some layers have no meaning or // cannot be used, but we show all of them, at least to be able // to edit a bad layer GetBoard()->SetVisibleAlls(); // However the "no net" mark on pads is useless, because there is // no net in footprint editor: make it non visible GetBoard()->SetElementVisibility( LAYER_NO_CONNECTS, false ); m_Layers = new PCB_LAYER_WIDGET( this, GetCanvas(), true ); // LoadSettings() *after* creating m_LayersManager, because LoadSettings() // initialize parameters in m_LayersManager LoadSettings( config() ); GetGalDisplayOptions().m_axesEnabled = true; SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) ); GetScreen()->SetMaxUndoItems( m_UndoRedoCountMax ); GetScreen()->AddGrid( m_UserGridSize, EDA_UNITS_T::UNSCALED_UNITS, ID_POPUP_GRID_USER ); GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId ); // In modedit, set the default paper size to A4: // this should be OK for all footprint to plot/print SetPageSettings( PAGE_INFO( PAGE_INFO::A4 ) ); SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y ); initLibraryTree(); m_treePane = new FOOTPRINT_TREE_PANE( this ); // Create the manager and dispatcher & route draw panel events to the dispatcher setupTools(); // ReCreateMenuBar(); // UseGalCanvas() will do this for us. ReCreateHToolbar(); ReCreateVToolbar(); ReCreateOptToolbar(); m_Layers->ReFill(); m_Layers->ReFillRender(); GetScreen()->m_Active_Layer = F_SilkS; m_Layers->SelectLayer( F_SilkS ); m_Layers->OnLayerSelected(); m_auimgr.SetManagedWindow( this ); m_auimgr.SetArtProvider( new EDA_DOCKART( this ) ); // Horizontal items; layers 4 - 6 m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); // Vertical items; layers 1 - 3 m_auimgr.AddPane( m_optionsToolBar, EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) ); m_auimgr.AddPane( m_treePane, EDA_PANE().Palette().Name( "Footprints" ).Left().Layer(1) .Caption( _( "Libraries" ) ).MinSize( 250, 400 ) .BestSize( m_defaultLibWidth, -1 ) ); m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_Layers, EDA_PANE().Palette().Name( "LayersManager" ).Right().Layer(3) .Caption( _( "Layers Manager" ) ).PaneBorder( false ) .MinSize( 80, -1 ).BestSize( m_Layers->GetBestSize() ) ); m_auimgr.AddPane( m_canvas, EDA_PANE().Canvas().Name( "DrawFrame" ).Center() ); m_auimgr.AddPane( GetGalCanvas(), EDA_PANE().Canvas().Name( "DrawFrameGal" ).Center().Hide() ); GetGalCanvas()->GetGAL()->SetAxesEnabled( true ); // Set up viewport KIGFX::VIEW* view = GetGalCanvas()->GetView(); view->SetScale( GetZoomLevelCoeff() / m_canvas->GetZoom() ); view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); UseGalCanvas(); m_auimgr.Update(); updateTitle(); Raise(); // On some window managers, this is needed Show( true ); Zoom_Automatique( false ); }
void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event ) { int* clientData; int eventId = ID_POPUP_GRID_LEVEL_100; if( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) { if( m_gridSelectBox == NULL ) return; /* * Don't use wxCommandEvent::GetClientData() here. It always * returns NULL in GTK. This solution is not as elegant but * it works. */ int index = m_gridSelectBox->GetSelection(); wxASSERT( index != wxNOT_FOUND ); clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( index ); if( clientData != NULL ) eventId = *clientData; } else { eventId = event.GetId(); /* Update the grid select combobox if the grid size was changed * by menu event. */ if( m_gridSelectBox != NULL ) { for( size_t i = 0; i < m_gridSelectBox->GetCount(); i++ ) { clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( i ); if( clientData && eventId == *clientData ) { m_gridSelectBox->SetSelection( i ); break; } } } } // Be sure m_LastGridSizeId is up to date. m_LastGridSizeId = eventId - ID_POPUP_GRID_LEVEL_1000; BASE_SCREEN* screen = GetScreen(); if( screen->GetGridId() == eventId ) return; /* * This allows for saving non-sequential command ID offsets used that * may be used in the grid size combobox. Do not use the selection * index returned by GetSelection(). */ screen->SetGrid( eventId ); SetCrossHairPosition( RefPos( true ) ); if( IsGalCanvasActive() ) { GetGalCanvas()->GetGAL()->SetGridSize( VECTOR2D( screen->GetGrid().m_Size.x, screen->GetGrid().m_Size.y ) ); GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); } m_canvas->Refresh(); }
// Cursor control int PCBNEW_CONTROL::CursorControl( const TOOL_EVENT& aEvent ) { long type = aEvent.Parameter<long>(); bool fastMove = type & COMMON_ACTIONS::CURSOR_FAST_MOVE; type &= ~COMMON_ACTIONS::CURSOR_FAST_MOVE; GRID_HELPER gridHelper( m_frame ); VECTOR2D cursor = getViewControls()->GetCursorPosition(); VECTOR2I gridSize = gridHelper.GetGrid(); VECTOR2D newCursor = gridHelper.Align( cursor ); if( fastMove ) gridSize = gridSize * 10; switch( type ) { case COMMON_ACTIONS::CURSOR_UP: newCursor -= VECTOR2D( 0, gridSize.y ); break; case COMMON_ACTIONS::CURSOR_DOWN: newCursor += VECTOR2D( 0, gridSize.y ); break; case COMMON_ACTIONS::CURSOR_LEFT: newCursor -= VECTOR2D( gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_RIGHT: newCursor += VECTOR2D( gridSize.x, 0 ); break; case COMMON_ACTIONS::CURSOR_CLICK: // fall through case COMMON_ACTIONS::CURSOR_DBL_CLICK: { TOOL_ACTIONS action = TA_NONE; int modifiers = 0; modifiers |= wxGetKeyState( WXK_SHIFT ) ? MD_SHIFT : 0; modifiers |= wxGetKeyState( WXK_CONTROL ) ? MD_CTRL : 0; modifiers |= wxGetKeyState( WXK_ALT ) ? MD_ALT : 0; if( type == COMMON_ACTIONS::CURSOR_CLICK ) action = TA_MOUSE_CLICK; else if( type == COMMON_ACTIONS::CURSOR_DBL_CLICK ) action = TA_MOUSE_DBLCLICK; else assert( false ); TOOL_EVENT evt( TC_MOUSE, action, BUT_LEFT | modifiers ); evt.SetMousePosition( getViewControls()->GetCursorPosition() ); m_toolMgr->ProcessEvent( evt ); return 0; } break; } // Handler cursor movement KIGFX::VIEW* view = getView(); newCursor = view->ToScreen( newCursor ); newCursor.x = KiROUND( newCursor.x ); newCursor.y = KiROUND( newCursor.y ); // Pan the screen if required const VECTOR2I& screenSize = view->GetGAL()->GetScreenPixelSize(); BOX2I screenBox( VECTOR2I( 0, 0 ), screenSize ); if( !screenBox.Contains( newCursor ) ) { VECTOR2D delta( 0, 0 ); if( newCursor.x < screenBox.GetLeft() ) { delta.x = newCursor.x - screenBox.GetLeft(); newCursor.x = screenBox.GetLeft(); } else if( newCursor.x > screenBox.GetRight() ) { delta.x = newCursor.x - screenBox.GetRight(); // -1 is to keep the cursor within the drawing area, // so the cursor coordinates are still updated newCursor.x = screenBox.GetRight() - 1; } if( newCursor.y < screenBox.GetTop() ) { delta.y = newCursor.y - screenBox.GetTop(); newCursor.y = screenBox.GetTop(); } else if( newCursor.y > screenBox.GetBottom() ) { delta.y = newCursor.y - screenBox.GetBottom(); // -1 is to keep the cursor within the drawing area, // so the cursor coordinates are still updated newCursor.y = screenBox.GetBottom() - 1; } view->SetCenter( view->GetCenter() + view->ToWorld( delta, false ) ); } m_frame->GetGalCanvas()->WarpPointer( newCursor.x, newCursor.y ); return 0; }