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.

1296 lines
37 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /******************************************/
  2. /* drawpanel.cpp - WinEDA_DrawPanel class */
  3. /******************************************/
  4. #ifdef __GNUG__
  5. #pragma implementation
  6. #endif
  7. #include "fctsys.h"
  8. #include "common.h"
  9. #include "macros.h"
  10. #include "id.h"
  11. // Local defines
  12. #define CURSOR_SIZE 12 // Cursor size in pixels
  13. // Events used by WinEDA_DrawPanel
  14. BEGIN_EVENT_TABLE( WinEDA_DrawPanel, EDA_DRAW_PANEL )
  15. EVT_LEAVE_WINDOW( WinEDA_DrawPanel::OnMouseLeaving )
  16. EVT_MOUSE_EVENTS( WinEDA_DrawPanel::OnMouseEvent )
  17. EVT_CHAR( WinEDA_DrawPanel::OnKeyEvent )
  18. EVT_CHAR_HOOK( WinEDA_DrawPanel::OnKeyEvent )
  19. EVT_PAINT( WinEDA_DrawPanel::OnPaint )
  20. EVT_SIZE( WinEDA_DrawPanel::OnSize )
  21. EVT_ERASE_BACKGROUND( WinEDA_DrawPanel::OnEraseBackground )
  22. EVT_SCROLLWIN( WinEDA_DrawPanel::OnScroll )
  23. EVT_ACTIVATE( WinEDA_DrawPanel::OnActivate )
  24. EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE,
  25. WinEDA_DrawPanel::Process_Popup_Zoom )
  26. END_EVENT_TABLE()
  27. /************************************************************************/
  28. /* WinEDA_DrawPanel basic functions (WinEDA_DrawPanel is the main panel)*/
  29. /************************************************************************/
  30. WinEDA_DrawPanel::WinEDA_DrawPanel( WinEDA_DrawFrame* parent, int id,
  31. const wxPoint& pos, const wxSize& size ) :
  32. EDA_DRAW_PANEL( parent, id, pos, size,
  33. wxBORDER | wxNO_FULL_REPAINT_ON_RESIZE )
  34. {
  35. m_Parent = parent;
  36. m_Ident = m_Parent->m_Ident;
  37. m_Scroll_unit = 1;
  38. m_ScrollButt_unit = 40;
  39. SetBackgroundColour( wxColour( ColorRefs[g_DrawBgColor].m_Red,
  40. ColorRefs[g_DrawBgColor].m_Green,
  41. ColorRefs[g_DrawBgColor].m_Blue ) );
  42. EnableScrolling( TRUE, TRUE );
  43. m_ClipBox.SetSize( size );
  44. m_ClipBox.SetX( 0 );
  45. m_ClipBox.SetY( 0 );
  46. m_CanStartBlock = -1; // Command block can start if >= 0
  47. m_AbortEnable = m_AbortRequest = FALSE;
  48. m_AutoPAN_Enable = TRUE;
  49. m_IgnoreMouseEvents = 0;
  50. ManageCurseur = NULL;
  51. ForceCloseManageCurseur = NULL;
  52. if( m_Parent->m_Parent->m_EDA_Config )
  53. m_AutoPAN_Enable = m_Parent->m_Parent->m_EDA_Config->Read( wxT( "AutoPAN" ), TRUE );
  54. m_AutoPAN_Request = FALSE;
  55. m_Block_Enable = FALSE;
  56. m_PanelDefaultCursor = m_PanelCursor = wxCURSOR_ARROW;
  57. m_CursorLevel = 0;
  58. }
  59. /*********************************************************************************/
  60. void WinEDA_DrawPanel::Trace_Curseur( wxDC* DC, int color )
  61. /*********************************************************************************/
  62. /*
  63. * Draw the schematic cursor which is usually on grid
  64. */
  65. {
  66. if( m_CursorLevel != 0 )
  67. {
  68. return;
  69. }
  70. if( DC == NULL )
  71. return;
  72. wxPoint Cursor = GetScreen()->m_Curseur;
  73. GRSetDrawMode( DC, GR_XOR );
  74. if( g_CursorShape == 1 ) /* Trace d'un reticule */
  75. {
  76. int dx = m_ClipBox.GetWidth() * GetZoom();
  77. int dy = m_ClipBox.GetHeight() * GetZoom();
  78. GRLine( &m_ClipBox, DC, Cursor.x - dx, Cursor.y,
  79. Cursor.x + dx, Cursor.y, 0, color ); // axe Y
  80. GRLine( &m_ClipBox, DC, Cursor.x, Cursor.y - dx,
  81. Cursor.x, Cursor.y + dy, 0, color ); // axe X
  82. }
  83. else
  84. {
  85. int len = CURSOR_SIZE * GetZoom();
  86. GRLine( &m_ClipBox, DC, Cursor.x - len, Cursor.y,
  87. Cursor.x + len, Cursor.y, 0, color );
  88. GRLine( &m_ClipBox, DC, Cursor.x, Cursor.y - len,
  89. Cursor.x, Cursor.y + len, 0, color );
  90. }
  91. }
  92. /*******************************************************************/
  93. void WinEDA_DrawPanel::CursorOff( wxDC* DC )
  94. /*******************************************************************/
  95. /*
  96. * Remove the grid cursor from the display in preparation for other drawing operations
  97. */
  98. {
  99. Trace_Curseur( DC );
  100. --m_CursorLevel;
  101. }
  102. /*******************************************************************/
  103. void WinEDA_DrawPanel::CursorOn( wxDC* DC )
  104. /*******************************************************************/
  105. /*
  106. * Display the grid cursor
  107. */
  108. {
  109. ++m_CursorLevel;
  110. Trace_Curseur( DC );
  111. if( m_CursorLevel > 0 ) // Shouldn't happen, but just in case ..
  112. m_CursorLevel = 0;
  113. }
  114. /***********************************/
  115. int WinEDA_DrawPanel::GetZoom()
  116. /***********************************/
  117. {
  118. return GetScreen()->GetZoom();
  119. }
  120. /***************************************/
  121. void WinEDA_DrawPanel::SetZoom( int zoom )
  122. /***************************************/
  123. {
  124. GetScreen()->SetZoom( zoom );
  125. }
  126. /************************************/
  127. wxSize WinEDA_DrawPanel::GetGrid()
  128. /************************************/
  129. {
  130. return GetScreen()->GetGrid();
  131. }
  132. /******************************************************/
  133. void WinEDA_DrawPanel::PrepareGraphicContext( wxDC* DC )
  134. /******************************************************/
  135. {
  136. GRResetPenAndBrush( DC );
  137. DC->SetBackgroundMode( wxTRANSPARENT );
  138. #ifdef WX_ZOOM
  139. int zoom = GetZoom();
  140. double f_scale = 1.0 / (double) zoom;
  141. DC->SetUserScale( f_scale, f_scale );
  142. PrepareDC( *DC );
  143. #endif
  144. SetBoundaryBox();
  145. }
  146. /*********************************************************************/
  147. wxPoint WinEDA_DrawPanel::CalcAbsolutePosition( const wxPoint& rel_pos )
  148. /*********************************************************************/
  149. /** Function CalcAbsolutePosition
  150. * @return absolute position in pixels, considering the scroll amount
  151. * @param rel_pos = relative position (screen position) in pixel
  152. * ( relative position = position in the panel draw area on screen )
  153. */
  154. {
  155. wxPoint pos;
  156. #ifdef WX_ZOOM
  157. CalcUnscrolledPosition( rel_pos.x, rel_pos.y, &pos.x, &pos.y );
  158. #else
  159. int ii, jj;
  160. GetViewStart( &pos.x, &pos.y ); // pos is the origin in scroll units
  161. GetScrollPixelsPerUnit( &ii, &jj );
  162. pos.x *= ii;
  163. pos.y *= jj; // pos is the origin in pixel units
  164. pos.x += rel_pos.x;
  165. pos.y += rel_pos.y;
  166. #endif
  167. return pos;
  168. }
  169. /**********************************************************************/
  170. wxPoint WinEDA_DrawPanel::CursorRealPosition( const wxPoint& ScreenPos )
  171. /**********************************************************************/
  172. /** CursorRealPosition (used to calculate the cursor position in internal units)
  173. * @return position (in internal units)
  174. * @param ScreenPos = absolute position in pixels
  175. */
  176. {
  177. wxPoint curpos = GetScreen()->CursorRealPosition( ScreenPos );
  178. return curpos;
  179. }
  180. /********************************************************/
  181. bool WinEDA_DrawPanel::IsPointOnDisplay( wxPoint ref_pos )
  182. /********************************************************/
  183. /** Funcion IsPointOnDisplay
  184. * @param ref_pos is the position to test in pixels, relative to the panel.
  185. * @return TRUE if ref_pos is a point currently visible on screen
  186. * FALSE if ref_pos is out of screen
  187. */
  188. {
  189. wxPoint pos;
  190. EDA_Rect display_rect;
  191. SetBoundaryBox();
  192. display_rect = m_ClipBox;
  193. // Reduction legere des dimension de l'ecran utile pour eviter cadrage
  194. // en limite d'ecran
  195. #define PIXEL_MARGIN 8
  196. display_rect.Inflate( -PIXEL_MARGIN, -PIXEL_MARGIN );
  197. // Conversion en coord physiques
  198. pos = CalcAbsolutePosition( display_rect.GetPosition() );
  199. pos.x *= GetZoom();
  200. pos.y *= GetZoom();
  201. pos.x += GetScreen()->m_DrawOrg.x;
  202. pos.y += GetScreen()->m_DrawOrg.y;
  203. display_rect.SetX( pos.x );
  204. display_rect.SetY( pos.y );
  205. display_rect.SetWidth( display_rect.GetWidth() * GetZoom() );
  206. display_rect.SetHeight( display_rect.GetHeight() * GetZoom() );
  207. return display_rect.Inside( ref_pos );
  208. }
  209. /************************************************************************/
  210. void WinEDA_DrawPanel::ConvertPcbUnitsToPixelsUnits( EDA_Rect& aRect )
  211. /************************************************************************/
  212. /** Function ConvertPcbUnitsToPixelsUnits
  213. * Convert pos and size off the given EDA_Rect to pos and size in pixels,
  214. * relative to the current draw area (origin 0,0 is the left top visible corner draw area)
  215. * according to the current scrool and zoom
  216. * @param aRect = the given rect
  217. */
  218. {
  219. // Calculate the draw area origin in internal units:
  220. wxPoint pos = aRect.GetPosition();
  221. ConvertPcbUnitsToPixelsUnits( pos );
  222. aRect.SetOrigin( pos ); // rect origin in pixel units
  223. aRect.m_Size.x /= GetZoom();
  224. aRect.m_Size.y /= GetZoom(); // size in pixel units
  225. }
  226. /***************************************************************************/
  227. void WinEDA_DrawPanel::ConvertPcbUnitsToPixelsUnits( wxPoint& aPosition )
  228. /***************************************************************************/
  229. /** Function ConvertPcbUnitsToPixelsUnits
  230. * Convert a given wxPoint position (in internal units) to the pos in pixels,
  231. * relative to the current draw area (origin 0,0 is the left top visible corner draw area)
  232. * according to the current scrool and zoom
  233. * @param aPosition = the given position
  234. */
  235. {
  236. // Calculate the draw area origin in internal units:
  237. wxPoint drwOrig;
  238. int x_axis_scale, y_axis_scale;
  239. GetViewStart( &drwOrig.x, &drwOrig.y ); // Origin in scrool units;
  240. GetScrollPixelsPerUnit( &x_axis_scale, &y_axis_scale );
  241. drwOrig.x *= x_axis_scale; drwOrig.y *= y_axis_scale; // Origin in pixels units;
  242. drwOrig.x *= GetZoom(); drwOrig.y *= GetZoom(); // Origin in internal units;
  243. drwOrig += GetScreen()->m_DrawOrg; // Real origin, according to the "plot" origin
  244. aPosition -= drwOrig; // position in internal units, relative to the visible draw area origin
  245. aPosition.x /= GetZoom();
  246. aPosition.y /= GetZoom(); // position in pixels, relative to the visible draw area origin
  247. }
  248. /********************************************************/
  249. wxPoint WinEDA_DrawPanel::CursorScreenPosition()
  250. /********************************************************/
  251. /** CursorScreenPosition
  252. * @return the curseur position in pixels in the panel draw area on screen )
  253. */
  254. {
  255. wxPoint curpos = GetScreen()->m_Curseur;
  256. curpos -= GetScreen()->m_DrawOrg;
  257. curpos.x /= GetZoom();
  258. curpos.y /= GetZoom();
  259. return curpos;
  260. }
  261. /*********************************************************/
  262. wxPoint WinEDA_DrawPanel::GetScreenCenterRealPosition( void )
  263. /*********************************************************/
  264. /** Function GetScreenCenterRealPosition()
  265. * @return position (in internal units) of the current area centre showed on screen
  266. */
  267. {
  268. wxSize size;
  269. wxPoint realpos;
  270. size = GetClientSize();
  271. size.x /= 2;
  272. size.y /= 2;
  273. realpos = CalcAbsolutePosition( wxPoint( size.x, size.y ) );
  274. realpos.x *= GetZoom();
  275. realpos.y *= GetZoom();
  276. realpos.x += GetScreen()->m_DrawOrg.x;
  277. realpos.y += GetScreen()->m_DrawOrg.y;
  278. return realpos;
  279. }
  280. /**********************************************/
  281. void WinEDA_DrawPanel::MouseToCursorSchema()
  282. /**********************************************/
  283. /* Move the mouse cursor to the current schematic cursor
  284. */
  285. {
  286. wxPoint Mouse = CursorScreenPosition();
  287. MouseTo( Mouse );
  288. }
  289. /****************************************************/
  290. void WinEDA_DrawPanel::MouseTo( const wxPoint& Mouse )
  291. /****************************************************/
  292. /** Move the mouse cursor to the position "Mouse"
  293. * @param Mouse = new mouse cursor position
  294. */
  295. {
  296. wxPoint mouse;
  297. #ifdef WX_ZOOM
  298. CalcScrolledPosition( Mouse.x, Mouse.y, &mouse.x, &mouse.y );
  299. #else
  300. mouse = Mouse;
  301. mouse.x -= GetScreen()->m_StartVisu.x;
  302. mouse.y -= GetScreen()->m_StartVisu.y;
  303. #endif
  304. GRMouseWarp( this, mouse );
  305. }
  306. /********************************************************/
  307. void WinEDA_DrawPanel::OnActivate( wxActivateEvent& event )
  308. /********************************************************/
  309. /**
  310. * Called on window activation.
  311. * init the member m_CanStartBlock to avoid a block start command
  312. * on activation (because a left mouse buton can be pressed and no block command wanted
  313. * This happens when enter on a hierarchycat sheet on double click
  314. */
  315. {
  316. m_CanStartBlock = -1; // Block Command can't start
  317. event.Skip();
  318. }
  319. /***********************************************************/
  320. void WinEDA_DrawPanel::OnEraseBackground( wxEraseEvent& event )
  321. /***********************************************************/
  322. {
  323. event.Skip();
  324. }
  325. /*********************************************************/
  326. void WinEDA_DrawPanel::OnScroll( wxScrollWinEvent& event )
  327. /*********************************************************/
  328. {
  329. int id = event.GetEventType();
  330. int dir, value = 0;
  331. int x, y;
  332. GetViewStart( &x, &y );
  333. dir = event.GetOrientation(); // wxHORIZONTAL or wxVERTICAL
  334. if( id == wxEVT_SCROLLWIN_LINEUP )
  335. value = -m_ScrollButt_unit;
  336. else if( id == wxEVT_SCROLLWIN_LINEDOWN )
  337. value = m_ScrollButt_unit;
  338. else if( id == wxEVT_SCROLLWIN_THUMBTRACK )
  339. {
  340. value = event.GetPosition();
  341. if( dir == wxHORIZONTAL )
  342. Scroll( value, -1 );
  343. else
  344. Scroll( -1, value );
  345. return;
  346. }
  347. else
  348. {
  349. event.Skip();
  350. return;
  351. }
  352. if( dir == wxHORIZONTAL )
  353. {
  354. Scroll( x + value, -1 );
  355. }
  356. else
  357. {
  358. Scroll( -1, y + value );
  359. }
  360. event.Skip();
  361. }
  362. /*************************************************/
  363. void WinEDA_DrawPanel::OnSize( wxSizeEvent& event )
  364. /*************************************************/
  365. {
  366. SetBoundaryBox();
  367. event.Skip();
  368. }
  369. /******************************************/
  370. void WinEDA_DrawPanel::SetBoundaryBox()
  371. /******************************************/
  372. /** Function SetBoundaryBox()
  373. * set the m_ClipBox member to the current displayed rectangle dimensions
  374. */
  375. {
  376. BASE_SCREEN* Screen = GetScreen();;
  377. if( !Screen )
  378. return;
  379. wxPoint org;
  380. int ii, jj;
  381. Screen->m_SizeVisu = GetClientSize();
  382. GetViewStart( &org.x, &org.y );
  383. GetScrollPixelsPerUnit( &ii, &jj );
  384. org.x *= ii;
  385. org.y *= jj;
  386. Screen->m_StartVisu = org;
  387. m_ClipBox.SetOrigin( org );
  388. m_ClipBox.SetSize( GetClientSize() );
  389. #ifdef WX_ZOOM
  390. m_ClipBox.m_Pos.x *= GetZoom();
  391. m_ClipBox.m_Pos.y *= GetZoom();
  392. m_ClipBox.m_Size.x *= GetZoom();
  393. m_ClipBox.m_Size.y *= GetZoom();
  394. #else
  395. m_ClipBox.m_Pos.x -= GetScreen()->m_StartVisu.x;
  396. m_ClipBox.m_Pos.y -= GetScreen()->m_StartVisu.y;
  397. #endif
  398. m_ScrollButt_unit = MIN( Screen->m_SizeVisu.x, Screen->m_SizeVisu.y ) / 4;
  399. if( m_ScrollButt_unit < 2 )
  400. m_ScrollButt_unit = 2;
  401. Screen->m_ScrollbarPos.x = GetScrollPos( wxHORIZONTAL );
  402. Screen->m_ScrollbarPos.y = GetScrollPos( wxVERTICAL );
  403. }
  404. /*********************************************/
  405. void WinEDA_DrawPanel::EraseScreen( wxDC* DC )
  406. /*********************************************/
  407. {
  408. GRSetDrawMode( DC, GR_COPY );
  409. GRSFilledRect( &m_ClipBox, DC, m_ClipBox.GetX(), m_ClipBox.GetY(),
  410. m_ClipBox.GetRight(), m_ClipBox.GetBottom(),
  411. g_DrawBgColor, g_DrawBgColor );
  412. }
  413. /***************************************************/
  414. void WinEDA_DrawPanel::OnPaint( wxPaintEvent& event )
  415. /***************************************************/
  416. #if 1 // new code without multiple calls to ReDraw()
  417. {
  418. wxPaintDC paintDC( this );
  419. EDA_Rect tmp;
  420. wxRect PaintClipBox;
  421. wxPoint org;
  422. PrepareGraphicContext( &paintDC );
  423. tmp = m_ClipBox;
  424. org = m_ClipBox.GetOrigin();
  425. static int counter;
  426. wxRegion upd = GetUpdateRegion(); // get the update rect list
  427. ++counter;
  428. PaintClipBox = upd.GetBox();
  429. #if 1 && defined (DEBUG)
  430. printf( "PaintClipBox[%d]=(%d, %d, %d, %d) org=(%d, %d) m_ClipBox=(%d, %d, %d, %d)\n",
  431. counter,
  432. PaintClipBox.x,
  433. PaintClipBox.y,
  434. PaintClipBox.width,
  435. PaintClipBox.height,
  436. org.x, org.y,
  437. m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y,
  438. m_ClipBox.m_Size.x, m_ClipBox.m_Size.y
  439. );
  440. #endif
  441. PaintClipBox.x += org.x;
  442. PaintClipBox.y += org.y;
  443. #ifdef WX_ZOOM
  444. m_ClipBox.m_Pos.x = PaintClipBox.x * GetZoom();
  445. m_ClipBox.m_Pos.y = PaintClipBox.y * GetZoom();
  446. m_ClipBox.m_Size.x = PaintClipBox.width * GetZoom();
  447. m_ClipBox.m_Size.y = PaintClipBox.height * GetZoom();
  448. #else
  449. m_ClipBox.SetX( PaintClipBox.GetX() );
  450. m_ClipBox.SetY( PaintClipBox.GetY() );
  451. m_ClipBox.SetWidth( PaintClipBox.GetWidth() );
  452. m_ClipBox.SetHeight( PaintClipBox.GetHeight() );
  453. #endif
  454. #if 1 // && defined(DEBUG)
  455. printf( "PaintClipBox[%d]=(%d, %d, %d, %d) org=(%d, %d) m_ClipBox=(%d, %d, %d, %d)\n",
  456. counter,
  457. PaintClipBox.x,
  458. PaintClipBox.y,
  459. PaintClipBox.width,
  460. PaintClipBox.height,
  461. org.x, org.y,
  462. m_ClipBox.m_Pos.x, m_ClipBox.m_Pos.y,
  463. m_ClipBox.m_Size.x, m_ClipBox.m_Size.y
  464. );
  465. #endif
  466. PaintClipBox = m_ClipBox;
  467. wxDCClipper* dcclip = new wxDCClipper( paintDC, PaintClipBox );
  468. ReDraw( &paintDC, TRUE );
  469. delete dcclip;
  470. m_ClipBox = tmp;
  471. event.Skip();
  472. }
  473. #else // old code
  474. {
  475. wxPaintDC paintDC( this );
  476. EDA_Rect tmp;
  477. wxRect PaintClipBox;
  478. wxPoint org;
  479. static int counter;
  480. ++counter;
  481. PrepareGraphicContext( &paintDC );
  482. tmp = m_ClipBox;
  483. org = m_ClipBox.GetOrigin();
  484. wxRegionIterator upd( GetUpdateRegion() ); // get the update rect list
  485. while( upd )
  486. {
  487. PaintClipBox = upd.GetRect();
  488. upd++;
  489. PaintClipBox.x += org.x;
  490. PaintClipBox.y += org.y;
  491. #if 0
  492. printf( "PaintClipBox[%d]=(%d, %d, %d, %d)\n",
  493. counter,
  494. PaintClipBox.x,
  495. PaintClipBox.y,
  496. PaintClipBox.width,
  497. PaintClipBox.height );
  498. #endif
  499. #ifdef WX_ZOOM
  500. m_ClipBox.m_Pos.x = PaintClipBox.x * GetZoom();
  501. m_ClipBox.m_Pos.y = PaintClipBox.y * GetZoom();
  502. m_ClipBox.m_Size.x = PaintClipBox.m_Size.x * GetZoom();
  503. m_ClipBox.m_Size.y = PaintClipBox.m_Size.y * GetZoom();
  504. PaintClipBox = m_ClipBox;
  505. #else
  506. m_ClipBox.SetX( PaintClipBox.GetX() );
  507. m_ClipBox.SetY( PaintClipBox.GetY() );
  508. m_ClipBox.SetWidth( PaintClipBox.GetWidth() );
  509. m_ClipBox.SetHeight( PaintClipBox.GetHeight() );
  510. #endif
  511. wxDCClipper* dcclip = new wxDCClipper( paintDC, PaintClipBox );
  512. ReDraw( &paintDC, TRUE );
  513. delete dcclip;
  514. }
  515. m_ClipBox = tmp;
  516. event.Skip();
  517. }
  518. #endif
  519. /****************************************************/
  520. void WinEDA_DrawPanel::ReDraw( wxDC* DC, bool erasebg )
  521. /****************************************************/
  522. {
  523. BASE_SCREEN* Screen = GetScreen();
  524. if( Screen == NULL )
  525. return;
  526. if( (g_DrawBgColor != WHITE) && (g_DrawBgColor != BLACK) )
  527. g_DrawBgColor = BLACK;
  528. if( g_DrawBgColor == WHITE )
  529. {
  530. g_XorMode = GR_NXOR;
  531. g_GhostColor = BLACK;
  532. }
  533. else
  534. {
  535. g_XorMode = GR_XOR;
  536. g_GhostColor = WHITE;
  537. }
  538. #ifdef WX_ZOOM
  539. int zoom = GetZoom();
  540. double f_scale = 1.0 / (double) zoom;
  541. DC->SetUserScale( f_scale, f_scale );
  542. #endif
  543. if( erasebg )
  544. PrepareGraphicContext( DC );
  545. DC->SetFont( *g_StdFont );
  546. SetBackgroundColour( wxColour( ColorRefs[g_DrawBgColor].m_Red,
  547. ColorRefs[g_DrawBgColor].m_Green,
  548. ColorRefs[g_DrawBgColor].m_Blue ) );
  549. GRResetPenAndBrush( DC );
  550. DC->SetBackground( *wxBLACK_BRUSH );
  551. DC->SetBackgroundMode( wxTRANSPARENT );
  552. m_Parent->RedrawActiveWindow( DC, erasebg );
  553. }
  554. /***********************************************/
  555. void WinEDA_DrawPanel::DrawBackGround( wxDC* DC )
  556. /***********************************************/
  557. /** Function DrawBackGround
  558. * @param DC = current Device Context
  559. * Draws X , Y axis
  560. * draws the grid
  561. * - the grid is drawn only if the zoom level allows a good visibility
  562. * - the grid is always centered on the screen centre
  563. */
  564. {
  565. int Color = BLUE;
  566. BASE_SCREEN* screen = GetScreen();
  567. int ii, jj, xg, yg, color;
  568. wxSize pas_grille_affichee;
  569. bool drawgrid = FALSE;
  570. int zoom = GetZoom();
  571. wxSize size;
  572. wxPoint org;
  573. double pasx, pasy;
  574. color = g_GridColor;
  575. GRSetDrawMode( DC, GR_COPY );
  576. /* The grid must be visible. this is possible only is grid value
  577. * and zoom value are sufficient
  578. */
  579. drawgrid = m_Parent->m_Draw_Grid;
  580. pas_grille_affichee = screen->GetGrid();
  581. ii = pas_grille_affichee.x / zoom;
  582. if( ii < 5 )
  583. {
  584. pas_grille_affichee.x *= 2;
  585. ii *= 2;
  586. }
  587. if( ii < 5 )
  588. drawgrid = FALSE; // The gris is small
  589. ii = pas_grille_affichee.y / zoom;
  590. if( ii < 5 )
  591. {
  592. pas_grille_affichee.y *= 2;
  593. ii *= 2;
  594. }
  595. if( ii < 5 )
  596. drawgrid = FALSE; // The gris is small
  597. GetViewStart( &org.x, &org.y );
  598. GetScrollPixelsPerUnit( &ii, &jj );
  599. org.x *= ii;
  600. org.y *= jj;
  601. screen->m_StartVisu = org;
  602. org.x *= zoom;
  603. org.y *= zoom;
  604. org.x += screen->m_DrawOrg.x;
  605. org.y += screen->m_DrawOrg.y;
  606. size = GetClientSize();
  607. size.x *= zoom;
  608. size.y *= zoom;
  609. pasx = screen->m_UserGrid.x * m_Parent->m_InternalUnits;
  610. pasy = screen->m_UserGrid.y * m_Parent->m_InternalUnits;
  611. if( screen->m_UserGridUnit != INCHES )
  612. {
  613. pasx /= 25.4;
  614. pasy /= 25.4;
  615. }
  616. if( drawgrid )
  617. {
  618. m_Parent->PutOnGrid( &org );
  619. GRSetColorPen( DC, color );
  620. for( ii = 0; ; ii++ )
  621. {
  622. xg = screen->m_UserGridIsON ? (int) ( (ii * pasx) + 0.5 )
  623. : ii * pas_grille_affichee.x;
  624. int xpos = org.x + xg;
  625. for( jj = 0; ; jj++ )
  626. {
  627. yg = screen->m_UserGridIsON ? (int) ( (jj * pasy) + 0.5 )
  628. : jj * pas_grille_affichee.y;
  629. GRPutPixel( &m_ClipBox, DC, xpos, org.y + yg, color );
  630. if( yg > size.y )
  631. break;
  632. }
  633. if( xg > size.x )
  634. break;
  635. }
  636. }
  637. /* Draw axis */
  638. if( m_Parent->m_Draw_Axis )
  639. {
  640. /* Draw the Y axis */
  641. GRDashedLine( &m_ClipBox, DC, 0, -screen->ReturnPageSize().y,
  642. 0, screen->ReturnPageSize().y, 0, Color );
  643. /* Draw the X axis */
  644. GRDashedLine( &m_ClipBox, DC, -screen->ReturnPageSize().x, 0,
  645. screen->ReturnPageSize().x, 0, 0, Color );
  646. }
  647. /* Draw auxiliary axis */
  648. if( m_Parent->m_Draw_Auxiliary_Axis )
  649. {
  650. m_Draw_Auxiliary_Axis( DC, FALSE );
  651. }
  652. }
  653. /********************************************************************/
  654. void WinEDA_DrawPanel::m_Draw_Auxiliary_Axis( wxDC* DC, int drawmode )
  655. /********************************************************************/
  656. /** m_Draw_Auxiliary_Axis
  657. * Draw the Auxiliary Axis, used in pcbnew which as origin coordinates
  658. * for gerber and excellon files
  659. */
  660. {
  661. if( m_Parent->m_Auxiliary_Axis_Position.x == 0
  662. && m_Parent->m_Auxiliary_Axis_Position.y == 0 )
  663. return;
  664. int Color = DARKRED;
  665. BASE_SCREEN* screen = GetScreen();
  666. GRSetDrawMode( DC, drawmode );
  667. /* Draw the Y axis */
  668. GRDashedLine( &m_ClipBox, DC,
  669. m_Parent->m_Auxiliary_Axis_Position.x, -screen->ReturnPageSize().y,
  670. m_Parent->m_Auxiliary_Axis_Position.x, screen->ReturnPageSize().y,
  671. 0, Color );
  672. /* Draw the X axis */
  673. GRDashedLine( &m_ClipBox, DC,
  674. -screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y,
  675. screen->ReturnPageSize().x, m_Parent->m_Auxiliary_Axis_Position.y,
  676. 0, Color );
  677. }
  678. /*******************************************************/
  679. bool WinEDA_DrawPanel::OnRightClick( wxMouseEvent& event )
  680. /*******************************************************/
  681. /** Build and display a Popup menu on a right mouse button click
  682. * @return true if a popup menu is shown, or false
  683. */
  684. {
  685. wxPoint pos;
  686. wxMenu MasterMenu;
  687. pos.x = event.GetX();
  688. pos.y = event.GetY();
  689. if( !m_Parent->OnRightClick( pos, &MasterMenu ) )
  690. return false;
  691. AddMenuZoom( &MasterMenu );
  692. m_IgnoreMouseEvents = TRUE;
  693. PopupMenu( &MasterMenu, pos );
  694. MouseToCursorSchema();
  695. m_IgnoreMouseEvents = FALSE;
  696. return true;
  697. }
  698. /******************************************************/
  699. void WinEDA_DrawPanel::OnMouseLeaving( wxMouseEvent& event )
  700. /*******************************************************/
  701. // Called when the canvas receives a mouse event leaving frame. //
  702. {
  703. if( ManageCurseur == NULL ) // Pas de commande encours
  704. m_AutoPAN_Request = FALSE;
  705. if( !m_AutoPAN_Enable || !m_AutoPAN_Request || m_IgnoreMouseEvents )
  706. return;
  707. // Auto pan if mouse is leave working aera:
  708. wxSize size = GetClientSize();
  709. if( ( size.x < event.GetX() )
  710. || ( size.y < event.GetY() )
  711. || ( event.GetX() <= 0) || ( event.GetY() <= 0 ) )
  712. m_Parent->OnZoom( ID_POPUP_ZOOM_CENTER );
  713. }
  714. /******************************************************/
  715. void WinEDA_DrawPanel::OnMouseEvent( wxMouseEvent& event )
  716. /*******************************************************/
  717. // Called when the canvas receives a mouse event. //
  718. {
  719. int localrealbutt = 0, localbutt = 0, localkey = 0;
  720. BASE_SCREEN* screen = GetScreen();
  721. static WinEDA_DrawPanel* LastPanel;
  722. static bool IgnoreNextLeftButtonRelease = false;
  723. if( !screen )
  724. return;
  725. #define MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND 5 /* Adjust value to filter mouse deplacement before
  726. * consider the drag mouse is really a drag command, not just a movement while click
  727. */
  728. static int MinDragEventCount; /* counts the drag events.
  729. * used to filter mouse moves before starting a block command
  730. * a block comman can be started only if MinDragEventCount > MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND
  731. * in order to avoid spurious block commands
  732. */
  733. if( event.Leaving() || event.Entering() )
  734. {
  735. m_CanStartBlock = -1;
  736. }
  737. if( ManageCurseur == NULL ) // No command in progress
  738. m_AutoPAN_Request = FALSE;
  739. if( m_Parent->m_FrameIsActive )
  740. SetFocus();
  741. else
  742. return;
  743. // Mouse Wheel is a zoom command:
  744. if( event.m_wheelRotation )
  745. {
  746. // This is a zoom in ou out command
  747. if( event.GetWheelRotation() > 0 )
  748. {
  749. if( event.ShiftDown() )
  750. localkey = EDA_PANNING_UP_KEY;
  751. else if( event.ControlDown() )
  752. localkey = EDA_PANNING_LEFT_KEY;
  753. else
  754. localkey = EDA_ZOOM_IN_FROM_MOUSE;
  755. }
  756. else
  757. {
  758. if( event.ShiftDown() )
  759. localkey = EDA_PANNING_DOWN_KEY;
  760. else if( event.ControlDown() )
  761. localkey = EDA_PANNING_RIGHT_KEY;
  762. else
  763. localkey = EDA_ZOOM_OUT_FROM_MOUSE;
  764. }
  765. }
  766. if( !event.IsButton() && !event.Moving()
  767. && !event.Dragging() && !localkey )
  768. {
  769. return;
  770. }
  771. if( event.RightDown() )
  772. {
  773. OnRightClick( event );
  774. return;
  775. }
  776. if( m_IgnoreMouseEvents )
  777. return;
  778. if( event.LeftIsDown() )
  779. localrealbutt |= GR_M_LEFT_DOWN;
  780. if( event.MiddleIsDown() )
  781. localrealbutt |= GR_M_MIDDLE_DOWN;
  782. if( event.LeftDown() )
  783. localbutt = GR_M_LEFT_DOWN;
  784. if( event.ButtonDClick( 1 ) )
  785. localbutt = GR_M_LEFT_DOWN | GR_M_DCLICK;
  786. if( event.MiddleDown() )
  787. localbutt = GR_M_MIDDLE_DOWN;
  788. if( event.ButtonDClick( 2 ) )
  789. {
  790. }
  791. ; // Unused
  792. localrealbutt |= localbutt; /* compensation defaut wxGTK */
  793. /* Compute absolute m_MousePosition in pixel units: */
  794. screen->m_MousePositionInPixels = CalcAbsolutePosition( wxPoint( event.GetX(), event.GetY() ) );
  795. /* Compute absolute m_MousePosition in user units: */
  796. screen->m_MousePosition = CursorRealPosition( screen->m_MousePositionInPixels );
  797. wxClientDC DC( this );
  798. int kbstat = 0;
  799. DC.SetBackground( *wxBLACK_BRUSH );
  800. PrepareGraphicContext( &DC );
  801. g_KeyPressed = localkey;
  802. if( event.ShiftDown() )
  803. kbstat |= GR_KB_SHIFT;
  804. if( event.ControlDown() )
  805. kbstat |= GR_KB_CTRL;
  806. if( event.AltDown() )
  807. kbstat |= GR_KB_ALT;
  808. g_MouseOldButtons = localrealbutt;
  809. // Calling Double Click and Click functions :
  810. if( localbutt == (int) (GR_M_LEFT_DOWN | GR_M_DCLICK) )
  811. {
  812. m_Parent->OnLeftDClick( &DC, screen->m_MousePositionInPixels );
  813. IgnoreNextLeftButtonRelease = true;
  814. }
  815. else if( event.LeftUp() )
  816. {
  817. if( screen->BlockLocate.m_State==STATE_NO_BLOCK && !IgnoreNextLeftButtonRelease )
  818. m_Parent->OnLeftClick( &DC, screen->m_MousePositionInPixels );
  819. IgnoreNextLeftButtonRelease = false;
  820. }
  821. if( event.ButtonUp( 2 ) && (screen->BlockLocate.m_State == STATE_NO_BLOCK) )
  822. {
  823. // The middle button has been relached, with no block command:
  824. // We use it for a zoom center command
  825. g_KeyPressed = localkey = EDA_ZOOM_CENTER_FROM_MOUSE;
  826. }
  827. /* Calling the general function on mouse changes (and pseudo key commands) */
  828. m_Parent->GeneralControle( &DC, screen->m_MousePositionInPixels );
  829. /*******************************/
  830. /* Control of block commands : */
  831. /*******************************/
  832. // Command block can't start if mouse is dragging a new panel
  833. if( LastPanel != this )
  834. {
  835. MinDragEventCount = 0;
  836. m_CanStartBlock = -1;
  837. }
  838. /* A new command block can start after a release buttons
  839. * and if the drag is enougth
  840. * This is to avoid a false start block when a dialog box is demiss,
  841. * or when changing panels in hierachy navigation
  842. * or when clicking while and moving mouse
  843. */
  844. if( !event.LeftIsDown() && !event.MiddleIsDown() )
  845. {
  846. MinDragEventCount = 0;
  847. m_CanStartBlock = 0;
  848. /* remember the last cursor position when a drag mouse starts
  849. * this is the last postion ** before ** clicking a button
  850. * this is usefull to start a block command from the point where the mouse was clicked first
  851. * (a filter creates a delay for the real block command start, and we must remember this point)
  852. */
  853. m_CursorStartPos = screen->m_Curseur;
  854. }
  855. if( m_Block_Enable && !(localbutt & GR_M_DCLICK) )
  856. {
  857. if( (screen->BlockLocate.m_Command == BLOCK_IDLE)
  858. || (screen->BlockLocate.m_State == STATE_NO_BLOCK) )
  859. {
  860. screen->BlockLocate.SetOrigin( m_CursorStartPos );
  861. }
  862. if( event.LeftDown() || event.MiddleDown() )
  863. {
  864. if( screen->BlockLocate.m_State == STATE_BLOCK_MOVE )
  865. {
  866. m_AutoPAN_Request = FALSE;
  867. m_Parent->HandleBlockPlace( &DC );
  868. IgnoreNextLeftButtonRelease = true;
  869. }
  870. }
  871. else if( (m_CanStartBlock >= 0 )
  872. && ( event.LeftIsDown() || event.MiddleIsDown() )
  873. && ManageCurseur == NULL
  874. && ForceCloseManageCurseur == NULL )
  875. { // Mouse is dragging: if no block in progress: start a block command
  876. if( screen->BlockLocate.m_State == STATE_NO_BLOCK )
  877. { // Start a block command
  878. int cmd_type = kbstat;
  879. if( event.MiddleIsDown() )
  880. cmd_type |= MOUSE_MIDDLE;
  881. /* A block command is started if the drag is enought.
  882. * A small drag is ignored (it is certainly a little mouse move when clicking)
  883. * not really a drag mouse
  884. */
  885. if( MinDragEventCount < MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND )
  886. MinDragEventCount++;
  887. else
  888. {
  889. if( !m_Parent->HandleBlockBegin( &DC, cmd_type, m_CursorStartPos ) )
  890. {
  891. // should not occurs: error
  892. m_Parent->DisplayToolMsg(
  893. wxT( "WinEDA_DrawPanel::OnMouseEvent() Block Error" ) );
  894. }
  895. else
  896. {
  897. m_AutoPAN_Request = TRUE;
  898. SetCursor( m_PanelCursor = wxCURSOR_SIZING );
  899. }
  900. }
  901. }
  902. }
  903. if( event.ButtonUp( 1 ) || event.ButtonUp( 2 ) )
  904. {
  905. /* Release the mouse button: end of block.
  906. * The command can finish (DELETE) or have a next command (MOVE, COPY).
  907. * However the block command is cancelled if the block size is small
  908. * Because a block command filtering is already made, this case happens,
  909. * but only when the on grid cursor has not moved.
  910. */
  911. #define BLOCK_MINSIZE_LIMIT 1
  912. bool BlockIsSmall =
  913. ( ABS( screen->BlockLocate.GetWidth() / GetZoom() ) < BLOCK_MINSIZE_LIMIT)
  914. && ( ABS( screen->BlockLocate.GetHeight() / GetZoom() ) < BLOCK_MINSIZE_LIMIT);
  915. if( (screen->BlockLocate.m_State != STATE_NO_BLOCK) && BlockIsSmall )
  916. {
  917. if( ForceCloseManageCurseur )
  918. {
  919. ForceCloseManageCurseur( this, &DC );
  920. m_AutoPAN_Request = FALSE;
  921. }
  922. SetCursor( m_PanelCursor = m_PanelDefaultCursor );
  923. }
  924. else if( screen->BlockLocate.m_State == STATE_BLOCK_END )
  925. {
  926. m_AutoPAN_Request = FALSE;
  927. m_Parent->HandleBlockEnd( &DC );
  928. SetCursor( m_PanelCursor = m_PanelDefaultCursor );
  929. if( screen->BlockLocate.m_State == STATE_BLOCK_MOVE )
  930. {
  931. m_AutoPAN_Request = TRUE;
  932. SetCursor( m_PanelCursor = wxCURSOR_HAND );
  933. }
  934. }
  935. }
  936. }
  937. // End of block command on a double click
  938. // To avoid an unwanted block move command if the move is moved while double click
  939. if( localbutt == (int) (GR_M_LEFT_DOWN | GR_M_DCLICK) )
  940. {
  941. if( screen->BlockLocate.m_Command != BLOCK_IDLE )
  942. {
  943. if( ForceCloseManageCurseur )
  944. {
  945. ForceCloseManageCurseur( this, &DC );
  946. m_AutoPAN_Request = FALSE;
  947. }
  948. }
  949. }
  950. #if 0
  951. wxString msg_debug;
  952. msg_debug.Printf( " block state %d, cmd %d",
  953. screen->BlockLocate.m_State, screen->BlockLocate.m_Command );
  954. m_Parent->PrintMsg( msg_debug );
  955. #endif
  956. LastPanel = this;
  957. m_Parent->SetToolbars();
  958. }
  959. /****************************************************/
  960. void WinEDA_DrawPanel::OnKeyEvent( wxKeyEvent& event )
  961. /****************************************************/
  962. {
  963. long key, localkey;
  964. bool escape = FALSE;
  965. key = localkey = event.GetKeyCode();
  966. switch( localkey )
  967. {
  968. case WXK_CONTROL:
  969. case WXK_CAPITAL:
  970. case WXK_SHIFT:
  971. case WXK_NUMLOCK:
  972. case WXK_LBUTTON:
  973. case WXK_RBUTTON:
  974. case WXK_ALT:
  975. return;
  976. case WXK_ESCAPE:
  977. escape = m_AbortRequest = TRUE;
  978. break;
  979. }
  980. if( event.ControlDown() )
  981. localkey |= GR_KB_CTRL;
  982. if( event.AltDown() )
  983. localkey |= GR_KB_ALT;
  984. if( event.ShiftDown() && (key > 256) )
  985. localkey |= GR_KB_SHIFT;
  986. wxClientDC DC( this );
  987. BASE_SCREEN* Screen = GetScreen();
  988. PrepareGraphicContext( &DC );
  989. g_KeyPressed = localkey;
  990. if( escape )
  991. {
  992. if( ManageCurseur && ForceCloseManageCurseur )
  993. {
  994. SetCursor( m_PanelCursor = m_PanelDefaultCursor );
  995. ForceCloseManageCurseur( this, &DC );
  996. SetCursor( m_PanelCursor = m_PanelDefaultCursor );
  997. }
  998. else
  999. {
  1000. m_PanelCursor = m_PanelDefaultCursor = wxCURSOR_ARROW;
  1001. m_Parent->SetToolID( 0, m_PanelCursor, wxEmptyString );
  1002. }
  1003. }
  1004. /* some key commands use the mouse position: refresh it */
  1005. #if wxCHECK_VERSION( 2, 8, 0 )
  1006. wxPoint mouse_pos = wxGetMousePosition(); // Get the mouse position on screen
  1007. wxPoint win_pos = GetScreenPosition(); // get the draw area (panel)position on screen
  1008. mouse_pos -= win_pos; // mouse_pos = is the mouse position relative to the panel
  1009. /* Compute absolute m_MousePosition in pixel units (i.e. considering the current scrool) : */
  1010. Screen->m_MousePositionInPixels = CalcAbsolutePosition( mouse_pos );
  1011. /* Compute absolute m_MousePosition in user units: */
  1012. Screen->m_MousePosition = CursorRealPosition( Screen->m_MousePositionInPixels );
  1013. #else
  1014. /* if wxGetMousePosition() does not exist,
  1015. * m_Cursor should be ok, use it to calculate the cursor position on screen
  1016. */
  1017. Screen->m_MousePositionInPixels = CursorScreenPosition();
  1018. #endif
  1019. m_Parent->GeneralControle( &DC, Screen->m_MousePositionInPixels );
  1020. #if 0
  1021. event.Skip(); // Allow menu shortcut processing
  1022. #endif
  1023. }