void PCB_TEXT::AddToBoard() { // Simple, not the best, but acceptable text positioning. m_name.textPositionX = m_positionX; m_name.textPositionY = m_positionY; CorrectTextPosition( &m_name, m_rotation ); TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board ); m_board->Add( pcbtxt, ADD_APPEND ); pcbtxt->SetText( m_name.text ); pcbtxt->SetSize( wxSize( KiROUND( m_name.textHeight / 2 ), KiROUND( m_name.textHeight / 1.1 ) ) ); pcbtxt->SetThickness( m_name.textstrokeWidth ); pcbtxt->SetOrientation( m_rotation ); pcbtxt->SetPosition( wxPoint( m_name.correctedPositionX, m_name.correctedPositionY ) ); pcbtxt->SetMirrored( m_name.mirror ); pcbtxt->SetTimeStamp( 0 ); pcbtxt->SetLayer( m_KiCadLayer ); }
void PCB_TEXT::AddToBoard() { m_name.textPositionX = m_positionX; m_name.textPositionY = m_positionY; m_name.textRotation = m_rotation; TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board ); m_board->Add( pcbtxt, ADD_APPEND ); pcbtxt->SetText( m_name.text ); SetTextSizeFromStrokeFontHeight( pcbtxt, m_name.textHeight ); pcbtxt->SetThickness( m_name.textstrokeWidth ); pcbtxt->SetOrientation( m_name.textRotation ); SetTextJustify( pcbtxt, m_name.justify ); pcbtxt->SetTextPosition( wxPoint( m_name.textPositionX, m_name.textPositionY ) ); pcbtxt->SetMirrored( m_name.mirror ); pcbtxt->SetTimeStamp( 0 ); pcbtxt->SetLayer( m_KiCadLayer ); }
// Move PCB text following the cursor. static void Move_Texte_Pcb( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition, bool aErase ) { TEXTE_PCB* TextePcb = (TEXTE_PCB*) aPanel->GetScreen()->GetCurItem(); if( TextePcb == NULL ) return; if( aErase ) TextePcb->Draw( aPanel, aDC, GR_XOR ); TextePcb->SetTextPosition( aPanel->GetParent()->GetCrossHairPosition() ); TextePcb->Draw( aPanel, aDC, GR_XOR ); }
/* * Abort current text edit progress. * If a text is selected, its initial coord are regenerated */ void Abort_Edit_Pcb_Text( EDA_DRAW_PANEL* Panel, wxDC* DC ) { TEXTE_PCB* TextePcb = (TEXTE_PCB*) Panel->GetScreen()->GetCurItem(); ( (PCB_EDIT_FRAME*) Panel->GetParent() )->SetCurItem( NULL ); Panel->SetMouseCapture( NULL, NULL ); if( TextePcb == NULL ) // Should not occur return; #ifndef USE_WX_OVERLAY TextePcb->Draw( Panel, DC, GR_XOR ); #endif if( TextePcb->IsNew() ) // If new: remove it { TextePcb->DeleteStructure(); return; } TextePcb->SwapData( &s_TextCopy ); TextePcb->ClearFlags(); #ifndef USE_WX_OVERLAY TextePcb->Draw( Panel, DC, GR_OR ); #else Panel->Refresh(); #endif }
void PCB_BASE_FRAME::ResetTextSize( BOARD_ITEM* aItem, wxDC* aDC ) { wxSize newSize; int newThickness; if( aItem->Type() == PCB_TEXT_T ) { newSize = GetDesignSettings().m_PcbTextSize; newThickness = GetDesignSettings().m_PcbTextWidth; TEXTE_PCB* text = static_cast<TEXTE_PCB*>( aItem ); // Exit if there's nothing to do if( text->GetTextSize() == newSize && text->GetThickness() == newThickness ) return; SaveCopyInUndoList( text, UR_CHANGED ); text->SetTextSize( newSize ); text->SetThickness( newThickness ); } else if( aItem->Type() == PCB_MODULE_TEXT_T ) { newSize = GetDesignSettings().m_ModuleTextSize; newThickness = GetDesignSettings().m_ModuleTextWidth; TEXTE_MODULE* text = static_cast<TEXTE_MODULE*>( aItem ); // Exit if there's nothing to do if( text->GetTextSize() == newSize && text->GetThickness() == newThickness ) return; SaveCopyInUndoList( text->GetParent(), UR_CHANGED ); text->SetTextSize( newSize ); text->SetThickness( newThickness ); } else return; if( aDC ) m_canvas->Refresh(); OnModify(); }
/* * Place the current text being moving */ void PCB_EDIT_FRAME::Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC ) { m_canvas->SetMouseCapture( NULL, NULL ); SetCurItem( NULL ); if( TextePcb == NULL ) return; TextePcb->Draw( m_canvas, DC, GR_OR ); OnModify(); if( TextePcb->IsNew() ) // If new: prepare undo command { SaveCopyInUndoList( TextePcb, UR_NEW ); TextePcb->ClearFlags(); return; } if( TextePcb->IsMoving() ) // If moved only { SaveCopyInUndoList( TextePcb, UR_MOVED, TextePcb->GetTextPosition() - s_TextCopy.GetTextPosition() ); } else { // Restore initial params TextePcb->SwapData( &s_TextCopy ); // Prepare undo command SaveCopyInUndoList( TextePcb, UR_CHANGED ); // Restore current params TextePcb->SwapData( &s_TextCopy ); } TextePcb->ClearFlags(); #ifdef USE_WX_OVERLAY m_canvas->Refresh(); #endif }
void PCB_EDIT_FRAME::StartMoveTextePcb( TEXTE_PCB* aTextePcb, wxDC* aDC, bool aErase ) { if( aTextePcb == NULL ) return; // if it is an existing item: prepare a copy to undo/abort command if( !aTextePcb->IsNew() ) s_TextCopy.Copy( aTextePcb ); aTextePcb->SetFlags( IS_MOVED ); SetMsgPanel( aTextePcb ); #ifdef USE_WX_OVERLAY m_canvas->Refresh(); #endif SetCrossHairPosition( aTextePcb->GetTextPosition() ); m_canvas->MoveCursorToCrossHair(); m_canvas->SetMouseCapture( Move_Texte_Pcb, Abort_Edit_Pcb_Text ); SetCurItem( aTextePcb ); m_canvas->CallMouseCapture( aDC, wxDefaultPosition, aErase ); }
TEXTE_PCB* PCB_EDIT_FRAME::CreateTextePcb( wxDC* aDC, TEXTE_PCB* aText ) { TEXTE_PCB* textePcb = new TEXTE_PCB( GetBoard() ); if( aText ) { textePcb->Copy( aText ); GetBoard()->Add( textePcb ); textePcb->SetFlags( IS_NEW ); if( aDC ) StartMoveTextePcb( textePcb, aDC, false ); // Don't erase aText when copying } else { GetBoard()->Add( textePcb ); textePcb->SetFlags( IS_NEW ); LAYER_NUM layer = ( (PCB_SCREEN*) GetScreen() )->m_Active_Layer; textePcb->SetLayer( layer ); // Set the mirrored option for layers on the BACK side of the board if( layer == LAYER_N_BACK || layer == SILKSCREEN_N_BACK || layer == SOLDERPASTE_N_BACK || layer == SOLDERMASK_N_BACK || layer == ADHESIVE_N_BACK ) textePcb->SetMirrored( true ); textePcb->SetSize( GetBoard()->GetDesignSettings().m_PcbTextSize ); textePcb->SetTextPosition( GetCrossHairPosition() ); textePcb->SetThickness( GetBoard()->GetDesignSettings().m_PcbTextWidth ); InstallTextPCBOptionsFrame( textePcb, aDC ); if( textePcb->GetText().IsEmpty() ) { textePcb->DeleteStructure(); textePcb = NULL; } else if( aDC ) { StartMoveTextePcb( textePcb, aDC ); } } return textePcb; }
void DRC::testTexts() { std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments) std::vector<D_PAD*> padList = m_pcb->GetPads(); // Test text areas for vias, tracks and pads inside text areas for( BOARD_ITEM* item = m_pcb->m_Drawings; item; item = item->Next() ) { // Drc test only items on copper layers if( ! IsCopperLayer( item->GetLayer() ) ) continue; // only texts on copper layers are tested if( item->Type() != PCB_TEXT_T ) continue; textShape.clear(); // So far the bounding box makes up the text-area TEXTE_PCB* text = (TEXTE_PCB*) item; text->TransformTextShapeToSegmentList( textShape ); if( textShape.size() == 0 ) // Should not happen (empty text?) continue; for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() ) { if( ! track->IsOnLayer( item->GetLayer() ) ) continue; // Test the distance between each segment and the current track/via int min_dist = ( track->GetWidth() + text->GetThickness() ) /2 + track->GetClearance(NULL); if( track->Type() == PCB_TRACE_T ) { SEG segref( track->GetStart(), track->GetEnd() ); // Error condition: Distance between text segment and track segment is // smaller than the clearance of the segment for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { SEG segtest( textShape[jj], textShape[jj+1] ); int dist = segref.Distance( segtest ); if( dist < min_dist ) { addMarkerToPcb( fillMarker( track, text, DRCE_TRACK_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } else if( track->Type() == PCB_VIA_T ) { // Error condition: Distance between text segment and via is // smaller than the clearance of the via for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { SEG segtest( textShape[jj], textShape[jj+1] ); if( segtest.PointCloserThan( track->GetPosition(), min_dist ) ) { addMarkerToPcb( fillMarker( track, text, DRCE_VIA_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } } // Test pads for( unsigned ii = 0; ii < padList.size(); ii++ ) { D_PAD* pad = padList[ii]; if( ! pad->IsOnLayer( item->GetLayer() ) ) continue; wxPoint shape_pos = pad->ShapePos(); for( unsigned jj = 0; jj < textShape.size(); jj += 2 ) { /* In order to make some calculations more easier or faster, * pads and tracks coordinates will be made relative * to the segment origin */ wxPoint origin = textShape[jj]; // origin will be the origin of other coordinates m_segmEnd = textShape[jj+1] - origin; wxPoint delta = m_segmEnd; m_segmAngle = 0; // for a non horizontal or vertical segment Compute the segment angle // in tenths of degrees and its length if( delta.x || delta.y ) // delta.x == delta.y == 0 for vias { // Compute the segment angle in 0,1 degrees m_segmAngle = ArcTangente( delta.y, delta.x ); // Compute the segment length: we build an equivalent rotated segment, // this segment is horizontal, therefore dx = length RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0 } m_segmLength = delta.x; m_padToTestPos = shape_pos - origin; if( !checkClearanceSegmToPad( pad, text->GetThickness(), pad->GetClearance(NULL) ) ) { addMarkerToPcb( fillMarker( pad, text, DRCE_PAD_INSIDE_TEXT, m_currentMarker ) ); m_currentMarker = nullptr; break; } } } } }
/* Initialise les cellules du board a la valeur HOLE et VIA_IMPOSSIBLE selon les marges d'isolement les elements de net_code = net_code ne seront pas places comme occupe mais en VIA_IMPOSSIBLE uniquement Pour Routage 1 seule face: le plan BOTTOM est utilise et Route_Layer_BOTTOM = Route_Layer_TOP Selon les bits = 1 du parametre flag: si FORCE_PADS : tous les pads seront places meme ceux de meme net_code */ void PlaceCells(BOARD * Pcb, int net_code, int flag) { int ii; LISTE_PAD* ptr; TRACK * pt_segm; TEXTE_PCB * PtText; DRAWSEGMENT * DrawSegm; EDA_BaseStruct * PtStruct; int ux0 = 0 , uy0 = 0, ux1, uy1, dx, dy; int marge, via_marge; int masque_layer; marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentTrackWidth /2); via_marge = g_DesignSettings.m_TrackClearence + (g_DesignSettings.m_CurrentViaSize /2); ///////////////////////////////////// // Placement des PADS sur le board // ///////////////////////////////////// ptr = (LISTE_PAD*)Pcb->m_Pads; ii = Pcb->m_NbPads; for( ; ii > 0 ; ii-- , ptr++) { if( (net_code != (*ptr)->m_NetCode ) || (flag & FORCE_PADS) ) { Place_1_Pad_Board(Pcb, *ptr, HOLE, marge, WRITE_CELL); } Place_1_Pad_Board(Pcb, *ptr, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL); } /////////////////////////////////////////////// // Placement des elements de modules sur PCB // /////////////////////////////////////////////// PtStruct = Pcb->m_Modules; for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) { EDA_BaseStruct * PtModStruct = ((MODULE*)PtStruct)->m_Drawings; for( ;PtModStruct != NULL; PtModStruct = PtModStruct->Pnext ) { switch( PtModStruct->m_StructType ) { case TYPEEDGEMODULE: { TRACK * TmpSegm = new TRACK(NULL); TmpSegm->m_Layer = ((EDGE_MODULE *) PtModStruct)->m_Layer; if(TmpSegm->m_Layer == EDGE_N) TmpSegm->m_Layer = -1; TmpSegm->m_Start = ((EDGE_MODULE *) PtModStruct)->m_Start; TmpSegm->m_End = ((EDGE_MODULE *) PtModStruct)->m_End; TmpSegm->m_Shape = ((EDGE_MODULE *) PtModStruct)->m_Shape; TmpSegm->m_Width = ((EDGE_MODULE *) PtModStruct)->m_Width; TmpSegm->m_Param = ((EDGE_MODULE *) PtModStruct)->m_Angle; TmpSegm->m_NetCode = -1; TraceSegmentPcb(Pcb, TmpSegm, HOLE, marge,WRITE_CELL ); TraceSegmentPcb(Pcb, TmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); delete TmpSegm; break; } default: break; } } } //////////////////////////////////////////// // Placement des contours et segments PCB // //////////////////////////////////////////// PtStruct = Pcb->m_Drawings; for( ; PtStruct != NULL; PtStruct = PtStruct->Pnext ) { switch( PtStruct->m_StructType) { case TYPEDRAWSEGMENT: { int type_cell = HOLE; TRACK * TmpSegm = new TRACK(NULL); DrawSegm = (DRAWSEGMENT *) PtStruct; TmpSegm->m_Layer = DrawSegm->m_Layer; if(DrawSegm->m_Layer == EDGE_N) { TmpSegm->m_Layer = -1; type_cell |= CELL_is_EDGE; } TmpSegm->m_Start = DrawSegm->m_Start; TmpSegm->m_End = DrawSegm->m_End; TmpSegm->m_Shape = DrawSegm->m_Shape; TmpSegm->m_Width = DrawSegm->m_Width; TmpSegm->m_Param = DrawSegm->m_Angle; TmpSegm->m_NetCode = -1; TraceSegmentPcb(Pcb, TmpSegm, type_cell, marge,WRITE_CELL ); // TraceSegmentPcb(Pcb, TmpSegm, VIA_IMPOSSIBLE, via_marge,WRITE_OR_CELL ); delete TmpSegm; break; } case TYPETEXTE: PtText = (TEXTE_PCB*) PtStruct; if(PtText->GetLength() == 0 ) break; ux0 = PtText->m_Pos.x; uy0 = PtText->m_Pos.y; dx = PtText->Pitch()* PtText->GetLength(); dy = PtText->m_Size.y + PtText->m_Width; /* Calcul du rectangle d'encadrement */ dx /= 2; dy /= 2; /* dx et dy = demi dimensionx X et Y */ ux1 = ux0 + dx; uy1 = uy0 + dy; ux0 -= dx; uy0 -= dy; masque_layer = g_TabOneLayerMask[PtText->m_Layer]; TraceFilledRectangle(Pcb, ux0-marge, uy0-marge, ux1+marge, uy1+marge, (int)(PtText->m_Orient), masque_layer, HOLE, WRITE_CELL); TraceFilledRectangle(Pcb, ux0-via_marge, uy0-via_marge, ux1+via_marge, uy1+via_marge, (int)(PtText->m_Orient), masque_layer, VIA_IMPOSSIBLE, WRITE_OR_CELL); break; default: break; } } /* Placement des PISTES */ pt_segm = Pcb->m_Track; for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext) { if(net_code == pt_segm->m_NetCode) continue; TraceSegmentPcb(Pcb, pt_segm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb(Pcb, pt_segm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } /* Placement des ZONES */ pt_segm = (TRACK*) Pcb->m_Zone; for( ; pt_segm != NULL; pt_segm = (TRACK*) pt_segm->Pnext) { if(net_code == pt_segm->m_NetCode) continue; TraceSegmentPcb(Pcb, pt_segm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb(Pcb, pt_segm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } }
/** * Function PlaceCells * Initialize the matrix routing by setting obstacles for each occupied cell * a cell set to HOLE is an obstacle for tracks and vias * a cell set to VIA_IMPOSSIBLE is an obstacle for vias only. * a cell set to CELL_is_EDGE is a frontier. * Tracks and vias having the same net code as net_code are skipped * (htey do not are obstacles) * * For single-sided Routing 1: * BOTTOM side is used, and Route_Layer_BOTTOM = Route_Layer_TOP * * If flag == FORCE_PADS: all pads will be put in matrix as obstacles. */ void PlaceCells( BOARD* aPcb, int net_code, int flag ) { int ux0 = 0, uy0 = 0, ux1, uy1, dx, dy; int marge, via_marge; LAYER_MSK layerMask; // use the default NETCLASS? NETCLASS* nc = aPcb->m_NetClasses.GetDefault(); int trackWidth = nc->GetTrackWidth(); int clearance = nc->GetClearance(); int viaSize = nc->GetViaDiameter(); marge = clearance + (trackWidth / 2); via_marge = clearance + (viaSize / 2); // Place PADS on matrix routing: for( unsigned i = 0; i < aPcb->GetPadCount(); ++i ) { D_PAD* pad = aPcb->GetPad( i ); if( net_code != pad->GetNet() || (flag & FORCE_PADS) ) { ::PlacePad( pad, HOLE, marge, WRITE_CELL ); } ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Place outlines of modules on matrix routing, if they are on a copper layer // or on the edge layer TRACK tmpSegm( NULL ); // A dummy track used to create segments. for( MODULE* module = aPcb->m_Modules; module; module = module->Next() ) { for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* edge = (EDGE_MODULE*) item; tmpSegm.SetLayer( edge->GetLayer() ); if( tmpSegm.GetLayer() == EDGE_N ) tmpSegm.SetLayer( UNDEFINED_LAYER ); tmpSegm.SetStart( edge->GetStart() ); tmpSegm.SetEnd( edge->GetEnd() ); tmpSegm.SetShape( edge->GetShape() ); tmpSegm.SetWidth( edge->GetWidth() ); tmpSegm.m_Param = edge->GetAngle(); tmpSegm.SetNet( -1 ); TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } break; default: break; } } } // Place board outlines and texts on copper layers: for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_LINE_T: { DRAWSEGMENT* DrawSegm; int type_cell = HOLE; DrawSegm = (DRAWSEGMENT*) item; tmpSegm.SetLayer( DrawSegm->GetLayer() ); if( DrawSegm->GetLayer() == EDGE_N ) { tmpSegm.SetLayer( UNDEFINED_LAYER ); type_cell |= CELL_is_EDGE; } tmpSegm.SetStart( DrawSegm->GetStart() ); tmpSegm.SetEnd( DrawSegm->GetEnd() ); tmpSegm.SetShape( DrawSegm->GetShape() ); tmpSegm.SetWidth( DrawSegm->GetWidth() ); tmpSegm.m_Param = DrawSegm->GetAngle(); tmpSegm.SetNet( -1 ); TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL ); } break; case PCB_TEXT_T: { TEXTE_PCB* PtText; PtText = (TEXTE_PCB*) item; if( PtText->GetText().Length() == 0 ) break; EDA_RECT textbox = PtText->GetTextBox( -1 ); ux0 = textbox.GetX(); uy0 = textbox.GetY(); dx = textbox.GetWidth(); dy = textbox.GetHeight(); /* Put bounding box (rectangle) on matrix */ dx /= 2; dy /= 2; ux1 = ux0 + dx; uy1 = uy0 + dy; ux0 -= dx; uy0 -= dy; layerMask = GetLayerMask( PtText->GetLayer() ); TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge, uy1 + marge, PtText->GetOrientation(), layerMask, HOLE, WRITE_CELL ); TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge, ux1 + via_marge, uy1 + via_marge, PtText->GetOrientation(), layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL ); } break; default: break; } } /* Put tracks and vias on matrix */ for( TRACK* track = aPcb->m_Track; track; track = track->Next() ) { if( net_code == track->GetNet() ) continue; TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } }
int DRAWING_TOOL::placeTextPcb() { TEXTE_PCB* text = NULL; 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 ); // do not capture or auto-pan until we start placing some text Activate(); m_frame->SetToolID( ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { VECTOR2I cursorPos = m_controls->GetCursorPosition(); if( evt->IsCancel() || evt->IsActivate() ) { if( text ) { // Delete the old text and have another try m_board->Delete( text ); // it was already added by CreateTextPcb() text = NULL; preview.Clear(); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_controls->ShowCursor( true ); } else break; if( evt->IsActivate() ) // now finish unconditionally break; } else if( text && evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { text->Flip( text->GetPosition() ); preview.ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); } } else if( evt->IsClick( BUT_LEFT ) ) { if( !text ) { // Init the new item attributes text = static_cast<PCB_EDIT_FRAME*>( m_frame )->CreateTextePcb( NULL ); if( text == NULL ) continue; m_controls->CaptureCursor( true ); m_controls->SetAutoPan( true ); preview.Add( text ); } else { assert( text->GetText().Length() > 0 ); assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); text->ClearFlags(); m_view->Add( text ); // m_board->Add( text ); // it is already added by CreateTextePcb() text->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); m_frame->OnModify(); m_frame->SaveCopyInUndoList( text, UR_NEW ); preview.Remove( text ); m_controls->CaptureCursor( false ); m_controls->SetAutoPan( false ); text = NULL; } } else if( text && evt->IsMotion() ) { text->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item 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; }
int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent ) { if( !m_frame->GetModel() ) return 0; DIALOG_DXF_IMPORT dlg( m_frame ); int dlgResult = dlg.ShowModal(); const std::list<BOARD_ITEM*>& list = dlg.GetImportedItems(); if( dlgResult != wxID_OK || list.empty() ) return 0; VECTOR2I cursorPos = m_controls->GetCursorPosition(); VECTOR2I delta = cursorPos - list.front()->GetPosition(); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); BOARD_COMMIT commit( m_frame ); // Build the undo list & add items to the current view for( auto item : list ) { assert( item->Type() == PCB_LINE_T || item->Type() == PCB_TEXT_T ); preview.Add( item ); } BOARD_ITEM* firstItem = preview.Front(); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF ); Activate(); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { cursorPos = m_controls->GetCursorPosition(); if( evt->IsMotion() ) { delta = cursorPos - firstItem->GetPosition(); for( auto item : preview ) item->Move( wxPoint( delta.x, delta.y ) ); m_view->Update( &preview ); } else if( evt->Category() == TC_COMMAND ) { // TODO it should be handled by EDIT_TOOL, so add items and select? if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { for( auto item : preview ) item->Rotate( wxPoint( cursorPos.x, cursorPos.y ), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { for( auto item : preview ) item->Flip( wxPoint( cursorPos.x, cursorPos.y ) ); m_view->Update( &preview ); } else if( evt->IsCancel() || evt->IsActivate() ) { preview.FreeItems(); break; } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { // Place the drawing BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); for( auto item : preview ) { if( m_editModules ) { // Modules use different types for the same things, // so we need to convert imported items to appropriate classes. BOARD_ITEM* converted = NULL; switch( item->Type() ) { case PCB_TEXT_T: { TEXTE_PCB* text = static_cast<TEXTE_PCB*>( item ); TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_TEXT_T type, // so it cannot be added to a module which handles PCB_MODULE_TEXT_T textMod->SetPosition( text->GetPosition() ); textMod->SetText( text->GetText() ); textMod->SetSize( text->GetSize() ); textMod->SetThickness( text->GetThickness() ); textMod->SetOrientation( text->GetOrientation() ); textMod->SetTextPosition( text->GetTextPosition() ); textMod->SetSize( text->GetSize() ); textMod->SetMirrored( text->IsMirrored() ); textMod->SetAttributes( text->GetAttributes() ); textMod->SetItalic( text->IsItalic() ); textMod->SetBold( text->IsBold() ); textMod->SetHorizJustify( text->GetHorizJustify() ); textMod->SetVertJustify( text->GetVertJustify() ); textMod->SetMultilineAllowed( text->IsMultilineAllowed() ); converted = textMod; break; } case PCB_LINE_T: { DRAWSEGMENT* seg = static_cast<DRAWSEGMENT*>( item ); EDGE_MODULE* modSeg = new EDGE_MODULE( (MODULE*) parent ); // Assignment operator also copies the item PCB_LINE_T type, // so it cannot be added to a module which handles PCB_MODULE_EDGE_T modSeg->SetWidth( seg->GetWidth() ); modSeg->SetStart( seg->GetStart() ); modSeg->SetEnd( seg->GetEnd() ); modSeg->SetAngle( seg->GetAngle() ); modSeg->SetShape( seg->GetShape() ); modSeg->SetType( seg->GetType() ); modSeg->SetBezControl1( seg->GetBezControl1() ); modSeg->SetBezControl2( seg->GetBezControl2() ); modSeg->SetBezierPoints( seg->GetBezierPoints() ); modSeg->SetPolyPoints( seg->GetPolyPoints() ); converted = modSeg; break; } default: assert( false ); break; } if( converted ) converted->SetLayer( item->GetLayer() ); delete item; item = converted; } if( item ) commit.Add( item ); } commit.Push( _( "Place a DXF drawing" ) ); break; } } preview.Clear(); m_controls->ShowCursor( false ); m_controls->SetSnapping( false ); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_view->Remove( &preview ); return 0; }
int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent ) { BOARD_ITEM* text = NULL; const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings(); BOARD_COMMIT commit( m_frame ); // Add a VIEW_GROUP that serves as a preview for the new item SELECTION preview( m_view ); m_view->Add( &preview ); m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear, true ); m_controls->ShowCursor( true ); m_controls->SetSnapping( true ); // do not capture or auto-pan until we start placing some text SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT ); Activate(); m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT, wxCURSOR_PENCIL, _( "Add text" ) ); // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { VECTOR2I cursorPos = m_controls->GetCursorPosition(); if( evt->IsCancel() || evt->IsActivate() ) { if( text ) { // Delete the old text and have another try delete text; text = NULL; preview.Clear(); m_controls->SetAutoPan( false ); m_controls->CaptureCursor( false ); m_controls->ShowCursor( true ); } else break; if( evt->IsActivate() ) // now finish unconditionally break; } else if( text && evt->Category() == TC_COMMAND ) { if( evt->IsAction( &COMMON_ACTIONS::rotate ) ) { text->Rotate( text->GetPosition(), m_frame->GetRotationAngle() ); m_view->Update( &preview ); } // TODO rotate CCW else if( evt->IsAction( &COMMON_ACTIONS::flip ) ) { text->Flip( text->GetPosition() ); m_view->Update( &preview ); } } else if ( evt->IsClick( BUT_RIGHT ) ) { showContextMenu(); } else if( evt->IsClick( BUT_LEFT ) ) { if( !text ) { // Init the new item attributes if( m_editModules ) { TEXTE_MODULE* textMod = new TEXTE_MODULE( (MODULE*) m_frame->GetModel() ); textMod->SetLayer( m_frame->GetActiveLayer() ); textMod->SetSize( dsnSettings.m_ModuleTextSize ); textMod->SetThickness( dsnSettings.m_ModuleTextWidth ); textMod->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); DialogEditModuleText textDialog( m_frame, textMod, NULL ); bool placing; RunMainStack( [&]() { placing = textDialog.ShowModal() && ( textMod->GetText().Length() > 0 ); } ); if( placing ) text = textMod; else delete textMod; } else { TEXTE_PCB* textPcb = new TEXTE_PCB( m_frame->GetModel() ); // TODO we have to set IS_NEW, otherwise InstallTextPCB.. creates an undo entry :| LEGACY_CLEANUP textPcb->SetFlags( IS_NEW ); LAYER_ID layer = m_frame->GetActiveLayer(); textPcb->SetLayer( layer ); // Set the mirrored option for layers on the BACK side of the board if( IsBackLayer( layer ) ) textPcb->SetMirrored( true ); textPcb->SetSize( dsnSettings.m_PcbTextSize ); textPcb->SetThickness( dsnSettings.m_PcbTextWidth ); textPcb->SetTextPosition( wxPoint( cursorPos.x, cursorPos.y ) ); RunMainStack( [&]() { getEditFrame<PCB_EDIT_FRAME>()->InstallTextPCBOptionsFrame( textPcb, NULL ); } ); if( textPcb->GetText().IsEmpty() ) delete textPcb; else text = textPcb; } if( text == NULL ) continue; m_controls->CaptureCursor( true ); m_controls->SetAutoPan( true ); //m_controls->ShowCursor( false ); preview.Add( text ); } else { //assert( text->GetText().Length() > 0 ); //assert( text->GetSize().x > 0 && text->GetSize().y > 0 ); text->ClearFlags(); preview.Remove( text ); commit.Add( text ); commit.Push( _( "Place a text" ) ); m_controls->CaptureCursor( false ); m_controls->SetAutoPan( false ); m_controls->ShowCursor( true ); text = NULL; } } else if( text && evt->IsMotion() ) { text->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) ); // Show a preview of the item m_view->Update( &preview ); } } 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; }