Commit d6072d8a authored by CHARRAS's avatar CHARRAS

Programmable hotkeys added in gerbview. Fixed a compilation probleme in ansi...

Programmable hotkeys added in gerbview. Fixed a compilation probleme in ansi mode (non unicode mode).
parent 67f15fe0
...@@ -5,6 +5,12 @@ Please add newer entries at the top, list the date and your name with ...@@ -5,6 +5,12 @@ Please add newer entries at the top, list the date and your name with
email address. email address.
2007-sept-10 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+ gerbview
Programmable hotkeys added. Fixed a compilation probleme in ansi mode (non unicode mode).
2007-Sep-8 UPDATE Dick Hollenbeck <dick@softplc.com> 2007-Sep-8 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
+ pcbnew + pcbnew
...@@ -13,7 +19,6 @@ email address. ...@@ -13,7 +19,6 @@ email address.
used like simple expressions. used like simple expressions.
All changes not yet committed. All changes not yet committed.
2007-sept-6 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr> 2007-sept-6 UPDATE Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================ ================================================================================
+ eeschema & pcbnew + eeschema & pcbnew
......
...@@ -427,7 +427,8 @@ int WinEDA_BasicFrame::WriteHotkeyConfigFile( const wxString& ...@@ -427,7 +427,8 @@ int WinEDA_BasicFrame::WriteHotkeyConfigFile( const wxString&
fprintf( cfgfile, DescList->m_Comment ); fprintf( cfgfile, DescList->m_Comment );
fprintf( cfgfile, "\n" ); fprintf( cfgfile, "\n" );
} }
fprintf( cfgfile, CONV_TO_UTF8( *DescList->m_SectionTag ) ); msg = *DescList->m_SectionTag;
fprintf( cfgfile, CONV_TO_UTF8( msg ) );
fprintf( cfgfile, "\n" ); fprintf( cfgfile, "\n" );
List = DescList->m_HK_InfoList; List = DescList->m_HK_InfoList;
for( ; *List != NULL; List++ ) for( ; *List != NULL; List++ )
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
/* Variables locales */ /* Variables locales */
#define HOTKEY_FILENAME wxT("eeschema")
/*********************************************************************/ /*********************************************************************/
void WinEDA_SchematicFrame::Process_Config(wxCommandEvent& event) void WinEDA_SchematicFrame::Process_Config(wxCommandEvent& event)
/*********************************************************************/ /*********************************************************************/
...@@ -76,7 +78,7 @@ wxString FullFileName; ...@@ -76,7 +78,7 @@ wxString FullFileName;
case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS: case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS:
FullFileName = DEFAULT_HOTKEY_FILENAME_PATH; FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += wxT("eeschema"); FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT; FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
WriteHotkeyConfigFile(FullFileName, s_Eeschema_Hokeys_Descr, true); WriteHotkeyConfigFile(FullFileName, s_Eeschema_Hokeys_Descr, true);
break; break;
...@@ -99,7 +101,7 @@ bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose ) ...@@ -99,7 +101,7 @@ bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose )
*/ */
{ {
wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH; wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += wxT("eeschema"); FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT; FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
frame->ReadHotkeyConfigFile(FullFileName, s_Eeschema_Hokeys_Descr, verbose); frame->ReadHotkeyConfigFile(FullFileName, s_Eeschema_Hokeys_Descr, verbose);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
/* local variables */ /* local variables */
/* Hotkey list: */ /* Hotkey list: */
// Common commands // Common commands
static Ki_HotkeyInfo HkZoomCenter( wxT( "Zoom Center" ), HK_ZOOM_CENTER, WXK_F4 ); static Ki_HotkeyInfo HkZoomCenter( wxT( "Zoom Center" ), HK_ZOOM_CENTER, WXK_F4 );
static Ki_HotkeyInfo HkZoomRedraw( wxT( "Zoom Redraw" ), HK_ZOOM_REDRAW, WXK_F3 ); static Ki_HotkeyInfo HkZoomRedraw( wxT( "Zoom Redraw" ), HK_ZOOM_REDRAW, WXK_F3 );
...@@ -67,7 +68,7 @@ static Ki_HotkeyInfo HkDelete( wxT( "Delete Item" ), HK_DELETE, WXK_DELETE ); ...@@ -67,7 +68,7 @@ static Ki_HotkeyInfo HkDelete( wxT( "Delete Item" ), HK_DELETE, WXK_DELETE );
static Ki_HotkeyInfo HkNextSearch( wxT( "Next Search" ), HK_NEXT_SEARCH, WXK_F5 ); static Ki_HotkeyInfo HkNextSearch( wxT( "Next Search" ), HK_NEXT_SEARCH, WXK_F5 );
// Library editor: // Library editor:
static Ki_HotkeyInfo HkInsertPin( wxT( "Repeat Pin" ), HK_REPEAT_LAST, WXK_INSERT ); static Ki_HotkeyInfo HkInsertPin( wxT( "Repeat Pin" ), HK_REPEAT_LAST, WXK_INSERT );
// List of common hotkey descriptors // List of common hotkey descriptors
...@@ -97,25 +98,28 @@ Ki_HotkeyInfo* s_LibEdit_Hotkey_List[] = ...@@ -97,25 +98,28 @@ Ki_HotkeyInfo* s_LibEdit_Hotkey_List[] =
}; };
// list of sections and corresponding hotkey list for eeschema (used to create an hotkey config file) // list of sections and corresponding hotkey list for eeschema (used to create an hotkey config file)
struct Ki_HotkeyInfoSectionDescriptor s_Eeschema_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Eeschema_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, "Common keys" }, {
{ &g_SchematicSectionTag, s_Schematic_Hotkey_List, "Schematic editor keys"}, { &g_CommonSectionTag, s_Common_Hotkey_List, "Common keys" },
{ &g_LibEditSectionTag, s_LibEdit_Hotkey_List, "library editor keys"}, { &g_SchematicSectionTag, s_Schematic_Hotkey_List, "Schematic editor keys" },
NULL, NULL { &g_LibEditSectionTag, s_LibEdit_Hotkey_List, "library editor keys" },
{ NULL, NULL }
}; };
// list of sections and corresponding hotkey list for the schematic editor (used to list current hotkeys) // list of sections and corresponding hotkey list for the schematic editor (used to list current hotkeys)
struct Ki_HotkeyInfoSectionDescriptor s_Schematic_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Schematic_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, NULL}, {
{ &g_SchematicSectionTag, s_Schematic_Hotkey_List, NULL}, { &g_CommonSectionTag, s_Common_Hotkey_List, NULL },
NULL, NULL { &g_SchematicSectionTag, s_Schematic_Hotkey_List, NULL },
{ NULL, NULL, NULL }
}; };
// list of sections and corresponding hotkey list for the component editor (used to list current hotkeys) // list of sections and corresponding hotkey list for the component editor (used to list current hotkeys)
struct Ki_HotkeyInfoSectionDescriptor s_Libedit_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Libedit_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, NULL}, {
{ &g_LibEditSectionTag, s_LibEdit_Hotkey_List, NULL}, { &g_CommonSectionTag, s_Common_Hotkey_List, NULL },
NULL, NULL { &g_LibEditSectionTag, s_LibEdit_Hotkey_List, NULL },
{ NULL, NULL, NULL }
}; };
/***********************************************************/ /***********************************************************/
...@@ -145,8 +149,8 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey, ...@@ -145,8 +149,8 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
// Search command from key : // Search command from key :
int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List ); int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List );
if ( CommandCode == HK_NOT_FOUND ) if( CommandCode == HK_NOT_FOUND )
CommandCode = GetCommandCodeFromHotkey( hotkey, s_Schematic_Hotkey_List ); CommandCode = GetCommandCodeFromHotkey( hotkey, s_Schematic_Hotkey_List );
switch( CommandCode ) switch( CommandCode )
{ {
...@@ -367,8 +371,8 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey, ...@@ -367,8 +371,8 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
if( (hotkey >= 'a') && (hotkey <= 'z') ) if( (hotkey >= 'a') && (hotkey <= 'z') )
hotkey += 'A' - 'a'; hotkey += 'A' - 'a';
int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List ); int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List );
if ( CommandCode == HK_NOT_FOUND ) if( CommandCode == HK_NOT_FOUND )
CommandCode = GetCommandCodeFromHotkey( hotkey, s_LibEdit_Hotkey_List ); CommandCode = GetCommandCodeFromHotkey( hotkey, s_LibEdit_Hotkey_List );
switch( CommandCode ) switch( CommandCode )
{ {
......
...@@ -67,37 +67,6 @@ int hotkey = 0; ...@@ -67,37 +67,6 @@ int hotkey = 0;
switch(g_KeyPressed) switch(g_KeyPressed)
{ {
case WXK_NUMPAD_SUBTRACT :
case WXK_SUBTRACT :
case '-' :
if(GetScreen()->m_Active_Layer > 0)
GetScreen()->m_Active_Layer--;
break ;
case WXK_NUMPAD_ADD :
case WXK_ADD :
case '+' :
if(GetScreen()->m_Active_Layer < 31)
GetScreen()->m_Active_Layer ++;
break ;
case 'F' | GR_KB_CTRL :
case 'f' | GR_KB_CTRL :
DisplayOpt.DisplayPcbTrackFill ^= 1; DisplayOpt.DisplayPcbTrackFill &= 1 ;
GetScreen()->SetRefreshReq();
break ;
case ' ' : /* Mise a jour de l'origine des coord relatives */
GetScreen()->m_O_Curseur = GetScreen()->m_Curseur;
break ;
case 'U' | GR_KB_CTRL :
case 'u' | GR_KB_CTRL :
if (g_UnitMetric == INCHES ) g_UnitMetric = MILLIMETRE ;
else g_UnitMetric = INCHES ;
break ;
case EDA_PANNING_UP_KEY : case EDA_PANNING_UP_KEY :
OnZoom(ID_ZOOM_PANNING_UP); OnZoom(ID_ZOOM_PANNING_UP);
curpos = m_CurrentScreen->m_Curseur; curpos = m_CurrentScreen->m_Curseur;
...@@ -118,21 +87,17 @@ int hotkey = 0; ...@@ -118,21 +87,17 @@ int hotkey = 0;
curpos = m_CurrentScreen->m_Curseur; curpos = m_CurrentScreen->m_Curseur;
break; break;
case WXK_F1 : case EDA_ZOOM_IN_FROM_MOUSE :
OnZoom(ID_ZOOM_PLUS_KEY); OnZoom(ID_ZOOM_PLUS_KEY);
curpos = GetScreen()->m_Curseur; curpos = GetScreen()->m_Curseur;
break; break;
case WXK_F2 : case EDA_ZOOM_OUT_FROM_MOUSE :
OnZoom(ID_ZOOM_MOINS_KEY); OnZoom(ID_ZOOM_MOINS_KEY);
curpos = GetScreen()->m_Curseur; curpos = GetScreen()->m_Curseur;
break; break;
case WXK_F3 : case EDA_ZOOM_CENTER_FROM_MOUSE :
OnZoom(ID_ZOOM_REDRAW_KEY);
break;
case WXK_F4 :
OnZoom(ID_ZOOM_CENTER_KEY); OnZoom(ID_ZOOM_CENTER_KEY);
curpos = GetScreen()->m_Curseur; curpos = GetScreen()->m_Curseur;
break; break;
...@@ -186,13 +151,19 @@ int hotkey = 0; ...@@ -186,13 +151,19 @@ int hotkey = 0;
} }
} }
SetToolbars();
Affiche_Status_Box(); /* Affichage des coord curseur */
if ( hotkey ) if ( hotkey )
{ {
OnHotKey(DC, hotkey, NULL); OnHotKey(DC, hotkey, NULL);
} }
if( GetScreen()->IsRefreshReq() )
{
RedrawActiveWindow( DC, TRUE );
}
SetToolbars();
Affiche_Status_Box(); /* Affichage des coord curseur */
} }
...@@ -216,7 +216,7 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event ) ...@@ -216,7 +216,7 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event )
break; break;
case ID_PCB_DELETE_ITEM_BUTT: case ID_PCB_DELETE_ITEM_BUTT:
SetToolID( id, wxCURSOR_PENCIL, wxT( "Delete item" ) ); SetToolID( id, wxCURSOR_BULLSEYE, wxT( "Delete item" ) );
break; break;
case ID_POPUP_SCH_MOVE_ITEM_REQUEST: case ID_POPUP_SCH_MOVE_ITEM_REQUEST:
......
...@@ -62,6 +62,8 @@ BEGIN_EVENT_TABLE(WinEDA_GerberFrame, wxFrame) ...@@ -62,6 +62,8 @@ BEGIN_EVENT_TABLE(WinEDA_GerberFrame, wxFrame)
EVT_MENU(ID_OPTIONS_SETUP, WinEDA_GerberFrame::Process_Config) EVT_MENU(ID_OPTIONS_SETUP, WinEDA_GerberFrame::Process_Config)
EVT_MENU(ID_PCB_LOOK_SETUP, WinEDA_GerberFrame::Process_Config) EVT_MENU(ID_PCB_LOOK_SETUP, WinEDA_GerberFrame::Process_Config)
EVT_MENU(ID_CONFIG_SAVE, WinEDA_GerberFrame::Process_Config) EVT_MENU(ID_CONFIG_SAVE, WinEDA_GerberFrame::Process_Config)
EVT_MENU(ID_PREFERENCES_CREATE_CONFIG_HOTKEYS, WinEDA_GerberFrame::Process_Config)
EVT_MENU(ID_PREFERENCES_READ_CONFIG_HOTKEYS, WinEDA_GerberFrame::Process_Config)
EVT_MENU_RANGE(ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END, EVT_MENU_RANGE(ID_LANGUAGE_CHOICE, ID_LANGUAGE_CHOICE_END,
WinEDA_DrawFrame::SetLanguage) WinEDA_DrawFrame::SetLanguage)
......
...@@ -43,6 +43,10 @@ wxString FFileName; ...@@ -43,6 +43,10 @@ wxString FFileName;
g_DrawBgColor = BLACK; g_DrawBgColor = BLACK;
Read_Hotkey_Config( m_PcbFrame, false ); /* Must be called before creating the main frame
* in order to display the real hotkeys
* in menus or tool tips */
m_GerberFrame = new WinEDA_GerberFrame(NULL, this, wxT("GerbView"), m_GerberFrame = new WinEDA_GerberFrame(NULL, this, wxT("GerbView"),
wxPoint(0,0), wxSize(600,400) ); wxPoint(0,0), wxSize(600,400) );
wxString Title = g_Main_Title + wxT(" ") + GetBuildVersion(); wxString Title = g_Main_Title + wxT(" ") + GetBuildVersion();
......
/******************************************/
/** gerbview_config.cpp : configuration pour Gerbview */
/******************************************/
/* lit ou met a jour la configuration de PCBNEW */
#include "fctsys.h"
#include "common.h"
#include "gerbview.h"
#include "pcbplot.h"
#include "id.h"
#include "hotkeys_basic.h"
#include "hotkeys.h"
#include "gerbview_config.h"
#include "protos.h"
/* Routines Locales */
/* Variables locales */
#define HOTKEY_FILENAME wxT("gerbview")
/*************************************************************/
void WinEDA_GerberFrame::Process_Config(wxCommandEvent& event)
/*************************************************************/
{
int id = event.GetId();
wxPoint pos;
wxString FullFileName;
pos = GetPosition();
pos.x += 20; pos.y += 20;
switch( id )
{
case ID_COLORS_SETUP :
DisplayColorSetupFrame(this, pos);
break;
case ID_CONFIG_REQ : // Creation de la fenetre de configuration
{
InstallConfigFrame(pos);
break;
}
case ID_PCB_TRACK_SIZE_SETUP:
case ID_PCB_LOOK_SETUP:
case ID_OPTIONS_SETUP:
InstallPcbOptionsFrame(pos, id);
break;
case ID_CONFIG_SAVE:
Update_config();
break;
case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS:
FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
WriteHotkeyConfigFile(FullFileName, s_Gerbview_Hokeys_Descr, true);
break;
case ID_PREFERENCES_READ_CONFIG_HOTKEYS:
Read_Hotkey_Config( this, true);
break;
default:
DisplayError(this, wxT("WinEDA_GerberFrame::Process_Config internal error"));
}
}
/*****************************************************/
bool Read_Config(void)
/*****************************************************/
/* lit la configuration, si elle n'a pas deja etee lue
1 - lit gerbview.cnf
2 - si non trouve lit <chemin de gerbview.exe>/gerbview.cnf
3 - si non trouve: init des variables aux valeurs par defaut
Retourne un pointeur su le message d'erreur a afficher
*/
{
g_Prj_Config_Filename_ext = wxT(".cnf");
EDA_Appl->ReadProjectConfig( wxT("gerbview"), GROUP, ParamCfgList, FALSE);
/* Inits autres variables */
if (ScreenPcb) ScreenPcb->SetGrid(TmpGrid);
if ( g_PhotoFilenameExt.IsEmpty() ) g_PhotoFilenameExt = wxT(".pho");
if ( g_DrillFilenameExt.IsEmpty() ) g_DrillFilenameExt = wxT(".drl");
if ( g_PenFilenameExt.IsEmpty() ) g_PenFilenameExt = wxT(".pen");
return TRUE;
}
/******************************************/
void WinEDA_GerberFrame::Update_config(void)
/******************************************/
/*
creation du fichier de config
*/
{
wxString FullFileName;
wxString mask( wxT("*") ),
g_Prj_Config_Filename_ext = wxT(".cnf";)
mask += g_Prj_Config_Filename_ext;
FullFileName = wxT("gerbview");
ChangeFileNameExt( FullFileName, g_Prj_Config_Filename_ext );
FullFileName = EDA_FileSelector(_("Save config file"),
wxEmptyString, /* Chemin par defaut */
FullFileName, /* nom fichier par defaut */
g_Prj_Config_Filename_ext, /* extension par defaut */
mask, /* Masque d'affichage */
this,
wxFD_SAVE,
TRUE
);
if ( FullFileName.IsEmpty() ) return;
/* ecriture de la configuration */
EDA_Appl->WriteProjectConfig(FullFileName, GROUP, ParamCfgList);
}
/***************************************************************/
bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose )
/***************************************************************/
/*
* Read the hotkey files config for pcbnew and module_edit
*/
{
wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
return frame->ReadHotkeyConfigFile(FullFileName, s_Gerbview_Hokeys_Descr, verbose);
}
/***************/
/* hotkeys.cpp */
/***************/
#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "pcbnew.h"
#include "id.h"
#include "hotkeys.h"
#include "protos.h"
/* How to add a new hotkey:
* add a new id in the enum hotkey_id_commnand like MY_NEW_ID_FUNCTION.
* add a new Ki_HotkeyInfo entry like:
* static Ki_HotkeyInfo HkMyNewEntry(wxT("Command Label"), MY_NEW_ID_FUNCTION, default key value);
* "Command Label" is the name used in hotkey list display, and the identifier in the hotkey list file
* MY_NEW_ID_FUNCTION is an equivalent id function used in the switch in OnHotKey() function.
* default key value is the default hotkey for this command. Can be overrided by the user hotkey list file
* add the HkMyNewEntry pointer in the s_board_edit_Hotkey_List list ( or/and the s_module_edit_Hotkey_List list)
* Add the new code in the switch in OnHotKey() function.
* when the variable PopupOn is true, an item is currently edited.
* This can be usefull if the new function cannot be executed while an item is currently being edited
* ( For example, one cannot start a new wire when a component is moving.)
*
* Note: If an hotkey is a special key, be sure the corresponding wxWidget keycode (WXK_XXXX)
* is handled in the hotkey_name_descr s_Hotkey_Name_List list (see hotkeys_basic.cpp)
* and see this list for some ascii keys (space ...)
*/
/* local variables */
/* Hotkey list: */
static Ki_HotkeyInfo HkResetLocalCoord( wxT( "Reset local coord." ), HK_RESET_LOCAL_COORD, ' ' );
static Ki_HotkeyInfo HkZoomCenter( wxT( "Zoom Center" ), HK_ZOOM_CENTER, WXK_F4 );
static Ki_HotkeyInfo HkZoomRedraw( wxT( "Zoom Redraw" ), HK_ZOOM_REDRAW, WXK_F3 );
static Ki_HotkeyInfo HkZoomOut( wxT( "Zoom Out" ), HK_ZOOM_OUT, WXK_F2 );
static Ki_HotkeyInfo HkZoomIn( wxT( "Zoom In" ), HK_ZOOM_IN, WXK_F1 );
static Ki_HotkeyInfo HkHelp( wxT( "Help: this message" ), HK_HELP, '?' );
static Ki_HotkeyInfo HkSwitchUnits( wxT( "Switch Units" ), HK_SWITCH_UNITS, 'U' );
static Ki_HotkeyInfo HkTrackDisplayMode( wxT(
"Track Display Mode" ),
HK_SWITCH_TRACK_DISPLAY_MODE, 'F' );
static Ki_HotkeyInfo HkSwitch2NextCopperLayer( wxT(
"Switch to Next Layer" ),
HK_SWITCH_LAYER_TO_NEXT, '+' );
static Ki_HotkeyInfo HkSwitch2PreviousCopperLayer( wxT(
"Switch to Previous Layer" ),
HK_SWITCH_LAYER_TO_PREVIOUS, '-' );
// List of common hotkey descriptors
Ki_HotkeyInfo* s_Gerbview_Hotkey_List[] = {
&HkHelp,
&HkZoomIn, &HkZoomOut, &HkZoomRedraw, &HkZoomCenter,
&HkSwitchUnits, &HkResetLocalCoord,
&HkTrackDisplayMode,
&HkSwitch2NextCopperLayer,
&HkSwitch2PreviousCopperLayer,
NULL
};
// list of sections and corresponding hotkey list for pcbnew (used to create an hotkey config file)
struct Ki_HotkeyInfoSectionDescriptor s_Gerbview_Hokeys_Descr[] =
{
{ &g_CommonSectionTag, s_Gerbview_Hotkey_List, NULL },
{ NULL, NULL, NULL }
};
/***********************************************************/
void WinEDA_GerberFrame::OnHotKey( wxDC* DC, int hotkey,
EDA_BaseStruct* DrawStruct )
/***********************************************************/
/* Hot keys. Some commands are relatives to the item under the mouse cursor
* Commands are case insensitive
* @param DC = current device context
* @param hotkey = hothey code (ascii or wxWidget code for special keys)
* @param DrawStruct = NULL or pointer on a EDA_BaseStruct under the mouse cursor
*/
{
// Remap the control key Ctrl A (0x01) to GR_KB_CTRL + 'A' (easier to handle...)
if( (hotkey & GR_KB_CTRL) != 0 )
hotkey += 'A' - 1;
/* Convert lower to upper case (the usual toupper function has problem with non ascii codes like function keys */
if( (hotkey >= 'a') && (hotkey <= 'z') )
hotkey += 'A' - 'a';
int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Gerbview_Hotkey_List );
switch( CommandCode )
{
default:
case HK_NOT_FOUND:
return;
break;
case HK_HELP: // Display Current hotkey list
DisplayHotkeyList( this, s_Gerbview_Hokeys_Descr );
break;
case HK_ZOOM_IN:
OnZoom( ID_ZOOM_PLUS_KEY );
break;
case HK_ZOOM_OUT:
OnZoom( ID_ZOOM_MOINS_KEY );
break;
case HK_ZOOM_REDRAW:
OnZoom( ID_ZOOM_REDRAW_KEY );
break;
case HK_ZOOM_CENTER:
OnZoom( ID_ZOOM_CENTER_KEY );
break;
case HK_RESET_LOCAL_COORD: /*Reset the relative coord */
GetScreen()->m_O_Curseur = GetScreen()->m_Curseur;
break;
case HK_SWITCH_UNITS:
g_UnitMetric = (g_UnitMetric == INCHES ) ? MILLIMETRE : INCHES;
break;
case HK_SWITCH_TRACK_DISPLAY_MODE:
DisplayOpt.DisplayPcbTrackFill ^= 1; DisplayOpt.DisplayPcbTrackFill &= 1;
GetScreen()->SetRefreshReq();
break;
case HK_SWITCH_LAYER_TO_PREVIOUS:
if( GetScreen()->m_Active_Layer > 0 )
GetScreen()->m_Active_Layer--;
break;
case HK_SWITCH_LAYER_TO_NEXT:
if( GetScreen()->m_Active_Layer < 31 )
GetScreen()->m_Active_Layer++;
break;
}
}
/***************/
/* hotkeys.h */
/***************/
#ifndef KOTKEYS_H
#define KOTKEYS_H
#include "hotkeys_basic.h"
enum hotkey_id_commnand {
HK_NOT_FOUND = 0,
HK_RESET_LOCAL_COORD,
HK_HELP,
HK_SWITCH_UNITS,
HK_SWITCH_TRACK_DISPLAY_MODE,
HK_ZOOM_IN,
HK_ZOOM_OUT,
HK_ZOOM_REDRAW,
HK_ZOOM_CENTER,
HK_SWITCH_LAYER_TO_NEXT,
HK_SWITCH_LAYER_TO_PREVIOUS
};
// List of hotkey descriptors for pcbnew
extern struct Ki_HotkeyInfoSectionDescriptor s_Gerbview_Hokeys_Descr[];
#endif // KOTKEYS_H
...@@ -21,7 +21,7 @@ OBJECTS= \ ...@@ -21,7 +21,7 @@ OBJECTS= \
drawframe.o\ drawframe.o\
drawpanel.o\ drawpanel.o\
set_color.o \ set_color.o \
cfg.o \ gerbview_config.o \
cursors.o \ cursors.o \
affiche.o \ affiche.o \
tracepcb.o \ tracepcb.o \
...@@ -32,6 +32,7 @@ OBJECTS= \ ...@@ -32,6 +32,7 @@ OBJECTS= \
options.o \ options.o \
initpcb.o\ initpcb.o\
locate.o\ locate.o\
hotkeys.o\
deltrack.o\ deltrack.o\
pcbplot.o\ pcbplot.o\
readgerb.o\ readgerb.o\
...@@ -59,6 +60,8 @@ drawframe.o: ../share/drawframe.cpp ...@@ -59,6 +60,8 @@ drawframe.o: ../share/drawframe.cpp
controle.o: controle.cpp $(COMMON) controle.o: controle.cpp $(COMMON)
hotkeys.o: hotkeys.cpp hotkeys.h $(COMMON)
set_color.o: set_color.cpp set_color.h $(COMMON) set_color.o: set_color.cpp set_color.h $(COMMON)
files.o: files.cpp $(COMMON) files.o: files.cpp $(COMMON)
...@@ -94,7 +97,7 @@ class_track.o: ../pcbnew/class_track.cpp $(COMMON) ...@@ -94,7 +97,7 @@ class_track.o: ../pcbnew/class_track.cpp $(COMMON)
$(TARGET).o: $(TARGET).cpp $(COMMON) $(TARGET).o: $(TARGET).cpp $(COMMON)
cfg.o: cfg.cpp cfg.h $(COMMON) gerbview_config.o: gerbview_config.cpp gerbview_config.h $(COMMON)
tracepcb.o: tracepcb.cpp $(COMMON) tracepcb.o: tracepcb.cpp $(COMMON)
......
...@@ -11,19 +11,26 @@ ...@@ -11,19 +11,26 @@
#include "pcbplot.h" #include "pcbplot.h"
#include "cfg.h" #include "cfg.h"
#include "id.h" #include "id.h"
#include "hotkeys_basic.h"
#include "hotkeys.h"
#include "protos.h" #include "protos.h"
/* Routines Locales */ /* Local functions */
static bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose );
/* Variables locales */ /* Variables locales */
#define HOTKEY_FILENAME wxT("gerbview")
/*************************************************************/ /*************************************************************/
void WinEDA_GerberFrame::Process_Config(wxCommandEvent& event) void WinEDA_GerberFrame::Process_Config(wxCommandEvent& event)
/*************************************************************/ /*************************************************************/
{ {
int id = event.GetId(); int id = event.GetId();
wxPoint pos; wxPoint pos;
wxString FullFileName;
pos = GetPosition(); pos = GetPosition();
pos.x += 20; pos.y += 20; pos.x += 20; pos.y += 20;
...@@ -50,6 +57,17 @@ wxPoint pos; ...@@ -50,6 +57,17 @@ wxPoint pos;
Update_config(); Update_config();
break; break;
case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS:
FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
WriteHotkeyConfigFile(FullFileName, s_Gerbview_Hokeys_Descr, true);
break;
case ID_PREFERENCES_READ_CONFIG_HOTKEYS:
Read_Hotkey_Config( this, true);
break;
default: default:
DisplayError(this, wxT("WinEDA_GerberFrame::Process_Config internal error")); DisplayError(this, wxT("WinEDA_GerberFrame::Process_Config internal error"));
} }
...@@ -111,3 +129,18 @@ wxString mask( wxT("*") ), ...@@ -111,3 +129,18 @@ wxString mask( wxT("*") ),
EDA_Appl->WriteProjectConfig(FullFileName, GROUP, ParamCfgList); EDA_Appl->WriteProjectConfig(FullFileName, GROUP, ParamCfgList);
} }
/***************************************************************/
bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose )
/***************************************************************/
/*
* Read the hotkey files config for pcbnew and module_edit
*/
{
wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
return frame->ReadHotkeyConfigFile(FullFileName, s_Gerbview_Hokeys_Descr, verbose);
}
...@@ -11,10 +11,11 @@ int * InstallDialogLayerPairChoice(WinEDA_GerberFrame * parent); ...@@ -11,10 +11,11 @@ int * InstallDialogLayerPairChoice(WinEDA_GerberFrame * parent);
BOARD_ITEM* SaveItemEfface( BOARD_ITEM* PtItem, int nbitems ); BOARD_ITEM* SaveItemEfface( BOARD_ITEM* PtItem, int nbitems );
/***********/ /***********************/
/* cfg.cpp */ /* gerbview_config.cpp */
/***********/ /***********************/
bool Read_Config(void); bool Read_Config(void);
bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose );
/* pcbplot.cpp */ /* pcbplot.cpp */
......
This diff is collapsed.
...@@ -782,6 +782,7 @@ public: ...@@ -782,6 +782,7 @@ public:
void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ); void OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
int BestZoom(); // Retourne le meilleur zoom int BestZoom(); // Retourne le meilleur zoom
void OnSelectOptionToolbar( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event );
void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
EDA_BaseStruct* GerberGeneralLocateAndDisplay(); EDA_BaseStruct* GerberGeneralLocateAndDisplay();
EDA_BaseStruct* Locate( int typeloc ); EDA_BaseStruct* Locate( int typeloc );
...@@ -941,7 +942,7 @@ public: ...@@ -941,7 +942,7 @@ public:
/* class WinEDA_SchematicFrame */ /* class WinEDA_SchematicFrame */
/*******************************/ /*******************************/
/* enum utilis� dans RotationMiroir() */ /* enum used in RotationMiroir() */
enum fl_rot_cmp { enum fl_rot_cmp {
CMP_NORMAL, // orientation normale (O, pas de miroir) CMP_NORMAL, // orientation normale (O, pas de miroir)
CMP_ROTATE_CLOCKWISE, // nouvelle rotation de -90 CMP_ROTATE_CLOCKWISE, // nouvelle rotation de -90
...@@ -981,6 +982,7 @@ public: ...@@ -981,6 +982,7 @@ public:
void ReCreateOptToolbar(); void ReCreateOptToolbar();
void ReCreateMenuBar(); void ReCreateMenuBar();
void SetToolbars(); void SetToolbars();
void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
SCH_SCREEN* GetScreen() { return (SCH_SCREEN*) m_CurrentScreen; } SCH_SCREEN* GetScreen() { return (SCH_SCREEN*) m_CurrentScreen; }
...@@ -1123,7 +1125,7 @@ private: ...@@ -1123,7 +1125,7 @@ private:
public: public:
void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct ); void Key( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
/* Gestion generale des operations sur block */ /* Gestion generale des operations sur block */
int ReturnBlockCommand( int key ); int ReturnBlockCommand( int key );
......
No preview for this file type
This diff is collapsed.
...@@ -59,11 +59,11 @@ static Ki_HotkeyInfo HkSwitch2InnerLayer6( wxT( ...@@ -59,11 +59,11 @@ static Ki_HotkeyInfo HkSwitch2InnerLayer6( wxT(
HK_SWITCH_LAYER_TO_INNER6, WXK_F10 ); HK_SWITCH_LAYER_TO_INNER6, WXK_F10 );
static Ki_HotkeyInfo HkSwitch2NextCopperLayer( wxT( static Ki_HotkeyInfo HkSwitch2NextCopperLayer( wxT(
"Switch to Next Layer" ), "Switch to Next Layer" ),
HK_SWITCH_LAYER_TO_NEXT, '+' ); HK_SWITCH_LAYER_TO_NEXT, '+' );
static Ki_HotkeyInfo HkSwitch2PreviousCopperLayer( wxT( static Ki_HotkeyInfo HkSwitch2PreviousCopperLayer( wxT(
"Switch to Previous Layer" ), "Switch to Previous Layer" ),
HK_SWITCH_LAYER_TO_PREVIOUS, '-'); HK_SWITCH_LAYER_TO_PREVIOUS, '-' );
static Ki_HotkeyInfo HkSavefile( wxT( "Save board" ), HK_SAVE_BOARD, 'S' + GR_KB_CTRL ); static Ki_HotkeyInfo HkSavefile( wxT( "Save board" ), HK_SAVE_BOARD, 'S' + GR_KB_CTRL );
static Ki_HotkeyInfo HkLoadfile( wxT( "Load board" ), HK_LOAD_BOARD, 'L' + GR_KB_CTRL ); static Ki_HotkeyInfo HkLoadfile( wxT( "Load board" ), HK_LOAD_BOARD, 'L' + GR_KB_CTRL );
...@@ -90,23 +90,23 @@ static Ki_HotkeyInfo HkTrackDisplayMode( wxT( ...@@ -90,23 +90,23 @@ static Ki_HotkeyInfo HkTrackDisplayMode( wxT(
"Track Display Mode" ), "Track Display Mode" ),
HK_SWITCH_TRACK_DISPLAY_MODE, 'F' ); HK_SWITCH_TRACK_DISPLAY_MODE, 'F' );
// List of common hotkey descriptors // List of common hotkey descriptors
Ki_HotkeyInfo* s_Common_Hotkey_List[] = { Ki_HotkeyInfo* s_Common_Hotkey_List[] = {
&HkHelp, &HkHelp,
&HkZoomIn, &HkZoomOut, &HkZoomRedraw, &HkZoomCenter, &HkZoomIn, &HkZoomOut, &HkZoomRedraw, &HkZoomCenter,
&HkSwitchUnits, &HkResetLocalCoord, &HkSwitchUnits, &HkResetLocalCoord,
NULL NULL
}; };
// List of hotkey descriptors for pcbnew // List of hotkey descriptors for pcbnew
Ki_HotkeyInfo* s_board_edit_Hotkey_List[] = { Ki_HotkeyInfo* s_board_edit_Hotkey_List[] = {
&HkTrackDisplayMode, &HkTrackDisplayMode,
&HkDelete, &HkBackspace, &HkDelete, &HkBackspace,
&HkAddVia, &HkEndTrack, &HkAddVia, &HkEndTrack,
&HkMoveFootprint, &HkFlipFootprint, &HkMoveFootprint, &HkFlipFootprint,
&HkRotateFootprint, &HkDragFootprint, &HkRotateFootprint, &HkDragFootprint,
&HkLock_Unlock_Footprint, &HkLock_Unlock_Footprint,
&HkSavefile, &HkLoadfile, &HkFindItem, &HkSavefile, &HkLoadfile, &HkFindItem,
&HkSwitch2CopperLayer, &HkSwitch2CopperLayer,
&HkSwitch2InnerLayer1, &HkSwitch2InnerLayer1,
&HkSwitch2InnerLayer2, &HkSwitch2InnerLayer2,
...@@ -115,8 +115,8 @@ Ki_HotkeyInfo* s_board_edit_Hotkey_List[] = { ...@@ -115,8 +115,8 @@ Ki_HotkeyInfo* s_board_edit_Hotkey_List[] = {
&HkSwitch2InnerLayer5, &HkSwitch2InnerLayer5,
&HkSwitch2InnerLayer6, &HkSwitch2InnerLayer6,
&HkSwitch2ComponentLayer, &HkSwitch2ComponentLayer,
&HkSwitch2NextCopperLayer, &HkSwitch2NextCopperLayer,
&HkSwitch2PreviousCopperLayer, &HkSwitch2PreviousCopperLayer,
NULL NULL
}; };
...@@ -127,29 +127,31 @@ Ki_HotkeyInfo* s_module_edit_Hotkey_List[] = { ...@@ -127,29 +127,31 @@ Ki_HotkeyInfo* s_module_edit_Hotkey_List[] = {
// list of sections and corresponding hotkey list for pcbnew (used to create an hotkey config file) // list of sections and corresponding hotkey list for pcbnew (used to create an hotkey config file)
struct Ki_HotkeyInfoSectionDescriptor s_Pcbnew_Editor_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Pcbnew_Editor_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, "Common keys"}, {
{ &g_BoardEditorSectionTag, s_board_edit_Hotkey_List, "Board editor keys"}, { &g_CommonSectionTag, s_Common_Hotkey_List, "Common keys" },
{ &g_ModuleEditSectionTag, s_module_edit_Hotkey_List, "Footprint editor keys"}, { &g_BoardEditorSectionTag, s_board_edit_Hotkey_List, "Board editor keys" },
{ NULL, NULL, NULL } { &g_ModuleEditSectionTag, s_module_edit_Hotkey_List, "Footprint editor keys" },
{ NULL, NULL, NULL}
}; };
// list of sections and corresponding hotkey list for the board editor (used to list current hotkeys) // list of sections and corresponding hotkey list for the board editor (used to list current hotkeys)
struct Ki_HotkeyInfoSectionDescriptor s_Board_Editor_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Board_Editor_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, NULL}, {
{ &g_BoardEditorSectionTag, s_board_edit_Hotkey_List, NULL}, { &g_CommonSectionTag, s_Common_Hotkey_List, NULL },
{ NULL, NULL, NULL } { &g_BoardEditorSectionTag, s_board_edit_Hotkey_List, NULL },
{ NULL, NULL, NULL }
}; };
// list of sections and corresponding hotkey list for the footprint editor (used to list current hotkeys) // list of sections and corresponding hotkey list for the footprint editor (used to list current hotkeys)
struct Ki_HotkeyInfoSectionDescriptor s_Module_Editor_Hokeys_Descr[] = { struct Ki_HotkeyInfoSectionDescriptor s_Module_Editor_Hokeys_Descr[] =
{ &g_CommonSectionTag, s_Common_Hotkey_List, NULL}, {
{ &g_ModuleEditSectionTag, s_module_edit_Hotkey_List, NULL}, { &g_CommonSectionTag, s_Common_Hotkey_List, NULL },
{ NULL, NULL, NULL } { &g_ModuleEditSectionTag, s_module_edit_Hotkey_List, NULL },
{ NULL, NULL, NULL }
}; };
/***********************************************************/ /***********************************************************/
void WinEDA_PcbFrame::OnHotKey( wxDC* DC, int hotkey, void WinEDA_PcbFrame::OnHotKey( wxDC* DC, int hotkey,
EDA_BaseStruct* DrawStruct ) EDA_BaseStruct* DrawStruct )
...@@ -182,8 +184,8 @@ void WinEDA_PcbFrame::OnHotKey( wxDC* DC, int hotkey, ...@@ -182,8 +184,8 @@ void WinEDA_PcbFrame::OnHotKey( wxDC* DC, int hotkey,
hotkey += 'A' - 'a'; hotkey += 'A' - 'a';
int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List ); int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List );
if ( CommandCode == HK_NOT_FOUND ) if( CommandCode == HK_NOT_FOUND )
CommandCode = GetCommandCodeFromHotkey( hotkey, s_board_edit_Hotkey_List ); CommandCode = GetCommandCodeFromHotkey( hotkey, s_board_edit_Hotkey_List );
int ll; int ll;
switch( CommandCode ) switch( CommandCode )
...@@ -481,8 +483,8 @@ void WinEDA_ModuleEditFrame::OnHotKey( wxDC* DC, int hotkey, ...@@ -481,8 +483,8 @@ void WinEDA_ModuleEditFrame::OnHotKey( wxDC* DC, int hotkey,
hotkey += 'A' - 'a'; hotkey += 'A' - 'a';
int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List ); int CommandCode = GetCommandCodeFromHotkey( hotkey, s_Common_Hotkey_List );
if ( CommandCode == HK_NOT_FOUND ) if( CommandCode == HK_NOT_FOUND )
CommandCode = GetCommandCodeFromHotkey( hotkey, s_module_edit_Hotkey_List ); CommandCode = GetCommandCodeFromHotkey( hotkey, s_module_edit_Hotkey_List );
switch( CommandCode ) switch( CommandCode )
{ {
......
...@@ -23,7 +23,8 @@ enum hotkey_id_commnand { ...@@ -23,7 +23,8 @@ enum hotkey_id_commnand {
HK_LOCK_UNLOCK_FOOTPRINT, HK_LOCK_UNLOCK_FOOTPRINT,
HK_ADD_VIA, HK_END_TRACK, HK_ADD_VIA, HK_END_TRACK,
HK_SAVE_BOARD, HK_LOAD_BOARD, HK_SAVE_BOARD, HK_LOAD_BOARD,
HK_SWITCH_UNITS, HK_SWITCH_TRACK_DISPLAY_MODE, HK_SWITCH_UNITS,
HK_SWITCH_TRACK_DISPLAY_MODE,
HK_FIND_ITEM, HK_FIND_ITEM,
HK_SWITCH_LAYER_TO_COPPER, HK_SWITCH_LAYER_TO_COPPER,
HK_SWITCH_LAYER_TO_COMPONENT, HK_SWITCH_LAYER_TO_COMPONENT,
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
/* Variables locales */ /* Variables locales */
#define HOTKEY_FILENAME wxT("pcbnew")
/***********************************************************/ /***********************************************************/
void WinEDA_PcbFrame::Process_Config(wxCommandEvent& event) void WinEDA_PcbFrame::Process_Config(wxCommandEvent& event)
...@@ -85,7 +86,7 @@ wxString FullFileName; ...@@ -85,7 +86,7 @@ wxString FullFileName;
case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS: case ID_PREFERENCES_CREATE_CONFIG_HOTKEYS:
FullFileName = DEFAULT_HOTKEY_FILENAME_PATH; FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += wxT("pcbnew"); FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT; FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
WriteHotkeyConfigFile(FullFileName, s_Pcbnew_Editor_Hokeys_Descr, true); WriteHotkeyConfigFile(FullFileName, s_Pcbnew_Editor_Hokeys_Descr, true);
break; break;
...@@ -108,7 +109,7 @@ bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose ) ...@@ -108,7 +109,7 @@ bool Read_Hotkey_Config( WinEDA_DrawFrame * frame, bool verbose )
*/ */
{ {
wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH; wxString FullFileName = DEFAULT_HOTKEY_FILENAME_PATH;
FullFileName += wxT("pcbnew"); FullFileName += HOTKEY_FILENAME;
FullFileName += DEFAULT_HOTKEY_FILENAME_EXT; FullFileName += DEFAULT_HOTKEY_FILENAME_EXT;
return frame->ReadHotkeyConfigFile(FullFileName, s_Pcbnew_Editor_Hokeys_Descr, verbose); return frame->ReadHotkeyConfigFile(FullFileName, s_Pcbnew_Editor_Hokeys_Descr, verbose);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment