void DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::OnOkClick( wxCommandEvent& event ) /*******************************************************************/ /* Copy values in text control to the item parameters */ { LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection(); if( IsCopperLayer( layer ) ) { /* an edge is put on a copper layer: this it is very dangerous. a * confirmation is requested */ if( !IsOK( NULL, _( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) ) return; } m_parent->SaveCopyInUndoList( m_module, UR_MODEDIT ); m_module->SetLastEditTime(); wxString msg; wxPoint coord; msg = m_Center_StartXCtrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_Center_StartYCtrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetStart( coord ); m_item->SetStart0( coord ); msg = m_EndX_Radius_Ctrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_EndY_Ctrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetEnd( coord ); m_item->SetEnd0( coord ); msg = m_ThicknessCtrl->GetValue(); m_item->SetWidth( ValueFromString( g_UserUnit, msg ) ); msg = m_DefaultThicknessCtrl->GetValue(); int thickness = ValueFromString( g_UserUnit, msg ); m_brdSettings.m_ModuleSegmentWidth = thickness; m_parent->SetDesignSettings( m_brdSettings ); m_item->SetLayer( layer ); if( m_item->GetShape() == S_ARC ) { double angle; m_Angle_Ctrl->GetValue().ToDouble( &angle ); NORMALIZE_ANGLE_360(angle); m_item->SetAngle( angle ); } m_parent->OnModify(); m_parent->SetMsgPanel( m_item ); Close( true ); }
bool DIALOG_MODEDIT_FP_BODY_ITEM_PROPERTIES::TransferDataFromWindow() { if( !DIALOG_GRAPHIC_ITEM_PROPERTIES_BASE::TransferDataFromWindow() ) return false; LAYER_NUM layer = m_LayerSelectionCtrl->GetLayerSelection(); if( IsCopperLayer( layer ) ) { /* an edge is put on a copper layer: this it is very dangerous. a * confirmation is requested */ if( !IsOK( NULL, _( "The graphic item will be on a copper layer. This is very dangerous. Are you sure?" ) ) ) return false;; } m_parent->SaveCopyInUndoList( m_module, UR_MODEDIT ); m_module->SetLastEditTime(); wxString msg; wxPoint coord; msg = m_Center_StartXCtrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_Center_StartYCtrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetStart( coord ); m_item->SetStart0( coord ); msg = m_EndX_Radius_Ctrl->GetValue(); coord.x = ValueFromString( g_UserUnit, msg ); msg = m_EndY_Ctrl->GetValue(); coord.y = ValueFromString( g_UserUnit, msg ); m_item->SetEnd( coord ); m_item->SetEnd0( coord ); msg = m_ThicknessCtrl->GetValue(); m_item->SetWidth( ValueFromString( g_UserUnit, msg ) ); msg = m_DefaultThicknessCtrl->GetValue(); int thickness = ValueFromString( g_UserUnit, msg ); m_brdSettings.m_ModuleSegmentWidth = thickness; m_parent->SetDesignSettings( m_brdSettings ); m_item->SetLayer( ToLAYER_ID( layer ) ); if( m_item->GetShape() == S_ARC ) { m_item->SetAngle( m_AngleValue * 10.0 ); } m_parent->OnModify(); m_parent->SetMsgPanel( m_item ); return true; }
/* Move marked items, at new position = old position + offset */ void MoveMarkedItems( MODULE* module, wxPoint offset ) { EDA_ITEM* item; if( module == NULL ) return; if( module->Reference().IsSelected() ) module->Reference().Move( offset ); if( module->Value().IsSelected() ) module->Value().Move( offset ); D_PAD* pad = module->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->SetPosition( pad->GetPosition() + offset ); pad->SetPos0( pad->GetPos0() + offset ); } item = module->GraphicalItems(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: static_cast<TEXTE_MODULE*>( item )->Move( offset ); break; case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; em->SetStart( em->GetStart() + offset ); em->SetEnd( em->GetEnd() + offset ); em->SetStart0( em->GetStart0() + offset ); em->SetEnd0( em->GetEnd0() + offset ); } break; default: ; } } ClearMarkItems( module ); }
/* Move marked items, at new position = old position + offset */ void MoveMarkedItems( MODULE* module, wxPoint offset ) { EDA_ITEM* item; if( module == NULL ) return; D_PAD* pad = module->Pads(); for( ; pad != NULL; pad = pad->Next() ) { if( !pad->IsSelected() ) continue; pad->SetPosition( pad->GetPosition() + offset ); pad->SetPos0( pad->GetPos0() + offset ); } item = module->GraphicalItems(); for( ; item != NULL; item = item->Next() ) { if( !item->IsSelected() ) continue; switch( item->Type() ) { case PCB_MODULE_TEXT_T: { TEXTE_MODULE* tm = (TEXTE_MODULE*) item; tm->Offset( offset ); tm->SetPos0( tm->GetPos0() + offset ); } break; case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; em->SetStart( em->GetStart() + offset ); em->SetEnd( em->GetEnd() + offset ); em->SetStart0( em->GetStart0() + offset ); em->SetEnd0( em->GetEnd0() + offset ); } break; default: ; } item->ClearFlags(); } }
MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern, PCB_EDIT_FRAME* aPcbFrame, wxString& aErrorMessage ) { /* Build a microwave inductor footprint. * - Length Mself.lng * - Extremities Mself.m_Start and Mself.m_End * We must determine: * Mself.nbrin = number of segments perpendicular to the direction * (The coil nbrin will demicercles + 1 + 2 1 / 4 circle) * Mself.lbrin = length of a strand * Mself.radius = radius of rounded parts of the coil * Mself.delta = segments extremities connection between him and the coil even * * The equations are * Mself.m_Size.x = 2 * Mself.radius + Mself.lbrin * Mself.m_Size.y * Mself.delta = 2 + 2 * Mself.nbrin * Mself.radius * Mself.lng = 2 * Mself.delta / / connections to the coil + (Mself.nbrin-2) * Mself.lbrin / / length of the strands except 1st and last + (Mself.nbrin 1) * (PI * Mself.radius) / / length of rounded * Mself.lbrin + / 2 - Melf.radius * 2) / / length of 1st and last bit * * The constraints are: * Nbrin >= 2 * Mself.radius < Mself.m_Size.x * Mself.m_Size.y = Mself.radius * 4 + 2 * Mself.raccord * Mself.lbrin> Mself.radius * 2 * * The calculation is conducted in the following way: * Initially: * Nbrin = 2 * Radius = 4 * m_Size.x (arbitrarily fixed value) * Then: * Increasing the number of segments to the desired length * (Radius decreases if necessary) */ D_PAD* pad; int ll; wxString msg; auto pt = inductorPattern.m_End - inductorPattern.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); inductorPattern.m_length = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, inductorPattern.m_length ); wxTextEntryDialog dlg( nullptr, wxEmptyString, _( "Length of Trace:" ), msg ); if( dlg.ShowModal() != wxID_OK ) return nullptr; // canceled by user msg = dlg.GetValue(); inductorPattern.m_length = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( inductorPattern.m_length < min_len ) { aErrorMessage = _( "Requested length < minimum length" ); return nullptr; } // Calculate the elements. std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, inductorPattern.m_Start, inductorPattern.m_End, inductorPattern.m_length, inductorPattern.m_Width ); if( !ll ) { aErrorMessage = _( "Requested length too large" ); return nullptr; } // Generate footprint. the value is also used as footprint name. msg = "L"; wxTextEntryDialog cmpdlg( nullptr, wxEmptyString, _( "Component Value:" ), msg ); cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) ); if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() ) return nullptr; // Aborted by user MODULE* module = aPcbFrame->CreateNewModule( msg ); // here the module is already in the BOARD, CreateNewModule() does that. module->SetFPID( LIB_ID( wxString( "mw_inductor" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( inductorPattern.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( inductorPattern.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItemsList().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->PadsList().PushFront( pad ); pad->SetName( "1" ); pad->SetPosition( inductorPattern.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( inductorPattern.m_Width, inductorPattern.m_Width ) ); pad->SetLayerSet( LSET( module->GetLayer() ) ); pad->SetAttribute( PAD_ATTRIB_SMD ); pad->SetShape( PAD_SHAPE_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->PadsList().Insert( newpad, pad->Next() ); pad = newpad; pad->SetName( "2" ); pad->SetPosition( inductorPattern.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. wxPoint refPos( ( inductorPattern.m_Start.x + inductorPattern.m_End.x ) / 2, ( inductorPattern.m_Start.y + inductorPattern.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetTextSize().y; module->Reference().SetPosition( refPos ); valPos.y += module->Value().GetTextSize().y; module->Value().SetPosition( valPos ); module->CalculateBoundingBox(); return module; }
/** Rotate marked items, refer to a rotation point at position offset * Note: because this function is used in global transform, * if force_all is true, all items will be rotated */ void RotateMarkedItems( MODULE* module, wxPoint offset, bool force_all ) { #define ROTATE( z ) RotatePoint( (&z), offset, 900 ) if( module == NULL ) return; for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( !pad->IsSelected() && !force_all ) continue; wxPoint pos = pad->GetPosition(); ROTATE( pos ); pad->SetPosition( pos ); pad->SetPos0( pad->GetPosition() ); pad->SetOrientation( pad->GetOrientation() + 900 ); } for( EDA_ITEM* item = module->GraphicalItems(); item; item = item->Next() ) { if( !item->IsSelected() && !force_all) continue; switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; wxPoint tmp = em->GetStart(); ROTATE( tmp ); em->SetStart( tmp ); em->SetStart0( tmp ); tmp = em->GetEnd(); ROTATE( tmp ); em->SetEnd( tmp ); em->SetEnd0( tmp ); } break; case PCB_MODULE_TEXT_T: { TEXTE_MODULE* tm = (TEXTE_MODULE*) item; wxPoint pos = tm->GetTextPosition(); ROTATE( pos ); tm->SetTextPosition( pos ); tm->SetPos0( tm->GetTextPosition() ); tm->SetOrientation( tm->GetOrientation() + 900 ); } break; default: ; } item->ClearFlags(); } }
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) { D_PAD* pad; int ll; wxString msg; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->SetMouseCapture( NULL, NULL ); if( s_inductor_pattern.m_Flag == false ) { DisplayError( this, wxT( "Starting point not init.." ) ); return NULL; } s_inductor_pattern.m_Flag = false; s_inductor_pattern.m_End = GetCrossHairPosition(); wxPoint pt = s_inductor_pattern.m_End - s_inductor_pattern.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); s_inductor_pattern.m_lenght = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, s_inductor_pattern.m_lenght ); wxTextEntryDialog dlg( this, wxEmptyString, _( "Length of Trace:" ), msg ); if( dlg.ShowModal() != wxID_OK ) return NULL; // canceled by user msg = dlg.GetValue(); s_inductor_pattern.m_lenght = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( s_inductor_pattern.m_lenght < min_len ) { DisplayError( this, _( "Requested length < minimum length" ) ); return NULL; } // Calculate the elements. s_inductor_pattern.m_Width = GetDesignSettings().GetCurrentTrackWidth(); std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, s_inductor_pattern.m_Start, s_inductor_pattern.m_End, s_inductor_pattern.m_lenght, s_inductor_pattern.m_Width ); if( !ll ) { DisplayError( this, _( "Requested length too large" ) ); return NULL; } // Generate footprint. the value is also used as footprint name. msg.Empty(); wxTextEntryDialog cmpdlg( this, wxEmptyString, _( "Component Value:" ), msg ); cmpdlg.SetTextValidator( FILE_NAME_CHAR_VALIDATOR( &msg ) ); if( ( cmpdlg.ShowModal() != wxID_OK ) || msg.IsEmpty() ) return NULL; // Aborted by user MODULE* module = CreateNewModule( msg ); // here the module is already in the BOARD, CreateNewModule() does that. module->SetFPID( FPID( std::string( "mw_inductor" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( s_inductor_pattern.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( s_inductor_pattern.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItems().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->Pads().PushFront( pad ); pad->SetPadName( wxT( "1" ) ); pad->SetPosition( s_inductor_pattern.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( s_inductor_pattern.m_Width, s_inductor_pattern.m_Width ) ); pad->SetLayerSet( LSET( module->GetLayer() ) ); pad->SetAttribute( PAD_ATTRIB_SMD ); pad->SetShape( PAD_SHAPE_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->Pads().Insert( newpad, pad->Next() ); pad = newpad; pad->SetPadName( wxT( "2" ) ); pad->SetPosition( s_inductor_pattern.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. SetMsgPanel( module ); wxPoint refPos( ( s_inductor_pattern.m_Start.x + s_inductor_pattern.m_End.x ) / 2, ( s_inductor_pattern.m_Start.y + s_inductor_pattern.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetSize().y; module->Reference().SetPosition( refPos ); valPos.y += module->Value().GetSize().y; module->Value().SetPosition( valPos ); module->CalculateBoundingBox(); module->Draw( m_canvas, DC, GR_OR ); return module; }
void MODULE::Flip( const wxPoint& aCentre ) { TEXTE_MODULE* text; // Move module to its final position: wxPoint finalPos = m_Pos; finalPos.y = aCentre.y - ( finalPos.y - aCentre.y ); /// Mirror the Y position SetPosition( finalPos ); // Flip layer SetLayer( FlipLayer( GetLayer() ) ); // Reverse mirror orientation. NEGATE( m_Orient ); NORMALIZE_ANGLE_POS( m_Orient ); // Mirror pads to other side of board about the x axis, i.e. vertically. for( D_PAD* pad = m_Pads; pad; pad = pad->Next() ) pad->Flip( m_Pos ); // Mirror reference. text = m_Reference; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE(text->m_Pos0.y); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); // Mirror value. text = m_Value; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE( text->m_Pos0.y ); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); // Reverse mirror module graphics and texts. for( EDA_ITEM* item = m_Drawings; item; item = item->Next() ) { switch( item->Type() ) { case PCB_MODULE_EDGE_T: { EDGE_MODULE* em = (EDGE_MODULE*) item; wxPoint s = em->GetStart(); s.y -= m_Pos.y; s.y = -s.y; s.y += m_Pos.y; em->SetStart( s ); wxPoint e = em->GetEnd(); e.y -= m_Pos.y; e.y = -e.y; e.y += m_Pos.y; em->SetEnd( e ); NEGATE( em->m_Start0.y ); NEGATE( em->m_End0.y ); if( em->GetShape() == S_ARC ) { em->SetAngle( -em->GetAngle() ); } em->SetLayer( FlipLayer( em->GetLayer() ) ); } break; case PCB_MODULE_TEXT_T: text = (TEXTE_MODULE*) item; text->m_Pos.y -= m_Pos.y; NEGATE( text->m_Pos.y ); text->m_Pos.y += m_Pos.y; NEGATE( text->m_Pos0.y ); NEGATE_AND_NORMALIZE_ANGLE_POS( text->m_Orient ); text->SetLayer( FlipLayer( text->GetLayer() ) ); text->m_Mirror = IsBackLayer( GetLayer() ); break; default: wxMessageBox( wxT( "MODULE::Flip() error: Unknown Draw Type" ) ); break; } } CalculateBoundingBox(); }
MODULE* PCB_EDIT_FRAME::Genere_Self( wxDC* DC ) { D_PAD* pad; int ll; wxString msg; m_canvas->CallMouseCapture( DC, wxDefaultPosition, false ); m_canvas->SetMouseCapture( NULL, NULL ); if( Self_On == 0 ) { DisplayError( this, wxT( "Starting point not init.." ) ); return NULL; } Self_On = 0; Mself.m_End = GetCrossHairPosition(); wxPoint pt = Mself.m_End - Mself.m_Start; int min_len = KiROUND( EuclideanNorm( pt ) ); Mself.lng = min_len; // Enter the desired length. msg = StringFromValue( g_UserUnit, Mself.lng ); wxTextEntryDialog dlg( this, _( "Length:" ), _( "Length" ), msg ); if( dlg.ShowModal() != wxID_OK ) return NULL; // canceled by user msg = dlg.GetValue(); Mself.lng = ValueFromString( g_UserUnit, msg ); // Control values (ii = minimum length) if( Mself.lng < min_len ) { DisplayError( this, _( "Requested length < minimum length" ) ); return NULL; } // Calculate the elements. Mself.m_Width = GetBoard()->GetCurrentTrackWidth(); std::vector <wxPoint> buffer; ll = BuildCornersList_S_Shape( buffer, Mself.m_Start, Mself.m_End, Mself.lng, Mself.m_Width ); if( !ll ) { DisplayError( this, _( "Requested length too large" ) ); return NULL; } // Generate module. MODULE* module; module = Create_1_Module( wxEmptyString ); if( module == NULL ) return NULL; // here the module is already in the BOARD, Create_1_Module() does that. module->SetFPID( FPID( std::string( "MuSelf" ) ) ); module->SetAttributes( MOD_VIRTUAL | MOD_CMS ); module->ClearFlags(); module->SetPosition( Mself.m_End ); // Generate segments for( unsigned jj = 1; jj < buffer.size(); jj++ ) { EDGE_MODULE* PtSegm; PtSegm = new EDGE_MODULE( module ); PtSegm->SetStart( buffer[jj - 1] ); PtSegm->SetEnd( buffer[jj] ); PtSegm->SetWidth( Mself.m_Width ); PtSegm->SetLayer( module->GetLayer() ); PtSegm->SetShape( S_SEGMENT ); PtSegm->SetStart0( PtSegm->GetStart() - module->GetPosition() ); PtSegm->SetEnd0( PtSegm->GetEnd() - module->GetPosition() ); module->GraphicalItems().PushBack( PtSegm ); } // Place a pad on each end of coil. pad = new D_PAD( module ); module->Pads().PushFront( pad ); pad->SetPadName( wxT( "1" ) ); pad->SetPosition( Mself.m_End ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); pad->SetSize( wxSize( Mself.m_Width, Mself.m_Width ) ); pad->SetLayerMask( GetLayerMask( module->GetLayer() ) ); pad->SetAttribute( PAD_SMD ); pad->SetShape( PAD_CIRCLE ); D_PAD* newpad = new D_PAD( *pad ); module->Pads().Insert( newpad, pad->Next() ); pad = newpad; pad->SetPadName( wxT( "2" ) ); pad->SetPosition( Mself.m_Start ); pad->SetPos0( pad->GetPosition() - module->GetPosition() ); // Modify text positions. SetMsgPanel( module ); wxPoint refPos( ( Mself.m_Start.x + Mself.m_End.x ) / 2, ( Mself.m_Start.y + Mself.m_End.y ) / 2 ); wxPoint valPos = refPos; refPos.y -= module->Reference().GetSize().y; module->Reference().SetTextPosition( refPos ); valPos.y += module->Value().GetSize().y; module->Value().SetTextPosition( valPos ); module->Reference().SetPos0( module->Reference().GetTextPosition() - module->GetPosition() ); module->Value().SetPos0( module->Value().GetTextPosition() - module->GetPosition() ); module->CalculateBoundingBox(); module->Draw( m_canvas, DC, GR_OR ); return module; }
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; }