kicad/eeschema/sch_text.cpp

1776 lines
46 KiB
C++
Raw Normal View History

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.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
*/
/**
* @file sch_text.cpp
* @brief Code for handling schematic texts (texts, labels, hlabels and global labels).
*/
#include <fctsys.h>
#include <gr_basic.h>
#include <macros.h>
#include <trigo.h>
#include <class_drawpanel.h>
#include <drawtxt.h>
#include <schframe.h>
#include <plot_common.h>
#include <msgpanel.h>
#include <gal/stroke_font.h>
#include <protos.h>
#include <sch_text.h>
#include <class_netlist_object.h>
2011-07-03 18:51:07 +00:00
extern void IncrementLabelMember( wxString& name, int aIncrement );
// Only for tests: set DRAW_BBOX to 1 to draw the bounding box of labels
#define DRAW_BBOX 0
// Margin in internal units (mils) between labels and wires
#define TXT_MARGIN 4
/* Names of sheet label types. */
const char* SheetLabelType[] =
{
"Input",
"Output",
"BiDi",
"3State",
"UnSpc",
"???"
};
/* Coding polygons for global symbol graphic shapes.
* the first parml is the number of corners
* others are the corners coordinates in reduced units
* the real coordinate is the reduced coordinate * text half size
*/
static int TemplateIN_HN[] = { 6, 0, 0, -1, -1, -2, -1, -2, 1, -1, 1, 0, 0 };
static int TemplateIN_HI[] = { 6, 0, 0, 1, 1, 2, 1, 2, -1, 1, -1, 0, 0 };
static int TemplateIN_UP[] = { 6, 0, 0, 1, -1, 1, -2, -1, -2, -1, -1, 0, 0 };
static int TemplateIN_BOTTOM[] = { 6, 0, 0, 1, 1, 1, 2, -1, 2, -1, 1, 0, 0 };
static int TemplateOUT_HN[] = { 6, -2, 0, -1, 1, 0, 1, 0, -1, -1, -1, -2, 0 };
static int TemplateOUT_HI[] = { 6, 2, 0, 1, -1, 0, -1, 0, 1, 1, 1, 2, 0 };
static int TemplateOUT_UP[] = { 6, 0, -2, 1, -1, 1, 0, -1, 0, -1, -1, 0, -2 };
static int TemplateOUT_BOTTOM[] = { 6, 0, 2, 1, 1, 1, 0, -1, 0, -1, 1, 0, 2 };
static int TemplateUNSPC_HN[] = { 5, 0, -1, -2, -1, -2, 1, 0, 1, 0, -1 };
static int TemplateUNSPC_HI[] = { 5, 0, -1, 2, -1, 2, 1, 0, 1, 0, -1 };
static int TemplateUNSPC_UP[] = { 5, 1, 0, 1, -2, -1, -2, -1, 0, 1, 0 };
static int TemplateUNSPC_BOTTOM[] = { 5, 1, 0, 1, 2, -1, 2, -1, 0, 1, 0 };
static int TemplateBIDI_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
static int TemplateBIDI_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
static int TemplateBIDI_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
static int TemplateBIDI_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
static int Template3STATE_HN[] = { 5, 0, 0, -1, -1, -2, 0, -1, 1, 0, 0 };
static int Template3STATE_HI[] = { 5, 0, 0, 1, -1, 2, 0, 1, 1, 0, 0 };
static int Template3STATE_UP[] = { 5, 0, 0, -1, -1, 0, -2, 1, -1, 0, 0 };
static int Template3STATE_BOTTOM[] = { 5, 0, 0, -1, 1, 0, 2, 1, 1, 0, 0 };
static int* TemplateShape[5][4] =
{
{ TemplateIN_HN, TemplateIN_UP, TemplateIN_HI, TemplateIN_BOTTOM },
{ TemplateOUT_HN, TemplateOUT_UP, TemplateOUT_HI, TemplateOUT_BOTTOM },
{ TemplateBIDI_HN, TemplateBIDI_UP, TemplateBIDI_HI, TemplateBIDI_BOTTOM },
{ Template3STATE_HN, Template3STATE_UP, Template3STATE_HI, Template3STATE_BOTTOM },
{ TemplateUNSPC_HN, TemplateUNSPC_UP, TemplateUNSPC_HI, TemplateUNSPC_BOTTOM }
};
SCH_TEXT::SCH_TEXT( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
SCH_ITEM( NULL, aType ),
EDA_TEXT( text ),
m_shape( NET_INPUT )
{
m_Layer = LAYER_NOTES;
m_Pos = pos;
m_isDangling = false;
m_MultilineAllowed = true;
m_schematicOrientation = 0;
}
SCH_TEXT::SCH_TEXT( const SCH_TEXT& aText ) :
SCH_ITEM( aText ),
EDA_TEXT( aText )
{
m_Pos = aText.m_Pos;
m_shape = aText.m_shape;
m_MultilineAllowed = aText.m_MultilineAllowed;
m_schematicOrientation = aText.m_schematicOrientation;
m_isDangling = false;
}
EDA_ITEM* SCH_TEXT::Clone() const
{
return new SCH_TEXT( *this );
}
2007-09-01 12:00:30 +00:00
void SCH_TEXT::IncrementLabel( int aIncrement )
{
IncrementLabelMember( m_Text, aIncrement );
}
wxPoint SCH_TEXT::GetSchematicTextOffset() const
{
wxPoint text_offset;
// add an offset to x ( or y) position to allow a text to
// be on a wire or a line and be readable
int thick_offset = TXT_MARGIN +
( GetPenSize() + GetDefaultLineThickness() ) / 2;
switch( m_schematicOrientation )
{
default:
case 0: /* Horiz Normal Orientation (left justified) */
text_offset.y = -thick_offset;
break;
case 1: /* Vert Orientation UP */
text_offset.x = -thick_offset;
break;
case 2: /* Horiz Orientation - Right justified */
text_offset.y = -thick_offset;
break;
case 3: /* Vert Orientation BOTTOM */
text_offset.x = -thick_offset;
break;
}
return text_offset;
}
bool SCH_TEXT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxPoint * aFindLocation )
{
wxLogTrace( traceFindItem, wxT( " item " ) + GetSelectMenuText() );
if( SCH_ITEM::Matches( m_Text, aSearchData ) )
{
EDA_RECT BoundaryBox = GetBoundingBox();
if( aFindLocation )
*aFindLocation = BoundaryBox.Centre();
return true;
}
return false;
}
void SCH_TEXT::MirrorY( int aYaxis_position )
{
// Text is NOT really mirrored; it is moved to a suitable horizontal position
switch( GetOrientation() )
{
case 0: // horizontal text
SetOrientation( 2 );
break;
case 2: // invert horizontal text
SetOrientation( 0 );
break;
case 1: // Vert Orientation UP
case 3: // Vert Orientation BOTTOM
default:
break;
}
MIRROR( m_Pos.x, aYaxis_position );
}
void SCH_TEXT::MirrorX( int aXaxis_position )
{
// Text is NOT really mirrored; it is moved to a suitable vertical position
switch( GetOrientation() )
{
case 1: // Vert Orientation UP
SetOrientation( 3 );
break;
case 3: // Vert Orientation BOTTOM
SetOrientation( 1 );
break;
case 0: // horizontal text
case 2: // invert horizontal text
default:
break;
}
MIRROR( m_Pos.y, aXaxis_position );
}
void SCH_TEXT::Rotate( wxPoint aPosition )
{
int dy;
RotatePoint( &m_Pos, aPosition, 900 );
SetOrientation( (GetOrientation() + 1) % 4 );
switch( GetOrientation() )
{
case 0: // horizontal text
dy = m_Size.y;
break;
case 1: // Vert Orientation UP
dy = 0;
break;
case 2: // invert horizontal text
dy = m_Size.y;
break;
case 3: // Vert Orientation BOTTOM
dy = 0;
break;
default:
dy = 0;
break;
}
m_Pos.y += dy;
}
void SCH_TEXT::SetOrientation( int aOrientation )
{
m_schematicOrientation = aOrientation;
switch( m_schematicOrientation )
{
default:
case 0: /* Horiz Normal Orientation (left justified) */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
break;
case 1: /* Vert Orientation UP */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
break;
case 2: /* Horiz Orientation - Right justified */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
break;
case 3: /* Vert Orientation BOTTOM */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_BOTTOM;
break;
}
}
void SCH_TEXT::SwapData( SCH_ITEM* aItem )
{
SCH_TEXT* item = (SCH_TEXT*) aItem;
std::swap( m_Text, item->m_Text );
std::swap( m_Pos, item->m_Pos );
std::swap( m_Size, item->m_Size );
std::swap( m_Thickness, item->m_Thickness );
std::swap( m_shape, item->m_shape );
std::swap( m_Orient, item->m_Orient );
std::swap( m_Layer, item->m_Layer );
std::swap( m_HJustify, item->m_HJustify );
std::swap( m_VJustify, item->m_VJustify );
std::swap( m_isDangling, item->m_isDangling );
std::swap( m_schematicOrientation, item->m_schematicOrientation );
}
int SCH_TEXT::GetPenSize() const
{
int pensize = m_Thickness;
if( pensize == 0 ) // Use default values for pen size
{
if( m_Bold )
pensize = GetPenSizeForBold( m_Size.x );
else
pensize = GetDefaultLineThickness();
}
// Clip pen size for small texts:
pensize = Clamp_Text_PenSize( pensize, m_Size, m_Bold );
return pensize;
}
void SCH_TEXT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& aOffset,
GR_DRAWMODE DrawMode, EDA_COLOR_T Color )
{
EDA_COLOR_T color;
int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness;
EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
if( Color >= 0 )
color = Color;
else
color = GetLayerColor( m_Layer );
GRSetDrawMode( DC, DrawMode );
wxPoint text_offset = aOffset + GetSchematicTextOffset();
std::swap( linewidth, m_Thickness ); // Set the minimum width
EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
std::swap( linewidth, m_Thickness ); // set initial value
if( m_isDangling && panel)
DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
// Enable these line to draw the bounding box (debug tests purposes only)
#if DRAW_BBOX
{
EDA_RECT BoundaryBox = GetBoundingBox();
GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
}
#endif
}
bool SCH_TEXT::Save( FILE* aFile ) const
{
bool success = true;
const char* shape = "~";
if( m_Italic )
shape = "Italic";
// For compatibility reason, the text must be saved in only one text line
// so we replace all E.O.L. by \\n
wxString text = m_Text;
text.Replace( wxT("\n"), wxT( "\\n" ) );
// Here we should have no CR or LF character in line
// This is not always the case if a multiline text was copied (using a copy/paste function)
// from a text that uses E.O.L characters that differs from the current EOL format
// This is mainly the case under Linux using LF symbol when copying a text from
// Windows (using CRLF symbol)
// So we must just remove the extra CR left (or LF left under MacOSX)
for( unsigned ii = 0; ii < text.Len(); )
{
if( text[ii] == 0x0A || text[ii] == 0x0D )
text.erase( ii, 1 );
else
ii++;
}
if( fprintf( aFile, "Text Notes %-4d %-4d %-4d %-4d %s %d\n%s\n",
m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
shape, m_Thickness, TO_UTF8( text ) ) == EOF )
{
success = false;
}
return success;
}
bool SCH_TEXT::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
char Name1[256];
char Name2[256];
char Name3[256];
int thickness = 0, size = 0, orient = 0;
Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
char* sline = (char*) aLine;
while( ( *sline != ' ' ) && *sline )
sline++;
// sline points the start of parameters
int ii = sscanf( sline, "%255s %d %d %d %d %255s %255s %d", Name1, &m_Pos.x, &m_Pos.y,
&orient, &size, Name2, Name3, &thickness );
if( ii < 4 )
{
aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( !aLine.ReadLine() )
{
aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( size == 0 )
size = GetDefaultTextSize();
char* text = strtok( (char*) aLine, "\n\r" );
if( text == NULL )
{
aErrorMsg.Printf( wxT( "Eeschema file text load error at line %d" ),
aLine.LineNumber() );
return false;
}
wxString val = FROM_UTF8( text );
2011-03-03 19:08:13 +00:00
for( ; ; )
{
int i = val.find( wxT( "\\n" ) );
if( i == wxNOT_FOUND )
break;
val.erase( i, 2 );
val.insert( i, wxT( "\n" ) );
}
m_Text = val;
m_Size.x = m_Size.y = size;
SetOrientation( orient );
if( isdigit( Name3[0] ) )
{
thickness = atol( Name3 );
m_Bold = ( thickness != 0 );
m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
}
if( strnicmp( Name2, "Italic", 6 ) == 0 )
m_Italic = 1;
return true;
}
void SCH_TEXT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
{
// Normal text labels cannot be tested for dangling ends.
if( Type() == SCH_TEXT_T )
return;
2011-12-06 21:02:21 +00:00
DANGLING_END_ITEM item( LABEL_END, this, m_Pos );
aItemList.push_back( item );
}
bool SCH_TEXT::IsDanglingStateChanged( std::vector< DANGLING_END_ITEM >& aItemList )
{
// Normal text labels cannot be tested for dangling ends.
if( Type() == SCH_TEXT_T )
return false;
bool previousState = m_isDangling;
m_isDangling = true;
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
{
DANGLING_END_ITEM& item = aItemList[ii];
2011-12-06 21:02:21 +00:00
if( item.GetItem() == this )
continue;
2011-12-06 21:02:21 +00:00
switch( item.GetType() )
{
case PIN_END:
case LABEL_END:
case SHEET_LABEL_END:
2011-12-06 21:02:21 +00:00
if( m_Pos == item.GetPosition() )
m_isDangling = false;
2011-12-06 21:02:21 +00:00
break;
case WIRE_START_END:
case BUS_START_END:
{
// These schematic items have created 2 DANGLING_END_ITEM one per end. But being
// a paranoid programmer, I'll check just in case.
ii++;
wxCHECK_MSG( ii < aItemList.size(), previousState != m_isDangling,
wxT( "Dangling end type list overflow. Bad programmer!" ) );
DANGLING_END_ITEM & nextItem = aItemList[ii];
m_isDangling = !IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_Pos );
}
break;
default:
break;
}
2013-03-30 19:55:26 +00:00
if( !m_isDangling )
break;
}
return previousState != m_isDangling;
}
bool SCH_TEXT::IsSelectStateChanged( const wxRect& aRect )
{
bool previousState = IsSelected();
if( aRect.Contains( m_Pos ) )
2013-03-30 19:55:26 +00:00
SetFlags( SELECTED );
else
ClearFlags( SELECTED );
return previousState != IsSelected();
}
void SCH_TEXT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
{
// Normal text labels do not have connection points. All others do.
if( Type() == SCH_TEXT_T )
return;
aPoints.push_back( m_Pos );
}
const EDA_RECT SCH_TEXT::GetBoundingBox() const
{
// We must pass the effective text thickness to GetTextBox
// when calculating the bounding box
int linewidth = ( m_Thickness == 0 ) ? GetDefaultLineThickness() : m_Thickness;
linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
EDA_RECT rect = GetTextBox( -1, linewidth );
if( m_Orient ) // Rotate rect
2008-04-15 19:38:19 +00:00
{
wxPoint pos = rect.GetOrigin();
wxPoint end = rect.GetEnd();
RotatePoint( &pos, m_Pos, m_Orient );
RotatePoint( &end, m_Pos, m_Orient );
rect.SetOrigin( pos );
rect.SetEnd( end );
2008-04-15 19:38:19 +00:00
}
rect.Normalize();
return rect;
2008-04-15 19:38:19 +00:00
}
wxString SCH_TEXT::GetSelectMenuText() const
{
2011-03-26 10:08:50 +00:00
wxString msg;
msg.Printf( _( "Graphic Text %s" ), GetChars( ShortenedShownText() ) );
2011-03-26 10:08:50 +00:00
return msg;
}
void SCH_TEXT::GetNetListItem( NETLIST_OBJECT_LIST& aNetListItems,
SCH_SHEET_PATH* aSheetPath )
{
if( GetLayer() == LAYER_NOTES || GetLayer() == LAYER_SHEETLABEL )
return;
NETLIST_OBJECT* item = new NETLIST_OBJECT();
item->m_SheetPath = *aSheetPath;
item->m_SheetPathInclude = *aSheetPath;
item->m_Comp = (SCH_ITEM*) this;
item->m_Type = NET_LABEL;
if( GetLayer() == LAYER_GLOBLABEL )
item->m_Type = NET_GLOBLABEL;
else if( GetLayer() == LAYER_HIERLABEL )
item->m_Type = NET_HIERLABEL;
item->m_Label = m_Text;
item->m_Start = item->m_End = m_Pos;
aNetListItems.push_back( item );
/* If a bus connects to label */
if( IsBusLabel( m_Text ) )
item->ConvertBusToNetListItems( aNetListItems );
}
bool SCH_TEXT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
EDA_RECT bBox = GetBoundingBox();
bBox.Inflate( aAccuracy );
return bBox.Contains( aPosition );
}
bool SCH_TEXT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
{
EDA_RECT bBox = GetBoundingBox();
bBox.Inflate( aAccuracy );
if( aContained )
return aRect.Contains( bBox );
return aRect.Intersects( bBox );
}
void SCH_TEXT::Plot( PLOTTER* aPlotter )
{
static std::vector <wxPoint> Poly;
EDA_COLOR_T color = GetLayerColor( GetLayer() );
int thickness = GetPenSize();
aPlotter->SetCurrentLineWidth( thickness );
if( m_MultilineAllowed )
{
std::vector<wxPoint> positions;
wxArrayString strings_list;
wxStringSplit( GetShownText(), strings_list, '\n' );
positions.reserve( strings_list.Count() );
GetPositionsOfLinesOfMultilineText(positions, strings_list.Count() );
for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
{
wxPoint textpos = positions[ii] + GetSchematicTextOffset();
wxString& txt = strings_list.Item( ii );
aPlotter->Text( textpos, color, txt, m_Orient, m_Size, m_HJustify,
m_VJustify, thickness, m_Italic, m_Bold );
}
}
else
{
wxPoint textpos = m_Pos + GetSchematicTextOffset();
aPlotter->Text( textpos, color, GetShownText(), m_Orient, m_Size, m_HJustify,
m_VJustify, thickness, m_Italic, m_Bold );
}
/* Draw graphic symbol for global or hierarchical labels */
CreateGraphicShape( Poly, m_Pos );
aPlotter->SetCurrentLineWidth( GetPenSize() );
if( Poly.size() )
aPlotter->PlotPoly( Poly, NO_FILL );
}
/*
* Display the type, shape, size and some other props to the Message panel
*/
void SCH_TEXT::GetMsgPanelInfo( MSG_PANEL_ITEMS& aList )
{
wxString msg;
switch( Type() )
{
case SCH_TEXT_T:
msg = _( "Graphic Text" );
break;
case SCH_LABEL_T:
msg = _( "Label" );
break;
case SCH_GLOBAL_LABEL_T:
msg = _( "Global Label" );
break;
case SCH_HIERARCHICAL_LABEL_T:
msg = _( "Hierarchical Label" );
break;
case SCH_SHEET_PIN_T:
msg = _( "Hierarchical Sheet Pin" );
break;
default:
return;
}
aList.push_back( MSG_PANEL_ITEM( msg, GetShownText(), DARKCYAN ) );
switch( GetOrientation() )
{
case 0: // horizontal text
msg = _( "Horizontal" );
break;
case 1: // Vert Orientation UP
msg = _( "Vertical up" );
break;
case 2: // invert horizontal text
msg = _( "Horizontal invert" );
break;
case 3: // Vert Orientation Down
msg = _( "Vertical down" );
break;
default:
msg = wxT( "???" );
break;
}
aList.push_back( MSG_PANEL_ITEM( _( "Orientation" ), msg, BROWN ) );
wxString textStyle[] = { _( "Normal" ), _( "Italic" ), _( "Bold" ), _( "Bold Italic" ) };
int style = 0;
if( m_Italic )
style = 1;
if( m_Bold )
style += 2;
aList.push_back( MSG_PANEL_ITEM( _( "Style" ), textStyle[style], BROWN ) );
// Display electricat type if it is relevant
if( (Type() == SCH_GLOBAL_LABEL_T) ||
(Type() == SCH_HIERARCHICAL_LABEL_T ) ||
(Type() == SCH_SHEET_PIN_T ) )
{
switch( GetShape() )
{
case NET_INPUT: msg = _( "Input" ); break;
case NET_OUTPUT: msg = _( "Output" ); break;
case NET_BIDI: msg = _( "Bidirectional" ); break;
case NET_TRISTATE: msg = _( "Tri-State" ); break;
case NET_UNSPECIFIED: msg = _( "Passive" ); break;
default: msg = wxT( "???" ); break;
}
aList.push_back( MSG_PANEL_ITEM( _( "Type" ), msg, BLUE ) );
}
// Display text size (X or Y value, with are the same value in Eeschema)
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
2014-03-20 00:42:08 +00:00
msg = StringFromValue( g_UserUnit, m_Size.x, true );
aList.push_back( MSG_PANEL_ITEM( _( "Size" ), msg, RED ) );
}
2008-04-22 16:38:23 +00:00
#if defined(DEBUG)
void SCH_TEXT::Show( int nestLevel, std::ostream& os ) const
2008-04-22 16:38:23 +00:00
{
// XML output:
wxString s = GetClass();
NestedSpace( nestLevel, os ) << '<' << s.Lower().mb_str()
<< " layer=\"" << m_Layer << '"'
<< " shape=\"" << m_shape << '"'
<< " dangling=\"" << m_isDangling << '"'
<< '>'
<< TO_UTF8( m_Text )
<< "</" << s.Lower().mb_str() << ">\n";
2008-04-22 16:38:23 +00:00
}
#endif
SCH_LABEL::SCH_LABEL( const wxPoint& pos, const wxString& text ) :
SCH_TEXT( pos, text, SCH_LABEL_T )
{
m_Layer = LAYER_LOCLABEL;
m_shape = NET_INPUT;
m_isDangling = true;
m_MultilineAllowed = false;
}
EDA_ITEM* SCH_LABEL::Clone() const
2008-04-15 19:38:19 +00:00
{
return new SCH_LABEL( *this );
}
wxPoint SCH_LABEL::GetSchematicTextOffset() const
{
return SCH_TEXT::GetSchematicTextOffset();
}
void SCH_LABEL::SetOrientation( int aOrientation )
{
SCH_TEXT::SetOrientation( aOrientation );
2008-04-15 19:38:19 +00:00
}
void SCH_LABEL::MirrorX( int aXaxis_position )
{
// Text is NOT really mirrored; it is moved to a suitable position
switch( GetOrientation() )
{
case 1: // Vert Orientation UP
SetOrientation( 3 );
break;
case 3: // Vert Orientation BOTTOM
SetOrientation( 1 );
break;
case 0: // horizontal text
case 2: // invert horizontal text
default:
break;
}
MIRROR( m_Pos.y, aXaxis_position );
}
void SCH_LABEL::Rotate( wxPoint aPosition )
{
RotatePoint( &m_Pos, aPosition, 900 );
SetOrientation( (GetOrientation() + 1) % 4 );
}
2008-04-15 19:38:19 +00:00
bool SCH_LABEL::Save( FILE* aFile ) const
{
bool success = true;
const char* shape = "~";
if( m_Italic )
shape = "Italic";
if( fprintf( aFile, "Text Label %-4d %-4d %-4d %-4d %s %d\n%s\n",
m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x, shape,
m_Thickness, TO_UTF8( m_Text ) ) == EOF )
2008-04-15 19:38:19 +00:00
{
success = false;
}
return success;
}
bool SCH_LABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
char Name1[256];
char Name2[256];
char Name3[256];
int thickness = 0, size = 0, orient = 0;
Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
char* sline = (char*) aLine;
while( ( *sline != ' ' ) && *sline )
sline++;
// sline points the start of parameters
int ii = sscanf( sline, "%255s %d %d %d %d %255s %255s %d", Name1, &m_Pos.x, &m_Pos.y,
&orient, &size, Name2, Name3, &thickness );
if( ii < 4 )
{
aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( !aLine.ReadLine() )
{
aErrorMsg.Printf( wxT( "Eeschema file label load error atline %d" ),
aLine.LineNumber() );
return false;
}
if( size == 0 )
size = GetDefaultTextSize();
char* text = strtok( (char*) aLine, "\n\r" );
if( text == NULL )
{
aErrorMsg.Printf( wxT( "Eeschema file label load error at line %d" ),
aLine.LineNumber() );
return false;
}
m_Text = FROM_UTF8( text );
m_Size.x = m_Size.y = size;
SetOrientation( orient );
if( isdigit( Name3[0] ) )
{
thickness = atol( Name3 );
m_Bold = ( thickness != 0 );
m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
}
if( stricmp( Name2, "Italic" ) == 0 )
m_Italic = 1;
return true;
}
void SCH_LABEL::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
GR_DRAWMODE DrawMode, EDA_COLOR_T Color )
{
SCH_TEXT::Draw( panel, DC, offset, DrawMode, Color );
}
const EDA_RECT SCH_LABEL::GetBoundingBox() const
{
int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
EDA_RECT rect = GetTextBox( -1, linewidth );
if( m_Orient )
{ // Rotate rect
wxPoint pos = rect.GetOrigin();
wxPoint end = rect.GetEnd();
RotatePoint( &pos, m_Pos, m_Orient );
RotatePoint( &end, m_Pos, m_Orient );
rect.SetOrigin( pos );
rect.SetEnd( end );
rect.Normalize();
}
return rect;
}
wxString SCH_LABEL::GetSelectMenuText() const
{
2011-03-26 10:08:50 +00:00
wxString msg;
msg.Printf( _( "Label %s" ), GetChars( ShortenedShownText() ) );
2011-03-26 10:08:50 +00:00
return msg;
}
2008-04-15 19:38:19 +00:00
SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) :
SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T )
2008-04-15 19:38:19 +00:00
{
m_Layer = LAYER_GLOBLABEL;
m_shape = NET_BIDI;
m_isDangling = true;
m_MultilineAllowed = false;
2008-04-15 19:38:19 +00:00
}
EDA_ITEM* SCH_GLOBALLABEL::Clone() const
{
return new SCH_GLOBALLABEL( *this );
}
2008-04-15 19:38:19 +00:00
bool SCH_GLOBALLABEL::Save( FILE* aFile ) const
{
bool success = true;
const char* shape = "~";
if( m_Italic )
shape = "Italic";
if( fprintf( aFile, "Text GLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
2008-04-15 19:38:19 +00:00
{
success = false;
}
return success;
}
bool SCH_GLOBALLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
char Name1[256];
char Name2[256];
char Name3[256];
int thickness = 0, size = 0, orient = 0;
Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
char* sline = (char*) aLine;
while( (*sline != ' ' ) && *sline )
sline++;
// sline points the start of parameters
int ii = sscanf( sline, "%255s %d %d %d %d %255s %255s %d", Name1, &m_Pos.x, &m_Pos.y,
&orient, &size, Name2, Name3, &thickness );
if( ii < 4 )
{
aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( !aLine.ReadLine() )
{
aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( size == 0 )
size = GetDefaultTextSize();
char* text = strtok( (char*) aLine, "\n\r" );
if( text == NULL )
{
aErrorMsg.Printf( wxT( "Eeschema file global label load error at line %d" ),
aLine.LineNumber() );
return false;
}
m_Text = FROM_UTF8( text );
m_Size.x = m_Size.y = size;
SetOrientation( orient );
m_shape = NET_INPUT;
m_Bold = ( thickness != 0 );
m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
m_shape = NET_OUTPUT;
if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
m_shape = NET_BIDI;
if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
m_shape = NET_TRISTATE;
if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
m_shape = NET_UNSPECIFIED;
if( stricmp( Name3, "Italic" ) == 0 )
m_Italic = 1;
return true;
}
void SCH_GLOBALLABEL::MirrorY( int aYaxis_position )
2008-04-15 19:38:19 +00:00
{
/* The global label is NOT really mirrored.
* for an horizontal label, the schematic orientation is changed.
* for a vertical label, the schematic orientation is not changed.
* and the label is moved to a suitable position
*/
switch( GetOrientation() )
{
case 0: /* horizontal text */
SetOrientation( 2 );
break;
case 2: /* invert horizontal text*/
SetOrientation( 0 );
break;
}
MIRROR( m_Pos.x, aYaxis_position );
2008-04-15 19:38:19 +00:00
}
void SCH_GLOBALLABEL::MirrorX( int aXaxis_position )
{
switch( GetOrientation() )
{
case 1: /* vertical text */
SetOrientation( 3 );
break;
case 3: /* invert vertical text*/
SetOrientation( 1 );
break;
}
MIRROR( m_Pos.y, aXaxis_position );
}
void SCH_GLOBALLABEL::Rotate( wxPoint aPosition )
{
RotatePoint( &m_Pos, aPosition, 900 );
SetOrientation( (GetOrientation() + 3) % 4 );
}
wxPoint SCH_GLOBALLABEL::GetSchematicTextOffset() const
2008-04-15 19:38:19 +00:00
{
wxPoint text_offset;
int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
width = Clamp_Text_PenSize( width, m_Size, m_Bold );
int halfSize = m_Size.x / 2;
int offset = width;
switch( m_shape )
2008-04-15 19:38:19 +00:00
{
case NET_INPUT:
case NET_BIDI:
case NET_TRISTATE:
offset += halfSize;
break;
case NET_OUTPUT:
case NET_UNSPECIFIED:
offset += TXT_MARGIN;
break;
default:
break;
2008-04-15 19:38:19 +00:00
}
switch( m_schematicOrientation )
{
case 0: /* Orientation horiz normal */
text_offset.x -= offset;
break;
case 1: /* Orientation vert UP */
text_offset.y -= offset;
break;
case 2: /* Orientation horiz inverse */
text_offset.x += offset;
break;
case 3: /* Orientation vert BOTTOM */
text_offset.y += offset;
break;
}
return text_offset;
2008-04-15 19:38:19 +00:00
}
void SCH_GLOBALLABEL::SetOrientation( int aOrientation )
{
m_schematicOrientation = aOrientation;
switch( m_schematicOrientation )
{
default:
case 0: /* Horiz Normal Orientation */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 1: /* Vert Orientation UP */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 2: /* Horiz Orientation */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 3: /* Vert Orientation BOTTOM */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
}
}
2008-04-15 19:38:19 +00:00
void SCH_GLOBALLABEL::Draw( EDA_DRAW_PANEL* panel,
wxDC* DC,
const wxPoint& aOffset,
GR_DRAWMODE DrawMode,
EDA_COLOR_T Color )
2007-05-06 16:03:28 +00:00
{
static std::vector <wxPoint> Poly;
EDA_COLOR_T color;
wxPoint text_offset = aOffset + GetSchematicTextOffset();
if( Color >= 0 )
color = Color;
else
color = GetLayerColor( m_Layer );
GRSetDrawMode( DC, DrawMode );
int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
std::swap( linewidth, m_Thickness ); // Set the minimum width
EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
std::swap( linewidth, m_Thickness ); // set initial value
2007-05-06 16:03:28 +00:00
CreateGraphicShape( Poly, m_Pos + aOffset );
GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
2007-05-06 16:03:28 +00:00
if( m_isDangling && panel )
DrawDanglingSymbol( panel, DC, m_Pos + aOffset, color );
2009-11-28 09:24:37 +00:00
// Enable these line to draw the bounding box (debug tests purposes only)
#if DRAW_BBOX
2009-11-28 09:24:37 +00:00
{
EDA_RECT BoundaryBox = GetBoundingBox();
GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
2009-11-28 09:24:37 +00:00
}
#endif
2007-05-06 16:03:28 +00:00
}
void SCH_GLOBALLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
{
int halfSize = m_Size.y / 2;
int linewidth = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
aPoints.clear();
int symb_len = LenSize( GetShownText() ) + ( TXT_MARGIN * 2 );
// Create outline shape : 6 points
int x = symb_len + linewidth + 3;
// Use negation bar Y position to calculate full vertical size
// Search for overbar symbol
bool hasOverBar = false;
for( unsigned ii = 1; ii < m_Text.size(); ii++ )
{
if( m_Text[ii-1] == '~' && m_Text[ii] != '~' )
{
hasOverBar = true;
break;
}
}
#define Y_CORRECTION 1.40
// Note: this factor is due to the fact the Y size of a few letters like [
// are bigger than the y size value, and we need a margin for the graphic symbol.
int y = KiROUND( halfSize * Y_CORRECTION );
// Note: this factor is due to the fact we need a margin for the graphic symbol.
#define Y_OVERBAR_CORRECTION 1.2
if( hasOverBar )
y = KiROUND( KIGFX::STROKE_FONT::GetInterline( halfSize, linewidth )
* Y_OVERBAR_CORRECTION );
// Gives room for line thickess and margin
y += linewidth // for line thickess
+ linewidth/2; // for margin
// Starting point(anchor)
aPoints.push_back( wxPoint( 0, 0 ) );
aPoints.push_back( wxPoint( 0, -y ) ); // Up
aPoints.push_back( wxPoint( -x, -y ) ); // left
aPoints.push_back( wxPoint( -x, 0 ) ); // Up left
aPoints.push_back( wxPoint( -x, y ) ); // left down
aPoints.push_back( wxPoint( 0, y ) ); // down
int x_offset = 0;
switch( m_shape )
{
case NET_INPUT:
x_offset = -halfSize;
aPoints[0].x += halfSize;
break;
case NET_OUTPUT:
aPoints[3].x -= halfSize;
break;
case NET_BIDI:
case NET_TRISTATE:
x_offset = -halfSize;
aPoints[0].x += halfSize;
aPoints[3].x -= halfSize;
break;
case NET_UNSPECIFIED:
default:
break;
}
int angle = 0;
switch( m_schematicOrientation )
{
case 0: /* Orientation horiz normal */
break;
case 1: /* Orientation vert UP */
angle = -900;
break;
case 2: /* Orientation horiz inverse */
angle = 1800;
break;
case 3: /* Orientation vert BOTTOM */
angle = 900;
break;
}
// Rotate outlines and move corners in real position
for( unsigned ii = 0; ii < aPoints.size(); ii++ )
{
aPoints[ii].x += x_offset;
if( angle )
RotatePoint( &aPoints[ii], angle );
aPoints[ii] += Pos;
}
aPoints.push_back( aPoints[0] ); // closing
}
const EDA_RECT SCH_GLOBALLABEL::GetBoundingBox() const
{
int x, y, dx, dy, length, height;
x = m_Pos.x;
y = m_Pos.y;
2008-03-30 11:48:18 +00:00
dx = dy = 0;
int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
height = ( (m_Size.y * 15) / 10 ) + width + 2 * TXT_MARGIN;
// text X size add height for triangular shapes(bidirectional)
length = LenSize( GetShownText() ) + height + DANGLING_SYMBOL_SIZE;
switch( m_schematicOrientation ) // respect orientation
{
case 0: /* Horiz Normal Orientation (left justified) */
dx = -length;
dy = height;
x += DANGLING_SYMBOL_SIZE;
y -= height / 2;
break;
case 1: /* Vert Orientation UP */
dx = height;
dy = -length;
x -= height / 2;
y += DANGLING_SYMBOL_SIZE;
break;
case 2: /* Horiz Orientation - Right justified */
dx = length;
dy = height;
x -= DANGLING_SYMBOL_SIZE;
y -= height / 2;
break;
case 3: /* Vert Orientation BOTTOM */
dx = height;
dy = length;
x -= height / 2;
y -= DANGLING_SYMBOL_SIZE;
break;
}
EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
box.Normalize();
return box;
}
wxString SCH_GLOBALLABEL::GetSelectMenuText() const
{
2011-03-26 10:08:50 +00:00
wxString msg;
msg.Printf( _( "Global Label %s" ), GetChars( ShortenedShownText() ) );
2011-03-26 10:08:50 +00:00
return msg;
}
SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
SCH_TEXT( pos, text, aType )
{
m_Layer = LAYER_HIERLABEL;
m_shape = NET_INPUT;
m_isDangling = true;
m_MultilineAllowed = false;
}
EDA_ITEM* SCH_HIERLABEL::Clone() const
{
return new SCH_HIERLABEL( *this );
}
bool SCH_HIERLABEL::Save( FILE* aFile ) const
{
bool success = true;
const char* shape = "~";
if( m_Italic )
shape = "Italic";
if( fprintf( aFile, "Text HLabel %-4d %-4d %-4d %-4d %s %s %d\n%s\n",
m_Pos.x, m_Pos.y, m_schematicOrientation, m_Size.x,
SheetLabelType[m_shape], shape, m_Thickness, TO_UTF8( m_Text ) ) == EOF )
{
success = false;
}
return success;
}
bool SCH_HIERLABEL::Load( LINE_READER& aLine, wxString& aErrorMsg )
{
char Name1[256];
char Name2[256];
char Name3[256];
int thickness = 0, size = 0, orient = 0;
Name1[0] = 0; Name2[0] = 0; Name3[0] = 0;
char* sline = (char*) aLine;
while( (*sline != ' ' ) && *sline )
sline++;
// sline points the start of parameters
int ii = sscanf( sline, "%255s %d %d %d %d %255s %255s %d", Name1, &m_Pos.x, &m_Pos.y,
&orient, &size, Name2, Name3, &thickness );
if( ii < 4 )
{
aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( !aLine.ReadLine() )
{
aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
aLine.LineNumber() );
return false;
}
if( size == 0 )
size = GetDefaultTextSize();
char* text = strtok( (char*) aLine, "\n\r" );
if( text == NULL )
{
aErrorMsg.Printf( wxT( "Eeschema file hierarchical label load error at line %d" ),
aLine.LineNumber() );
return false;
}
m_Text = FROM_UTF8( text );
m_Size.x = m_Size.y = size;
SetOrientation( orient );
m_shape = NET_INPUT;
m_Bold = ( thickness != 0 );
m_Thickness = m_Bold ? GetPenSizeForBold( size ) : 0;
if( stricmp( Name2, SheetLabelType[NET_OUTPUT] ) == 0 )
m_shape = NET_OUTPUT;
if( stricmp( Name2, SheetLabelType[NET_BIDI] ) == 0 )
m_shape = NET_BIDI;
if( stricmp( Name2, SheetLabelType[NET_TRISTATE] ) == 0 )
m_shape = NET_TRISTATE;
if( stricmp( Name2, SheetLabelType[NET_UNSPECIFIED] ) == 0 )
m_shape = NET_UNSPECIFIED;
if( stricmp( Name3, "Italic" ) == 0 )
m_Italic = 1;
return true;
}
void SCH_HIERLABEL::SetOrientation( int aOrientation )
{
m_schematicOrientation = aOrientation;
switch( m_schematicOrientation )
{
default:
case 0: /* Horiz Normal Orientation */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 1: /* Vert Orientation UP */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 2: /* Horiz Orientation */
m_Orient = TEXT_ORIENT_HORIZ;
m_HJustify = GR_TEXT_HJUSTIFY_LEFT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
case 3: /* Vert Orientation BOTTOM */
m_Orient = TEXT_ORIENT_VERT;
m_HJustify = GR_TEXT_HJUSTIFY_RIGHT;
m_VJustify = GR_TEXT_VJUSTIFY_CENTER;
break;
}
}
void SCH_HIERLABEL::Draw( EDA_DRAW_PANEL* panel,
wxDC* DC,
const wxPoint& offset,
GR_DRAWMODE DrawMode,
EDA_COLOR_T Color )
{
static std::vector <wxPoint> Poly;
EDA_COLOR_T color;
int linewidth = m_Thickness == 0 ?
GetDefaultLineThickness() : m_Thickness;
EDA_RECT* clipbox = panel? panel->GetClipBox() : NULL;
linewidth = Clamp_Text_PenSize( linewidth, m_Size, m_Bold );
if( Color >= 0 )
color = Color;
else
color = GetLayerColor( m_Layer );
GRSetDrawMode( DC, DrawMode );
std::swap( linewidth, m_Thickness ); // Set the minimum width
wxPoint text_offset = offset + GetSchematicTextOffset();
EDA_TEXT::Draw( clipbox, DC, text_offset, color, DrawMode, FILLED, UNSPECIFIED_COLOR );
std::swap( linewidth, m_Thickness ); // set initial value
CreateGraphicShape( Poly, m_Pos + offset );
GRPoly( clipbox, DC, Poly.size(), &Poly[0], 0, linewidth, color, color );
if( m_isDangling && panel )
DrawDanglingSymbol( panel, DC, m_Pos + offset, color );
2009-11-28 09:24:37 +00:00
// Enable these line to draw the bounding box (debug tests purposes only)
#if DRAW_BBOX
2009-11-28 09:24:37 +00:00
{
EDA_RECT BoundaryBox = GetBoundingBox();
GRRect( clipbox, DC, BoundaryBox, 0, BROWN );
2009-11-28 09:24:37 +00:00
}
#endif
}
void SCH_HIERLABEL::CreateGraphicShape( std::vector <wxPoint>& aPoints, const wxPoint& Pos )
{
int* Template = TemplateShape[m_shape][m_schematicOrientation];
int halfSize = m_Size.x / 2;
int imax = *Template; Template++;
aPoints.clear();
for( int ii = 0; ii < imax; ii++ )
{
wxPoint corner;
corner.x = ( halfSize * (*Template) ) + Pos.x;
Template++;
corner.y = ( halfSize * (*Template) ) + Pos.y;
Template++;
aPoints.push_back( corner );
}
}
const EDA_RECT SCH_HIERLABEL::GetBoundingBox() const
{
int x, y, dx, dy, length, height;
x = m_Pos.x;
y = m_Pos.y;
2008-03-30 11:48:18 +00:00
dx = dy = 0;
int width = (m_Thickness == 0) ? GetDefaultLineThickness() : m_Thickness;
height = m_Size.y + width + 2 * TXT_MARGIN;
length = LenSize( GetShownText() )
+ height // add height for triangular shapes
+ 2 * DANGLING_SYMBOL_SIZE;
switch( m_schematicOrientation ) // respect orientation
{
case 0: /* Horiz Normal Orientation (left justified) */
dx = -length;
dy = height;
x += DANGLING_SYMBOL_SIZE;
y -= height / 2;
break;
case 1: /* Vert Orientation UP */
dx = height;
dy = -length;
x -= height / 2;
y += DANGLING_SYMBOL_SIZE;
break;
case 2: /* Horiz Orientation - Right justified */
dx = length;
dy = height;
x -= DANGLING_SYMBOL_SIZE;
y -= height / 2;
break;
case 3: /* Vert Orientation BOTTOM */
dx = height;
dy = length;
x -= height / 2;
y -= DANGLING_SYMBOL_SIZE;
break;
}
EDA_RECT box( wxPoint( x, y ), wxSize( dx, dy ) );
box.Normalize();
return box;
}
wxPoint SCH_HIERLABEL::GetSchematicTextOffset() const
2009-11-28 09:24:37 +00:00
{
wxPoint text_offset;
int width = std::max( m_Thickness, GetDefaultLineThickness() );
int ii = m_Size.x + TXT_MARGIN + width;
switch( m_schematicOrientation )
{
case 0: /* Orientation horiz normale */
text_offset.x = -ii;
break;
case 1: /* Orientation vert UP */
text_offset.y = -ii;
break;
case 2: /* Orientation horiz inverse */
text_offset.x = ii;
break;
case 3: /* Orientation vert BOTTOM */
text_offset.y = ii;
break;
}
return text_offset;
}
2009-11-28 09:24:37 +00:00
void SCH_HIERLABEL::MirrorY( int aYaxis_position )
2009-11-28 09:24:37 +00:00
{
/* The hierarchical label is NOT really mirrored for an horizontal label, the schematic
* orientation is changed. For a vertical label, the schematic orientation is not changed
* and the label is moved to a suitable position.
*/
switch( GetOrientation() )
{
case 0: /* horizontal text */
SetOrientation( 2 );
break;
2009-11-28 09:24:37 +00:00
case 2: /* invert horizontal text*/
SetOrientation( 0 );
break;
}
MIRROR( m_Pos.x, aYaxis_position );
}
void SCH_HIERLABEL::MirrorX( int aXaxis_position )
{
switch( GetOrientation() )
2009-11-28 09:24:37 +00:00
{
case 1: /* vertical text */
SetOrientation( 3 );
break;
case 3: /* invert vertical text*/
SetOrientation( 1 );
break;
2009-11-28 09:24:37 +00:00
}
MIRROR( m_Pos.y, aXaxis_position );
}
void SCH_HIERLABEL::Rotate( wxPoint aPosition )
{
RotatePoint( &m_Pos, aPosition, 900 );
SetOrientation( (GetOrientation() + 3) % 4 );
2009-11-28 09:24:37 +00:00
}
wxString SCH_HIERLABEL::GetSelectMenuText() const
{
2011-03-26 10:08:50 +00:00
wxString msg;
msg.Printf( _( "Hierarchical Label %s" ), GetChars( ShortenedShownText() ) );
2011-03-26 10:08:50 +00:00
return msg;
}