diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 91cfb68056..532dc838a1 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -189,6 +189,7 @@ int EDA_TEXT::LenSize( const wxString& aLine, int aThickness ) const { basic_gal.SetFontItalic( IsItalic() ); basic_gal.SetFontBold( IsBold() ); + basic_gal.SetFontUnderlined( false ); basic_gal.SetLineWidth( (float) aThickness ); basic_gal.SetGlyphSize( VECTOR2D( GetTextSize() ) ); @@ -282,7 +283,7 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, bool aInvertY ) const { // A overbar adds an extra size to the text // Height from the base line text of chars like [ or { double curr_height = GetTextHeight() * 1.15; - double overbarPosition = font.ComputeOverbarVerticalPosition( fontSize.y, penWidth ); + double overbarPosition = font.ComputeOverbarVerticalPosition( fontSize.y ); int extra_height = KiROUND( overbarPosition - curr_height ); extra_height += thickness / 2; diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp index ff834b7610..7456541455 100644 --- a/common/gal/graphics_abstraction_layer.cpp +++ b/common/gal/graphics_abstraction_layer.cpp @@ -150,6 +150,7 @@ void GAL::SetTextAttributes( const EDA_TEXT* aText ) SetVerticalJustify( aText->GetVertJustify() ); SetFontBold( aText->IsBold() ); SetFontItalic( aText->IsItalic() ); + SetFontUnderlined( false ); SetTextMirrored( aText->IsMirrored() ); } @@ -165,6 +166,7 @@ void GAL::ResetTextAttributes() SetFontBold( false ); SetFontItalic( false ); + SetFontUnderlined( false ); SetTextMirrored( false ); } diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp index ed849533b9..e287de2438 100644 --- a/common/gal/stroke_font.cpp +++ b/common/gal/stroke_font.cpp @@ -37,6 +37,7 @@ using namespace KIGFX; const double STROKE_FONT::INTERLINE_PITCH_RATIO = 1.61; const double STROKE_FONT::OVERBAR_POSITION_FACTOR = 1.33; +const double STROKE_FONT::UNDERLINE_POSITION_FACTOR = 0.41; const double STROKE_FONT::BOLD_FACTOR = 1.3; const double STROKE_FONT::STROKE_FONT_SCALE = 1.0 / 21.0; const double STROKE_FONT::ITALIC_TILT = 1.0 / 8; @@ -444,6 +445,15 @@ void STROKE_FONT::drawSingleLineText( const UTF8& aText ) last_had_overbar = false; } + if( m_gal->IsFontUnderlined() ) + { + double vOffset = computeUnderlineVerticalPosition(); + VECTOR2D startUnderline( xOffset, - vOffset ); + VECTOR2D endUnderline( xOffset + glyphSize.x * bbox.GetEnd().x, - vOffset ); + + m_gal->DrawLine( startUnderline, endUnderline ); + } + for( const std::vector* ptList : *glyph ) { std::deque ptListScaled; @@ -475,13 +485,9 @@ void STROKE_FONT::drawSingleLineText( const UTF8& aText ) } -double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const +double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight ) const { // Static method. - // Compute the Y position of the overbar. This is the distance between the text base line - // and the overbar axis. - // Don't use the glyph thickness anymore. We don't know how much of it is "real" and how - // much it has been plumped for drop shadows, etc. return aGlyphHeight * OVERBAR_POSITION_FACTOR; } @@ -490,7 +496,15 @@ double STROKE_FONT::computeOverbarVerticalPosition() const { // Compute the Y position of the overbar. This is the distance between // the text base line and the overbar axis. - return ComputeOverbarVerticalPosition( m_gal->GetGlyphSize().y, m_gal->GetLineWidth() ); + return ComputeOverbarVerticalPosition( m_gal->GetGlyphSize().y ); +} + + +double STROKE_FONT::computeUnderlineVerticalPosition() const +{ + // Compute the Y position of the underline. This is the distance between + // the text base line and the underline axis. + return - m_gal->GetGlyphSize().y * UNDERLINE_POSITION_FACTOR; } diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 74f0c7ea29..bbc0749325 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -266,6 +266,7 @@ set( EESCHEMA_SRCS tools/sch_editor_control.cpp tools/sch_line_wire_bus_tool.cpp tools/sch_move_tool.cpp + tools/sch_navigate_tool.cpp ) diff --git a/eeschema/ee_collectors.cpp b/eeschema/ee_collectors.cpp index 66f9afc025..9e6b84f0a3 100644 --- a/eeschema/ee_collectors.cpp +++ b/eeschema/ee_collectors.cpp @@ -59,18 +59,6 @@ const KICAD_T EE_COLLECTOR::EditableItems[] = { }; -const KICAD_T EE_COLLECTOR::AnchorableItems[] = { - SCH_PIN_T, - SCH_LABEL_T, - SCH_GLOBAL_LABEL_T, - SCH_HIER_LABEL_T, - SCH_SHEET_PIN_T, - SCH_JUNCTION_T, - SCH_LINE_T, - EOT -}; - - const KICAD_T EE_COLLECTOR::ComponentsOnly[] = { SCH_COMPONENT_T, EOT diff --git a/eeschema/ee_collectors.h b/eeschema/ee_collectors.h index af8c455c65..9e29bd19d9 100644 --- a/eeschema/ee_collectors.h +++ b/eeschema/ee_collectors.h @@ -46,7 +46,6 @@ public: static const KICAD_T EditableItems[]; static const KICAD_T ComponentsOnly[]; static const KICAD_T SheetsOnly[]; - static const KICAD_T AnchorableItems[]; EE_COLLECTOR( const KICAD_T* aScanTypes = EE_COLLECTOR::AllItems ) : m_Unit( 0 ), diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp index c95f04a27f..bb0135ef20 100644 --- a/eeschema/sch_edit_frame.cpp +++ b/eeschema/sch_edit_frame.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -343,6 +344,7 @@ void SCH_EDIT_FRAME::setupTools() m_toolManager->RegisterTool( new EE_INSPECTION_TOOL ); m_toolManager->RegisterTool( new SCH_EDITOR_CONTROL ); m_toolManager->RegisterTool( new EE_POINT_EDITOR ); + m_toolManager->RegisterTool( new SCH_NAVIGATE_TOOL ); m_toolManager->InitTools(); // Run the selection tool, it is supposed to be always active diff --git a/eeschema/sch_iref.cpp b/eeschema/sch_iref.cpp index 8d0bdd6b6b..390b997ddc 100644 --- a/eeschema/sch_iref.cpp +++ b/eeschema/sch_iref.cpp @@ -26,19 +26,20 @@ #include #include #include -#include #include +#include +#include SCH_IREF::SCH_IREF( const wxPoint& pos, const wxString& text, SCH_GLOBALLABEL* aParent, KICAD_T aType ) : SCH_TEXT( pos, text, SCH_IREF_T ) - { m_Layer = LAYER_GLOBLABEL; m_parent = aParent; SetMultilineAllowed( false ); } + void SCH_IREF::PlaceAtDefaultPosition() { wxPoint offset; @@ -62,11 +63,13 @@ wxPoint SCH_IREF::GetSchematicTextOffset( RENDER_SETTINGS* aSettings ) const return m_parent->GetSchematicTextOffset( aSettings ); } + EDA_ITEM* SCH_IREF::Clone() const { return new SCH_IREF( *this ); } + void SCH_IREF::SetIrefOrientation( LABEL_SPIN_STYLE aSpinStyle ) { wxPoint pt = GetTextPos() - GetParent()->GetPosition(); @@ -107,6 +110,7 @@ void SCH_IREF::SetIrefOrientation( LABEL_SPIN_STYLE aSpinStyle ) SetPosition( GetParent()->GetPosition() + pt ); } + void SCH_IREF::CopyParentStyle() { SetTextSize( m_parent->GetTextSize() ); @@ -115,3 +119,22 @@ void SCH_IREF::CopyParentStyle() SetTextThickness( m_parent->GetTextThickness() ); SetIrefOrientation( m_parent->GetLabelSpinStyle() ); } + + +void SCH_IREF::BuildHypertextMenu( wxMenu* aMenu ) +{ + std::map sheetNames; + + for( const SCH_SHEET_PATH& sheet : Schematic()->GetSheets() ) + sheetNames[ sheet.GetPageNumber() ] = sheet.Last()->GetName(); + + for( int i : m_refTable ) + { + aMenu->Append( i, wxString::Format( _( "Go to Page %d (%s)" ), + i, + i == 1 ? _( "Root" ) : sheetNames[ i ] ) ); + } + + aMenu->AppendSeparator(); + aMenu->Append( ID_HYPERTEXT_BACK, _( "Back" ) ); +} \ No newline at end of file diff --git a/eeschema/sch_iref.h b/eeschema/sch_iref.h index d51ae0c0ad..d7719e88d0 100644 --- a/eeschema/sch_iref.h +++ b/eeschema/sch_iref.h @@ -72,6 +72,8 @@ public: void SetScreen( SCH_SCREEN* screen ) { m_screen = screen; } + void BuildHypertextMenu( wxMenu* aMenu ); + private: void SetIrefOrientation( LABEL_SPIN_STYLE aSpinStyle ); diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp index 50ab643871..be135c6979 100644 --- a/eeschema/sch_painter.cpp +++ b/eeschema/sch_painter.cpp @@ -706,6 +706,7 @@ void SCH_PAINTER::draw( LIB_TEXT *aText, int aLayer ) m_gal->SetGlyphSize( VECTOR2D( aText->GetTextSize() ) ); m_gal->SetFontBold( aText->IsBold() ); m_gal->SetFontItalic( aText->IsItalic() ); + m_gal->SetFontUnderlined( false ); strokeText( aText->GetText(), pos, orient ); } @@ -806,6 +807,7 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer ) m_gal->SetLineWidth( getLineWidth( aPin, drawingShadows ) ); m_gal->SetStrokeColor( color ); m_gal->SetFontBold( false ); + m_gal->SetFontUnderlined( false ); m_gal->SetFontItalic( false ); const int radius = externalPinDecoSize( *aPin ); @@ -1295,6 +1297,13 @@ void SCH_PAINTER::draw( SCH_TEXT *aText, int aLayer ) } COLOR4D color = getRenderColor( aText, aLayer, drawingShadows ); + m_gal->SetFontUnderlined( false ); + + if( aText->Type() == SCH_IREF_T && ( aText->GetFlags() & IS_ROLLOVER ) > 0 ) + { + color = BLUE; + m_gal->SetFontUnderlined( true ); + } if( m_schematic ) { @@ -1536,6 +1545,7 @@ void SCH_PAINTER::draw( SCH_FIELD *aField, int aLayer ) m_gal->SetGlyphSize( VECTOR2D( aField->GetTextSize() ) ); m_gal->SetFontBold( aField->IsBold() ); m_gal->SetFontItalic( aField->IsItalic() ); + m_gal->SetFontUnderlined( false ); m_gal->SetTextMirrored( aField->IsMirrored() ); m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) ); diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index 454c2ef767..1c505e041c 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -603,22 +603,6 @@ TOOL_ACTION EE_ACTIONS::generateBOM( "eeschema.EditorControl.generateBOM", _( "Generate BOM..." ), _( "Generate a bill of materials for the current schematic" ), bom_xpm ); -TOOL_ACTION EE_ACTIONS::enterSheet( "eeschema.EditorControl.enterSheet", - AS_GLOBAL, 0, "", - _( "Enter Sheet" ), _( "Display the selected sheet's contents in the Eeschema window" ), - enter_sheet_xpm ); - -TOOL_ACTION EE_ACTIONS::leaveSheet( "eeschema.EditorControl.leaveSheet", - AS_GLOBAL, - MD_ALT + WXK_BACK, LEGACY_HK_NAME( "Leave Sheet" ), - _( "Leave Sheet" ), _( "Display the parent sheet in the Eeschema window" ), - leave_sheet_xpm ); - -TOOL_ACTION EE_ACTIONS::navigateHierarchy( "eeschema.EditorControl.navigateHierarchy", - AS_GLOBAL, 0, "", - _( "Show Hierarchy Navigator" ), "", - hierarchy_nav_xpm ); - TOOL_ACTION EE_ACTIONS::explicitCrossProbe( "eeschema.EditorControl.explicitCrossProbe", AS_GLOBAL, 0, "", _( "Highlight on PCB" ), _( "Highlight corresponding items in PCBNew" ), @@ -640,6 +624,30 @@ TOOL_ACTION EE_ACTIONS::toggleForceHV( "eeschema.EditorControl.forceHVLines", lines90_xpm ); +// SCH_NAVIGATE_TOOL +// +TOOL_ACTION EE_ACTIONS::enterSheet( "eeschema.NavigateTool.enterSheet", + AS_GLOBAL, 0, "", + _( "Enter Sheet" ), _( "Display the selected sheet's contents in the Eeschema window" ), + enter_sheet_xpm ); + +TOOL_ACTION EE_ACTIONS::leaveSheet( "eeschema.NavigateTool.leaveSheet", + AS_GLOBAL, + MD_ALT + WXK_BACK, LEGACY_HK_NAME( "Leave Sheet" ), + _( "Leave Sheet" ), _( "Display the parent sheet in the Eeschema window" ), + leave_sheet_xpm ); + +TOOL_ACTION EE_ACTIONS::navigateHierarchy( "eeschema.NavigateTool.navigateHierarchy", + AS_GLOBAL, 0, "", + _( "Show Hierarchy Navigator" ), "", + hierarchy_nav_xpm ); + +TOOL_ACTION EE_ACTIONS::hypertextCommand( "eeschema.NavigateTool.hypertextCommand", + AS_GLOBAL, 0, "", + _( "Navigate to page" ), "", + nullptr ); + + // SCH_LINE_WIRE_BUS_TOOL // TOOL_ACTION EE_ACTIONS::addNeededJunctions( diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index 94d94e9463..17e5a293aa 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -183,6 +183,7 @@ public: static TOOL_ACTION enterSheet; static TOOL_ACTION leaveSheet; static TOOL_ACTION navigateHierarchy; + static TOOL_ACTION hypertextCommand; // Global edit tools static TOOL_ACTION cleanupSheetPins; diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index 2805304f45..5f12605000 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -298,10 +299,13 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) { m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW ); + KIID lastRolloverItem = niluuid; + // Main loop: keep receiving events while( TOOL_EVENT* evt = Wait() ) { bool displayPencil = false; + KIID rolloverItem = niluuid; m_additive = m_subtractive = m_exclusive_or = false; if( evt->Modifier( MD_SHIFT ) && evt->Modifier( MD_CTRL ) ) @@ -315,51 +319,61 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) // items without removing less likely selection candidates m_skip_heuristics = !!evt->Modifier( MD_ALT ); + EE_GRID_HELPER grid( m_toolMgr ); + + VECTOR2I rawPos = evt->IsPrime() ? evt->Position() : getViewControls()->GetMousePosition(); + VECTOR2I cursorPos = grid.BestSnapAnchor( rawPos, nullptr ); + // Single click? Select single object if( evt->IsClick( BUT_LEFT ) ) { - if( auto schframe = dynamic_cast( m_frame ) ) + if( SCH_EDIT_FRAME* schframe = dynamic_cast( m_frame ) ) schframe->FocusOnItem( nullptr ); EE_COLLECTOR collector; + bool continueSelect = true; // Collect items at the clicked location (doesn't select them yet) - if( !CollectHits( evt->Position(), collector, EE_COLLECTOR::AllItems, false ) ) + if( collectHits( collector, evt->Position() ) ) { - return false; - } + narrowSelection( collector, evt->Position(), false ); - // Check if we want to auto start wires if we clicked on anchors of items - bool continueSelect = true; - if( collector.GetCount() == 1 && m_frame->eeconfig()->m_Drawing.auto_start_wires ) - { - EE_GRID_HELPER grid( m_toolMgr ); - - wxPoint cursorPos = wxPoint( grid.BestSnapAnchor( - evt->IsPrime() ? evt->Position() : getViewControls()->GetMousePosition(), - nullptr ) ); - if( collector[0]->IsPointClickableAnchor( cursorPos ) ) + if( collector.GetCount() == 1 ) { - OPT_TOOL_EVENT newEvt = EE_ACTIONS::drawWire.MakeEvent(); + // Check if we want to auto start wires + if( m_frame->eeconfig()->m_Drawing.auto_start_wires + && collector[0]->IsPointClickableAnchor( (wxPoint) cursorPos ) ) + { + OPT_TOOL_EVENT newEvt = EE_ACTIONS::drawWire.MakeEvent(); + auto* params = newEvt->Parameter(); + auto* newParams = new DRAW_SEGMENT_EVENT_PARAMS(); - DRAW_SEGMENT_EVENT_PARAMS* params = - newEvt->Parameter(); - DRAW_SEGMENT_EVENT_PARAMS* newParams = new DRAW_SEGMENT_EVENT_PARAMS(); - *newParams = *params; - newParams->quitOnDraw = true; - newEvt->SetParameter( newParams ); + *newParams= *params; + newParams->quitOnDraw = true; + newEvt->SetParameter( newParams ); - newEvt->SetMousePosition( newEvt->Position() ); - m_toolMgr->ProcessEvent( *newEvt ); - continueSelect = false; + newEvt->SetMousePosition( newEvt->Position() ); + m_toolMgr->ProcessEvent( *newEvt ); + continueSelect = false; + } + else if( collector[0]->Type() == SCH_IREF_T ) + { + wxMenu menu; + + static_cast( collector[0] )->BuildHypertextMenu( &menu ); + + intptr_t sel = m_frame->GetPopupMenuSelectionFromUser( menu ); + m_toolMgr->RunAction( EE_ACTIONS::hypertextCommand, true, (void*) sel ); + } } } if( continueSelect ) { - // If we didn't click on an anchor, we perform a normal select, pass in the items we previously collected - SelectPoint( - collector, nullptr, nullptr, m_additive, m_subtractive, m_exclusive_or ); + // If we didn't click on an anchor, we perform a normal select, pass in the + // items we previously collected + SelectPoint( collector, nullptr, nullptr, m_additive, m_subtractive, + m_exclusive_or ); } } @@ -369,7 +383,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) bool selectionCancelled = false; if( m_selection.Empty() || - !m_selection.GetBoundingBox().Contains( wxPoint( evt->Position() ) ) ) + !m_selection.GetBoundingBox().Contains( (wxPoint) evt->Position() ) ) { ClearSelection(); SelectPoint( evt->Position(), EE_COLLECTOR::AllItems, nullptr, @@ -483,24 +497,24 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) else if( evt->IsMotion() ) { - if( m_frame->eeconfig()->m_Drawing.auto_start_wires ) + EE_COLLECTOR collector; + + // We are checking if we should display a pencil when hovering over anchors + // for "auto starting" wires when clicked + if( collectHits( collector, evt->Position() ) ) { - EE_COLLECTOR collector; + narrowSelection( collector, evt->Position(), false ); - // We are checking if we should display a pencil when hovering over anchors for "auto starting" wires when clicked - if( CollectHits( - evt->Position(), collector, EE_COLLECTOR::AnchorableItems, false ) ) + if( collector.GetCount() == 1 ) { - if( collector.GetCount() == 1 ) + if( m_frame->eeconfig()->m_Drawing.auto_start_wires + && collector[0]->IsPointClickableAnchor( (wxPoint) cursorPos ) ) { - SCH_ITEM* item = collector[0]; - - if( item - && item->IsPointClickableAnchor( static_cast( - getViewControls()->GetCursorPosition( true ) ) ) ) - { - displayPencil = true; - } + displayPencil = true; + } + else if( collector[0]->Type() == SCH_IREF_T ) + { + rolloverItem = collector[0]->m_Uuid; } } } @@ -509,16 +523,35 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) else evt->SetPassEvent(); + if( rolloverItem != lastRolloverItem ) + { + EDA_ITEM* item = m_frame->GetItem( lastRolloverItem ); + + if( item ) + { + item->ClearFlags( IS_ROLLOVER ); + lastRolloverItem = niluuid; + m_frame->GetCanvas()->GetView()->Update( item ); + } + + item = m_frame->GetItem( rolloverItem ); + + if( item && m_frame->ToolStackIsEmpty() ) + { + item->SetFlags( IS_ROLLOVER ); + lastRolloverItem = rolloverItem; + m_frame->GetCanvas()->GetView()->Update( item ); + } + } + if( m_frame->ToolStackIsEmpty() ) { if( displayPencil ) - { m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_PENCIL ); - } + else if( rolloverItem != niluuid ) + m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_HAND ); else - { m_frame->GetCanvas()->SetCurrentCursor( wxCURSOR_ARROW ); - } } } @@ -532,8 +565,8 @@ EE_SELECTION& EE_SELECTION_TOOL::GetSelection() } -bool EE_SELECTION_TOOL::CollectHits( const VECTOR2I& aWhere, EE_COLLECTOR& aCollector, - const KICAD_T* aFilterList, bool aCheckLocked ) +bool EE_SELECTION_TOOL::collectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere, + const KICAD_T* aFilterList ) { aCollector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) ); @@ -544,39 +577,45 @@ bool EE_SELECTION_TOOL::CollectHits( const VECTOR2I& aWhere, EE_COLLECTOR& aColl if( !part ) return false; - aCollector.Collect( - part->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit, m_convert ); + aCollector.Collect( part->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit, + m_convert ); } else { - aCollector.Collect( - m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit, m_convert ); + aCollector.Collect( m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit, + m_convert ); } - // Post-process collected items - for( int i = aCollector.GetCount() - 1; i >= 0; --i ) + return aCollector.GetCount() > 0; +} + + +void EE_SELECTION_TOOL::narrowSelection( EE_COLLECTOR& collector, const VECTOR2I& aWhere, + bool aCheckLocked ) +{ + for( int i = collector.GetCount() - 1; i >= 0; --i ) { - if( !Selectable( aCollector[i] ) ) + if( !Selectable( collector[i] ) ) { - aCollector.Remove( i ); + collector.Remove( i ); continue; } - if( aCheckLocked && aCollector[i]->IsLocked() ) + if( aCheckLocked && collector[i]->IsLocked() ) { - aCollector.Remove( i ); + collector.Remove( i ); continue; } // SelectPoint, unlike other selection routines, can select line ends - if( aCollector[i]->Type() == SCH_LINE_T ) + if( collector[i]->Type() == SCH_LINE_T ) { - SCH_LINE* line = (SCH_LINE*) aCollector[i]; + SCH_LINE* line = (SCH_LINE*) collector[i]; line->ClearFlags( STARTPOINT | ENDPOINT ); - if( HitTestPoints( line->GetStartPoint(), (wxPoint) aWhere, aCollector.m_Threshold ) ) + if( HitTestPoints( line->GetStartPoint(), (wxPoint) aWhere, collector.m_Threshold ) ) line->SetFlags( STARTPOINT ); - else if( HitTestPoints( line->GetEndPoint(), (wxPoint) aWhere, aCollector.m_Threshold ) ) + else if( HitTestPoints( line->GetEndPoint(), (wxPoint) aWhere, collector.m_Threshold ) ) line->SetFlags( ENDPOINT ); else line->SetFlags( STARTPOINT | ENDPOINT ); @@ -584,20 +623,27 @@ bool EE_SELECTION_TOOL::CollectHits( const VECTOR2I& aWhere, EE_COLLECTOR& aColl } // Apply some ugly heuristics to avoid disambiguation menus whenever possible - if( aCollector.GetCount() > 1 && !m_skip_heuristics ) + if( collector.GetCount() > 1 && !m_skip_heuristics ) { - GuessSelectionCandidates( aCollector, aWhere ); + GuessSelectionCandidates( collector, aWhere ); } - - return true; } bool EE_SELECTION_TOOL::SelectPoint( EE_COLLECTOR& aCollector, EDA_ITEM** aItem, - bool* aSelectionCancelledFlag, bool aAdd, bool aSubtract, bool aExclusiveOr ) + bool* aSelectionCancelledFlag, bool aAdd, bool aSubtract, + bool aExclusiveOr ) { m_selection.ClearReferencePoint(); + // We have to allow SCH_IREFs in Selectable() for hypertext rollovers and linking to work, + // but at the end of the day we don't actually want them to be selectable. + for( int i = aCollector.GetCount() - 1; i >= 0; --i ) + { + if( aCollector[i]->Type() == SCH_IREF_T ) + aCollector.Remove( i ); + } + // If still more than one item we're going to have to ask the user. if( aCollector.GetCount() > 1 ) { @@ -662,10 +708,10 @@ bool EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T* aFil { EE_COLLECTOR collector; - if( !CollectHits( aWhere, collector, aFilterList, aCheckLocked ) ) - { + if( !collectHits( collector, aWhere, aFilterList ) ) return false; - } + + narrowSelection( collector, aWhere, aCheckLocked ); return SelectPoint( collector, aItem, aSelectionCancelledFlag, aAdd, aSubtract, aExclusiveOr ); } @@ -985,7 +1031,8 @@ bool EE_SELECTION_TOOL::selectMultiple() { EDA_ITEM* item = dynamic_cast( pair.first ); - if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) ) + if( item && Selectable( item ) && item->Type() != SCH_IREF_T + && item->HitTest( selectionRect, windowSelection ) ) { if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) ) { @@ -1462,9 +1509,6 @@ bool EE_SELECTION_TOOL::Selectable( const EDA_ITEM* aItem, bool checkVisibilityO case SCH_MARKER_T: // Always selectable return true; - case SCH_IREF_T: // Never selectable - return false; - default: // Suppress warnings break; } diff --git a/eeschema/tools/ee_selection_tool.h b/eeschema/tools/ee_selection_tool.h index bd011061c9..4be93789d4 100644 --- a/eeschema/tools/ee_selection_tool.h +++ b/eeschema/tools/ee_selection_tool.h @@ -122,21 +122,6 @@ public: bool* aSelectionCancelledFlag = nullptr, bool aAdd = false, bool aSubtract = false, bool aExclusiveOr = false ); - /** - * Function CollectHits() - * Selects one or more items at the location given by parameter aWhere. - * - * This method does not attempt to disambiguate multiple items and is simply "collecting" - * - * @param aWhere is the place where the item should be selected. - * @param aCollector is the collector object that will store found item(s) - * @param aFilterList is a list of items that are acceptable for collection - * @param aCheckLocked indicates if locked items should be excluded. - */ - bool CollectHits( const VECTOR2I& aWhere, EE_COLLECTOR& aCollector, - const KICAD_T* aFilterList = EE_COLLECTOR::AllItems, - bool aCheckLocked = false ); - int AddItemToSel( const TOOL_EVENT& aEvent ); void AddItemToSel( EDA_ITEM* aItem, bool aQuietMode = false ); int AddItemsToSel( const TOOL_EVENT& aEvent ); @@ -198,6 +183,29 @@ public: void RebuildSelection(); private: + /** + * Function CollectHits() + * Selects one or more items at the location given by parameter aWhere. + * + * This method does not attempt to disambiguate multiple items and is simply "collecting" + * + * @param aCollector is the collector object that will store found item(s) + * @param aWhere is the place where the item should be selected. + * @param aFilterList is a list of items that are acceptable for collection + * @param aCheckLocked indicates if locked items should be excluded. + */ + bool collectHits( EE_COLLECTOR& aCollector, const VECTOR2I& aWhere, + const KICAD_T* aFilterList = EE_COLLECTOR::AllItems ); + + /** + * Applies rules to narrow the collection down to selectable objects, and then heuristics + * to try and narrow it to a single object. + * @param collector + * @param aWhere + * @param aCheckLocked + */ + void narrowSelection( EE_COLLECTOR& collector, const VECTOR2I& aWhere, bool aCheckLocked ); + /** * Function selectMultiple() * Handles drawing a selection box that allows one to select many items at diff --git a/eeschema/tools/sch_navigate_tool.cpp b/eeschema/tools/sch_navigate_tool.cpp new file mode 100644 index 0000000000..a12c1f5a1e --- /dev/null +++ b/eeschema/tools/sch_navigate_tool.cpp @@ -0,0 +1,120 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 CERN + * Copyright (C) 1992-2020 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 + */ + +#include +#include +#include + + +int SCH_NAVIGATE_TOOL::NavigateHierarchy( const TOOL_EVENT& aEvent ) +{ + m_frame->UpdateHierarchyNavigator( true ); + return 0; +} + + +int SCH_NAVIGATE_TOOL::HypertextCommand( const TOOL_EVENT& aEvent ) +{ + intptr_t target = aEvent.Parameter(); + + auto goToPage = + [&]( intptr_t aPage ) + { + for( const SCH_SHEET_PATH& sheet : m_frame->Schematic().GetSheets() ) + { + if( sheet.GetPageNumber() == aPage ) + { + m_frame->GetToolManager()->RunAction( ACTIONS::cancelInteractive, true ); + m_frame->GetToolManager()->RunAction( EE_ACTIONS::clearSelection, true ); + + m_frame->SetCurrentSheet( sheet ); + m_frame->DisplayCurrentSheet(); + + return; + } + } + }; + + if( target == ID_HYPERTEXT_BACK ) + { + if( m_hypertextStack.size() > 0 ) + { + goToPage( m_hypertextStack.top() ); + m_hypertextStack.pop(); + } + } + else + { + m_hypertextStack.push( m_frame->GetCurrentSheet().GetPageNumber() ); + goToPage( target ); + } + + return 0; +} + + +int SCH_NAVIGATE_TOOL::EnterSheet( const TOOL_EVENT& aEvent ) +{ + EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool(); + const EE_SELECTION& selection = selTool->RequestSelection( EE_COLLECTOR::SheetsOnly ); + + if( selection.GetSize() == 1 ) + { + SCH_SHEET* sheet = (SCH_SHEET*) selection.Front(); + + m_toolMgr->RunAction( ACTIONS::cancelInteractive, true ); + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + + m_frame->GetCurrentSheet().push_back( sheet ); + m_frame->DisplayCurrentSheet(); + m_frame->UpdateHierarchyNavigator(); + } + + return 0; +} + + +int SCH_NAVIGATE_TOOL::LeaveSheet( const TOOL_EVENT& aEvent ) +{ + if( m_frame->GetCurrentSheet().Last() != &m_frame->Schematic().Root() ) + { + m_toolMgr->RunAction( ACTIONS::cancelInteractive, true ); + m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true ); + + m_frame->GetCurrentSheet().pop_back(); + m_frame->DisplayCurrentSheet(); + m_frame->UpdateHierarchyNavigator(); + } + + return 0; +} + + +void SCH_NAVIGATE_TOOL::setTransitions() +{ + Go( &SCH_NAVIGATE_TOOL::EnterSheet, EE_ACTIONS::enterSheet.MakeEvent() ); + Go( &SCH_NAVIGATE_TOOL::LeaveSheet, EE_ACTIONS::leaveSheet.MakeEvent() ); + Go( &SCH_NAVIGATE_TOOL::NavigateHierarchy, EE_ACTIONS::navigateHierarchy.MakeEvent() ); + Go( &SCH_NAVIGATE_TOOL::HypertextCommand, EE_ACTIONS::hypertextCommand.MakeEvent() ); +} diff --git a/eeschema/tools/sch_navigate_tool.h b/eeschema/tools/sch_navigate_tool.h new file mode 100644 index 0000000000..bf4a56b4cf --- /dev/null +++ b/eeschema/tools/sch_navigate_tool.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2019 CERN + * Copyright (C) 2019 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 + */ + + +#ifndef SCH_NAVIGATE_TOOL_H +#define SCH_NAVIGATE_TOOL_H + +#include +#include +#include + +class SCH_EDIT_FRAME; + +#define ID_HYPERTEXT_BACK 999 + +/** + * SCH_NAVIGATE_TOOL + * + * Handles actions specific to the schematic editor in eeschema. + */ +class SCH_NAVIGATE_TOOL : public wxEvtHandler, public EE_TOOL_BASE +{ +public: + SCH_NAVIGATE_TOOL() : + EE_TOOL_BASE( "eeschema.NavigateTool" ) + { } + + ~SCH_NAVIGATE_TOOL() { } + + int EnterSheet( const TOOL_EVENT& aEvent ); + int LeaveSheet( const TOOL_EVENT& aEvent ); + int NavigateHierarchy( const TOOL_EVENT& aEvent ); + int HypertextCommand( const TOOL_EVENT& aEvent ); + +private: + ///> Sets up handlers for various events. + void setTransitions() override; + +private: + std::stack m_hypertextStack; +}; + + +#endif // SCH_NAVIGATE_TOOL_H diff --git a/gerbview/gerbview_painter.cpp b/gerbview/gerbview_painter.cpp index 27c4c2a18f..f572e9138c 100644 --- a/gerbview/gerbview_painter.cpp +++ b/gerbview/gerbview_painter.cpp @@ -227,6 +227,7 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer ) m_gal->SetLineWidth( textSize/10 ); m_gal->SetFontBold( false ); m_gal->SetFontItalic( false ); + m_gal->SetFontUnderlined( false ); m_gal->SetTextMirrored( false ); m_gal->SetGlyphSize( VECTOR2D( textSize, textSize) ); m_gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_CENTER ); diff --git a/include/base_struct.h b/include/base_struct.h index e573c9964c..1b6118e368 100644 --- a/include/base_struct.h +++ b/include/base_struct.h @@ -135,7 +135,7 @@ typedef const INSPECTOR_FUNC& INSPECTOR; /// std::function passed to nested u #define BEGIN_ONPAD (1 << 22) ///< Pcbnew: flag set for track segment starting on a pad #define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad #define OBSOLETE_3 (1 << 24) ///< Not presently used -#define OBSOLETE_4 (1 << 25) ///< Not presently used +#define IS_ROLLOVER (1 << 25) ///< Rollover active. Used for hyperlink highlighting. #define BRIGHTENED (1 << 26) ///< item is drawn with a bright contour #define DP_COUPLED (1 << 27) ///< item is coupled with another item making a differential pair diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h index 089761626b..9c2c0ebea6 100644 --- a/include/gal/graphics_abstraction_layer.h +++ b/include/gal/graphics_abstraction_layer.h @@ -378,16 +378,6 @@ public: */ VECTOR2D GetTextLineSize( const UTF8& aText ) const; - /** - * Compute the vertical position of an overbar, sometimes used in texts. - * This is the distance between the text base line and the overbar. - * @return the relative position of the overbar axis. - */ - double GetOverbarVerticalPosition() const - { - return strokeFont.computeOverbarVerticalPosition(); - } - /** * @brief Loads attributes of the given text (bold/italic/underline/mirrored and so on). * @@ -408,72 +398,35 @@ public: * * @param aGlyphSize is the new font glyph size. */ - inline void SetGlyphSize( const VECTOR2D aGlyphSize ) - { - textProperties.m_glyphSize = aGlyphSize; - } - - /** - * @return the current font glyph size. - */ - const VECTOR2D& GetGlyphSize() const - { - return textProperties.m_glyphSize; - } + inline void SetGlyphSize( const VECTOR2D aSize ) { textProperties.m_glyphSize = aSize; } + const VECTOR2D& GetGlyphSize() const { return textProperties.m_glyphSize; } /** * @brief Set bold property of current font. * * @param aBold tells if the font should be bold or not. */ - inline void SetFontBold( const bool aBold ) - { - textProperties.m_bold = aBold; - } - - /** - * @brief Returns true if current font has 'bold' attribute enabled. - */ - inline bool IsFontBold() const - { - return textProperties.m_bold; - } + inline void SetFontBold( const bool aBold ) { textProperties.m_bold = aBold; } + inline bool IsFontBold() const { return textProperties.m_bold; } /** * @brief Set italic property of current font. * * @param aItalic tells if the font should be italic or not. */ - inline void SetFontItalic( const bool aItalic ) - { - textProperties.m_italic = aItalic; - } + inline void SetFontItalic( bool aItalic ) { textProperties.m_italic = aItalic; } + inline bool IsFontItalic() const { return textProperties.m_italic; } - /** - * @brief Returns true if current font has 'italic' attribute enabled. - */ - inline bool IsFontItalic() const - { - return textProperties.m_italic; - } + inline void SetFontUnderlined( bool aUnderlined ) { textProperties.m_underlined = aUnderlined; } + inline bool IsFontUnderlined() const { return textProperties.m_underlined; } /** * @brief Set a mirrored property of text. * * @param aMirrored tells if the text should be mirrored or not. */ - inline void SetTextMirrored( const bool aMirrored ) - { - textProperties.m_mirrored = aMirrored; - } - - /** - * @brief Returns true if text should displayed mirrored. - */ - inline bool IsTextMirrored() const - { - return textProperties.m_mirrored; - } + inline void SetTextMirrored( const bool aMirrored ) { textProperties.m_mirrored = aMirrored; } + inline bool IsTextMirrored() const { return textProperties.m_mirrored; } /** * @brief Set the horizontal justify for text drawing. @@ -1189,6 +1142,7 @@ private: EDA_TEXT_VJUSTIFY_T m_verticalJustify; ///< Vertical justification bool m_bold; bool m_italic; + bool m_underlined; bool m_mirrored; } textProperties; }; diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h index aff2397e8b..51bebf875e 100644 --- a/include/gal/stroke_font.h +++ b/include/gal/stroke_font.h @@ -98,10 +98,9 @@ public: * Compute the vertical position of an overbar, sometimes used in texts. * This is the distance between the text base line and the overbar. * @param aGlyphHeight is the height (vertical size) of the text. - * @param aGlyphThickness is the thickness of the lines used to draw the text. * @return the relative position of the overbar axis. */ - double ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const; + double ComputeOverbarVerticalPosition( double aGlyphHeight ) const; /** * @brief Compute the distance (interline) between 2 lines of text (for multiline texts). @@ -133,6 +132,7 @@ private: * @return the relative position of the overbar axis. */ double computeOverbarVerticalPosition() const; + double computeUnderlineVerticalPosition() const; /** * @brief Compute the bounding box of a given glyph. @@ -168,6 +168,7 @@ private: ///> Factor that determines relative vertical position of the overbar. static const double OVERBAR_POSITION_FACTOR; + static const double UNDERLINE_POSITION_FACTOR; ///> Factor that determines relative line width for bold text. static const double BOLD_FACTOR; diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index d0e73354f4..233a50f1fc 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -504,6 +504,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) m_gal->SetLineWidth( width / 10.0 ); m_gal->SetFontBold( false ); m_gal->SetFontItalic( false ); + m_gal->SetFontUnderlined( false ); m_gal->SetTextMirrored( false ); m_gal->SetGlyphSize( VECTOR2D( textSize * 0.7, textSize * 0.7 ) ); m_gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_CENTER ); @@ -773,6 +774,7 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) m_gal->SetVerticalJustify( GR_TEXT_VJUSTIFY_CENTER ); m_gal->SetFontBold( false ); m_gal->SetFontItalic( false ); + m_gal->SetFontUnderlined( false ); m_gal->SetTextMirrored( false ); m_gal->SetStrokeColor( m_pcbSettings.GetColor( NULL, aLayer ) ); m_gal->SetIsStroke( true );