Add an infobar widget to display information above the canvas

This widget allows for non-intrusive display of text
above the editing canvas. Currently, this is used
for displaying the read only status of the files.
This commit is contained in:
Ian McInerney 2020-05-19 00:44:58 +01:00
parent 5a9e69b146
commit a2f027e063
12 changed files with 348 additions and 16 deletions

View File

@ -211,6 +211,7 @@ set( COMMON_WIDGET_SRCS
widgets/wx_busy_indicator.cpp widgets/wx_busy_indicator.cpp
widgets/wx_grid.cpp widgets/wx_grid.cpp
widgets/wx_angle_text.cpp widgets/wx_angle_text.cpp
widgets/wx_infobar.cpp
) )
set( COMMON_PAGE_LAYOUT_SRCS set( COMMON_PAGE_LAYOUT_SRCS

View File

@ -80,6 +80,7 @@ EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
m_canvas = NULL; m_canvas = NULL;
m_toolDispatcher = NULL; m_toolDispatcher = NULL;
m_messagePanel = NULL; m_messagePanel = NULL;
m_infoBar = nullptr;
m_currentScreen = NULL; m_currentScreen = NULL;
m_showBorderAndTitleBlock = false; // true to display reference sheet. m_showBorderAndTitleBlock = false; // true to display reference sheet.
m_LastGridSizeId = 0; m_LastGridSizeId = 0;

View File

@ -0,0 +1,136 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney@ieee.org>
* Copyright (C) 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <id.h>
#include <widgets/wx_infobar.h>
#include <wx/aui/framemanager.h>
#include <wx/infobar.h>
BEGIN_EVENT_TABLE( WX_INFOBAR, wxInfoBarGeneric )
EVT_BUTTON( ID_CLOSE_INFOBAR, WX_INFOBAR::OnCloseButton )
END_EVENT_TABLE()
WX_INFOBAR::WX_INFOBAR( wxWindow* aParent, wxAuiManager *aMgr, wxWindowID aWinid )
: wxInfoBarGeneric( aParent, aWinid ),
m_auiManager( aMgr )
{
// On GTK, the infobar seems to start too small, so increase its height
#ifdef __WXGTK__
int sx, sy;
GetSize( &sx, &sy );
SetSize( sx, 1.5 * sy );
#endif
}
void WX_INFOBAR::ShowMessage( const wxString& aMessage, int aFlags )
{
wxInfoBarGeneric::ShowMessage( aMessage, aFlags );
UpdateAuiLayout( true );
}
void WX_INFOBAR::Dismiss()
{
wxInfoBarGeneric::Dismiss();
UpdateAuiLayout( false );
}
void WX_INFOBAR::UpdateAuiLayout( bool aShow )
{
// Update the AUI pane that contains the infobar
if( m_auiManager )
{
if( aShow )
m_auiManager->GetPane( this ).Show();
else
m_auiManager->GetPane( this ).Hide();
m_auiManager->Update();
}
}
void WX_INFOBAR::AddButton( wxWindowID aId, const wxString& aLabel )
{
wxButton* button = new wxButton( this, aId, aLabel );
AddButton( button );
}
void WX_INFOBAR::AddButton( wxButton* aButton )
{
wxSizer* sizer = GetSizer();
#ifdef __WXMAC__
// Based on the code in the original class:
// smaller buttons look better in the (narrow) info bar under OS X
aButton->SetWindowVariant( wxWINDOW_VARIANT_SMALL );
#endif // __WXMAC__
sizer->Add( aButton, wxSizerFlags().Centre() );
if( IsShown() )
sizer->Layout();
}
void WX_INFOBAR::AddCloseButton( const wxString& aTooltip )
{
wxBitmapButton* button = wxBitmapButton::NewCloseButton( this, ID_CLOSE_INFOBAR );
button->SetToolTip( aTooltip );
AddButton( button );
}
void WX_INFOBAR::RemoveAllButtons()
{
wxSizer* sizer = GetSizer();
if( sizer->GetItemCount() == 0 )
return;
// The last item is already the spacer
if( sizer->GetItem( sizer->GetItemCount() - 1 )->IsSpacer() )
return;
for( int i = sizer->GetItemCount() - 1; i >= 0; i-- )
{
wxSizerItem* sItem = sizer->GetItem( i );
// The spacer is the end of the custom buttons
if( sItem->IsSpacer() )
break;
delete sItem->GetWindow();
}
}
void WX_INFOBAR::OnCloseButton( wxCommandEvent& aEvt )
{
Dismiss();
}

View File

@ -55,6 +55,7 @@
#include <tool/actions.h> #include <tool/actions.h>
#include <tools/sch_editor_control.h> #include <tools/sch_editor_control.h>
#include <netlist.h> #include <netlist.h>
#include <widgets/wx_infobar.h>
bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName, bool SCH_EDIT_FRAME::SaveEEFile( SCH_SHEET* aSheet, bool aSaveUnderNewName,
@ -493,6 +494,15 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
UpdateTitle(); UpdateTitle();
wxFileName fn = Prj().AbsolutePath( GetScreen()->GetFileName() );
if( fn.FileExists() && !fn.IsFileWritable() )
{
m_infoBar->RemoveAllButtons();
m_infoBar->AddCloseButton();
m_infoBar->ShowMessage( "Schematic file is read only.", wxICON_WARNING );
}
// If requested, generate a netlist and exit immediately. // If requested, generate a netlist and exit immediately.
// NOTE: This is intended as a developer-only feature for now, and can be removed in lieu of // NOTE: This is intended as a developer-only feature for now, and can be removed in lieu of
// Python scripting once that is possible. // Python scripting once that is possible.

View File

@ -69,6 +69,7 @@
#include <tools/sch_editor_control.h> #include <tools/sch_editor_control.h>
#include <tools/sch_line_wire_bus_tool.h> #include <tools/sch_line_wire_bus_tool.h>
#include <tools/sch_move_tool.h> #include <tools/sch_move_tool.h>
#include <widgets/wx_infobar.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <wx/cmdline.h> #include <wx/cmdline.h>
@ -239,6 +240,8 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
ReCreateVToolbar(); ReCreateVToolbar();
ReCreateOptToolbar(); ReCreateOptToolbar();
m_infoBar = new WX_INFOBAR( this, &m_auimgr );
// Initialize common print setup dialog settings. // Initialize common print setup dialog settings.
m_pageSetupData.GetPrintData().SetPrintMode( wxPRINT_MODE_PRINTER ); m_pageSetupData.GetPrintData().SetPrintMode( wxPRINT_MODE_PRINTER );
m_pageSetupData.GetPrintData().SetQuality( wxPRINT_QUALITY_MEDIUM ); m_pageSetupData.GetPrintData().SetQuality( wxPRINT_QUALITY_MEDIUM );
@ -247,11 +250,21 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ):
m_auimgr.SetManagedWindow( this ); m_auimgr.SetManagedWindow( this );
m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_mainToolBar,
m_auimgr.AddPane( m_optionsToolBar, EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) ); EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_optionsToolBar,
m_auimgr.AddPane( GetCanvas(), EDA_PANE().Canvas().Name( "DrawFrame" ).Center() ); EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) );
m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); m_auimgr.AddPane( m_drawToolBar,
EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(2) );
m_auimgr.AddPane( m_infoBar,
EDA_PANE().InfoBar().Name( "InfoBar" ).Top().Layer(1) );
m_auimgr.AddPane( GetCanvas(),
EDA_PANE().Canvas().Name( "DrawFrame" ).Center() );
m_auimgr.AddPane( m_messagePanel,
EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) );
// We don't want the infobar displayed right away
m_auimgr.GetPane( "InfoBar" ).Hide();
m_auimgr.Update(); m_auimgr.Update();

View File

@ -616,6 +616,17 @@ public:
Resizable( true ); // expand to fit available space Resizable( true ); // expand to fit available space
return *this; return *this;
} }
/**
* Turn *this into a infobar for KiCad.
*/
EDA_PANE& InfoBar()
{
CaptionVisible( false );
Movable( false );
Resizable( true );
return *this;
}
}; };
#endif // EDA_BASE_FRAME_H_ #endif // EDA_BASE_FRAME_H_

View File

@ -40,6 +40,7 @@ class ACTION_TOOLBAR;
class COLOR_SETTINGS; class COLOR_SETTINGS;
class TOOL_MENU; class TOOL_MENU;
class APP_SETTINGS_BASE; class APP_SETTINGS_BASE;
class WX_INFOBAR;
namespace KIGFX namespace KIGFX
{ {
@ -113,6 +114,8 @@ protected:
EDA_MSG_PANEL* m_messagePanel; EDA_MSG_PANEL* m_messagePanel;
int m_MsgFrameHeight; int m_MsgFrameHeight;
WX_INFOBAR* m_infoBar;
COLOR_SETTINGS* m_colorSettings; COLOR_SETTINGS* m_colorSettings;
/// The current canvas type /// The current canvas type

View File

@ -113,6 +113,9 @@ enum main_id
ID_OPT_TOOLBAR, ID_OPT_TOOLBAR,
ID_AUX_TOOLBAR, ID_AUX_TOOLBAR,
// ID for the close button on the frame's infobar
ID_CLOSE_INFOBAR,
ID_EDIT_HOTKEY, ID_EDIT_HOTKEY,
ID_NO_TOOL_SELECTED, ID_NO_TOOL_SELECTED,

View File

@ -0,0 +1,107 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 Ian McInerney <ian.s.mcinerney@ieee.org>
* Copyright (C) 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include <wx/infobar.h>
#include <wx/wx.h>
class wxAuiManager;
/**
* A modified version of the wxInfoBar class that allows us to:
* * Show the close button along with the other buttons
* * Remove all user-provided buttons at once
*
* This inherits from the generic infobar because the native infobar
* on GTK doesn't include the icon on the left and it looks worse.
*/
class WX_INFOBAR : public wxInfoBarGeneric
{
public:
/**
* Construct an infobar that can exist inside an AUI managed frame.
*
* @param aParent is the parent
* @param aMgr is the AUI manager that this infobar is added to
* @param aWinId is the ID for this infobar object
*/
WX_INFOBAR( wxWindow* aParent, wxAuiManager* aMgr = nullptr, wxWindowID aWinid = wxID_ANY );
/**
* Add the default close button to the infobar on the right side.
*
* @param aTooltip is the tooltip to give the close button
*/
void AddCloseButton( const wxString& aTooltip = _( "Hide this message." ) );
/**
* Add an already created button to the infobar.
* New buttons are added in the right-most position.
*
* @param aButton is the button to add
*/
void AddButton( wxButton* aButton );
/**
* Add a button with the provided ID and text.
* The new button is created on the right-most positon.
*
* @param aId is the ID to assign to the button
* @param aLabel is the text for the button
*/
void AddButton( wxWindowID aId, const wxString& aLabel = wxEmptyString ) override;
/**
* Remove all the buttons that have been added by the user.
*/
void RemoveAllButtons();
/**
* Show the info bar with the provided message and icon.
*
* @param aMessage is the message to display
* @param aFlags is the flag containing the icon to display on the left side of the infobar
*/
void ShowMessage( const wxString& aMessage, int aFlags = wxICON_INFORMATION ) override;
/**
* Dismisses the infobar and updates the containing layout and AUI manager
* (if one is provided).
*/
void Dismiss() override;
protected:
/**
* Event handler for the close button.
* This is bound to ID_CLOSE_INFOBAR on the infobar.
*/
void OnCloseButton( wxCommandEvent& aEvt );
/**
* Update the AUI pane to show or hide this infobar.
*
* @param aShow is true to show the pane
*/
void UpdateAuiLayout( bool aShow );
wxAuiManager* m_auiManager;
DECLARE_EVENT_TABLE()
};

View File

@ -34,6 +34,7 @@
#include <pl_editor_frame.h> #include <pl_editor_frame.h>
#include <properties_frame.h> #include <properties_frame.h>
#include <pl_editor_id.h> #include <pl_editor_id.h>
#include <widgets/wx_infobar.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
@ -228,6 +229,16 @@ bool PL_EDITOR_FRAME::LoadPageLayoutDescrFile( const wxString& aFullFileName )
SetCurrentFileName( aFullFileName ); SetCurrentFileName( aFullFileName );
UpdateFileHistory( aFullFileName ); UpdateFileHistory( aFullFileName );
GetScreen()->ClrModify(); GetScreen()->ClrModify();
wxFileName fn = aFullFileName;
if( fn.FileExists() && !fn.IsFileWritable() )
{
m_infoBar->RemoveAllButtons();
m_infoBar->AddCloseButton();
m_infoBar->ShowMessage( "Layout file is read only.", wxICON_WARNING );
}
return true; return true;
} }

View File

@ -56,6 +56,7 @@
#include <tools/pl_point_editor.h> #include <tools/pl_point_editor.h>
#include <invoke_pl_editor_dialog.h> #include <invoke_pl_editor_dialog.h>
#include <tools/pl_editor_control.h> #include <tools/pl_editor_control.h>
#include <widgets/wx_infobar.h>
BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME ) BEGIN_EVENT_TABLE( PL_EDITOR_FRAME, EDA_DRAW_FRAME )
EVT_CLOSE( PL_EDITOR_FRAME::OnCloseWindow ) EVT_CLOSE( PL_EDITOR_FRAME::OnCloseWindow )
@ -124,6 +125,8 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
ReCreateHToolbar(); ReCreateHToolbar();
ReCreateVToolbar(); ReCreateVToolbar();
m_infoBar = new WX_INFOBAR( this, &m_auimgr );
wxWindow* stsbar = GetStatusBar(); wxWindow* stsbar = GetStatusBar();
int dims[] = { int dims[] = {
@ -159,13 +162,18 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
m_propertiesPagelayout = new PROPERTIES_FRAME( this ); m_propertiesPagelayout = new PROPERTIES_FRAME( this );
// Horizontal items; layers 4 - 6 // Horizontal items; layers 4 - 6
m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_mainToolBar,
m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
m_auimgr.AddPane( m_messagePanel,
EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) );
m_auimgr.AddPane( m_infoBar,
EDA_PANE().InfoBar().Name( "InfoBar" ).Top().Layer(1) );
// Vertical items; layers 1 - 3 // Vertical items; layers 1 - 3
m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_drawToolBar,
EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(2) );
m_auimgr.AddPane( m_propertiesPagelayout, EDA_PANE().Palette().Name( "Props" ).Right().Layer(2) m_auimgr.AddPane( m_propertiesPagelayout, EDA_PANE().Palette().Name( "Props" ).Right().Layer(3)
.Caption( _( "Properties" ) ).MinSize( m_propertiesPagelayout->GetMinSize() ) .Caption( _( "Properties" ) ).MinSize( m_propertiesPagelayout->GetMinSize() )
.BestSize( m_propertiesFrameWidth, -1 ) ); .BestSize( m_propertiesFrameWidth, -1 ) );
@ -174,6 +182,9 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
GetCanvas()->GetView()->SetScale( GetZoomLevelCoeff() / GetScreen()->GetZoom() ); GetCanvas()->GetView()->SetScale( GetZoomLevelCoeff() / GetScreen()->GetZoom() );
ActivateGalCanvas(); ActivateGalCanvas();
// We don't want the infobar displayed right away
m_auimgr.GetPane( "InfoBar" ).Hide();
m_auimgr.Update(); m_auimgr.Update();
// Add the exit key handler // Add the exit key handler

View File

@ -87,6 +87,7 @@
#include <netlist_reader/pcb_netlist.h> #include <netlist_reader/pcb_netlist.h>
#include <wx/wupdlock.h> #include <wx/wupdlock.h>
#include <dialog_drc.h> // for DIALOG_DRC_WINDOW_NAME definition #include <dialog_drc.h> // for DIALOG_DRC_WINDOW_NAME definition
#include <widgets/wx_infobar.h>
#if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON) #if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON)
#include <python_scripting.h> #include <python_scripting.h>
@ -222,19 +223,30 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
ReCreateOptToolbar(); ReCreateOptToolbar();
ReCreateMicrowaveVToolbar(); ReCreateMicrowaveVToolbar();
m_infoBar = new WX_INFOBAR( this, &m_auimgr );
m_auimgr.SetManagedWindow( this ); m_auimgr.SetManagedWindow( this );
// Horizontal items; layers 4 - 6 // Horizontal items; layers 4 - 6
m_auimgr.AddPane( m_mainToolBar, EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) ); m_auimgr.AddPane( m_mainToolBar,
m_auimgr.AddPane( m_auxiliaryToolBar, EDA_PANE().HToolbar().Name( "AuxToolbar" ).Top().Layer(4) ); EDA_PANE().HToolbar().Name( "MainToolbar" ).Top().Layer(6) );
m_auimgr.AddPane( m_messagePanel, EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) ); m_auimgr.AddPane( m_auxiliaryToolBar,
EDA_PANE().HToolbar().Name( "AuxToolbar" ).Top().Layer(5) );
m_auimgr.AddPane( m_messagePanel,
EDA_PANE().Messages().Name( "MsgPanel" ).Bottom().Layer(6) );
m_auimgr.AddPane( m_infoBar,
EDA_PANE().InfoBar().Name( "InfoBar" ).Top().Layer(1) );
// Vertical items; layers 1 - 3 // Vertical items; layers 1 - 3
m_auimgr.AddPane( m_optionsToolBar, EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) ); m_auimgr.AddPane( m_optionsToolBar,
EDA_PANE().VToolbar().Name( "OptToolbar" ).Left().Layer(3) );
m_auimgr.AddPane( m_microWaveToolBar, EDA_PANE().VToolbar().Name( "MicrowaveToolbar" ).Right().Layer(1) ); m_auimgr.AddPane( m_microWaveToolBar,
m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(2) ); EDA_PANE().VToolbar().Name( "MicrowaveToolbar" ).Right().Layer(2) );
m_auimgr.AddPane( m_Layers, EDA_PANE().Palette().Name( "LayersManager" ).Right().Layer(3) m_auimgr.AddPane( m_drawToolBar,
EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(3) );
m_auimgr.AddPane( m_Layers,
EDA_PANE().Palette().Name( "LayersManager" ).Right().Layer(4)
.Caption( _( "Layers Manager" ) ).PaneBorder( false ) .Caption( _( "Layers Manager" ) ).PaneBorder( false )
.MinSize( 80, -1 ).BestSize( m_Layers->GetBestSize() ) ); .MinSize( 80, -1 ).BestSize( m_Layers->GetBestSize() ) );
@ -248,6 +260,9 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
// because contents establish size // because contents establish size
syncLayerWidgetLayer(); syncLayerWidgetLayer();
// We don't want the infobar displayed right away
m_auimgr.GetPane( "InfoBar" ).Hide();
m_auimgr.Update(); m_auimgr.Update();
GetToolManager()->RunAction( ACTIONS::gridPreset, true, m_LastGridSizeId ); GetToolManager()->RunAction( ACTIONS::gridPreset, true, m_LastGridSizeId );
GetToolManager()->RunAction( ACTIONS::zoomFitScreen, false ); GetToolManager()->RunAction( ACTIONS::zoomFitScreen, false );
@ -698,6 +713,16 @@ void PCB_EDIT_FRAME::onBoardLoaded()
{ {
UpdateTitle(); UpdateTitle();
wxFileName fn = GetBoard()->GetFileName();
// Display a warning that the file is read only
if( fn.FileExists() && !fn.IsFileWritable() )
{
m_infoBar->RemoveAllButtons();
m_infoBar->AddCloseButton();
m_infoBar->ShowMessage( "Board file is read only.", wxICON_WARNING );
}
// Re-create layers manager based on layer info in board // Re-create layers manager based on layer info in board
ReFillLayerWidget(); ReFillLayerWidget();
ReCreateLayerBox(); ReCreateLayerBox();