589 lines
13 KiB
C++
589 lines
13 KiB
C++
/******************************************************************/
|
|
/* drawpanel.cpp - fonctions des classes du type WinEDA_DrawPanel */
|
|
/******************************************************************/
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "fctsys.h"
|
|
#include "common.h"
|
|
|
|
|
|
/* defines locaux */
|
|
#define CURSOR_SIZE 12 /* taille de la croix du curseur PCB */
|
|
|
|
/*******************************************************/
|
|
/* Class BASE_SCREEN: classe de gestion d'un affichage */
|
|
/*******************************************************/
|
|
BASE_SCREEN::BASE_SCREEN( int idscreen, KICAD_T aType ) :
|
|
EDA_BaseStruct( aType )
|
|
{
|
|
EEDrawList = NULL; /* Schematic items list */
|
|
m_Type = idscreen;
|
|
m_ZoomList = NULL;
|
|
m_GridList = NULL;
|
|
m_UndoList = NULL;
|
|
m_RedoList = NULL;
|
|
m_UndoRedoCountMax = 1;
|
|
m_FirstRedraw = TRUE;
|
|
InitDatas();
|
|
}
|
|
|
|
|
|
/******************************/
|
|
BASE_SCREEN::~BASE_SCREEN()
|
|
/******************************/
|
|
{
|
|
if( m_ZoomList )
|
|
free( m_ZoomList );
|
|
|
|
if( m_GridList )
|
|
free( m_GridList );
|
|
|
|
ClearUndoRedoList();
|
|
}
|
|
|
|
|
|
/*******************************/
|
|
void BASE_SCREEN::InitDatas()
|
|
/*******************************/
|
|
{
|
|
m_SheetNumber = m_NumberOfSheet = 1; /* gestion hierarchie: Root: SheetNumber = 1 */
|
|
m_Zoom = 32;
|
|
m_Grid = wxSize( 50, 50 ); /* pas de la grille */
|
|
m_UserGrid = g_UserGrid; /* pas de la grille "utilisateur" */
|
|
m_UserGridIsON = FALSE;
|
|
m_UserGridUnit = g_UserGrid_Unit;
|
|
m_Diviseur_Grille = 1;
|
|
m_Center = TRUE;
|
|
|
|
/* offsets pour tracer le circuit sur l'ecran */
|
|
switch( m_Type ) // Init taille sheet par defaut
|
|
{
|
|
case SCHEMATIC_FRAME:
|
|
m_Center = FALSE;
|
|
m_CurrentSheet = &g_Sheet_A4;
|
|
break;
|
|
|
|
default:
|
|
case CVPCB_DISPLAY_FRAME:
|
|
case MODULE_EDITOR_FRAME:
|
|
case PCB_FRAME:
|
|
m_CurrentSheet = &g_Sheet_A4;
|
|
break;
|
|
|
|
case GERBER_FRAME:
|
|
m_CurrentSheet = &g_Sheet_GERBER;
|
|
break;
|
|
}
|
|
|
|
if( m_Center )
|
|
{
|
|
m_Curseur.x = m_Curseur.y = 0;
|
|
m_DrawOrg.x = -ReturnPageSize().x / 2;
|
|
m_DrawOrg.y = -ReturnPageSize().y / 2;
|
|
}
|
|
else
|
|
{
|
|
m_DrawOrg.x = m_DrawOrg.y = 0;
|
|
m_Curseur.x = ReturnPageSize().x / 2;
|
|
m_Curseur.y = ReturnPageSize().y / 2;
|
|
}
|
|
|
|
// DrawOrg est rendu multiple du zoom min :
|
|
m_DrawOrg.x -= m_DrawOrg.x % 256;
|
|
m_DrawOrg.y -= m_DrawOrg.y % 256;
|
|
|
|
m_O_Curseur = m_Curseur;
|
|
|
|
SetCurItem( NULL );
|
|
|
|
/* indicateurs divers */
|
|
m_FlagRefreshReq = 0; /* indique que l'ecran doit redessine */
|
|
m_FlagModified = 0; // indique modif du PCB,utilise pour eviter une sortie sans sauvegarde
|
|
m_FlagSave = 1; // indique sauvegarde auto faite
|
|
}
|
|
|
|
|
|
/******************************************************************/
|
|
wxPoint BASE_SCREEN::CursorRealPosition( const wxPoint& ScreenPos )
|
|
/******************************************************************/
|
|
{
|
|
wxPoint curpos;
|
|
|
|
D(printf("curpos=%d,%d GetZoom=%d, mDrawOrg=%d,%d\n",
|
|
curpos.x, curpos.y, GetZoom(), m_DrawOrg.x, m_DrawOrg.y );)
|
|
|
|
curpos.x = ScreenPos.x * GetZoom();
|
|
curpos.y = ScreenPos.y * GetZoom();
|
|
|
|
curpos.x += m_DrawOrg.x;
|
|
curpos.y += m_DrawOrg.y;
|
|
|
|
return curpos;
|
|
}
|
|
|
|
|
|
/***************************************/
|
|
int BASE_SCREEN::GetInternalUnits()
|
|
/***************************************/
|
|
{
|
|
switch( m_Type )
|
|
{
|
|
default:
|
|
case SCHEMATIC_FRAME:
|
|
return EESCHEMA_INTERNAL_UNIT;
|
|
break;
|
|
|
|
case GERBER_FRAME:
|
|
case CVPCB_DISPLAY_FRAME:
|
|
case MODULE_EDITOR_FRAME:
|
|
case PCB_FRAME:
|
|
return PCB_INTERNAL_UNIT;
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************/
|
|
wxSize BASE_SCREEN::ReturnPageSize()
|
|
/*****************************************/
|
|
|
|
/* Retourne en unites internes la taille de la feuille de dessin
|
|
* (la taille de la feuille est connue en 1/1000 ")
|
|
*/
|
|
{
|
|
wxSize PageSize;
|
|
|
|
switch( m_Type )
|
|
{
|
|
default:
|
|
case SCHEMATIC_FRAME:
|
|
PageSize = m_CurrentSheet->m_Size;
|
|
break;
|
|
|
|
case GERBER_FRAME:
|
|
case CVPCB_DISPLAY_FRAME:
|
|
case MODULE_EDITOR_FRAME:
|
|
case PCB_FRAME:
|
|
PageSize.x = m_CurrentSheet->m_Size.x * (PCB_INTERNAL_UNIT / 1000);
|
|
PageSize.y = m_CurrentSheet->m_Size.y * (PCB_INTERNAL_UNIT / 1000);
|
|
break;
|
|
}
|
|
|
|
return PageSize;
|
|
}
|
|
|
|
|
|
/********************************************/
|
|
void BASE_SCREEN::SetZoomList( int* zoomlist )
|
|
/********************************************/
|
|
|
|
/* init liste des zoom (NULL terminated)
|
|
*/
|
|
{
|
|
int ii, nbitems, * zoom;
|
|
|
|
// Decompte des items
|
|
for( nbitems = 1, zoom = zoomlist; ; zoom++, nbitems++ )
|
|
{
|
|
if( *zoom == 0 )
|
|
break;
|
|
}
|
|
|
|
// Init liste
|
|
if( m_ZoomList )
|
|
free( m_ZoomList );
|
|
|
|
m_ZoomList = (int*) MyZMalloc( nbitems * sizeof( int) );
|
|
|
|
for( ii = 0, zoom = zoomlist; ii < nbitems; zoom++, ii++ )
|
|
{
|
|
m_ZoomList[ii] = *zoom;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************/
|
|
void BASE_SCREEN::SetFirstZoom()
|
|
/***********************************/
|
|
/* ajuste le coeff de zoom a 1*/
|
|
{
|
|
m_Zoom = 1;
|
|
}
|
|
|
|
|
|
/****************************/
|
|
int BASE_SCREEN::GetZoom()
|
|
/****************************/
|
|
/* retourne le coeff de zoom */
|
|
{
|
|
return m_Zoom;
|
|
}
|
|
|
|
|
|
/***********************************/
|
|
void BASE_SCREEN::SetZoom( int coeff )
|
|
/***********************************/
|
|
/* ajuste le coeff de zoom a coeff */
|
|
{
|
|
m_Zoom = coeff;
|
|
if( m_Zoom < 1 )
|
|
m_Zoom = 1;
|
|
}
|
|
|
|
|
|
/********************************/
|
|
void BASE_SCREEN::SetNextZoom()
|
|
/********************************/
|
|
|
|
/* Selectionne le prochain coeff de zoom
|
|
*/
|
|
{
|
|
m_Zoom *= 2;
|
|
|
|
if( m_ZoomList == NULL )
|
|
return;
|
|
|
|
int ii, zoom_max = 512;
|
|
for( ii = 0; m_ZoomList[ii] != 0; ii++ )
|
|
zoom_max = m_ZoomList[ii];
|
|
|
|
if( m_Zoom > zoom_max )
|
|
m_Zoom = zoom_max;
|
|
}
|
|
|
|
|
|
/*************************************/
|
|
void BASE_SCREEN::SetPreviousZoom()
|
|
/*************************************/
|
|
|
|
/* Selectionne le precedent coeff de zoom
|
|
*/
|
|
{
|
|
m_Zoom /= 2;
|
|
if( m_Zoom < 1 )
|
|
m_Zoom = 1;
|
|
}
|
|
|
|
|
|
/**********************************/
|
|
void BASE_SCREEN::SetLastZoom()
|
|
/**********************************/
|
|
|
|
/* ajuste le coeff de zoom au max
|
|
*/
|
|
{
|
|
if( m_ZoomList == NULL )
|
|
return;
|
|
int ii;
|
|
for( ii = 0; m_ZoomList[ii] != 0; ii++ )
|
|
m_Zoom = m_ZoomList[ii];
|
|
}
|
|
|
|
|
|
/********************************************/
|
|
void BASE_SCREEN::SetGridList( wxSize* gridlist )
|
|
/********************************************/
|
|
|
|
/* init liste des zoom (NULL terminated)
|
|
*/
|
|
{
|
|
int ii, nbitems;
|
|
wxSize* grid;
|
|
|
|
// Decompte des items
|
|
for( nbitems = 0, grid = gridlist; ; grid++, nbitems++ )
|
|
{
|
|
if( (grid->x <= 0) || (grid->y <= 0) )
|
|
break;
|
|
}
|
|
|
|
// Init liste
|
|
if( m_GridList )
|
|
free( m_GridList );
|
|
m_GridList = (wxSize*) MyZMalloc( nbitems * sizeof(wxSize) );
|
|
|
|
for( ii = 0, grid = gridlist; ii < nbitems; grid++, ii++ )
|
|
{
|
|
m_GridList[ii] = *grid;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************/
|
|
void BASE_SCREEN::SetGrid( const wxSize& size )
|
|
/**********************************************/
|
|
{
|
|
if( m_GridList == NULL )
|
|
return;
|
|
|
|
if( (size.x <= 0) || (size.y <= 0) )
|
|
{
|
|
m_UserGrid = g_UserGrid;
|
|
m_UserGridIsON = TRUE;
|
|
}
|
|
else
|
|
{
|
|
m_Grid = size;
|
|
m_UserGridIsON = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************/
|
|
wxSize BASE_SCREEN::GetGrid()
|
|
/*********************************/
|
|
{
|
|
wxSize grid = m_Grid;
|
|
double xx, scale;
|
|
|
|
if( m_GridList == NULL )
|
|
return wxSize( 1, 1 );
|
|
|
|
if( m_UserGridIsON || m_Grid.x < 0 || m_Grid.y < 0 )
|
|
{
|
|
if( m_UserGridUnit == INCHES )
|
|
scale = 10000;
|
|
else
|
|
scale = 10000 / 25.4;
|
|
xx = m_UserGrid.x * scale;
|
|
grid.x = (int) (xx + 0.5);
|
|
xx = m_UserGrid.y * scale;
|
|
grid.y = (int) (xx + 0.5);
|
|
}
|
|
return grid;
|
|
}
|
|
|
|
|
|
/*********************************/
|
|
void BASE_SCREEN::SetNextGrid()
|
|
/*********************************/
|
|
|
|
/* Selectionne la prochaine grille
|
|
*/
|
|
{
|
|
int ii;
|
|
|
|
if( m_GridList == NULL )
|
|
return;
|
|
|
|
for( ii = 0; ; ii++ )
|
|
{
|
|
if( m_GridList[ii].x <= 0 )
|
|
break;
|
|
if( (m_Grid.x == m_GridList[ii].x) && (m_Grid.y == m_GridList[ii].y) )
|
|
break;
|
|
}
|
|
|
|
if( (m_GridList[ii].x > 0) && (ii > 0) )
|
|
m_Grid = m_GridList[ii - 1];
|
|
}
|
|
|
|
|
|
/*************************************/
|
|
void BASE_SCREEN::SetPreviousGrid()
|
|
/*************************************/
|
|
|
|
/* Selectionne le precedent coeff de grille
|
|
*/
|
|
{
|
|
int ii;
|
|
|
|
if( m_GridList == NULL )
|
|
return;
|
|
|
|
for( ii = 0; ; ii++ )
|
|
{
|
|
if( m_GridList[ii].x <= 0 )
|
|
break;
|
|
if( (m_Grid.x == m_GridList[ii].x) && (m_Grid.y == m_GridList[ii].y) )
|
|
break;
|
|
}
|
|
|
|
if( (m_GridList[ii].x > 0) && (m_GridList[ii + 1].x > 0) )
|
|
m_Grid = m_GridList[ii + 1];
|
|
}
|
|
|
|
|
|
/**********************************/
|
|
void BASE_SCREEN::SetFirstGrid()
|
|
/**********************************/
|
|
|
|
/* ajuste le coeff de grille a 1
|
|
*/
|
|
{
|
|
if( m_GridList == NULL )
|
|
return;
|
|
|
|
int ii = 0;
|
|
while( m_GridList[ii].x > 0 )
|
|
ii++;
|
|
|
|
m_Grid = m_GridList[ii - 1];
|
|
}
|
|
|
|
|
|
/**********************************/
|
|
void BASE_SCREEN::SetLastGrid()
|
|
/**********************************/
|
|
|
|
/* ajuste le coeff de grille au max
|
|
*/
|
|
{
|
|
if( m_GridList == NULL )
|
|
return;
|
|
m_Grid = m_GridList[0];
|
|
}
|
|
|
|
|
|
/*****************************************/
|
|
void BASE_SCREEN::ClearUndoRedoList()
|
|
/*****************************************/
|
|
|
|
/* free the undo and the redo lists
|
|
*/
|
|
{
|
|
EDA_BaseStruct* nextitem;
|
|
|
|
while( m_UndoList )
|
|
{
|
|
nextitem = m_UndoList->Pnext;
|
|
delete m_UndoList;
|
|
m_UndoList = nextitem;
|
|
}
|
|
|
|
while( m_RedoList )
|
|
{
|
|
nextitem = m_RedoList->Pnext;
|
|
delete m_RedoList;
|
|
m_RedoList = nextitem;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************/
|
|
void BASE_SCREEN::AddItemToUndoList( EDA_BaseStruct* newitem )
|
|
/************************************************************/
|
|
|
|
/* Put newitem in head of undo list
|
|
* Deletes olds items if > count max.
|
|
*/
|
|
{
|
|
int ii;
|
|
EDA_BaseStruct* item, * nextitem;
|
|
|
|
if( newitem == NULL )
|
|
return;
|
|
|
|
newitem->Pnext = m_UndoList;
|
|
m_UndoList = newitem;
|
|
|
|
/* Free first items, if count max reached */
|
|
for( ii = 0, item = m_UndoList; ii < m_UndoRedoCountMax; ii++ )
|
|
{
|
|
if( item->Pnext == NULL )
|
|
return;
|
|
item = item->Pnext;
|
|
}
|
|
|
|
if( item == NULL )
|
|
return;
|
|
|
|
nextitem = item->Pnext;
|
|
item->Pnext = NULL; // Set end of chain
|
|
|
|
// Delete the extra items
|
|
for( item = nextitem; item != NULL; item = nextitem )
|
|
{
|
|
nextitem = item->Pnext;
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************/
|
|
void BASE_SCREEN::AddItemToRedoList( EDA_BaseStruct* newitem )
|
|
/***********************************************************/
|
|
{
|
|
int ii;
|
|
EDA_BaseStruct* item, * nextitem;
|
|
|
|
if( newitem == NULL )
|
|
return;
|
|
|
|
newitem->Pnext = m_RedoList;
|
|
m_RedoList = newitem;
|
|
/* Free first items, if count max reached */
|
|
for( ii = 0, item = m_RedoList; ii < m_UndoRedoCountMax; ii++ )
|
|
{
|
|
if( item->Pnext == NULL )
|
|
break;
|
|
item = item->Pnext;
|
|
}
|
|
|
|
if( item == NULL )
|
|
return;
|
|
|
|
nextitem = item->Pnext;
|
|
item->Pnext = NULL; // Set end of chain
|
|
|
|
// Delete the extra items
|
|
for( item = nextitem; item != NULL; item = nextitem )
|
|
{
|
|
nextitem = item->Pnext;
|
|
delete item;
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************/
|
|
EDA_BaseStruct* BASE_SCREEN::GetItemFromUndoList()
|
|
/*****************************************************/
|
|
{
|
|
EDA_BaseStruct* item = m_UndoList;
|
|
|
|
if( item )
|
|
m_UndoList = item->Pnext;
|
|
return item;
|
|
}
|
|
|
|
|
|
/******************************************************/
|
|
EDA_BaseStruct* BASE_SCREEN::GetItemFromRedoList()
|
|
/******************************************************/
|
|
{
|
|
EDA_BaseStruct* item = m_RedoList;
|
|
|
|
if( item )
|
|
m_RedoList = item->Pnext;
|
|
return item;
|
|
}
|
|
|
|
|
|
#if defined(DEBUG)
|
|
/**
|
|
* Function Show
|
|
* is used to output the object tree, currently for debugging only.
|
|
* @param nestLevel An aid to prettier tree indenting, and is the level
|
|
* of nesting of this object within the overall tree.
|
|
* @param os The ostream& to output to.
|
|
*/
|
|
void BASE_SCREEN::Show( int nestLevel, std::ostream& os )
|
|
{
|
|
EDA_BaseStruct* item = EEDrawList;
|
|
|
|
// for now, make it look like XML, expand on this later.
|
|
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
|
|
">\n";
|
|
|
|
for( ; item; item = item->Next() )
|
|
{
|
|
item->Show( nestLevel+1, os );
|
|
}
|
|
|
|
NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
|
|
}
|
|
#endif
|
|
|