You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

531 lines
16 KiB

  1. /*********************************************************/
  2. /* Modules de creations de Traits, Wires, Bus, Junctions */
  3. /*********************************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "program.h"
  8. #include "libcmp.h"
  9. #include "general.h"
  10. #include "protos.h"
  11. /* Routines Locales */
  12. static void Polyline_in_Ghost(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
  13. static void Segment_in_Ghost(WinEDA_DrawPanel * panel, wxDC * DC, bool erase);
  14. static void ExitTrace(WinEDA_DrawFrame * frame, wxDC * DC);
  15. static bool IsTerminalPoint(SCH_SCREEN * screen, const wxPoint & pos, int layer );
  16. /*************************************************************/
  17. void WinEDA_SchematicFrame::BeginSegment(wxDC * DC, int type)
  18. /*************************************************************/
  19. /* Routine de Trace de segments ( WIRES, BUS ) pour lesquels chaque segment
  20. est une structure.
  21. */
  22. {
  23. DrawSegmentStruct * oldsegment, * newsegment;
  24. wxPoint pos = GetScreen()->m_Curseur;
  25. if ( GetScreen()->m_CurrentItem &&
  26. (GetScreen()->m_CurrentItem->m_Flags == 0) )
  27. GetScreen()->m_CurrentItem = NULL;
  28. if ( GetScreen()->m_CurrentItem )
  29. {
  30. switch (GetScreen()->m_CurrentItem->m_StructType )
  31. {
  32. case DRAW_SEGMENT_STRUCT_TYPE:
  33. case DRAW_POLYLINE_STRUCT_TYPE:
  34. break;
  35. default:
  36. return;
  37. }
  38. }
  39. oldsegment = newsegment =
  40. (DrawSegmentStruct *) GetScreen()->m_CurrentItem;
  41. if (!newsegment) /* 1er point : creation de la 1ere structure */
  42. {
  43. switch(type)
  44. {
  45. default:
  46. newsegment = new DrawSegmentStruct(pos, LAYER_NOTES);
  47. break;
  48. case LAYER_WIRE:
  49. newsegment = new DrawSegmentStruct(pos, LAYER_WIRE);
  50. if ( LocatePinEnd(GetScreen()->EEDrawList, pos) )
  51. newsegment->m_StartIsDangling = FALSE;
  52. break;
  53. case LAYER_BUS:
  54. newsegment = new DrawSegmentStruct(pos, LAYER_BUS);
  55. break;
  56. }
  57. newsegment->m_Flags = IS_NEW;
  58. GetScreen()->m_CurrentItem = newsegment;
  59. GetScreen()->ManageCurseur = Segment_in_Ghost;
  60. GetScreen()->ForceCloseManageCurseur = ExitTrace;
  61. g_ItemToRepeat = NULL;
  62. }
  63. else /* Trace en cours: Placement d'un point supplementaire */
  64. {
  65. if( (oldsegment->m_Start.x == oldsegment->m_End.x) &&
  66. (oldsegment->m_Start.y == oldsegment->m_End.y) ) /* Structure inutile */
  67. return;
  68. GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);
  69. oldsegment->m_EndIsDangling = FALSE;
  70. /* Creation du segment suivant ou fin de trac� si point sur pin, jonction ...*/
  71. if ( IsTerminalPoint(GetScreen(), oldsegment->m_End, oldsegment->m_Layer) )
  72. {
  73. EndSegment(DC); return;
  74. }
  75. /* Placement en liste generale */
  76. oldsegment->Pnext = GetScreen()->EEDrawList;
  77. g_ItemToRepeat = GetScreen()->EEDrawList = oldsegment;
  78. GetScreen()->CursorOff(DrawPanel, DC); // Erase schematic cursor
  79. RedrawOneStruct(DrawPanel,DC, oldsegment, GR_DEFAULT_DRAWMODE);
  80. GetScreen()->CursorOn(DrawPanel, DC); // Display schematic cursor
  81. /* Creation du segment suivant */
  82. newsegment = oldsegment->GenCopy();
  83. newsegment->m_Start = oldsegment->m_End;
  84. newsegment->m_End = pos;
  85. oldsegment->m_Flags = 0;
  86. newsegment->m_Flags = IS_NEW;
  87. GetScreen()->m_CurrentItem = newsegment;
  88. GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);
  89. newsegment->m_StartIsDangling = FALSE;
  90. newsegment->m_EndIsDangling = TRUE;
  91. }
  92. }
  93. /*************************************************************/
  94. /* Routine de fin de trace d'une struct segment (Wire, Bus */
  95. /*************************************************************/
  96. void WinEDA_SchematicFrame::EndSegment(wxDC *DC)
  97. {
  98. DrawSegmentStruct * segment = (DrawSegmentStruct *)GetScreen()->m_CurrentItem;
  99. if ( GetScreen()->ManageCurseur == NULL ) return;
  100. if ( segment == NULL ) return;
  101. if ( (segment->m_Flags & IS_NEW) == 0) return;
  102. if( (segment->m_Start.x == segment->m_End.x) &&
  103. (segment->m_Start.y == segment->m_End.y) ) /* Structure inutile */
  104. {
  105. EraseStruct(segment, (SCH_SCREEN*)GetScreen());
  106. segment = NULL;
  107. }
  108. else
  109. { /* Placement en liste generale */
  110. GetScreen()->ManageCurseur(DrawPanel, DC, FALSE);
  111. segment->Pnext = GetScreen()->EEDrawList;
  112. g_ItemToRepeat = GetScreen()->EEDrawList = segment;
  113. segment->m_Flags = 0;
  114. }
  115. /* Fin de trace */
  116. GetScreen()->ManageCurseur = NULL;
  117. GetScreen()->ForceCloseManageCurseur = NULL;
  118. GetScreen()->m_CurrentItem = NULL;
  119. TestDanglingEnds(GetScreen()->EEDrawList, DC);
  120. SetFlagModify(GetScreen());
  121. if( segment )
  122. {
  123. GetScreen()->CursorOff(DrawPanel, DC); // Erase schematic cursor
  124. RedrawOneStruct(DrawPanel,DC, segment, GR_DEFAULT_DRAWMODE);
  125. GetScreen()->CursorOn(DrawPanel, DC); // Display schematic cursor
  126. }
  127. }
  128. /****************************************************************************/
  129. static void Segment_in_Ghost(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
  130. /****************************************************************************/
  131. /* Dessin du Segment Fantome lors des deplacements du curseur
  132. */
  133. {
  134. DrawSegmentStruct * segment =
  135. (DrawSegmentStruct *) panel->m_Parent->GetScreen()->m_CurrentItem;
  136. wxPoint endpos;
  137. int color;
  138. if ( segment == NULL ) return;
  139. color = ReturnLayerColor(segment->m_Layer) ^ HIGHT_LIGHT_FLAG;
  140. endpos = panel->m_Parent->GetScreen()->m_Curseur;
  141. if( g_HVLines ) /* Coerce the line to vertical or horizontal one: */
  142. {
  143. if (ABS(endpos.x - segment->m_Start.x) < ABS(endpos.y - segment->m_Start.y))
  144. endpos.x = segment->m_Start.x;
  145. else
  146. endpos.y = segment->m_Start.y;
  147. }
  148. if( erase ) // Redraw if segment lengtht != 0
  149. {
  150. if ( (segment->m_Start.x != segment->m_End.x) ||
  151. (segment->m_Start.y != segment->m_End.y) )
  152. RedrawOneStruct(panel,DC, segment, XOR_MODE, color);
  153. }
  154. segment->m_End = endpos;
  155. // Redraw if segment lengtht != 0
  156. if ( (segment->m_Start.x != segment->m_End.x) ||
  157. (segment->m_Start.y != segment->m_End.y) )
  158. RedrawOneStruct(panel,DC, segment, XOR_MODE,color);
  159. }
  160. /*****************************************************************************/
  161. static void Polyline_in_Ghost(WinEDA_DrawPanel * panel, wxDC * DC, bool erase)
  162. /*****************************************************************************/
  163. /* Dessin du du Polyline Fantome lors des deplacements du curseur
  164. */
  165. {
  166. DrawPolylineStruct * NewPoly =
  167. (DrawPolylineStruct *)panel->m_Parent->GetScreen()->m_CurrentItem;
  168. int color;
  169. wxPoint endpos;
  170. endpos = panel->m_Parent->GetScreen()->m_Curseur;
  171. color = ReturnLayerColor(NewPoly->m_Layer);
  172. GRSetDrawMode(DC, XOR_MODE);
  173. if( g_HVLines )
  174. {
  175. /* Coerce the line to vertical or horizontal one: */
  176. if (ABS(endpos.x - NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 2]) <
  177. ABS(endpos.y - NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 1]))
  178. endpos.x = NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 2];
  179. else
  180. endpos.y = NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 1];
  181. }
  182. NewPoly->m_NumOfPoints++;
  183. if( erase )
  184. RedrawOneStruct(panel,DC, NewPoly, XOR_MODE, color);
  185. NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 2] = endpos.x;
  186. NewPoly->m_Points[NewPoly->m_NumOfPoints * 2 - 1] = endpos.y;
  187. RedrawOneStruct(panel,DC, NewPoly, XOR_MODE, color);
  188. NewPoly->m_NumOfPoints--;
  189. }
  190. /**********************************************************/
  191. void WinEDA_SchematicFrame::DeleteCurrentSegment(wxDC * DC)
  192. /**********************************************************/
  193. /*
  194. Routine effacant le dernier trait trace, ou l'element pointe par la souris
  195. */
  196. {
  197. g_ItemToRepeat = NULL;
  198. if( (GetScreen()->m_CurrentItem == NULL) ||
  199. ((GetScreen()->m_CurrentItem->m_Flags & IS_NEW) == 0) )
  200. {
  201. return;
  202. }
  203. /* Trace en cours: annulation */
  204. if (GetScreen()->m_CurrentItem->m_StructType == DRAW_POLYLINE_STRUCT_TYPE)
  205. {
  206. Polyline_in_Ghost(DrawPanel, DC, FALSE); /* Effacement du trace en cours */
  207. }
  208. else
  209. {
  210. Segment_in_Ghost(DrawPanel, DC, FALSE); /* Effacement du trace en cours */
  211. }
  212. EraseStruct(GetScreen()->m_CurrentItem, GetScreen());
  213. GetScreen()->ManageCurseur = NULL;
  214. GetScreen()->m_CurrentItem = NULL;
  215. }
  216. /***************************************************************************/
  217. EDA_BaseStruct * WinEDA_SchematicFrame::CreateNewJunctionStruct(wxDC * DC)
  218. /***************************************************************************/
  219. /* Routine to create new connection struct.
  220. */
  221. {
  222. DrawJunctionStruct *NewConnect;
  223. NewConnect = new DrawJunctionStruct(GetScreen()->m_Curseur);
  224. g_ItemToRepeat = NewConnect;
  225. GetScreen()->CursorOff(DrawPanel, DC); // Erase schematic cursor
  226. RedrawOneStruct(DrawPanel,DC, NewConnect, GR_DEFAULT_DRAWMODE);
  227. GetScreen()->CursorOn(DrawPanel, DC); // Display schematic cursor
  228. NewConnect->Pnext = GetScreen()->EEDrawList;
  229. GetScreen()->EEDrawList = NewConnect;
  230. SetFlagModify(GetScreen());
  231. return(NewConnect);
  232. }
  233. /*************************************************************************/
  234. EDA_BaseStruct *WinEDA_SchematicFrame::CreateNewNoConnectStruct(wxDC * DC)
  235. /*************************************************************************/
  236. /*Routine to create new NoConnect struct. ( Symbole de Non Connexion)
  237. */
  238. {
  239. DrawNoConnectStruct *NewNoConnect;
  240. NewNoConnect = new DrawNoConnectStruct(GetScreen()->m_Curseur);
  241. g_ItemToRepeat = NewNoConnect;
  242. GetScreen()->CursorOff(DrawPanel, DC); // Erase schematic cursor
  243. RedrawOneStruct(DrawPanel,DC, NewNoConnect, GR_DEFAULT_DRAWMODE);
  244. GetScreen()->CursorOn(DrawPanel, DC); // Display schematic cursor
  245. NewNoConnect->Pnext = GetScreen()->EEDrawList;
  246. GetScreen()->EEDrawList = NewNoConnect;
  247. SetFlagModify(GetScreen());
  248. return(NewNoConnect);
  249. }
  250. /**********************************************************/
  251. static void ExitTrace(WinEDA_DrawFrame * frame, wxDC * DC)
  252. /**********************************************************/
  253. /* Routine de sortie des menus de trace */
  254. {
  255. BASE_SCREEN * Screen = frame->GetScreen();
  256. if( Screen->m_CurrentItem) /* trace en cours */
  257. {
  258. Screen->ManageCurseur(frame->DrawPanel, DC, FALSE);
  259. Screen->ManageCurseur = NULL;
  260. Screen->ForceCloseManageCurseur = NULL;
  261. EraseStruct(Screen->m_CurrentItem,(SCH_SCREEN*) Screen);
  262. Screen->m_CurrentItem = NULL;
  263. return;
  264. }
  265. else g_ItemToRepeat = NULL; // Fin de commande generale
  266. }
  267. /***************************************************/
  268. void WinEDA_SchematicFrame::RepeatDrawItem(wxDC *DC)
  269. /***************************************************/
  270. /* Routine de recopie du dernier element dessine
  271. Les elements duplicables sont
  272. fils, bus, traits, textes, labels
  273. Les labels termines par un nombre seront incrementes
  274. */
  275. {
  276. char Line[256];
  277. int ox = 0, oy = 0;
  278. if( g_ItemToRepeat == NULL ) return;
  279. switch( g_ItemToRepeat->m_StructType )
  280. {
  281. case DRAW_JUNCTION_STRUCT_TYPE:
  282. #undef STRUCT
  283. #define STRUCT ((DrawJunctionStruct*) g_ItemToRepeat)
  284. g_ItemToRepeat = STRUCT->GenCopy();
  285. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  286. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  287. break;
  288. case DRAW_NOCONNECT_STRUCT_TYPE:
  289. #undef STRUCT
  290. #define STRUCT ((DrawNoConnectStruct*) g_ItemToRepeat)
  291. g_ItemToRepeat = STRUCT->GenCopy();
  292. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  293. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  294. break;
  295. case DRAW_TEXT_STRUCT_TYPE:
  296. #undef STRUCT
  297. #define STRUCT ((DrawTextStruct*) g_ItemToRepeat)
  298. g_ItemToRepeat = STRUCT->GenCopy();
  299. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  300. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  301. /*** Increment du numero de label ***/
  302. strcpy(Line,STRUCT->GetText());
  303. IncrementLabelMember(Line);
  304. STRUCT->m_Text = Line;
  305. break;
  306. case DRAW_LABEL_STRUCT_TYPE:
  307. #undef STRUCT
  308. #define STRUCT ((DrawLabelStruct*) g_ItemToRepeat)
  309. g_ItemToRepeat = STRUCT->GenCopy();
  310. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  311. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  312. /*** Increment du numero de label ***/
  313. strcpy(Line,STRUCT->GetText());
  314. IncrementLabelMember(Line);
  315. STRUCT->m_Text = Line;
  316. break;
  317. case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
  318. #undef STRUCT
  319. #define STRUCT ((DrawGlobalLabelStruct*) g_ItemToRepeat)
  320. g_ItemToRepeat = STRUCT->GenCopy();
  321. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  322. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  323. /*** Increment du numero de label ***/
  324. strcpy(Line,STRUCT->GetText());
  325. IncrementLabelMember(Line);
  326. STRUCT->m_Text = Line;
  327. break;
  328. case DRAW_SEGMENT_STRUCT_TYPE:
  329. #undef STRUCT
  330. #define STRUCT ((DrawSegmentStruct*) g_ItemToRepeat)
  331. g_ItemToRepeat = STRUCT->GenCopy();
  332. STRUCT->m_Start.x += g_RepeatStep.x; ox = STRUCT->m_Start.x;
  333. STRUCT->m_Start.y += g_RepeatStep.y; oy = STRUCT->m_Start.y;
  334. STRUCT->m_End.x += g_RepeatStep.x;
  335. STRUCT->m_End.y += g_RepeatStep.y;
  336. break;
  337. case DRAW_RACCORD_STRUCT_TYPE:
  338. #undef STRUCT
  339. #define STRUCT ((DrawRaccordStruct*) g_ItemToRepeat)
  340. g_ItemToRepeat = STRUCT->GenCopy();
  341. STRUCT->m_Pos.x += g_RepeatStep.x; ox = STRUCT->m_Pos.x;
  342. STRUCT->m_Pos.y += g_RepeatStep.y; oy = STRUCT->m_Pos.y;
  343. break;
  344. default:
  345. g_ItemToRepeat = NULL;
  346. DisplayError(this, "Repeat Type Error", 10);
  347. break;
  348. }
  349. if ( g_ItemToRepeat )
  350. {
  351. g_ItemToRepeat->Pnext = GetScreen()->EEDrawList;
  352. GetScreen()->EEDrawList = g_ItemToRepeat;
  353. TestDanglingEnds(GetScreen()->EEDrawList, NULL);
  354. RedrawOneStruct(DrawPanel,DC, g_ItemToRepeat, GR_DEFAULT_DRAWMODE);
  355. // GetScreen()->Curseur.x = ox; GetScreen()->Curseur.x = oy;
  356. // GRMouseWarp(DrawPanel, DrawPanel->CursorScreenPosition() );
  357. }
  358. }
  359. /******************************************/
  360. void IncrementLabelMember(char * Line)
  361. /******************************************/
  362. /* Routine incrementant les labels, c'est a dire pour les textes finissant
  363. par un nombre, ajoutant <RepeatDeltaLabel> a ce nombre
  364. */
  365. {
  366. char * strnum;
  367. int ii;
  368. strnum = Line + strlen(Line) - 1;
  369. if( !isdigit(*strnum) ) return;
  370. while( (strnum >= Line) && isdigit(*strnum) ) strnum--;
  371. strnum++; /* pointe le debut de la chaine des digits */
  372. ii = atoi(strnum) + g_RepeatDeltaLabel;
  373. sprintf(strnum, "%d", ii);
  374. }
  375. /***************************************************************************/
  376. static bool IsTerminalPoint(SCH_SCREEN * screen, const wxPoint & pos, int layer)
  377. /***************************************************************************/
  378. /* Returne TRUE si pos est un point possible pour terminer automatiquement un
  379. segment, c'est a dire pour
  380. - type WIRE, si il y a
  381. - une jonction
  382. - ou une pin
  383. - ou une extrmit unique de fil
  384. - type BUS, si il y a
  385. - ou une extrmit unique de BUS
  386. */
  387. {
  388. EDA_BaseStruct * item;
  389. LibDrawPin * pin;
  390. DrawLibItemStruct * LibItem = NULL;
  391. DrawSheetLabelStruct * pinsheet;
  392. wxPoint itempos;
  393. switch ( layer )
  394. {
  395. case LAYER_BUS:
  396. item = PickStruct(screen, BUSITEM);
  397. if ( item ) return TRUE;
  398. pinsheet = LocateAnyPinSheet(pos, screen->EEDrawList );
  399. if ( pinsheet && IsBusLabel(pinsheet->GetText()) )
  400. {
  401. itempos = pinsheet->m_Pos;
  402. if ( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE;
  403. }
  404. break;
  405. case LAYER_NOTES:
  406. item = PickStruct(screen, DRAWITEM);
  407. if ( item )
  408. return TRUE;
  409. break;
  410. case LAYER_WIRE:
  411. item = PickStruct(screen, RACCORDITEM |JUNCTIONITEM);
  412. if ( item ) return TRUE;
  413. pin = LocateAnyPin( screen->EEDrawList, pos, &LibItem );
  414. if ( pin && LibItem )
  415. {
  416. // calcul de la position exacte du point de connexion de la pin,
  417. // selon orientation du composant:
  418. itempos = LibItem->GetScreenCoord(pin->m_Pos);
  419. itempos.x += LibItem->m_Pos.x;
  420. itempos.y += LibItem->m_Pos.y;
  421. if ( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE;
  422. }
  423. item = PickStruct(screen, WIREITEM);
  424. if ( item ) return TRUE;
  425. item = PickStruct(screen, LABELITEM);
  426. if ( item && (item->m_StructType != DRAW_TEXT_STRUCT_TYPE) &&
  427. ( ((DrawGlobalLabelStruct*)item)->m_Pos.x == pos.x) &&
  428. ( ((DrawGlobalLabelStruct*)item)->m_Pos.y == pos.y) )
  429. return TRUE;
  430. pinsheet = LocateAnyPinSheet( pos, screen->EEDrawList );
  431. if ( pinsheet && ! IsBusLabel(pinsheet->GetText()) )
  432. {
  433. itempos = pinsheet->m_Pos;
  434. if ( (itempos.x == pos.x) && (itempos.y == pos.y) ) return TRUE;
  435. }
  436. break;
  437. default:
  438. break;
  439. }
  440. return FALSE;
  441. }