2007-08-20 01:20:48 +00:00
|
|
|
|
/******************************************************/
|
|
|
|
|
/* edit.cpp: fonctions generales de l'edition du PCB */
|
|
|
|
|
/******************************************************/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
#include "fctsys.h"
|
2009-02-04 15:25:03 +00:00
|
|
|
|
#include "id.h"
|
|
|
|
|
#include "class_drawpanel.h"
|
|
|
|
|
#include "confirm.h"
|
|
|
|
|
#include "gestfich.h"
|
2009-04-05 20:49:15 +00:00
|
|
|
|
#include "appl_wxstruct.h"
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
#include "gerbview.h"
|
|
|
|
|
#include "pcbplot.h"
|
|
|
|
|
#include "protos.h"
|
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
static void Process_Move_Item( WinEDA_GerberFrame* frame,
|
|
|
|
|
EDA_BaseStruct* DrawStruct, wxDC* DC );
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
void WinEDA_GerberFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
/************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
2008-02-12 21:12:46 +00:00
|
|
|
|
/* Traite les commandes declench<63>e par le bouton gauche de la souris,
|
|
|
|
|
* quand un outil est deja selectionn<EFBFBD>
|
2007-08-20 01:20:48 +00:00
|
|
|
|
*/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2008-04-17 16:25:29 +00:00
|
|
|
|
BOARD_ITEM* DrawStruct = GetScreen()->GetCurItem();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
|
|
if( m_ID_current_state == 0 )
|
|
|
|
|
{
|
|
|
|
|
if( DrawStruct && DrawStruct->m_Flags ) // Commande "POPUP" en cours
|
|
|
|
|
{
|
2007-09-01 12:00:30 +00:00
|
|
|
|
switch( DrawStruct->Type() )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
msg.Printf(
|
|
|
|
|
wxT( "WinEDA_GerberFrame::ProcessCommand err: Struct %d, m_Flags = %X" ),
|
2007-09-01 12:00:30 +00:00
|
|
|
|
(unsigned) DrawStruct->Type(),
|
2007-08-20 01:20:48 +00:00
|
|
|
|
(unsigned) DrawStruct->m_Flags );
|
|
|
|
|
DisplayError( this, msg );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DrawStruct = GerberGeneralLocateAndDisplay();
|
|
|
|
|
GetScreen()->SetCurItem( DrawStruct );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch( m_ID_current_state )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_NO_SELECT_BUTT:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case ID_PCB_DELETE_ITEM_BUTT:
|
|
|
|
|
DrawStruct = GerberGeneralLocateAndDisplay();
|
|
|
|
|
if( DrawStruct == NULL )
|
|
|
|
|
break;
|
2008-12-04 04:28:11 +00:00
|
|
|
|
if( DrawStruct->Type() == TYPE_TRACK )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
|
|
|
|
Delete_Segment( DC, (TRACK*) DrawStruct );
|
|
|
|
|
GetScreen()->SetCurItem( NULL );
|
|
|
|
|
GetScreen()->SetModify();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
DisplayError( this, wxT( "WinEDA_GerberFrame::ProcessCommand error" ) );
|
|
|
|
|
SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/********************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
/********************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
/* Traite les selections d'outils et les commandes appelees du menu POPUP
|
2007-08-20 01:20:48 +00:00
|
|
|
|
*/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
|
int id = event.GetId();
|
2008-04-17 16:25:29 +00:00
|
|
|
|
int layer = GetScreen()->m_Active_Layer;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
GERBER* gerber_layer = g_GERBER_List[layer];
|
2007-08-20 01:20:48 +00:00
|
|
|
|
wxPoint pos;
|
|
|
|
|
wxClientDC dc( DrawPanel );
|
|
|
|
|
|
|
|
|
|
DrawPanel->PrepareGraphicContext( &dc );
|
|
|
|
|
|
|
|
|
|
wxGetMousePosition( &pos.x, &pos.y );
|
|
|
|
|
|
|
|
|
|
pos.y += 20;
|
|
|
|
|
|
2008-02-12 21:12:46 +00:00
|
|
|
|
switch( id ) // Arret eventuel de la commande de d<>placement en cours
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
|
|
|
|
case wxID_CUT:
|
|
|
|
|
case wxID_COPY:
|
2009-05-02 18:53:04 +00:00
|
|
|
|
case ID_POPUP_MIRROR_X_BLOCK:
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_POPUP_DELETE_BLOCK:
|
|
|
|
|
case ID_POPUP_PLACE_BLOCK:
|
|
|
|
|
case ID_POPUP_ZOOM_BLOCK:
|
|
|
|
|
case ID_POPUP_INVERT_BLOCK:
|
|
|
|
|
case ID_POPUP_ROTATE_BLOCK:
|
|
|
|
|
case ID_POPUP_COPY_BLOCK:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_CANCEL_CURRENT_COMMAND:
|
|
|
|
|
if( DrawPanel->ManageCurseur
|
|
|
|
|
&& DrawPanel->ForceCloseManageCurseur )
|
|
|
|
|
{
|
|
|
|
|
DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc );
|
|
|
|
|
}
|
|
|
|
|
/* ne devrait pas etre execute, sauf bug */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
if( GetScreen()->BlockLocate.m_Command != BLOCK_IDLE )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
2008-04-17 16:25:29 +00:00
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_IDLE;
|
|
|
|
|
GetScreen()->BlockLocate.m_State = STATE_NO_BLOCK;
|
|
|
|
|
GetScreen()->BlockLocate.m_BlockDrawStruct = NULL;
|
2007-08-20 01:20:48 +00:00
|
|
|
|
}
|
|
|
|
|
if( m_ID_current_state == 0 )
|
|
|
|
|
SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
|
|
|
|
|
else
|
|
|
|
|
SetCursor( DrawPanel->m_PanelCursor = DrawPanel->m_PanelDefaultCursor );
|
|
|
|
|
break;
|
|
|
|
|
|
2008-02-12 21:12:46 +00:00
|
|
|
|
default: // Arret dea commande de d<>placement en cours
|
2007-08-20 01:20:48 +00:00
|
|
|
|
if( DrawPanel->ManageCurseur
|
|
|
|
|
&& DrawPanel->ForceCloseManageCurseur )
|
|
|
|
|
{
|
|
|
|
|
DrawPanel->ForceCloseManageCurseur( DrawPanel, &dc );
|
|
|
|
|
}
|
|
|
|
|
SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch( id ) // Traitement des commandes
|
|
|
|
|
{
|
|
|
|
|
case ID_EXIT:
|
|
|
|
|
Close( TRUE );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_NEW_PROJECT:
|
|
|
|
|
case ID_LOAD_PROJECT:
|
|
|
|
|
Files_io( event );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_PCB_GLOBAL_DELETE:
|
2007-12-03 06:54:19 +00:00
|
|
|
|
Erase_Current_Layer( TRUE );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case wxID_CUT:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case wxID_COPY:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case wxID_PASTE:
|
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
// HandleBlockBegin(&dc, BLOCK_PASTE);
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_UNDO_BUTT:
|
|
|
|
|
UnDeleteItem( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_GET_TOOLS:
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
// InstallToolsFrame(this, wxPoint(-1,-1) );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_FIND_ITEMS:
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
// InstallFindFrame(this, pos);
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_BUS_BUTT:
|
|
|
|
|
SetToolID( id, wxCURSOR_PENCIL, wxT( "Add Tracks" ) );
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_LINE_COMMENT_BUTT:
|
|
|
|
|
SetToolID( id, wxCURSOR_PENCIL, wxT( "Add Drawing" ) );
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_TEXT_COMMENT_BUTT:
|
|
|
|
|
SetToolID( id, wxCURSOR_PENCIL, wxT( "Add Text" ) );
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_NO_SELECT_BUTT:
|
|
|
|
|
SetToolID( 0, 0, wxEmptyString );
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_POPUP_CLOSE_CURRENT_TOOL:
|
|
|
|
|
SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_POPUP_CANCEL_CURRENT_COMMAND:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_END_LINE:
|
|
|
|
|
DrawPanel->MouseToCursorSchema();
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
// EndSegment(&dc);
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_PCB_DELETE_TRACKSEG:
|
|
|
|
|
DrawPanel->MouseToCursorSchema();
|
|
|
|
|
if( GetScreen()->GetCurItem() == NULL )
|
|
|
|
|
break;
|
|
|
|
|
Delete_Segment( &dc, (TRACK*) GetScreen()->GetCurItem() );
|
|
|
|
|
GetScreen()->SetCurItem( NULL );
|
|
|
|
|
GetScreen()->SetModify();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_PCB_DELETE_ITEM_BUTT:
|
2007-09-10 04:51:01 +00:00
|
|
|
|
SetToolID( id, wxCURSOR_BULLSEYE, wxT( "Delete item" ) );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_SCH_MOVE_ITEM_REQUEST:
|
|
|
|
|
DrawPanel->MouseToCursorSchema();
|
|
|
|
|
Process_Move_Item( this, GetScreen()->GetCurItem(), &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_TOOLBARH_PCB_SELECT_LAYER:
|
2008-02-12 21:12:46 +00:00
|
|
|
|
((PCB_SCREEN*)GetScreen())->m_Active_Layer = m_SelLayerBox->GetChoice();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
DrawPanel->Refresh( TRUE );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_TOOLBARH_GERBER_SELECT_TOOL:
|
|
|
|
|
if( gerber_layer )
|
|
|
|
|
{
|
|
|
|
|
int tool = m_SelLayerTool->GetChoice();
|
|
|
|
|
if( tool > 0 )
|
|
|
|
|
tool = tool - 1 + FIRST_DCODE;
|
|
|
|
|
else
|
|
|
|
|
tool = 0;
|
|
|
|
|
gerber_layer->m_Selected_Tool = tool;
|
|
|
|
|
DrawPanel->Refresh( TRUE );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
DisplayError( this, _( "No layer selected" ) );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_GERBVIEW_SHOW_LIST_DCODES:
|
|
|
|
|
Liste_D_Codes( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_GERBVIEW_SHOW_SOURCE:
|
|
|
|
|
if( gerber_layer )
|
|
|
|
|
{
|
2009-04-05 20:49:15 +00:00
|
|
|
|
wxString editorname = wxGetApp().GetEditorName();
|
2007-08-20 01:20:48 +00:00
|
|
|
|
if( !editorname.IsEmpty() )
|
2009-04-29 17:09:00 +00:00
|
|
|
|
{
|
|
|
|
|
wxFileName fn( gerber_layer->m_FileName );
|
|
|
|
|
ExecuteFile( this, editorname, QuoteFullPath( fn ) );
|
|
|
|
|
}
|
2007-08-20 01:20:48 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_PLACE_BLOCK:
|
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_MOVE;
|
|
|
|
|
DrawPanel->m_AutoPAN_Request = FALSE;
|
|
|
|
|
HandleBlockPlace( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_COPY_BLOCK:
|
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_COPY;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
GetScreen()->BlockLocate.SetMessageBlock( this );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
DrawPanel->m_AutoPAN_Request = FALSE;
|
|
|
|
|
HandleBlockEnd( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_ZOOM_BLOCK:
|
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_ZOOM;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
GetScreen()->BlockLocate.SetMessageBlock( this );
|
|
|
|
|
GetScreen()->BlockLocate.SetMessageBlock( this );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
HandleBlockEnd( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ID_POPUP_DELETE_BLOCK:
|
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_DELETE;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
GetScreen()->BlockLocate.SetMessageBlock( this );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
HandleBlockEnd( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
2009-05-02 18:53:04 +00:00
|
|
|
|
case ID_POPUP_MIRROR_X_BLOCK:
|
|
|
|
|
GetScreen()->BlockLocate.m_Command = BLOCK_MIRROR_X;
|
|
|
|
|
GetScreen()->BlockLocate.SetMessageBlock( this );
|
|
|
|
|
HandleBlockEnd( &dc );
|
|
|
|
|
break;
|
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
case ID_GERBVIEW_POPUP_DELETE_DCODE_ITEMS:
|
|
|
|
|
if( gerber_layer )
|
2008-02-12 21:12:46 +00:00
|
|
|
|
Delete_DCode_Items( &dc, gerber_layer->m_Selected_Tool, ((PCB_SCREEN*)GetScreen())->m_Active_Layer );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
wxMessageBox( wxT( "WinEDA_GerberFrame::Process_Special_Functions error" ) );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetToolbars();
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
static void Process_Move_Item( WinEDA_GerberFrame* frame,
|
|
|
|
|
EDA_BaseStruct* DrawStruct, wxDC* DC )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
/****************************************************************/
|
|
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
|
if( DrawStruct == NULL )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
frame->DrawPanel->MouseToCursorSchema();
|
|
|
|
|
|
2007-09-01 12:00:30 +00:00
|
|
|
|
switch( DrawStruct->Type() )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
wxString msg;
|
|
|
|
|
msg.Printf(
|
|
|
|
|
wxT( "WinEDA_LibeditFrame::Move_Item Error: Bad DrawType %d" ),
|
2007-09-01 12:00:30 +00:00
|
|
|
|
DrawStruct->Type() );
|
2007-08-20 01:20:48 +00:00
|
|
|
|
DisplayError( frame, msg );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
void WinEDA_GerberFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
/**************************************************************************/
|
2007-08-20 01:20:48 +00:00
|
|
|
|
|
2008-02-12 21:12:46 +00:00
|
|
|
|
/* Appel<65> sur un double click:
|
|
|
|
|
* pour un <EFBFBD>l<EFBFBD>ment editable (textes, composant):
|
2007-08-20 01:20:48 +00:00
|
|
|
|
* appel de l'editeur correspondant.
|
|
|
|
|
* pour une connexion en cours:
|
|
|
|
|
* termine la connexion
|
|
|
|
|
*/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2007-08-20 01:20:48 +00:00
|
|
|
|
EDA_BaseStruct* DrawStruct = GetScreen()->GetCurItem();
|
|
|
|
|
wxClientDC dc( DrawPanel );
|
|
|
|
|
|
|
|
|
|
DrawPanel->PrepareGraphicContext( &dc );
|
|
|
|
|
|
|
|
|
|
switch( m_ID_current_state )
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
if( (DrawStruct == NULL) || (DrawStruct->m_Flags == 0) )
|
|
|
|
|
{
|
|
|
|
|
DrawStruct = GerberGeneralLocateAndDisplay();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( (DrawStruct == NULL) || (DrawStruct->m_Flags != 0) )
|
|
|
|
|
break;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2008-02-12 21:12:46 +00:00
|
|
|
|
// Element localis<69>
|
2007-09-01 12:00:30 +00:00
|
|
|
|
switch( DrawStruct->Type() )
|
2007-08-20 01:20:48 +00:00
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2007-08-20 01:20:48 +00:00
|
|
|
|
break; // end case 0
|
|
|
|
|
|
|
|
|
|
case ID_BUS_BUTT:
|
|
|
|
|
case ID_WIRE_BUTT:
|
|
|
|
|
|
|
|
|
|
// if ( DrawStruct && (DrawStruct->m_Flags & IS_NEW) )
|
|
|
|
|
// EndSegment(DC);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|