368 lines
11 KiB
C++
368 lines
11 KiB
C++
/**
|
|
* @file page_layout_graphic_items.cpp
|
|
* @brief description of graphic items and texts to build a title block
|
|
*/
|
|
|
|
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 1992-2013 Jean-Pierre Charras <jp.charras at wanadoo.fr>.
|
|
* Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors.
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you may find one here:
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
|
|
/*
|
|
* the class WORKSHEET_DATAITEM (and WORKSHEET_DATAITEM_TEXT) defines
|
|
* a basic shape of a page layout ( frame references and title block )
|
|
* Basic shapes are line, rect and texts
|
|
* the WORKSHEET_DATAITEM coordinates units is the mm, and are relative to
|
|
* one of 4 page corners.
|
|
*
|
|
* These items cannot be drawn or plot "as this". they should be converted
|
|
* to a "draw list" (WS_DRAW_ITEM_BASE and derived items)
|
|
|
|
* The list of these items is stored in a WORKSHEET_LAYOUT instance.
|
|
*
|
|
* When building the draw list:
|
|
* the WORKSHEET_LAYOUT is used to create a WS_DRAW_ITEM_LIST
|
|
* coordinates are converted to draw/plot coordinates.
|
|
* texts are expanded if they contain format symbols.
|
|
* Items with m_RepeatCount > 1 are created m_RepeatCount times
|
|
*
|
|
* the WORKSHEET_LAYOUT is created only once.
|
|
* the WS_DRAW_ITEM_LIST is created each time the page layout is plotted/drawn
|
|
*
|
|
* the WORKSHEET_LAYOUT instance is created from a S expression which
|
|
* describes the page layout (can be the default page layout or a custom file).
|
|
*/
|
|
|
|
#include <fctsys.h>
|
|
#include <drawtxt.h>
|
|
#include <worksheet.h>
|
|
#include <class_title_block.h>
|
|
#include <worksheet_shape_builder.h>
|
|
#include <class_worksheet_dataitem.h>
|
|
|
|
/* a helper function to draw graphic symbols at start point or end point of
|
|
* an item.
|
|
* The start point symbol is a filled rectangle
|
|
* The start point symbol is a filled circle
|
|
*/
|
|
inline void drawMarker( EDA_RECT* aClipBox, wxDC* aDC,
|
|
const wxPoint& aPos, int aSize, bool aEndPointShape = false )
|
|
{
|
|
int markerHalfSize = aSize/2;
|
|
|
|
if( aEndPointShape )
|
|
GRFilledCircle( aClipBox, aDC, aPos.x, aPos.y, markerHalfSize,
|
|
0, GREEN, GREEN );
|
|
else
|
|
GRFilledRect( aClipBox, aDC,
|
|
aPos.x - markerHalfSize, aPos.y - markerHalfSize,
|
|
aPos.x + markerHalfSize, aPos.y + markerHalfSize,
|
|
0, GREEN, GREEN );
|
|
}
|
|
|
|
/* Draws the item list created by BuildWorkSheetGraphicList
|
|
* aClipBox = the clipping rect, or NULL if no clipping
|
|
* aDC = the current Device Context
|
|
* The not selected items are drawn first (most of items)
|
|
* The selected items are drawn after (usually 0 or 1)
|
|
* to be sure they are seen, even for overlapping items
|
|
*/
|
|
void WS_DRAW_ITEM_LIST::Draw( EDA_RECT* aClipBox, wxDC* aDC )
|
|
{
|
|
// The not selected items are drawn first (most of items)
|
|
for( WS_DRAW_ITEM_BASE* item = GetFirst(); item; item = GetNext() )
|
|
{
|
|
if( item->GetParent() && item->GetParent()->IsSelected() )
|
|
continue;
|
|
|
|
item->DrawWsItem( aClipBox, aDC );
|
|
}
|
|
|
|
// The selected items are drawn after (usually 0 or 1)
|
|
int markerSize = WORKSHEET_DATAITEM::GetMarkerSizeUi();
|
|
|
|
for( WS_DRAW_ITEM_BASE* item = GetFirst(); item; item = GetNext() )
|
|
{
|
|
if( !item->GetParent() || !item->GetParent()->IsSelected() )
|
|
continue;
|
|
|
|
item->DrawWsItem( aClipBox, aDC );
|
|
|
|
switch( item->GetType() )
|
|
{
|
|
case WS_DRAW_ITEM_BASE::wsg_line:
|
|
{
|
|
WS_DRAW_ITEM_LINE* line = (WS_DRAW_ITEM_LINE*) item;
|
|
|
|
if( markerSize )
|
|
{
|
|
drawMarker( aClipBox, aDC, line->GetStart(), markerSize );
|
|
drawMarker( aClipBox, aDC, line->GetEnd(), markerSize, true );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WS_DRAW_ITEM_BASE::wsg_rect:
|
|
{
|
|
WS_DRAW_ITEM_RECT* rect = (WS_DRAW_ITEM_RECT*) item;
|
|
|
|
if( markerSize )
|
|
{
|
|
drawMarker( aClipBox, aDC, rect->GetStart(), markerSize );
|
|
drawMarker( aClipBox, aDC, rect->GetEnd(), markerSize, true );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WS_DRAW_ITEM_BASE::wsg_text:
|
|
{
|
|
WS_DRAW_ITEM_TEXT* text = (WS_DRAW_ITEM_TEXT*) item;
|
|
|
|
if( markerSize )
|
|
drawMarker( aClipBox, aDC, text->GetTextPosition(),
|
|
markerSize );
|
|
}
|
|
break;
|
|
|
|
case WS_DRAW_ITEM_BASE::wsg_poly:
|
|
{
|
|
WS_DRAW_ITEM_POLYGON* poly = (WS_DRAW_ITEM_POLYGON*) item;
|
|
|
|
if( markerSize )
|
|
{
|
|
drawMarker( aClipBox, aDC, poly->GetPosition(),
|
|
markerSize );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
WS_DRAW_ITEM_TEXT::WS_DRAW_ITEM_TEXT( WORKSHEET_DATAITEM* aParent,
|
|
wxString& aText, wxPoint aPos, wxSize aSize,
|
|
int aPenWidth, EDA_COLOR_T aColor,
|
|
bool aItalic, bool aBold ) :
|
|
WS_DRAW_ITEM_BASE( aParent, wsg_text, aColor ), EDA_TEXT( aText )
|
|
{
|
|
SetTextPosition( aPos );
|
|
SetSize( aSize );
|
|
SetThickness( aPenWidth );
|
|
SetItalic( aItalic );
|
|
SetBold( aBold );
|
|
}
|
|
|
|
void WS_DRAW_ITEM_TEXT::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC )
|
|
{
|
|
Draw( aClipBox, aDC, wxPoint(0,0),
|
|
GetColor(), UNSPECIFIED_DRAWMODE, FILLED, UNSPECIFIED_COLOR );
|
|
}
|
|
|
|
// return true if the point aPosition is on the text
|
|
bool WS_DRAW_ITEM_TEXT::HitTest( const wxPoint& aPosition)
|
|
{
|
|
return EDA_TEXT::TextHitTest( aPosition, 0 );
|
|
}
|
|
|
|
/* return true if the point aPosition is on the starting point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_TEXT::HitTestStartPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetTextPosition();
|
|
|
|
if( std::abs( pos.x - aPosition.x) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 &&
|
|
std::abs( pos.y - aPosition.y) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void WS_DRAW_ITEM_POLYGON::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC )
|
|
{
|
|
GRPoly( aClipBox, aDC,
|
|
m_Corners.size(), &m_Corners[0],
|
|
IsFilled() ? FILLED_SHAPE : NO_FILL,
|
|
GetPenWidth(),
|
|
GetColor(), GetColor() );
|
|
}
|
|
|
|
// return true if the point aPosition is inside one of polygons
|
|
#include <polygon_test_point_inside.h>
|
|
bool WS_DRAW_ITEM_POLYGON::HitTest( const wxPoint& aPosition)
|
|
{
|
|
return TestPointInsidePolygon( &m_Corners[0],
|
|
m_Corners.size(), aPosition );
|
|
}
|
|
|
|
/* return true if the point aPosition is on the starting point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_POLYGON::HitTestStartPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetPosition();
|
|
|
|
if( std::abs( pos.x - aPosition.x) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 &&
|
|
std::abs( pos.y - aPosition.y) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void WS_DRAW_ITEM_RECT::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC )
|
|
{
|
|
GRRect( aClipBox, aDC,
|
|
GetStart().x, GetStart().y,
|
|
GetEnd().x, GetEnd().y,
|
|
GetPenWidth(), GetColor() );
|
|
}
|
|
|
|
// return true if the point aPosition is on the rect outline
|
|
bool WS_DRAW_ITEM_RECT::HitTest( const wxPoint& aPosition)
|
|
{
|
|
int dist = GetPenWidth()/2;
|
|
wxPoint start = GetStart();
|
|
wxPoint end;
|
|
end.x = GetEnd().x;
|
|
end.y = start.y;
|
|
|
|
// Upper line
|
|
if( TestSegmentHit( aPosition, start, end, dist ) )
|
|
return true;
|
|
|
|
// Right line
|
|
start = end;
|
|
end.y = GetEnd().y;
|
|
if( TestSegmentHit( aPosition, start, end, dist ) )
|
|
return true;
|
|
|
|
// lower line
|
|
start = end;
|
|
end.x = GetStart().x;
|
|
if( TestSegmentHit( aPosition, start, end, dist ) )
|
|
return true;
|
|
|
|
// left line
|
|
start = end;
|
|
end = GetStart();
|
|
if( TestSegmentHit( aPosition, start, end, dist ) )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* return true if the point aPosition is on the starting point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_RECT::HitTestStartPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetStart();
|
|
|
|
if( std::abs( pos.x - aPosition.x) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 &&
|
|
std::abs( pos.y - aPosition.y) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* return true if the point aPosition is on the ending point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_RECT::HitTestEndPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetEnd();
|
|
|
|
int dist = (int) hypot( pos.x - aPosition.x, pos.y - aPosition.y );
|
|
|
|
if( dist <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void WS_DRAW_ITEM_LINE::DrawWsItem( EDA_RECT* aClipBox, wxDC* aDC )
|
|
{
|
|
GRLine( aClipBox, aDC, GetStart(), GetEnd(),
|
|
GetPenWidth(), GetColor() );
|
|
}
|
|
|
|
// return true if the point aPosition is on the text
|
|
bool WS_DRAW_ITEM_LINE::HitTest( const wxPoint& aPosition)
|
|
{
|
|
return TestSegmentHit( aPosition, GetStart(), GetEnd(), GetPenWidth()/2 );
|
|
}
|
|
|
|
/* return true if the point aPosition is on the starting point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_LINE::HitTestStartPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetStart();
|
|
|
|
if( std::abs( pos.x - aPosition.x) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 &&
|
|
std::abs( pos.y - aPosition.y) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* return true if the point aPosition is on the ending point of this item
|
|
*/
|
|
bool WS_DRAW_ITEM_LINE::HitTestEndPoint( const wxPoint& aPosition)
|
|
{
|
|
wxPoint pos = GetEnd();
|
|
|
|
if( std::abs( pos.x - aPosition.x) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 &&
|
|
std::abs( pos.y - aPosition.y) <= WORKSHEET_DATAITEM::GetMarkerSizeUi()/2 )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Locate graphic items in m_graphicList at location aPosition
|
|
* aList = the list of items found
|
|
* aPosition is the position (in user units) to locate items
|
|
*/
|
|
void WS_DRAW_ITEM_LIST::Locate( std::vector <WS_DRAW_ITEM_BASE*>& aList,
|
|
const wxPoint& aPosition)
|
|
{
|
|
for( WS_DRAW_ITEM_BASE* item = GetFirst(); item; item = GetNext() )
|
|
{
|
|
item->m_Flags &= ~(LOCATE_STARTPOINT|LOCATE_ENDPOINT);
|
|
bool found = false;
|
|
|
|
if( item->HitTestStartPoint ( aPosition ) )
|
|
{
|
|
item->m_Flags |= LOCATE_STARTPOINT;
|
|
found = true;
|
|
}
|
|
|
|
if( item->HitTestEndPoint ( aPosition ) )
|
|
{
|
|
item->m_Flags |= LOCATE_ENDPOINT;
|
|
found = true;
|
|
}
|
|
|
|
if( found || item->HitTest( aPosition ) )
|
|
{
|
|
aList.push_back( item );
|
|
}
|
|
}
|
|
}
|