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.

1274 lines
36 KiB

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