Properly ellipsize layer names in the GerbView layer manager

Before, the layers were always ellipsized if the name was >30
characters, even if the widget was wide enough to display
the full name. Now they are ellipsized when needed (e.g. if
the widget is shrunk small enough).

Fixes https://gitlab.com/kicad/code/kicad/issues/1919
This commit is contained in:
Ian McInerney 2021-03-26 15:47:02 +00:00
parent f6041fb52d
commit 3146d03aaa
9 changed files with 152 additions and 15 deletions

View File

@ -242,6 +242,7 @@ set( COMMON_WIDGET_SRCS
widgets/widget_hotkey_list.cpp widgets/widget_hotkey_list.cpp
widgets/wx_aui_art_providers.cpp widgets/wx_aui_art_providers.cpp
widgets/wx_busy_indicator.cpp widgets/wx_busy_indicator.cpp
widgets/wx_ellipsized_static_text.cpp
widgets/wx_grid.cpp widgets/wx_grid.cpp
) )

View File

@ -0,0 +1,41 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 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 <widgets/ui_common.h>
#include <widgets/wx_ellipsized_static_text.h>
WX_ELLIPSIZED_STATIC_TEXT::WX_ELLIPSIZED_STATIC_TEXT( wxWindow* aParent, wxWindowID aID,
const wxString& aLabel, const wxPoint& aPos,
const wxSize& aSize, long aStyle )
: wxStaticText( aParent, aID, aLabel, aPos, aSize, aStyle ),
m_minimumString( "M...M" )
{
}
wxSize WX_ELLIPSIZED_STATIC_TEXT::DoGetBestSize() const
{
// This is slightly awkward because DoGetBestSize is const upstream, but we need the non-const
// object to measure the text size in this function.
return KIUI::GetTextSize( m_minimumString, const_cast<WX_ELLIPSIZED_STATIC_TEXT*>( this ) );
}

View File

@ -118,7 +118,7 @@ void GERBER_FILE_IMAGE_LIST::DeleteImage( int aIdx )
} }
// Build a name for image aIdx which can be used in layers manager // Build a name for image aIdx which can be used in layers manager
const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly ) const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly, bool aFullName )
{ {
wxString name; wxString name;
@ -136,10 +136,10 @@ const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly
wxFileName fn( gerber->m_FileName ); wxFileName fn( gerber->m_FileName );
wxString filename = fn.GetFullName(); wxString filename = fn.GetFullName();
// if the filename is too long, display a shortened name: // If the filename is too long, display a shortened name if requested
const int maxlen = 30; const int maxlen = 30;
if( filename.Length() > maxlen ) if( !aFullName && filename.Length() > maxlen )
{ {
wxString shortenedfn = filename.Left(2) + "..." + filename.Right(maxlen-5); wxString shortenedfn = filename.Left(2) + "..." + filename.Right(maxlen-5);
filename = shortenedfn; filename = shortenedfn;

View File

@ -76,8 +76,8 @@ public:
unsigned ImagesMaxCount() { return m_GERBER_List.size(); } unsigned ImagesMaxCount() { return m_GERBER_List.size(); }
/** /**
* Add a GERBER_FILE_IMAGE* at index aIdx * Add a GERBER_FILE_IMAGE* at index aIdx or at the first free location if aIdx < 0
* or at the first free location if aIdx < 0 *
* @param aGbrImage = the image to add * @param aGbrImage = the image to add
* @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) * @param aIdx = the location to use ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
* @return true if the index used, or -1 if no room to add image * @return true if the index used, or -1 if no room to add image
@ -86,17 +86,25 @@ public:
/** /**
* remove all loaded data in list, and delete all images. Memory is freed * Remove all loaded data in list, and delete all images, freeing the memory.
*/ */
void DeleteAllImages(); void DeleteAllImages();
/** /**
* delete the loaded data of image aIdx. Memory is freed * Delete the loaded data of image aIdx, freeing the memory.
*
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 ) * @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
*/ */
void DeleteImage( int aIdx ); void DeleteImage( int aIdx );
/** /**
* Get the display name for the layer at aIdx.
*
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
* @param aNameOnly = false (default) to add the layer number (for layers manager)
* or true to return only the name without layer name (status bar)
* @param aFullName = false (default) to ellipsize the name, true to return the full name.
*
* @return a name for image aIdx which can be used in layers manager * @return a name for image aIdx which can be used in layers manager
* and layer selector or in the status bar * and layer selector or in the status bar
* if a file is loaded, the name is: * if a file is loaded, the name is:
@ -105,11 +113,8 @@ public:
* "<aIdx+1> <short filename> *" * "<aIdx+1> <short filename> *"
* if no file loaded, the name is: * if no file loaded, the name is:
* "Layer n" with n = aIdx+1 * "Layer n" with n = aIdx+1
* @param aIdx = the index ( 0 ... GERBER_DRAWLAYERS_COUNT-1 )
* @param aNameOnly = false (default) to add the layer number (for layers manager)
* or true to return only the name without layer name (status bar)
*/ */
const wxString GetDisplayName( int aIdx, bool aNameOnly = false ); const wxString GetDisplayName( int aIdx, bool aNameOnly = false, bool aFullName = false );
/** /**
* Sort loaded images by Z order priority, if they have the X2 FileFormat info * Sort loaded images by Z order priority, if they have the X2 FileFormat info

View File

@ -134,6 +134,10 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent )
// Create the PCB_LAYER_WIDGET *after* SetLayout(): // Create the PCB_LAYER_WIDGET *after* SetLayout():
m_LayersManager = new GERBER_LAYER_WIDGET( this, GetCanvas() ); m_LayersManager = new GERBER_LAYER_WIDGET( this, GetCanvas() );
// Update the minimum string length in the layer panel with the length of the last default layer
wxString lyrName = GetImagesList()->GetDisplayName( GetImagesList()->ImagesMaxCount(), false, true );
m_LayersManager->SetSmallestLayerString( lyrName );
// LoadSettings() *after* creating m_LayersManager, because LoadSettings() // LoadSettings() *after* creating m_LayersManager, because LoadSettings()
// initialize parameters in m_LayersManager // initialize parameters in m_LayersManager
LoadSettings( config() ); LoadSettings( config() );

View File

@ -221,7 +221,8 @@ void GERBER_LAYER_WIDGET::ReFill()
int aRow = findLayerRow( layer ); int aRow = findLayerRow( layer );
bool visible = true; bool visible = true;
COLOR4D color = myframe->GetLayerColor( GERBER_DRAW_LAYER( layer ) ); COLOR4D color = myframe->GetLayerColor( GERBER_DRAW_LAYER( layer ) );
wxString msg = GetImagesList()->GetDisplayName( layer ); wxString msg = GetImagesList()->GetDisplayName( layer, /* include layer number */ false,
/* Get the full name */ true );
if( myframe->GetCanvas() ) if( myframe->GetCanvas() )
visible = myframe->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) ); visible = myframe->GetCanvas()->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) );

View File

@ -39,6 +39,7 @@
#include <macros.h> #include <macros.h>
#include <menus_helpers.h> #include <menus_helpers.h>
#include <widgets/indicator_icon.h> #include <widgets/indicator_icon.h>
#include <widgets/wx_ellipsized_static_text.h>
#include <algorithm> #include <algorithm>
@ -345,11 +346,16 @@ void LAYER_WIDGET::insertLayerRow( int aRow, const ROW& aSpec )
// column 3 (COLUMN_COLOR_LYRNAME) // column 3 (COLUMN_COLOR_LYRNAME)
col = COLUMN_COLOR_LYRNAME; col = COLUMN_COLOR_LYRNAME;
wxStaticText* st = new wxStaticText( m_LayerScrolledWindow, encodeId( col, aSpec.id ), aSpec.rowName ); WX_ELLIPSIZED_STATIC_TEXT* st = new WX_ELLIPSIZED_STATIC_TEXT( m_LayerScrolledWindow,
encodeId( col, aSpec.id ),
aSpec.rowName, wxDefaultPosition,
wxDefaultSize,
wxST_ELLIPSIZE_MIDDLE );
shrinkFont( st, m_PointSize ); shrinkFont( st, m_PointSize );
st->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this ); st->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this );
st->SetToolTip( aSpec.tooltip ); st->SetToolTip( aSpec.tooltip );
m_LayersFlexGridSizer->wxSizer::Insert( index+col, st, 0, flags ); st->SetMinimumStringLength( m_smallestLayerString );
m_LayersFlexGridSizer->wxSizer::Insert( index+col, st, 0, flags | wxEXPAND );
// column 4 (COLUMN_ALPHA_INDICATOR) // column 4 (COLUMN_ALPHA_INDICATOR)
col = COLUMN_ALPHA_INDICATOR; col = COLUMN_ALPHA_INDICATOR;
@ -475,7 +481,8 @@ void LAYER_WIDGET::passOnFocus()
LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, wxWindowID id, LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style ) : const wxPoint& pos, const wxSize& size, long style ) :
wxPanel( aParent, id, pos, size, style ) wxPanel( aParent, id, pos, size, style ),
m_smallestLayerString( "M...M" )
{ {
int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x; int indicatorSize = ConvertDialogToPixels( wxSize( 6, 6 ) ).x;
m_IconProvider = new ROW_ICON_PROVIDER( indicatorSize ); m_IconProvider = new ROW_ICON_PROVIDER( indicatorSize );
@ -512,6 +519,9 @@ LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, wxWindowID
m_LayersFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL ); m_LayersFlexGridSizer->SetFlexibleDirection( wxHORIZONTAL );
m_LayersFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE ); m_LayersFlexGridSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_NONE );
// Make column 3 growable/stretchable
m_LayersFlexGridSizer->AddGrowableCol( 3, 1 );
m_LayerScrolledWindow->SetSizer( m_LayersFlexGridSizer ); m_LayerScrolledWindow->SetSizer( m_LayersFlexGridSizer );
m_LayerScrolledWindow->Layout(); m_LayerScrolledWindow->Layout();
m_LayersFlexGridSizer->Fit( m_LayerScrolledWindow ); m_LayersFlexGridSizer->Fit( m_LayerScrolledWindow );

View File

@ -138,6 +138,8 @@ protected:
ROW_ICON_PROVIDER* m_IconProvider; ROW_ICON_PROVIDER* m_IconProvider;
wxString m_smallestLayerString;
/** /**
* Virtual Function useAlternateBitmap * Virtual Function useAlternateBitmap
* @return true if bitmaps shown in Render layer list * @return true if bitmaps shown in Render layer list
@ -271,6 +273,14 @@ public:
virtual ~LAYER_WIDGET(); virtual ~LAYER_WIDGET();
/**
* Set the string that is used for determining the smallest string displayed in the layer's tab.
*/
void SetSmallestLayerString( const wxString& aString )
{
m_smallestLayerString = aString;
}
/** /**
* Function GetBestSize * Function GetBestSize
* returns the preferred minimum size, taking into consideration the * returns the preferred minimum size, taking into consideration the

View File

@ -0,0 +1,65 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 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 WX_ELLIPSIZED_STATIC_TEXT_H_
#define WX_ELLIPSIZED_STATIC_TEXT_H_
#include <wx/stattext.h>
/**
* A version of a wxStaticText control that will request a smaller size than the full string.
*
* This can be used with the ellipsization styles to ensure that the control will actually ellipsize
* properly inside sizer elements (since they ask for the best size but GTK reports the best size
* as being the full string length, even when ellipsization is enabled). This work around is discussed
* in upstream ticket https://trac.wxwidgets.org/ticket/18992.
*/
class WX_ELLIPSIZED_STATIC_TEXT: public wxStaticText
{
public:
WX_ELLIPSIZED_STATIC_TEXT( wxWindow* aParent, wxWindowID aID, const wxString& aLabel,
const wxPoint& aPos = wxDefaultPosition,
const wxSize& aSize = wxDefaultSize,
long aStyle = 0 );
/**
* Set the string that is used for determining the requested size of the control. The control
* will return this string length from GetBestSize(), irregardless of what string the control
* is displaying.
*
* @param aString is the smallest string to display without ellipses
*/
void SetMinimumStringLength( const wxString& aString )
{
m_minimumString = aString;
}
protected:
wxSize DoGetBestSize() const override;
private:
wxString m_minimumString; // The string that is used to set the minimum control width
};
#endif // WX_ELLIPSIZED_STATIC_TEXT_H_