bool DIALOG_KEEPOUT_AREA_PROPERTIES::TransferDataFromWindow() { // Init keepout parameters: m_zonesettings.SetIsKeepout( true ); m_zonesettings.SetDoNotAllowTracks( m_cbTracksCtrl->GetValue() ); m_zonesettings.SetDoNotAllowVias( m_cbViasCtrl->GetValue() ); m_zonesettings.SetDoNotAllowCopperPour( m_cbCopperPourCtrl->GetValue() ); // Test for not allowed items: should have at least one item not allowed: if( ! m_zonesettings.GetDoNotAllowTracks() && ! m_zonesettings.GetDoNotAllowVias() && ! m_zonesettings.GetDoNotAllowCopperPour() ) { DisplayError( NULL, _("Tracks, vias, and pads are allowed. The keepout will have no effect." ) ); return false; } if( m_zonesettings.m_Layers.count() == 0 ) { DisplayError( NULL, _( "No layers selected." ) ); return false; } switch( m_OutlineAppearanceCtrl->GetSelection() ) { case 0: m_zonesettings.m_Zone_HatchingStyle = ZONE_CONTAINER::NO_HATCH; break; case 1: m_zonesettings.m_Zone_HatchingStyle = ZONE_CONTAINER::DIAGONAL_EDGE; break; case 2: m_zonesettings.m_Zone_HatchingStyle = ZONE_CONTAINER::DIAGONAL_FULL; break; } if( m_config ) m_config->Write( ZONE_NET_OUTLINES_STYLE_KEY, (long) m_zonesettings.m_Zone_HatchingStyle ); m_zonesettings.m_Zone_45_Only = m_cbConstrainCtrl->GetValue(); m_zonesettings.m_ZonePriority = 0; // for a keepout, this param is not used. *m_ptr = m_zonesettings; return true; }
int PCB_EDIT_FRAME::Begin_Zone( wxDC* DC ) { ZONE_SETTINGS zoneInfo = GetZoneSettings(); // verify if s_CurrentZone exists (could be deleted since last selection) : int ii; for( ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) { if( s_CurrentZone == GetBoard()->GetArea( ii ) ) break; } if( ii >= GetBoard()->GetAreaCount() ) // Not found: could be deleted since last selection { s_AddCutoutToCurrentZone = false; s_CurrentZone = NULL; } // If no zone contour in progress, a new zone is being created: if( !GetBoard()->m_CurrentZoneContour ) { if( GetToolId() == ID_PCB_KEEPOUT_AREA_BUTT && getActiveLayer() >= FIRST_NON_COPPER_LAYER ) { DisplayError( this, _( "Error: a keepout area is allowed only on copper layers" ) ); return 0; } else GetBoard()->m_CurrentZoneContour = new ZONE_CONTAINER( GetBoard() ); } ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour; if( zone->GetNumCorners() == 0 ) // Start a new contour: init zone params (net, layer ...) { if( !s_CurrentZone ) // A new outline is created, from scratch { ZONE_EDIT_T edited; // Init zone params to reasonable values zone->SetLayer( getActiveLayer() ); // Prompt user for parameters: m_canvas->SetIgnoreMouseEvents( true ); if( zone->IsOnCopperLayer() ) { // Put a zone on a copper layer if( GetBoard()->GetHighLightNetCode() > 0 ) { zoneInfo.m_NetcodeSelection = GetBoard()->GetHighLightNetCode(); zone->SetNet( zoneInfo.m_NetcodeSelection ); zone->SetNetNameFromNetCode( ); } double tmp = ZONE_THERMAL_RELIEF_GAP_MIL; wxGetApp().GetSettings()->Read( ZONE_THERMAL_RELIEF_GAP_STRING_KEY, &tmp ); zoneInfo.m_ThermalReliefGap = KiROUND( tmp * IU_PER_MILS); tmp = ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL; wxGetApp().GetSettings()->Read( ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY, &tmp ); zoneInfo.m_ThermalReliefCopperBridge = KiROUND( tmp * IU_PER_MILS ); tmp = ZONE_CLEARANCE_MIL; wxGetApp().GetSettings()->Read( ZONE_CLEARANCE_WIDTH_STRING_KEY, &tmp ); zoneInfo.m_ZoneClearance = KiROUND( tmp * IU_PER_MILS ); tmp = ZONE_THICKNESS_MIL; wxGetApp().GetSettings()->Read( ZONE_MIN_THICKNESS_WIDTH_STRING_KEY, &tmp ); zoneInfo.m_ZoneMinThickness = KiROUND( tmp * IU_PER_MILS ); zoneInfo.m_CurrentZone_Layer = zone->GetLayer(); if( GetToolId() == ID_PCB_KEEPOUT_AREA_BUTT ) { zoneInfo.SetIsKeepout( true ); edited = InvokeKeepoutAreaEditor( this, &zoneInfo ); } else { zoneInfo.SetIsKeepout( false ); edited = InvokeCopperZonesEditor( this, &zoneInfo ); } } else // Put a zone on a non copper layer (technical layer) { zoneInfo.SetIsKeepout( false ); zoneInfo.m_NetcodeSelection = 0; // No net for non copper zones edited = InvokeNonCopperZonesEditor( this, zone, &zoneInfo ); } m_canvas->MoveCursorToCrossHair(); m_canvas->SetIgnoreMouseEvents( false ); if( edited == ZONE_ABORT ) return 0; // Switch active layer to the selected zone layer setActiveLayer( zoneInfo.m_CurrentZone_Layer ); SetZoneSettings( zoneInfo ); } else { // Start a new contour: init zone params (net and layer) from an existing // zone (add cutout or similar zone) zoneInfo.m_CurrentZone_Layer = s_CurrentZone->GetLayer(); setActiveLayer( s_CurrentZone->GetLayer() ); zoneInfo << *s_CurrentZone; SetZoneSettings( zoneInfo ); } // Show the Net for zones on copper layers if( zoneInfo.m_CurrentZone_Layer < FIRST_NO_COPPER_LAYER && ! zoneInfo.GetIsKeepout() ) { if( s_CurrentZone ) { zoneInfo.m_NetcodeSelection = s_CurrentZone->GetNet(); GetBoard()->SetZoneSettings( zoneInfo ); } if( GetBoard()->IsHighLightNetON() ) { HighLight( DC ); // Remove old highlight selection } GetBoard()->SetHighLightNet( zoneInfo.m_NetcodeSelection ); HighLight( DC ); } if( !s_AddCutoutToCurrentZone ) s_CurrentZone = NULL; // the zone is used only once ("add similar zone" command) } // if first segment if( zone->GetNumCorners() == 0 ) { zone->SetFlags( IS_NEW ); zone->SetTimeStamp( GetNewTimeStamp() ); zoneInfo.ExportSetting( *zone ); zone->m_Poly->Start( zoneInfo.m_CurrentZone_Layer, GetScreen()->GetCrossHairPosition().x, GetScreen()->GetCrossHairPosition().y, zone->GetHatchStyle() ); zone->AppendCorner( GetScreen()->GetCrossHairPosition() ); if( Drc_On && (m_drc->Drc( zone, 0 ) == BAD_DRC) && zone->IsOnCopperLayer() ) { zone->ClearFlags(); zone->RemoveAllContours(); // use the form of SetCurItem() which does not write to the msg panel, // SCREEN::SetCurItem(), so the DRC error remains on screen. // PCB_EDIT_FRAME::SetCurItem() calls DisplayInfo(). GetScreen()->SetCurItem( NULL ); DisplayError( this, _( "DRC error: this start point is inside or too close an other area" ) ); return 0; } SetCurItem( zone ); m_canvas->SetMouseCapture( Show_New_Edge_While_Move_Mouse, Abort_Zone_Create_Outline ); } else // edge in progress: { ii = zone->GetNumCorners() - 1; // edge in progress : the current corner coordinate was set // by Show_New_Edge_While_Move_Mouse if( zone->GetCornerPosition( ii - 1 ) != zone->GetCornerPosition( ii ) ) { if( !Drc_On || !zone->IsOnCopperLayer() || ( m_drc->Drc( zone, ii - 1 ) == OK_DRC ) ) { // Ok, we can add a new corner if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxPoint(0,0), false ); zone->AppendCorner( GetScreen()->GetCrossHairPosition() ); SetCurItem( zone ); // calls DisplayInfo(). if( m_canvas->IsMouseCaptured() ) m_canvas->CallMouseCapture( DC, wxPoint(0,0), false ); } } } return zone->GetNumCorners(); }
int DRAWING_TOOL::drawZone( bool aKeepout ) { ZONE_CONTAINER* zone = NULL; DRAWSEGMENT line45; DRAWSEGMENT* helperLine = NULL; // we will need more than one helper line // if one day it is possible to draw zones in the footprint editor, // then hereby I'm letting you know that this tool does not handle UR_MODEDIT undo yet assert( !m_editModules ); // Add a VIEW_GROUP that serves as a preview for the new item KIGFX::VIEW_GROUP preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); Activate(); VECTOR2I origin; int numPoints = 0; bool direction45 = false; // 45 degrees only mode // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { bool updatePreview = false; // should preview be updated VECTOR2I cursorPos = m_controls->GetCursorPosition(); // Enable 45 degrees lines only mode by holding control if( direction45 != ( evt->Modifier( MD_CTRL ) && numPoints > 0 ) ) { direction45 = evt->Modifier( MD_CTRL ); if( direction45 ) { preview.Add( &line45 ); make45DegLine( helperLine, &line45 ); } else { preview.Remove( &line45 ); helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); } updatePreview = true; } if( evt->IsCancel() || evt->IsActivate() ) { if( numPoints > 0 ) // cancel the current zone { delete zone; zone = NULL; m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); if( direction45 ) { preview.Remove( &line45 ); direction45 = false; } preview.FreeItems(); updatePreview = true; numPoints = 0; } else // there is no zone currently drawn - just stop the tool break; if( evt->IsActivate() ) // now finish unconditionally break; } else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) ) { // Check if it is double click / closing line (so we have to finish the zone) if( evt->IsDblClick( BUT_LEFT ) || ( numPoints > 0 && cursorPos == origin ) ) { if( numPoints > 2 ) // valid zone consists of more than 2 points { assert( zone->GetNumCorners() > 2 ); // Finish the zone if( direction45 ) zone->AppendCorner( cursorPos == origin ? line45.GetStart() : line45.GetEnd() ); zone->Outline()->CloseLastContour(); zone->Outline()->RemoveNullSegments(); m_board->Add( zone ); m_view->Add( zone ); if( !aKeepout ) static_cast<PCB_EDIT_FRAME*>( m_frame )->Fill_Zone( zone ); zone->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_board->GetRatsnest()->Update( zone ); m_frame->OnModify(); m_frame->SaveCopyInUndoList( zone, UR_NEW ); zone = NULL; } else { delete zone; zone = NULL; } numPoints = 0; m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); if( direction45 ) { preview.Remove( &line45 ); direction45 = false; } preview.FreeItems(); updatePreview = true; } else { if( numPoints == 0 ) // it's the first click { // Get the current default settings for zones ZONE_SETTINGS zoneInfo = m_frame->GetZoneSettings(); zoneInfo.m_CurrentZone_Layer = m_frame->GetScreen()->m_Active_Layer; zoneInfo.SetIsKeepout( aKeepout ); m_controls->SetAutoPan( true ); m_controls->CaptureCursor( true ); // Show options dialog ZONE_EDIT_T dialogResult; if( aKeepout ) dialogResult = InvokeKeepoutAreaEditor( m_frame, &zoneInfo ); else { if( IsCopperLayer( zoneInfo.m_CurrentZone_Layer ) ) dialogResult = InvokeCopperZonesEditor( m_frame, &zoneInfo ); else dialogResult = InvokeNonCopperZonesEditor( m_frame, NULL, &zoneInfo ); } if( dialogResult == ZONE_ABORT ) { m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); continue; } // Apply the selected settings zone = new ZONE_CONTAINER( m_board ); zoneInfo.ExportSetting( *zone ); m_frame->GetGalCanvas()->SetTopLayer( zoneInfo.m_CurrentZone_Layer ); // Add the first point zone->Outline()->Start( zoneInfo.m_CurrentZone_Layer, cursorPos.x, cursorPos.y, zone->GetHatchStyle() ); origin = cursorPos; // Helper line represents the currently drawn line of the zone polygon helperLine = new DRAWSEGMENT; helperLine->SetShape( S_SEGMENT ); helperLine->SetWidth( 1 ); helperLine->SetLayer( zoneInfo.m_CurrentZone_Layer ); helperLine->SetStart( wxPoint( cursorPos.x, cursorPos.y ) ); helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); line45 = *helperLine; preview.Add( helperLine ); } else { zone->AppendCorner( helperLine->GetEnd() ); helperLine = new DRAWSEGMENT( *helperLine ); helperLine->SetStart( helperLine->GetEnd() ); preview.Add( helperLine ); } ++numPoints; updatePreview = true; } } else if( evt->IsMotion() && numPoints > 0 ) { // 45 degree lines if( direction45 ) make45DegLine( helperLine, &line45 ); else helperLine->SetEnd( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item updatePreview = true; } if( updatePreview ) preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); m_frame->SetToolID( ID_NO_TOOL_SELECTED, wxCURSOR_DEFAULT, wxEmptyString ); return 0; }