diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index a2b9f2adf6..61ea2567ef 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -69,7 +69,24 @@ set( GAL_SRCS gal/cairo/cairo_compositor.cpp ) +set( LEGACY_GAL_SRCS + legacy_gal/block.cpp + legacy_gal/eda_draw_frame.cpp + legacy_gal/other.cpp + ) + +set( LEGACY_WX_SRCS + legacy_wx/block.cpp + legacy_wx/eda_draw_frame.cpp + legacy_wx/eda_draw_panel.cpp + legacy_wx/other.cpp + ) + add_library( gal STATIC ${GAL_SRCS} ) +add_library( legacy_gal STATIC ${LEGACY_GAL_SRCS} ) +add_library( legacy_wx STATIC ${LEGACY_WX_SRCS} ) + +target_include_directories( legacy_wx PUBLIC ../include/legacy_wx ) target_link_libraries( gal ${GLEW_LIBRARIES} @@ -249,7 +266,6 @@ set( COMMON_SRCS bin_mod.cpp bitmap.cpp bitmap_base.cpp - block_commande.cpp build_version.cpp colors_design_settings.cpp colors.cpp @@ -258,11 +274,8 @@ set( COMMON_SRCS config_params.cpp confirm.cpp convert_basic_shapes_to_polygon.cpp - copy_to_clipboard.cpp dialog_shim.cpp displlst.cpp - draw_frame.cpp - draw_panel.cpp draw_graphic_text.cpp dsnlexer.cpp eagle_parser.cpp @@ -326,7 +339,6 @@ set( COMMON_SRCS worksheet.cpp wxdataviewctrl_helpers.cpp xnode.cpp - zoom.cpp ) if( TRUE OR NOT USE_KIWAY_DLLS ) @@ -466,6 +478,11 @@ set_source_files_properties( ${PCB_COMMON_SRCS} PROPERTIES add_library( pcbcommon STATIC ${PCB_COMMON_SRCS} ) +target_include_directories( pcbcommon PUBLIC + ../include/legacy_wx +) + + # auto-generate netlist_lexer.h and netlist_keywords.cpp make_lexer( ${CMAKE_CURRENT_SOURCE_DIR}/netlist.keywords diff --git a/common/copy_to_clipboard.cpp b/common/copy_to_clipboard.cpp deleted file mode 100644 index e8eaefa26c..0000000000 --- a/common/copy_to_clipboard.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 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 - */ - -/** - * @file copy_to_clipboard.cpp - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ); - - -void EDA_DRAW_FRAME::CopyToClipboard( wxCommandEvent& event ) -{ - DrawPageOnClipboard( this ); - - if( event.GetId() == ID_GEN_COPY_BLOCK_TO_CLIPBOARD ) - { - if( GetScreen()->IsBlockActive() ) - m_canvas->SetCursor( wxCursor( (wxStockCursor) m_canvas->GetDefaultCursor() ) ); - - m_canvas->EndMouseCapture(); - } -} - - -/* copy the current page or block to the clipboard , - * to export drawings to other applications (word processing ...) - * This is not suitable for copy command within Eeschema or Pcbnew - */ -bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ) -{ - bool DrawBlock = false; - wxRect DrawArea; - BASE_SCREEN* screen = aFrame->GetCanvas()->GetScreen(); - - if( screen->IsBlockActive() ) - { - DrawBlock = true; - DrawArea.SetX( screen->m_BlockLocate.GetX() ); - DrawArea.SetY( screen->m_BlockLocate.GetY() ); - DrawArea.SetWidth( screen->m_BlockLocate.GetWidth() ); - DrawArea.SetHeight( screen->m_BlockLocate.GetHeight() ); - } - else - DrawArea.SetSize( aFrame->GetPageSizeIU() ); - - // Calculate a reasonable dc size, in pixels, and the dc scale to fit - // the drawings into the dc size - // scale is the ratio resolution (in PPI) / internal units - double ppi = 300; // Use 300 pixels per inch to create bitmap images on start - double inch2Iu = 1000.0 * (double) screen->MilsToIuScalar(); - double scale = ppi / inch2Iu; - - wxSize dcsize = DrawArea.GetSize(); - - int maxdim = std::max( dcsize.x, dcsize.y ); - // the max size in pixels of the bitmap used to byuild the sheet copy - const int maxbitmapsize = 3000; - - while( int( maxdim * scale ) > maxbitmapsize ) - { - ppi = ppi / 1.5; - scale = ppi / inch2Iu; - } - - dcsize.x *= scale; - dcsize.y *= scale; - - // Set draw offset, zoom... to values needed to draw in the memory DC - // after saving initial values: - wxPoint tmp_startvisu = screen->m_StartVisu; - double tmpzoom = screen->GetZoom(); - wxPoint old_org = screen->m_DrawOrg; - screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0; - screen->m_StartVisu.x = screen->m_StartVisu.y = 0; - - screen->SetZoom( 1 ); // we use zoom = 1 in draw functions. - - wxMemoryDC dc; - wxBitmap image( dcsize ); - dc.SelectObject( image ); - - EDA_RECT tmp = *aFrame->GetCanvas()->GetClipBox(); - GRResetPenAndBrush( &dc ); - GRForceBlackPen( false ); - screen->m_IsPrinting = true; - dc.SetUserScale( scale, scale ); - - aFrame->GetCanvas()->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), - wxSize( 0x7FFFFF0, 0x7FFFFF0 ) ) ); - - if( DrawBlock ) - { - dc.SetClippingRegion( DrawArea ); - } - - dc.Clear(); - aFrame->GetCanvas()->EraseScreen( &dc ); - const LSET allLayersMask = LSET().set(); - aFrame->PrintPage( &dc, allLayersMask, false ); - screen->m_IsPrinting = false; - aFrame->GetCanvas()->SetClipBox( tmp ); - - bool success = true; - - if( wxTheClipboard->Open() ) - { - // This data objects are held by the clipboard, - // so do not delete them in the app. - wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image ); - wxTheClipboard->SetData( clipbrd_data ); - wxTheClipboard->Close(); - } - else - success = false; - - // Deselect Bitmap from DC in order to delete the MemoryDC safely - // without deleting the bitmap - dc.SelectObject( wxNullBitmap ); - - GRForceBlackPen( false ); - - screen->m_StartVisu = tmp_startvisu; - screen->m_DrawOrg = old_org; - screen->SetZoom( tmpzoom ); - - return success; -} diff --git a/common/legacy_gal/block.cpp b/common/legacy_gal/block.cpp new file mode 100644 index 0000000000..1968ef23ea --- /dev/null +++ b/common/legacy_gal/block.cpp @@ -0,0 +1,205 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 + */ + +/** + * @file block_commande.cpp + * @brief Common routines for managing on block commands. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +BLOCK_SELECTOR::BLOCK_SELECTOR() : + EDA_RECT() +{ + m_state = STATE_NO_BLOCK; // State (enum BLOCK_STATE_T) of block. + m_command = BLOCK_IDLE; // Type (enum BLOCK_COMMAND_T) of operation. + m_color = BROWN; +} + + +BLOCK_SELECTOR::~BLOCK_SELECTOR() +{ + ClearListAndDeleteItems(); +} + + +void BLOCK_SELECTOR::SetMessageBlock( EDA_DRAW_FRAME* frame ) +{ + wxString msg; + + switch( m_command ) + { + case BLOCK_IDLE: + break; + + case BLOCK_MOVE: // Move + case BLOCK_PRESELECT_MOVE: // Move with preselection list + case BLOCK_MOVE_EXACT: + msg = _( "Block Move" ); + break; + + case BLOCK_DRAG: // Drag + msg = _( "Block Drag" ); + break; + + case BLOCK_DRAG_ITEM: // Drag + msg = _( "Drag item" ); + break; + + case BLOCK_DUPLICATE: // Duplicate + msg = _( "Block Duplicate" ); + break; + + case BLOCK_DELETE: // Delete + msg = _( "Block Delete" ); + break; + + case BLOCK_COPY: // Copy + msg = _( "Block Copy" ); + break; + + case BLOCK_PASTE: + msg = _( "Block Paste" ); + break; + + case BLOCK_ZOOM: // Window Zoom + msg = _( "Zoom to selection" ); + break; + + case BLOCK_ROTATE: // Rotate 90 deg + msg = _( "Block Rotate" ); + break; + + case BLOCK_FLIP: // Flip + msg = _( "Block Flip" ); + break; + + case BLOCK_MIRROR_X: + case BLOCK_MIRROR_Y: // mirror + msg = _( "Block Mirror" ); + break; + + case BLOCK_ABORT: + break; + + default: + msg = wxT( "???" ); + break; + } + + frame->DisplayToolMsg( msg ); +} + + +void BLOCK_SELECTOR::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, + GR_DRAWMODE aDrawMode, COLOR4D aColor ) +{ + if( !aDC ) + return; + + int w = GetWidth(); + int h = GetHeight(); + + GRSetDrawMode( aDC, aDrawMode ); + + if( w == 0 || h == 0 ) + GRLine( aPanel->GetClipBox(), aDC, GetX() + aOffset.x, GetY() + aOffset.y, + GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor ); + else + GRRect( aPanel->GetClipBox(), aDC, GetX() + aOffset.x, GetY() + aOffset.y, + GetRight() + aOffset.x, GetBottom() + aOffset.y, 0, aColor ); +} + + +void BLOCK_SELECTOR::InitData( EDA_DRAW_PANEL* aPanel, const wxPoint& startpos ) +{ + m_state = STATE_BLOCK_INIT; + SetOrigin( startpos ); + SetSize( wxSize( 0, 0 ) ); + m_items.ClearItemsList(); + aPanel->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand ); +} + + +void BLOCK_SELECTOR::ClearItemsList() +{ + m_items.ClearItemsList(); +} + + +void BLOCK_SELECTOR::ClearListAndDeleteItems() +{ + m_items.ClearListAndDeleteItems(); +} + + +void BLOCK_SELECTOR::PushItem( ITEM_PICKER& aItem ) +{ + m_items.PushItem( aItem ); +} + + +void BLOCK_SELECTOR::Clear() +{ + if( m_command != BLOCK_IDLE ) + { + m_command = BLOCK_IDLE; + m_state = STATE_NO_BLOCK; + ClearItemsList(); + } +} + +void AbortBlockCurrentCommand( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) +{ + BASE_SCREEN* screen = aPanel->GetScreen(); + + if( aPanel->IsMouseCaptured() ) // Erase current drawing on screen + { + // Clear block outline. + aPanel->CallMouseCapture( aDC, wxDefaultPosition, false ); + aPanel->SetMouseCapture( NULL, NULL ); + screen->SetCurItem( NULL ); + + // Delete the picked wrapper if this is a picked list. + screen->m_BlockLocate.ClearItemsList(); + } + + screen->m_BlockLocate.SetState( STATE_NO_BLOCK ); + screen->m_BlockLocate.SetCommand( BLOCK_ABORT ); + aPanel->GetParent()->HandleBlockEnd( aDC ); + + screen->m_BlockLocate.SetCommand( BLOCK_IDLE ); + aPanel->GetParent()->DisplayToolMsg( wxEmptyString ); + aPanel->SetDefaultCursor(); +} diff --git a/common/legacy_gal/eda_draw_frame.cpp b/common/legacy_gal/eda_draw_frame.cpp new file mode 100644 index 0000000000..7de58f9b49 --- /dev/null +++ b/common/legacy_gal/eda_draw_frame.cpp @@ -0,0 +1,1767 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2008 Wayne Stambaugh + * Copyright (C) 2004-2018 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 + */ + +/** + * @file draw_frame.cpp + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include "../eeschema/sch_draw_panel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * Definition for enabling and disabling scroll bar setting trace output. See the + * wxWidgets documentation on useing the WXTRACE environment variable. + */ +static const wxString traceScrollSettings( wxT( "KicadScrollSettings" ) ); + + +///@{ +/// \ingroup config + +/// User units +static const wxString UserUnitsEntryKeyword( wxT( "Units" ) ); +static const wxString FpEditorUserUnitsEntryKeyword( wxT( "FpEditorUnits" ) ); +/// Nonzero to show grid (suffix) +static const wxString ShowGridEntryKeyword( wxT( "ShowGrid" ) ); +/// Grid color ID (suffix) +static const wxString GridColorEntryKeyword( wxT( "GridColor" ) ); +/// Most recently used grid size (suffix) +static const wxString LastGridSizeIdKeyword( wxT( "_LastGridSize" ) ); +/// GAL Display Options +static const wxString GalDisplayOptionsKeyword( wxT( "GalDisplayOptions" ) ); + +const wxChar EDA_DRAW_FRAME::CANVAS_TYPE_KEY[] = wxT( "canvas_type" ); + +static const wxString FirstRunShownKeyword( wxT( "FirstRunShown" ) ); + +///@} + +/** + * Integer to set the maximum number of undo items on the stack. If zero, + * undo items are unlimited. + * + * Present as: + * + * - SchematicFrameDevelMaxUndoItems (file: eeschema) + * - LibeditFrameDevelMaxUndoItems (file: eeschema) + * - PcbFrameDevelMaxUndoItems (file: pcbnew) + * - ModEditFrameDevelMaxUndoItems (file: pcbnew) + * + * \ingroup develconfig + */ +static const wxString MaxUndoItemsEntry(wxT( "DevelMaxUndoItems" ) ); + +BEGIN_EVENT_TABLE( EDA_DRAW_FRAME, KIWAY_PLAYER ) + EVT_CHAR_HOOK( EDA_DRAW_FRAME::OnCharHook ) + + EVT_MOUSEWHEEL( EDA_DRAW_FRAME::OnMouseEvent ) + EVT_MENU_OPEN( EDA_DRAW_FRAME::OnMenuOpen ) + EVT_ACTIVATE( EDA_DRAW_FRAME::OnActivate ) + EVT_MENU_RANGE( ID_ZOOM_BEGIN, ID_ZOOM_END, EDA_DRAW_FRAME::OnZoom ) + + EVT_MENU_RANGE( ID_POPUP_ZOOM_START_RANGE, ID_POPUP_ZOOM_END_RANGE, + EDA_DRAW_FRAME::OnZoom ) + + EVT_MENU_RANGE( ID_POPUP_GRID_LEVEL_1000, ID_POPUP_GRID_USER, + EDA_DRAW_FRAME::OnSelectGrid ) + + EVT_TOOL( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnToggleGridState ) + EVT_TOOL_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH, + EDA_DRAW_FRAME::OnSelectUnits ) + + EVT_TOOL( ID_TB_OPTIONS_SELECT_CURSOR, EDA_DRAW_FRAME::OnToggleCrossHairStyle ) + + EVT_UPDATE_UI( wxID_UNDO, EDA_DRAW_FRAME::OnUpdateUndo ) + EVT_UPDATE_UI( wxID_REDO, EDA_DRAW_FRAME::OnUpdateRedo ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_GRID, EDA_DRAW_FRAME::OnUpdateGrid ) + EVT_UPDATE_UI( ID_TB_OPTIONS_SELECT_CURSOR, EDA_DRAW_FRAME::OnUpdateCrossHairStyle ) + EVT_UPDATE_UI_RANGE( ID_TB_OPTIONS_SELECT_UNIT_MM, ID_TB_OPTIONS_SELECT_UNIT_INCH, + EDA_DRAW_FRAME::OnUpdateUnits ) +END_EVENT_TABLE() + + +EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, + FRAME_T aFrameType, + const wxString& aTitle, + const wxPoint& aPos, const wxSize& aSize, + long aStyle, const wxString & aFrameName ) : + KIWAY_PLAYER( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ), + m_galDisplayOptions( std::make_unique() ) +{ + m_useSingleCanvasPane = false; + m_socketServer = nullptr; + m_drawToolBar = NULL; + m_optionsToolBar = NULL; + m_auxiliaryToolBar = NULL; + m_gridSelectBox = NULL; + m_zoomSelectBox = NULL; + m_hotkeysDescrList = NULL; + + m_canvas = NULL; + m_canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + m_canvasTypeDirty = false; + m_galCanvas = NULL; + m_galCanvasActive = false; + m_actions = NULL; + m_toolManager = NULL; + m_toolDispatcher = NULL; + m_messagePanel = NULL; + m_currentScreen = NULL; + m_toolId = ID_NO_TOOL_SELECTED; + m_lastDrawToolId = ID_NO_TOOL_SELECTED; + m_showAxis = false; // true to draw axis. + m_showBorderAndTitleBlock = false; // true to display reference sheet. + m_showGridAxis = false; // true to draw the grid axis + m_showOriginAxis = false; // true to draw the grid origin + m_LastGridSizeId = 0; + m_drawGrid = true; // hide/Show grid. default = show + m_gridColor = COLOR4D( DARKGRAY ); // Default grid color + m_showPageLimits = false; + m_drawBgColor = COLOR4D( BLACK ); // the background color of the draw canvas: + // BLACK for Pcbnew, BLACK or WHITE for eeschema + m_snapToGrid = true; + m_MsgFrameHeight = EDA_MSG_PANEL::GetRequiredHeight(); + m_movingCursorWithKeyboard = false; + m_zoomLevelCoeff = 1.0; + + m_auimgr.SetFlags(wxAUI_MGR_DEFAULT); + + CreateStatusBar( 6 ); + + // set the size of the status bar subwindows: + + wxWindow* stsbar = GetStatusBar(); + + int dims[] = { + + // remainder of status bar on far left is set to a default or whatever is left over. + -1, + + // When using GetTextSize() remember the width of character '1' is not the same + // as the width of '0' unless the font is fixed width, and it usually won't be. + + // zoom: + GetTextSize( wxT( "Z 762000" ), stsbar ).x + 10, + + // cursor coords + GetTextSize( wxT( "X 0234.567890 Y 0234.567890" ), stsbar ).x + 10, + + // delta distances + GetTextSize( wxT( "dx 0234.567890 dx 0234.567890 d 0234.567890" ), stsbar ).x + 10, + + // units display, Inches is bigger than mm + GetTextSize( _( "Inches" ), stsbar ).x + 10, + + // Size for the panel used as "Current tool in play": will take longest string from + // void PCB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent ) in pcbnew/edit.cpp + GetTextSize( wxT( "Add layer alignment target" ), stsbar ).x + 10, + }; + + SetStatusWidths( DIM( dims ), dims ); + + // Create child subwindows. + GetClientSize( &m_FrameSize.x, &m_FrameSize.y ); + m_FramePos.x = m_FramePos.y = 0; + m_FrameSize.y -= m_MsgFrameHeight; + + printf("calling createCanvas\n"); + createCanvas(); + printf("Canvas %p\n", m_canvas); + + m_messagePanel = new EDA_MSG_PANEL( this, -1, wxPoint( 0, m_FrameSize.y ), + wxSize( m_FrameSize.x, m_MsgFrameHeight ) ); + + m_messagePanel->SetBackgroundColour( COLOR4D( LIGHTGRAY ).ToColour() ); +} + +EDA_DRAW_FRAME::~EDA_DRAW_FRAME() +{ + delete m_socketServer; + for( auto socket : m_sockets ) + { + socket->Shutdown(); + socket->Destroy(); + } + + if( m_canvasTypeDirty ) + saveCanvasTypeSetting( m_canvasType ); + + delete m_actions; + delete m_toolManager; + delete m_toolDispatcher; + delete m_galCanvas; + + delete m_currentScreen; + m_currentScreen = NULL; + + m_auimgr.UnInit(); + + ReleaseFile(); +} + + +void EDA_DRAW_FRAME::OnCharHook( wxKeyEvent& event ) +{ + wxLogTrace( kicadTraceKeyEvent, "EDA_DRAW_FRAME::OnCharHook %s", dump( event ) ); + // Key events can be filtered here. + // Currently no filtering is made. + event.Skip(); +} + + +void EDA_DRAW_FRAME::ReleaseFile() +{ + m_file_checker = nullptr; +} + + +bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName ) +{ + m_file_checker = ::LockFile( aFileName ); + + return bool( m_file_checker ); +} + + +void EDA_DRAW_FRAME::unitsChangeRefresh() +{ + UpdateStatusBar(); + UpdateMsgPanel(); +} + +void EDA_DRAW_FRAME::CommonSettingsChanged() +{ + EDA_BASE_FRAME::CommonSettingsChanged(); + + bool option; + Pgm().CommonSettings()->Read( ENBL_MOUSEWHEEL_PAN_KEY, &option ); + m_canvas->SetEnableMousewheelPan( option ); + + Pgm().CommonSettings()->Read( ENBL_ZOOM_NO_CENTER_KEY, &option ); + m_canvas->SetEnableZoomNoCenter( option ); + + Pgm().CommonSettings()->Read( ENBL_AUTO_PAN_KEY, &option ); + m_canvas->SetEnableAutoPan( option ); +} + + +void EDA_DRAW_FRAME::EraseMsgBox() +{ + if( m_messagePanel ) + m_messagePanel->EraseMsgBox(); +} + + +void EDA_DRAW_FRAME::OnActivate( wxActivateEvent& event ) +{ + if( m_canvas ) + m_canvas->SetCanStartBlock( -1 ); + + event.Skip(); // required under wxMAC +} + + +void EDA_DRAW_FRAME::OnMenuOpen( wxMenuEvent& event ) +{ + if( m_canvas ) + m_canvas->SetCanStartBlock( -1 ); + + event.Skip(); +} + + +void EDA_DRAW_FRAME::SkipNextLeftButtonReleaseEvent() +{ + m_canvas->SetIgnoreLeftButtonReleaseEvent( true ); +} + + +void EDA_DRAW_FRAME::OnToggleGridState( wxCommandEvent& aEvent ) +{ + SetGridVisibility( !IsGridVisible() ); + + if( IsGalCanvasActive() ) + { + GetGalCanvas()->GetGAL()->SetGridVisibility( IsGridVisible() ); + GetGalCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); + } + + m_canvas->Refresh(); +} + +bool EDA_DRAW_FRAME::GetToolToggled( int aToolId ) +{ + // Checks all the toolbars and returns true if the given tool id is toggled. + return ( ( m_mainToolBar && m_mainToolBar->GetToolToggled( aToolId ) ) || + ( m_optionsToolBar && m_optionsToolBar->GetToolToggled( aToolId ) ) || + ( m_drawToolBar && m_drawToolBar->GetToolToggled( aToolId ) ) || + ( m_auxiliaryToolBar && m_auxiliaryToolBar->GetToolToggled( aToolId ) ) + ); +} + + +wxAuiToolBarItem* EDA_DRAW_FRAME::GetToolbarTool( int aToolId ) +{ + // Checks all the toolbars and returns a reference to the given tool id + // (or the first tool found, but only one or 0 tool is expected, because on + // Windows, when different tools have the same ID, it creates issues) + if( m_mainToolBar && m_mainToolBar->FindTool( aToolId ) ) + return m_mainToolBar->FindTool( aToolId ); + + if( m_optionsToolBar && m_optionsToolBar->FindTool( aToolId ) ) + return m_optionsToolBar->FindTool( aToolId ); + + if( m_drawToolBar && m_drawToolBar->FindTool( aToolId ) ) + return m_drawToolBar->FindTool( aToolId ); + + if( m_auxiliaryToolBar && m_auxiliaryToolBar->FindTool( aToolId ) ) + return m_auxiliaryToolBar->FindTool( aToolId ); + + return nullptr; +} + + +void EDA_DRAW_FRAME::OnSelectUnits( wxCommandEvent& aEvent ) +{ + if( aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MM && m_UserUnits != MILLIMETRES ) + { + m_UserUnits = MILLIMETRES; + unitsChangeRefresh(); + } + else if( aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH && m_UserUnits != INCHES ) + { + m_UserUnits = INCHES; + unitsChangeRefresh(); + } +} + + +void EDA_DRAW_FRAME::OnToggleCrossHairStyle( wxCommandEvent& aEvent ) +{ + auto& galOpts = GetGalDisplayOptions(); + galOpts.m_fullscreenCursor = !galOpts.m_fullscreenCursor; + galOpts.NotifyChanged(); + + auto canvas = GetCanvas(); + + canvas->CrossHairOff( ); + canvas->CrossHairOn( ); +} + + +void EDA_DRAW_FRAME::OnUpdateUndo( wxUpdateUIEvent& aEvent ) +{ + if( GetScreen() ) + aEvent.Enable( GetScreen()->GetUndoCommandCount() > 0 ); +} + + +void EDA_DRAW_FRAME::OnUpdateRedo( wxUpdateUIEvent& aEvent ) +{ + if( GetScreen() ) + aEvent.Enable( GetScreen()->GetRedoCommandCount() > 0 ); +} + + +void EDA_DRAW_FRAME::OnUpdateUnits( wxUpdateUIEvent& aEvent ) +{ + bool enable; + + enable = ( ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_MM) && (m_UserUnits == MILLIMETRES)) + || ((aEvent.GetId() == ID_TB_OPTIONS_SELECT_UNIT_INCH) && (m_UserUnits == INCHES)) ); + + aEvent.Check( enable ); + DisplayUnitsMsg(); +} + + +void EDA_DRAW_FRAME::OnUpdateGrid( wxUpdateUIEvent& aEvent ) +{ + wxString tool_tip = IsGridVisible() ? _( "Hide grid" ) : _( "Show grid" ); + + aEvent.Check( IsGridVisible() ); + m_optionsToolBar->SetToolShortHelp( ID_TB_OPTIONS_SHOW_GRID, tool_tip ); +} + + +void EDA_DRAW_FRAME::OnUpdateCrossHairStyle( wxUpdateUIEvent& aEvent ) +{ + aEvent.Check( GetGalDisplayOptions().m_fullscreenCursor ); +} + + +void EDA_DRAW_FRAME::ReCreateAuxiliaryToolbar() +{ +} + + +void EDA_DRAW_FRAME::ReCreateMenuBar() +{ +} + + +bool EDA_DRAW_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition, EDA_ITEM* aItem ) +{ + return false; +} + +int EDA_DRAW_FRAME::WriteHotkeyConfig( struct EDA_HOTKEY_CONFIG* aDescList, wxString* aFullFileName ) +{ + int result = EDA_BASE_FRAME::WriteHotkeyConfig( aDescList, aFullFileName ); + + if( IsGalCanvasActive() ) + GetToolManager()->UpdateHotKeys(); + + return result; +} + +void EDA_DRAW_FRAME::ToolOnRightClick( wxCommandEvent& event ) +{ +} + + +void EDA_DRAW_FRAME::PrintPage( wxDC* aDC, LSET aPrintMask, bool aPrintMirrorMode, void* aData ) +{ + wxMessageBox( wxT("EDA_DRAW_FRAME::PrintPage() error") ); +} + + +void EDA_DRAW_FRAME::OnSelectGrid( wxCommandEvent& event ) +{ + int* clientData; + int eventId = ID_POPUP_GRID_LEVEL_100; + + if( event.GetEventType() == wxEVT_CHOICE ) + { + if( m_gridSelectBox == NULL ) // Should not happen + return; + + /* + * Don't use wxCommandEvent::GetClientData() here. It always + * returns NULL in GTK. This solution is not as elegant but + * it works. + */ + int index = m_gridSelectBox->GetSelection(); + wxASSERT( index != wxNOT_FOUND ); + clientData = (int*) m_gridSelectBox->wxItemContainer::GetClientData( index ); + + if( clientData != NULL ) + eventId = *clientData; + } + else + { + eventId = event.GetId(); + } + + int idx = eventId - ID_POPUP_GRID_LEVEL_1000; + + // Notify GAL + TOOL_MANAGER* mgr = GetToolManager(); + + if( mgr && IsGalCanvasActive() ) + { + mgr->RunAction( "common.Control.gridPreset", true, idx ); + } + else + SetPresetGrid( idx ); + + m_canvas->Refresh(); +} + + +void EDA_DRAW_FRAME::OnSelectZoom( wxCommandEvent& event ) +{ + if( m_zoomSelectBox == NULL ) + return; // Should not happen! + + int id = m_zoomSelectBox->GetCurrentSelection(); + + if( id < 0 || !( id < (int)m_zoomSelectBox->GetCount() ) ) + return; + + if( id == 0 ) // Auto zoom (Fit in Page) + { + Zoom_Automatique( true ); + } + else + { + double selectedZoom = GetScreen()->m_ZoomList[id-1]; + + if( GetScreen()->GetZoom() == selectedZoom ) + return; + + GetScreen()->SetZoom( selectedZoom ); + RedrawScreen( GetScrollCenterPosition(), false ); + } + + // Notify GAL + TOOL_MANAGER* mgr = GetToolManager(); + + if( mgr && IsGalCanvasActive() ) + { + mgr->RunAction( "common.Control.zoomPreset", true, id ); + UpdateStatusBar(); + } +} + + +double EDA_DRAW_FRAME::GetZoom() +{ + return GetScreen()->GetZoom(); +} + + +void EDA_DRAW_FRAME::OnMouseEvent( wxMouseEvent& event ) +{ + event.Skip(); +} + + +void EDA_DRAW_FRAME::OnLeftDClick( wxDC* DC, const wxPoint& MousePos ) +{ +} + + +void EDA_DRAW_FRAME::DisplayToolMsg( const wxString& msg ) +{ + SetStatusText( msg, 5 ); +} + + +void EDA_DRAW_FRAME::DisplayUnitsMsg() +{ + wxString msg; + + switch( m_UserUnits ) + { + case INCHES: + msg = _( "Inches" ); + break; + + case MILLIMETRES: + msg = _( "mm" ); + break; + + default: + msg = _( "Units" ); + break; + } + + SetStatusText( msg, 4 ); +} + + + +void EDA_DRAW_FRAME::OnSize( wxSizeEvent& SizeEv ) +{ + m_FrameSize = GetClientSize( ); + + SizeEv.Skip(); +} + + +void EDA_DRAW_FRAME::SetToolID( int aId, int aCursor, const wxString& aToolMsg ) +{ + // Keep default cursor in toolbars + SetCursor( wxNullCursor ); + + // Change m_canvas cursor if requested. + if( m_canvas && aCursor >= 0 ) + m_canvas->SetCurrentCursor( aCursor ); + + // Change GAL canvas cursor if requested. + if( IsGalCanvasActive() && aCursor >= 0 ) + GetGalCanvas()->SetCurrentCursor( aCursor ); + + DisplayToolMsg( aToolMsg ); + + if( aId < 0 ) + return; + + wxCHECK2_MSG( aId >= ID_NO_TOOL_SELECTED, aId = ID_NO_TOOL_SELECTED, + wxString::Format( wxT( "Current tool ID cannot be set to %d." ), aId ) ); + + m_toolId = aId; +} + + +void EDA_DRAW_FRAME::SetNoToolSelected() +{ + // Select the ID_NO_TOOL_SELECTED id tool (Idle tool) + + int defaultCursor = wxCURSOR_DEFAULT; + + // Change GAL canvas cursor if requested. + if( IsGalCanvasActive() ) + defaultCursor = GetGalCanvas()->GetDefaultCursor(); + else if( m_canvas ) + defaultCursor = m_canvas->GetDefaultCursor(); + + SetToolID( ID_NO_TOOL_SELECTED, defaultCursor, wxEmptyString ); +} + +wxPoint EDA_DRAW_FRAME::GetGridPosition( const wxPoint& aPosition ) const +{ + wxPoint pos = aPosition; + + if( m_currentScreen != NULL && m_snapToGrid ) + pos = GetNearestGridPosition( aPosition ); + + return pos; +} + + +void EDA_DRAW_FRAME::SetNextGrid() +{ + BASE_SCREEN * screen = GetScreen(); + + int new_grid_cmd = screen->GetGridCmdId(); + + // if the grid id is the not the last, increment it + if( screen->GridExists( new_grid_cmd + 1 ) ) + new_grid_cmd += 1; + + SetPresetGrid( new_grid_cmd - ID_POPUP_GRID_LEVEL_1000 ); +} + + +void EDA_DRAW_FRAME::SetPrevGrid() +{ + BASE_SCREEN * screen = GetScreen(); + + int new_grid_cmd = screen->GetGridCmdId(); + + // if the grid id is the not the first, increment it + if( screen->GridExists( new_grid_cmd - 1 ) ) + new_grid_cmd -= 1; + + SetPresetGrid( new_grid_cmd - ID_POPUP_GRID_LEVEL_1000 ); +} + + +void EDA_DRAW_FRAME::SetPresetGrid( int aIndex ) +{ + BASE_SCREEN * screen = GetScreen(); + + if( ! screen->GridExists( aIndex + ID_POPUP_GRID_LEVEL_1000 ) ) + aIndex = screen->GetGrids()[0].m_CmdId; + + // aIndex is a Command Id relative to ID_POPUP_GRID_LEVEL_1000 comand id code. + // we need an index in grid list (the cmd id in list is is screen->GetGrids()[0].m_CmdId): + int glistIdx = aIndex + ID_POPUP_GRID_LEVEL_1000 - screen->GetGrids()[0].m_CmdId; + + if( m_gridSelectBox ) + { + if( glistIdx < 0 || glistIdx >= (int) m_gridSelectBox->GetCount() ) + { + wxASSERT_MSG( false, "Invalid grid index" ); + return; + } + + m_gridSelectBox->SetSelection( glistIdx ); + } + + // Be sure m_LastGridSizeId is up to date. + m_LastGridSizeId = aIndex; + GetScreen()->SetGrid( aIndex + ID_POPUP_GRID_LEVEL_1000 ); + + // Put cursor on new grid + SetCrossHairPosition( RefPos( true ) ); +} + + +int EDA_DRAW_FRAME::BlockCommand( EDA_KEY key ) +{ + return 0; +} + + +void EDA_DRAW_FRAME::InitBlockPasteInfos() +{ + GetScreen()->m_BlockLocate.ClearItemsList(); + m_canvas->SetMouseCaptureCallback( NULL ); +} + + +void EDA_DRAW_FRAME::HandleBlockPlace( wxDC* DC ) +{ +} + + +bool EDA_DRAW_FRAME::HandleBlockEnd( wxDC* DC ) +{ + return false; +} + + +void EDA_DRAW_FRAME::UpdateStatusBar() +{ + SetStatusText( GetZoomLevelIndicator(), 1 ); + + // Absolute and relative cursor positions are handled by overloading this function and + // handling the internal to user units conversion at the appropriate level. + + // refresh units display + DisplayUnitsMsg(); +} + +const wxString EDA_DRAW_FRAME::GetZoomLevelIndicator() const +{ + wxString Line; + double level = 0.0; + + if( IsGalCanvasActive() ) + { + KIGFX::GAL* gal = m_galCanvas->GetGAL(); + KIGFX::VIEW* view = m_galCanvas->GetView(); + double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); + level = m_zoomLevelCoeff * zoomFactor * view->GetScale(); + } + else if( BASE_SCREEN* screen = GetScreen() ) + { + level = m_zoomLevelCoeff / (double) screen->GetZoom(); + } + + // returns a human readable value which can be displayed as zoom + // level indicator in dialogs. + Line.Printf( wxT( "Z %.2f" ), level ); + + return Line; +} + + +void EDA_DRAW_FRAME::LoadSettings( wxConfigBase* aCfg ) +{ + EDA_BASE_FRAME::LoadSettings( aCfg ); + + wxString baseCfgName = ConfigBaseName(); + + // Read units used in dialogs and toolbars + EDA_UNITS_T unitsTmp; + + if( aCfg->Read( baseCfgName + UserUnitsEntryKeyword, (int*) &unitsTmp ) ) + SetUserUnits( unitsTmp ); + else + SetUserUnits( MILLIMETRES ); + + // Read show/hide grid entry + bool btmp; + if( aCfg->Read( baseCfgName + ShowGridEntryKeyword, &btmp ) ) + SetGridVisibility( btmp ); + + // Read grid color: + COLOR4D wtmp = COLOR4D::UNSPECIFIED; + + if( wtmp.SetFromWxString( aCfg->Read( + baseCfgName + GridColorEntryKeyword, wxT( "NONE" ) ) ) ) + SetGridColor( wtmp ); + + aCfg->Read( baseCfgName + LastGridSizeIdKeyword, &m_LastGridSizeId, 0L ); + + // m_LastGridSizeId is an offset, expected to be >= 0 + if( m_LastGridSizeId < 0 ) + m_LastGridSizeId = 0; + + m_UndoRedoCountMax = aCfg->Read( baseCfgName + MaxUndoItemsEntry, + long( DEFAULT_MAX_UNDO_ITEMS ) ); + + aCfg->Read( baseCfgName + FirstRunShownKeyword, &m_firstRunDialogSetting, 0L ); + + m_galDisplayOptions->ReadConfig( aCfg, baseCfgName + GalDisplayOptionsKeyword ); +} + + +void EDA_DRAW_FRAME::SaveSettings( wxConfigBase* aCfg ) +{ + EDA_BASE_FRAME::SaveSettings( aCfg ); + + wxString baseCfgName = ConfigBaseName(); + + aCfg->Write( baseCfgName + UserUnitsEntryKeyword, (int) m_UserUnits ); + aCfg->Write( baseCfgName + ShowGridEntryKeyword, IsGridVisible() ); + aCfg->Write( baseCfgName + GridColorEntryKeyword, + GetGridColor().ToColour().GetAsString( wxC2S_CSS_SYNTAX ) ); + aCfg->Write( baseCfgName + LastGridSizeIdKeyword, ( long ) m_LastGridSizeId ); + aCfg->Write( baseCfgName + FirstRunShownKeyword, m_firstRunDialogSetting ); + + if( GetScreen() ) + aCfg->Write( baseCfgName + MaxUndoItemsEntry, long( GetScreen()->GetMaxUndoItems() ) ); + + m_galDisplayOptions->WriteConfig( aCfg, baseCfgName + GalDisplayOptionsKeyword ); +} + + +void EDA_DRAW_FRAME::AppendMsgPanel( const wxString& textUpper, + const wxString& textLower, + COLOR4D color, int pad ) +{ + if( m_messagePanel == NULL ) + return; + + m_messagePanel->AppendMessage( textUpper, textLower, color, pad ); +} + + +void EDA_DRAW_FRAME::ClearMsgPanel() +{ + if( m_messagePanel == NULL ) + return; + + m_messagePanel->EraseMsgBox(); +} + + +void EDA_DRAW_FRAME::SetMsgPanel( const MSG_PANEL_ITEMS& aList ) +{ + if( m_messagePanel == NULL ) + return; + + ClearMsgPanel(); + + for( unsigned i = 0; i < aList.size(); i++ ) + m_messagePanel->AppendMessage( aList[i] ); +} + + +void EDA_DRAW_FRAME::SetMsgPanel( EDA_ITEM* aItem ) +{ + wxCHECK_RET( aItem != NULL, wxT( "Invalid EDA_ITEM pointer. Bad programmer." ) ); + + MSG_PANEL_ITEMS items; + aItem->GetMsgPanelInfo( m_UserUnits, items ); + SetMsgPanel( items ); +} + + +void EDA_DRAW_FRAME::UpdateMsgPanel() +{ + EDA_ITEM* item = GetScreen()->GetCurItem(); + + if( item ) + SetMsgPanel( item ); +} + +// FIXME: There needs to be a better way for child windows to load preferences. +// This function pushes four preferences from a parent window to a child window +// i.e. from eeschema to the schematic symbol editor +void EDA_DRAW_FRAME::PushPreferences( const EDA_DRAW_PANEL* aParentCanvas ) +{ + m_canvas->SetEnableZoomNoCenter( aParentCanvas->GetEnableZoomNoCenter() ); + m_canvas->SetEnableAutoPan( aParentCanvas->GetEnableAutoPan() ); +} + +bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* aDC, EDA_KEY aKey, const wxPoint& aPosition, + int aExplicitCommand ) +{ + BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate; + + if( ( block->GetCommand() != BLOCK_IDLE ) || ( block->GetState() != STATE_NO_BLOCK ) ) + return false; + + if( aExplicitCommand == 0 ) + block->SetCommand( (BLOCK_COMMAND_T) BlockCommand( aKey ) ); + else + block->SetCommand( (BLOCK_COMMAND_T) aExplicitCommand ); + + if( block->GetCommand() == 0 ) + return false; + + switch( block->GetCommand() ) + { + case BLOCK_IDLE: + break; + + case BLOCK_MOVE: // Move + case BLOCK_DRAG: // Drag (block defined) + case BLOCK_DRAG_ITEM: // Drag from a drag item command + case BLOCK_DUPLICATE: // Duplicate + case BLOCK_DUPLICATE_AND_INCREMENT: // Duplicate and increment relevant references + case BLOCK_DELETE: // Delete + case BLOCK_COPY: // Copy + case BLOCK_ROTATE: // Rotate 90 deg + case BLOCK_FLIP: // Flip + case BLOCK_ZOOM: // Window Zoom + case BLOCK_MIRROR_X: + case BLOCK_MIRROR_Y: // mirror + case BLOCK_PRESELECT_MOVE: // Move with preselection list + block->InitData( m_canvas, aPosition ); + break; + + case BLOCK_PASTE: + block->InitData( m_canvas, aPosition ); + block->SetLastCursorPosition( wxPoint( 0, 0 ) ); + InitBlockPasteInfos(); + + if( block->GetCount() == 0 ) // No data to paste + { + DisplayError( this, wxT( "No block to paste" ), 20 ); + GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE ); + m_canvas->SetMouseCaptureCallback( NULL ); + block->SetState( STATE_NO_BLOCK ); + block->SetMessageBlock( this ); + return true; + } + + if( !m_canvas->IsMouseCaptured() ) + { + block->ClearItemsList(); + DisplayError( this, + wxT( "EDA_DRAW_FRAME::HandleBlockBegin() Err: m_mouseCaptureCallback NULL" ) ); + block->SetState( STATE_NO_BLOCK ); + block->SetMessageBlock( this ); + return true; + } + + block->SetState( STATE_BLOCK_MOVE ); + m_canvas->CallMouseCapture( aDC, aPosition, false ); + break; + + default: + { + wxString msg; + msg << wxT( "EDA_DRAW_FRAME::HandleBlockBegin() error: Unknown command " ) << + block->GetCommand(); + DisplayError( this, msg ); + } + break; + } + + block->SetMessageBlock( this ); + return true; +} + + +// I am not seeing a problem with this size yet: +static const double MAX_AXIS = INT_MAX - 100; + +#define VIRT_MIN (-MAX_AXIS/2.0) ///< min X or Y coordinate in virtual space +#define VIRT_MAX (MAX_AXIS/2.0) ///< max X or Y coordinate in virtual space + + +void EDA_DRAW_FRAME::AdjustScrollBars( const wxPoint& aCenterPositionIU ) +{ +} + + +void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable ) +{ + KIGFX::VIEW* view = GetGalCanvas()->GetView(); + KIGFX::GAL* gal = GetGalCanvas()->GetGAL(); + + // Display the same view after canvas switching + if( aEnable ) + { + // Switch to GAL renderer from legacy + if( !m_galCanvasActive ) + { + // Set up viewport + double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); + double zoom = 1.0 / ( zoomFactor * m_canvas->GetZoom() ); + view->SetScale( zoom ); + view->SetCenter( VECTOR2D( m_canvas->GetScreenCenterLogicalPosition() ) ); + } + + // fixme-gal + gal->SetGridVisibility( true ); + gal->SetGridColor( COLOR4D(0.0,0.0,0.0,1.0)); + + + // Transfer EDA_DRAW_PANEL settings + GetGalCanvas()->GetViewControls()->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() ); + GetGalCanvas()->GetViewControls()->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() ); + GetGalCanvas()->GetViewControls()->EnableAutoPan( m_canvas->GetEnableAutoPan() ); + } + else if( m_galCanvasActive ) + { + // Switch to legacy renderer from GAL + double zoomFactor = gal->GetWorldScale() / gal->GetZoomFactor(); + // TODO replace it with EDA_DRAW_PANEL_GAL::GetLegacyZoom + m_canvas->SetZoom( 1.0 / ( zoomFactor * view->GetScale() ) ); + VECTOR2D center = view->GetCenter(); + AdjustScrollBars( wxPoint( center.x, center.y ) ); + } + + GetGalCanvas()->SetEvtHandlerEnabled( aEnable ); + + + // Reset current tool on switch(); + SetNoToolSelected(); + + m_galCanvasActive = aEnable; +} + + +bool EDA_DRAW_FRAME::SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) +{ + auto galCanvas = GetGalCanvas(); + wxCHECK( galCanvas, false ); + bool use_gal = galCanvas->SwitchBackend( aCanvasType ); + use_gal &= aCanvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + UseGalCanvas( use_gal ); + m_canvasType = use_gal ? aCanvasType : EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + m_canvasTypeDirty = true; + + return use_gal; +} + + +EDA_DRAW_PANEL_GAL::GAL_TYPE EDA_DRAW_FRAME::loadCanvasTypeSetting() const +{ + EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + wxConfigBase* cfg = Kiface().KifaceSettings(); + + if( cfg ) + canvasType = (EDA_DRAW_PANEL_GAL::GAL_TYPE) cfg->ReadLong( CANVAS_TYPE_KEY, + EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE ); + + if( canvasType < EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE + || canvasType >= EDA_DRAW_PANEL_GAL::GAL_TYPE_LAST ) + { + assert( false ); + canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + } + + return canvasType; +} + + +bool EDA_DRAW_FRAME::saveCanvasTypeSetting( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) +{ + if( aCanvasType < EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE + || aCanvasType >= EDA_DRAW_PANEL_GAL::GAL_TYPE_LAST ) + { + assert( false ); + return false; + } + + wxConfigBase* cfg = Kiface().KifaceSettings(); + + if( cfg ) + return cfg->Write( CANVAS_TYPE_KEY, (long) aCanvasType ); + + return false; +} + +//-----< BASE_SCREEN API moved here >-------------------------------------------- + +wxPoint EDA_DRAW_FRAME::GetCrossHairPosition( bool aInvertY ) const +{ + + printf("GetCrossHairPos\n"); + // subject to change, borrow from old BASE_SCREEN for now. + if( IsGalCanvasActive() ) + { + VECTOR2I cursor = GetGalCanvas()->GetViewControls()->GetCursorPosition(); + + printf("gal %d %d\n", cursor.x, cursor.y ); + + return wxPoint( cursor.x, aInvertY ? -cursor.y : cursor.y ); + } + else + { + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->getCrossHairPosition( aInvertY ); + } +} + + +void EDA_DRAW_FRAME::SetCrossHairPosition( const wxPoint& aPosition, bool aSnapToGrid ) +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + screen->setCrossHairPosition( aPosition, GetGridOrigin(), aSnapToGrid ); +} + + +wxPoint EDA_DRAW_FRAME::GetCursorPosition( bool aOnGrid, wxRealPoint* aGridSize ) const +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->getCursorPosition( aOnGrid, GetGridOrigin(), aGridSize ); +} + + +wxPoint EDA_DRAW_FRAME::GetNearestGridPosition( const wxPoint& aPosition, wxRealPoint* aGridSize ) const +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->getNearestGridPosition( aPosition, GetGridOrigin(), aGridSize ); +} + + +wxPoint EDA_DRAW_FRAME::GetCrossHairScreenPosition() const +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->getCrossHairScreenPosition(); +} + + +void EDA_DRAW_FRAME::SetMousePosition( const wxPoint& aPosition ) +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + screen->setMousePosition( aPosition ); +} + + +wxPoint EDA_DRAW_FRAME::RefPos( bool useMouse ) const +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->refPos( useMouse ); +} + + +const wxPoint& EDA_DRAW_FRAME::GetScrollCenterPosition() const +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + return screen->getScrollCenterPosition(); +} + + +void EDA_DRAW_FRAME::SetScrollCenterPosition( const wxPoint& aPoint ) +{ + BASE_SCREEN* screen = GetScreen(); // virtual call + screen->setScrollCenterPosition( aPoint ); +} + +//------------------------------------------------- + +void EDA_DRAW_FRAME::RefreshCrossHair( const wxPoint &aOldPos, + const wxPoint &aEvtPos, + wxDC* aDC ) +{ + wxPoint newpos = GetCrossHairPosition(); + + + // Redraw the crosshair if it moved + //if( aOldPos != newpos ) + { + SetCrossHairPosition( aOldPos, false ); + m_canvas->CrossHairOff( aDC ); + SetCrossHairPosition( newpos, false ); + m_canvas->CrossHairOn( aDC ); + + if( m_canvas->IsMouseCaptured() ) + { + m_canvas->CallMouseCapture( aDC, aEvtPos, true ); + } + } +} + +bool EDA_DRAW_FRAME::GeneralControlKeyMovement( int aHotKey, wxPoint *aPos, + bool aSnapToGrid ) +{ + bool key_handled = false; + + // If requested snap the current position to the grid + if( aSnapToGrid ) + *aPos = GetNearestGridPosition( *aPos ); + + switch( aHotKey ) + { + // All these keys have almost the same treatment + case GR_KB_CTRL | WXK_NUMPAD8: + case GR_KB_CTRL | WXK_UP: + case GR_KB_CTRL | WXK_NUMPAD2: + case GR_KB_CTRL | WXK_DOWN: + case GR_KB_CTRL | WXK_NUMPAD4: + case GR_KB_CTRL | WXK_LEFT: + case GR_KB_CTRL | WXK_NUMPAD6: + case GR_KB_CTRL | WXK_RIGHT: + case WXK_NUMPAD8: + case WXK_UP: + case WXK_NUMPAD2: + case WXK_DOWN: + case WXK_NUMPAD4: + case WXK_LEFT: + case WXK_NUMPAD6: + case WXK_RIGHT: + key_handled = true; + { + /* Here's a tricky part: when doing cursor key movement, the + * 'previous' point should be taken from memory, *not* from the + * freshly computed position in the event. Otherwise you can't do + * sub-pixel movement. The m_movingCursorWithKeyboard oneshot 'eats' + * the automatic motion event generated by cursor warping */ + wxRealPoint gridSize = GetScreen()->GetGridSize(); + *aPos = GetCrossHairPosition(); + + // Bonus: ^key moves faster (x10) + switch( aHotKey ) + { + case GR_KB_CTRL|WXK_NUMPAD8: + case GR_KB_CTRL|WXK_UP: + aPos->y -= KiROUND( 10 * gridSize.y ); + break; + + case GR_KB_CTRL|WXK_NUMPAD2: + case GR_KB_CTRL|WXK_DOWN: + aPos->y += KiROUND( 10 * gridSize.y ); + break; + + case GR_KB_CTRL|WXK_NUMPAD4: + case GR_KB_CTRL|WXK_LEFT: + aPos->x -= KiROUND( 10 * gridSize.x ); + break; + + case GR_KB_CTRL|WXK_NUMPAD6: + case GR_KB_CTRL|WXK_RIGHT: + aPos->x += KiROUND( 10 * gridSize.x ); + break; + + case WXK_NUMPAD8: + case WXK_UP: + aPos->y -= KiROUND( gridSize.y ); + break; + + case WXK_NUMPAD2: + case WXK_DOWN: + aPos->y += KiROUND( gridSize.y ); + break; + + case WXK_NUMPAD4: + case WXK_LEFT: + aPos->x -= KiROUND( gridSize.x ); + break; + + case WXK_NUMPAD6: + case WXK_RIGHT: + aPos->x += KiROUND( gridSize.x ); + break; + + default: /* Can't happen since we entered the statement */ + break; + } + + m_canvas->MoveCursor( *aPos ); + m_movingCursorWithKeyboard = true; + } + break; + + default: + break; + } + + return key_handled; +} + + +bool EDA_DRAW_FRAME::isBusy() const +{ + const BASE_SCREEN* screen = const_cast< BASE_SCREEN* >( GetScreen() ); + + if( !screen ) + return false; + + return ( screen->GetCurItem() && screen->GetCurItem()->GetFlags() ) + || ( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ); +} + +const BOX2I EDA_DRAW_FRAME::GetDocumentExtents() const +{ + return BOX2I(); +} + +void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer ) +{ +} + + +void EDA_DRAW_FRAME::RedrawScreen2( const wxPoint& posBefore ) +{ +} + + +// Factor out the calculation portion of the various BestZoom() implementations. +// +// Note that like it's forerunners this routine has an intentional side-effect: it +// sets the scroll centre position. While I'm not happy about that, it's probably +// not worth fixing as its days are numbered (GAL canvases use a different method). +double EDA_DRAW_FRAME::bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre ) +{ + return 1.0; +} + + +void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer ) +{ + if ( IsGalCanvasActive() ) + { + m_toolManager->RunAction( "common.Control.zoomFitScreen", true ); + return; + } + +} + + +void EDA_DRAW_FRAME::Window_Zoom( EDA_RECT& Rect ) +{ +} + + +void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event ) +{ + if( m_canvas == NULL ) + return; + + int id = event.GetId(); + bool zoom_at_cursor = false; + BASE_SCREEN* screen = GetScreen(); + wxPoint center = GetScrollCenterPosition(); + + if ( id == ID_KEY_ZOOM_IN ) + { + id = GetCanvas()->GetEnableZoomNoCenter() ? + ID_OFFCENTER_ZOOM_IN : ID_POPUP_ZOOM_IN; + } + else if ( id == ID_KEY_ZOOM_OUT ) + { + id = GetCanvas()->GetEnableZoomNoCenter() ? + ID_OFFCENTER_ZOOM_OUT : ID_POPUP_ZOOM_OUT; + } + + switch( id ) + { + case ID_OFFCENTER_ZOOM_IN: + center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); + + if( screen->SetPreviousZoom() ) + RedrawScreen2( center ); + break; + + case ID_POPUP_ZOOM_IN: + zoom_at_cursor = true; + center = GetCrossHairPosition(); + + // fall thru + case ID_VIEWER_ZOOM_IN: + case ID_ZOOM_IN: + if( screen->SetPreviousZoom() ) + RedrawScreen( center, zoom_at_cursor ); + break; + + case ID_OFFCENTER_ZOOM_OUT: + center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); + + if( screen->SetNextZoom() ) + RedrawScreen2( center ); + break; + + case ID_POPUP_ZOOM_OUT: + zoom_at_cursor = true; + center = GetCrossHairPosition(); + + // fall thru + case ID_VIEWER_ZOOM_OUT: + case ID_ZOOM_OUT: + if( screen->SetNextZoom() ) + RedrawScreen( center, zoom_at_cursor ); + break; + + case ID_VIEWER_ZOOM_REDRAW: + case ID_POPUP_ZOOM_REDRAW: + case ID_ZOOM_REDRAW: + m_canvas->Refresh(); + break; + + case ID_POPUP_ZOOM_CENTER: + center = GetCrossHairPosition(); + RedrawScreen( center, true ); + break; + + case ID_POPUP_ZOOM_PAGE: + case ID_VIEWER_ZOOM_PAGE: + case ID_ZOOM_PAGE: + Zoom_Automatique( false ); + break; + + case ID_POPUP_ZOOM_SELECT: + break; + + case ID_POPUP_CANCEL: + m_canvas->MoveCursorToCrossHair(); + break; + + default: + SetPresetZoom( id - ID_POPUP_ZOOM_LEVEL_START ); + } + + UpdateStatusBar(); +} + + +void EDA_DRAW_FRAME::SetNextZoom() +{ + GetScreen()->SetNextZoom(); +} + + +void EDA_DRAW_FRAME::SetPrevZoom() +{ + GetScreen()->SetPreviousZoom(); +} + + +void EDA_DRAW_FRAME::SetPresetZoom( int aIndex ) +{ + BASE_SCREEN* screen = GetScreen(); + + if( aIndex >= (int) screen->m_ZoomList.size() ) + { + wxLogDebug( wxT( "%s %d: index %d is outside the bounds of the zoom list." ), + __TFILE__, __LINE__, aIndex ); + return; + } + + if( m_zoomSelectBox ) + m_zoomSelectBox->SetSelection( aIndex ); + + if( screen->SetZoom( screen->m_ZoomList[aIndex] ) ) + RedrawScreen( GetScrollCenterPosition(), true ); + + UpdateStatusBar(); +} + + +void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu ) +{ + int maxZoomIds; + double zoom; + wxString msg; + BASE_SCREEN* screen = m_canvas->GetScreen(); + + msg = AddHotkeyName( _( "Center" ), m_hotkeysDescrList, HK_ZOOM_CENTER ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_CENTER, msg, KiBitmap( zoom_center_on_screen_xpm ) ); + msg = AddHotkeyName( _( "Zoom In" ), m_hotkeysDescrList, HK_ZOOM_IN ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_IN, msg, KiBitmap( zoom_in_xpm ) ); + msg = AddHotkeyName( _( "Zoom Out" ), m_hotkeysDescrList, HK_ZOOM_OUT ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_OUT, msg, KiBitmap( zoom_out_xpm ) ); + msg = AddHotkeyName( _( "Redraw View" ), m_hotkeysDescrList, HK_ZOOM_REDRAW ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_REDRAW, msg, KiBitmap( zoom_redraw_xpm ) ); + msg = AddHotkeyName( _( "Zoom to Fit" ), m_hotkeysDescrList, HK_ZOOM_AUTO ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_PAGE, msg, KiBitmap( zoom_fit_in_page_xpm ) ); + + + wxMenu* zoom_choice = new wxMenu; + AddMenuItem( MasterMenu, zoom_choice, + ID_POPUP_ZOOM_SELECT, _( "Zoom" ), + KiBitmap( zoom_selection_xpm ) ); + + zoom = screen->GetZoom(); + maxZoomIds = ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START; + maxZoomIds = ( (size_t) maxZoomIds < screen->m_ZoomList.size() ) ? + maxZoomIds : screen->m_ZoomList.size(); + + // Populate zoom submenu. + for( int i = 0; i < maxZoomIds; i++ ) + { + msg.Printf( wxT( "%.2f" ), m_zoomLevelCoeff / screen->m_ZoomList[i] ); + + zoom_choice->Append( ID_POPUP_ZOOM_LEVEL_START + i, _( "Zoom: " ) + msg, + wxEmptyString, wxITEM_CHECK ); + if( zoom == screen->m_ZoomList[i] ) + zoom_choice->Check( ID_POPUP_ZOOM_LEVEL_START + i, true ); + } + + // Create grid submenu as required. + if( screen->GetGridCount() ) + { + wxMenu* gridMenu = new wxMenu; + AddMenuItem( MasterMenu, gridMenu, ID_POPUP_GRID_SELECT, + _( "Grid" ), KiBitmap( grid_select_xpm ) ); + + wxArrayString gridsList; + int icurr = screen->BuildGridsChoiceList( gridsList, GetUserUnits() != INCHES ); + + for( unsigned i = 0; i < gridsList.GetCount(); i++ ) + { + GRID_TYPE& grid = screen->GetGrid( i ); + gridMenu->Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK ); + + if( (int)i == icurr ) + gridMenu->Check( grid.m_CmdId, true ); + } + } + + MasterMenu->AppendSeparator(); + AddMenuItem( MasterMenu, ID_POPUP_CANCEL, _( "Close" ), KiBitmap( cancel_xpm ) ); +} + +static bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ); + + +void EDA_DRAW_FRAME::CopyToClipboard( wxCommandEvent& event ) +{ + DrawPageOnClipboard( this ); + + if( event.GetId() == ID_GEN_COPY_BLOCK_TO_CLIPBOARD ) + { + // fixme-gal + //if( GetScreen()->IsBlockActive() ) + //m_canvas->SetCursor( wxCursor( (wxStockCursor) m_canvas->GetDefaultCursor() ) ); + + m_canvas->EndMouseCapture(); + } +} + + +/* copy the current page or block to the clipboard , + * to export drawings to other applications (word processing ...) + * This is not suitable for copy command within Eeschema or Pcbnew + */ +bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ) +{ + bool DrawBlock = false; + wxRect DrawArea; + BASE_SCREEN* screen = aFrame->GetCanvas()->GetScreen(); + + if( screen->IsBlockActive() ) + { + DrawBlock = true; + DrawArea.SetX( screen->m_BlockLocate.GetX() ); + DrawArea.SetY( screen->m_BlockLocate.GetY() ); + DrawArea.SetWidth( screen->m_BlockLocate.GetWidth() ); + DrawArea.SetHeight( screen->m_BlockLocate.GetHeight() ); + } + else + DrawArea.SetSize( aFrame->GetPageSizeIU() ); + + // Calculate a reasonable dc size, in pixels, and the dc scale to fit + // the drawings into the dc size + // scale is the ratio resolution (in PPI) / internal units + double ppi = 300; // Use 300 pixels per inch to create bitmap images on start + double inch2Iu = 1000.0 * (double) screen->MilsToIuScalar(); + double scale = ppi / inch2Iu; + + wxSize dcsize = DrawArea.GetSize(); + + int maxdim = std::max( dcsize.x, dcsize.y ); + // the max size in pixels of the bitmap used to byuild the sheet copy + const int maxbitmapsize = 3000; + + while( int( maxdim * scale ) > maxbitmapsize ) + { + ppi = ppi / 1.5; + scale = ppi / inch2Iu; + } + + dcsize.x *= scale; + dcsize.y *= scale; + + // Set draw offset, zoom... to values needed to draw in the memory DC + // after saving initial values: + wxPoint tmp_startvisu = screen->m_StartVisu; + double tmpzoom = screen->GetZoom(); + wxPoint old_org = screen->m_DrawOrg; + screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0; + screen->m_StartVisu.x = screen->m_StartVisu.y = 0; + + screen->SetZoom( 1 ); // we use zoom = 1 in draw functions. + + wxMemoryDC dc; + wxBitmap image( dcsize ); + dc.SelectObject( image ); + + EDA_RECT tmp = *aFrame->GetCanvas()->GetClipBox(); + GRResetPenAndBrush( &dc ); + GRForceBlackPen( false ); + screen->m_IsPrinting = true; + dc.SetUserScale( scale, scale ); + + aFrame->GetCanvas()->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), + wxSize( 0x7FFFFF0, 0x7FFFFF0 ) ) ); + + if( DrawBlock ) + { + dc.SetClippingRegion( DrawArea ); + } + + dc.Clear(); + aFrame->GetCanvas()->EraseScreen( &dc ); + const LSET allLayersMask = LSET().set(); + aFrame->PrintPage( &dc, allLayersMask, false ); + screen->m_IsPrinting = false; + aFrame->GetCanvas()->SetClipBox( tmp ); + + bool success = true; + + if( wxTheClipboard->Open() ) + { + // This data objects are held by the clipboard, + // so do not delete them in the app. + wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image ); + wxTheClipboard->SetData( clipbrd_data ); + wxTheClipboard->Close(); + } + else + success = false; + + // Deselect Bitmap from DC in order to delete the MemoryDC safely + // without deleting the bitmap + dc.SelectObject( wxNullBitmap ); + + GRForceBlackPen( false ); + + screen->m_StartVisu = tmp_startvisu; + screen->m_DrawOrg = old_org; + screen->SetZoom( tmpzoom ); + + return success; +} + +static const wxString productName = wxT( "KiCad E.D.A. " ); + +void DrawPageLayout( wxDC* aDC, EDA_RECT* aClipBox, + const PAGE_INFO& aPageInfo, + const wxString &aFullSheetName, + const wxString& aFileName, + TITLE_BLOCK& aTitleBlock, + int aSheetCount, int aSheetNumber, + int aPenWidth, double aScalar, + COLOR4D aColor, COLOR4D aAltColor, + const wxString& aSheetLayer ) +{ + WS_DRAW_ITEM_LIST drawList; + + drawList.SetPenSize( aPenWidth ); + drawList.SetMilsToIUfactor( aScalar ); + drawList.SetSheetNumber( aSheetNumber ); + drawList.SetSheetCount( aSheetCount ); + drawList.SetFileName( aFileName ); + drawList.SetSheetName( aFullSheetName ); + drawList.SetSheetLayer( aSheetLayer ); + + drawList.BuildWorkSheetGraphicList( aPageInfo, + aTitleBlock, aColor, aAltColor ); + + // Draw item list + drawList.Draw( aClipBox, aDC ); +} + + +void EDA_DRAW_FRAME::DrawWorkSheet( wxDC* aDC, BASE_SCREEN* aScreen, int aLineWidth, + double aScalar, const wxString &aFilename, + const wxString &aSheetLayer ) +{ + if( !m_showBorderAndTitleBlock ) + return; + + const PAGE_INFO& pageInfo = GetPageSettings(); + wxSize pageSize = pageInfo.GetSizeMils(); + + // if not printing, draw the page limits: + if( !aScreen->m_IsPrinting && m_showPageLimits ) + { + GRSetDrawMode( aDC, GR_COPY ); + GRRect( m_canvas->GetClipBox(), aDC, 0, 0, + pageSize.x * aScalar, pageSize.y * aScalar, aLineWidth, + m_drawBgColor == WHITE ? LIGHTGRAY : DARKDARKGRAY ); + } + + TITLE_BLOCK t_block = GetTitleBlock(); + COLOR4D color = COLOR4D( RED ); + + wxPoint origin = aDC->GetDeviceOrigin(); + + if( aScreen->m_IsPrinting && origin.y > 0 ) + { + aDC->SetDeviceOrigin( 0, 0 ); + aDC->SetAxisOrientation( true, false ); + } + + DrawPageLayout( aDC, m_canvas->GetClipBox(), pageInfo, + GetScreenDesc(), aFilename, t_block, + aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, + aLineWidth, aScalar, color, color, aSheetLayer ); + + if( aScreen->m_IsPrinting && origin.y > 0 ) + { + aDC->SetDeviceOrigin( origin.x, origin.y ); + aDC->SetAxisOrientation( true, true ); + } +} + + +wxString EDA_DRAW_FRAME::GetScreenDesc() const +{ + // Virtual function. In basic class, returns + // an empty string. + return wxEmptyString; +} + +bool EDA_DRAW_FRAME::LibraryFileBrowser( bool doOpen, wxFileName& aFilename, + const wxString& wildcard, const wxString& ext ) +{ + aFilename.SetExt( ext ); + + wxFileDialog dlg( this, + doOpen ? _( "Select Library" ) : _( "New Library" ), + Prj().GetProjectPath(), + doOpen ? wxString( wxEmptyString ) : aFilename.GetFullName() , + wildcard, + doOpen ? wxFD_OPEN | wxFD_FILE_MUST_EXIST : wxFD_SAVE | wxFD_CHANGE_DIR | wxFD_OVERWRITE_PROMPT ); + + if( dlg.ShowModal() == wxID_CANCEL ) + return false; + + aFilename = dlg.GetPath(); + aFilename.SetExt( ext ); + + return true; +} diff --git a/common/legacy_gal/other.cpp b/common/legacy_gal/other.cpp new file mode 100644 index 0000000000..918a77a7ac --- /dev/null +++ b/common/legacy_gal/other.cpp @@ -0,0 +1,16 @@ +#include "fctsys.h" +#include "gr_basic.h" +#include "base_screen.h" +#include "common.h" +#include "macros.h" +#include "legacy_gal/class_drawpanel.h" +#include "marker_base.h" +#include "dialog_display_info_HTML_base.h" + + + +void MARKER_BASE::DrawMarker( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, + const wxPoint& aOffset ) +{ + +} diff --git a/common/block_commande.cpp b/common/legacy_wx/block.cpp similarity index 100% rename from common/block_commande.cpp rename to common/legacy_wx/block.cpp diff --git a/common/draw_frame.cpp b/common/legacy_wx/eda_draw_frame.cpp similarity index 75% rename from common/draw_frame.cpp rename to common/legacy_wx/eda_draw_frame.cpp index 49bdec3b20..06a2241aa5 100644 --- a/common/draw_frame.cpp +++ b/common/legacy_wx/eda_draw_frame.cpp @@ -47,6 +47,16 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include + + #include #include #include @@ -56,6 +66,11 @@ #include #include +#include +#include +#include +#include + /** * Definition for enabling and disabling scroll bar setting trace output. See the * wxWidgets documentation on useing the WXTRACE environment variable. @@ -1538,3 +1553,497 @@ bool EDA_DRAW_FRAME::isBusy() const return ( screen->GetCurItem() && screen->GetCurItem()->GetFlags() ) || ( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK ); } + +void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer ) +{ + if( IsGalCanvasActive() ) + return; + + AdjustScrollBars( aCenterPoint ); + + // Move the mouse cursor to the on grid graphic cursor position + if( aWarpPointer ) + m_canvas->MoveCursorToCrossHair(); + + m_canvas->Refresh(); + m_canvas->Update(); +} + + +void EDA_DRAW_FRAME::RedrawScreen2( const wxPoint& posBefore ) +{ + if( IsGalCanvasActive() ) + return; + + // Account for scrollbars (see EDA_DRAW_FRAME::AdjustScrollBars that takes + // in account scroolbars area to adjust scroll bars) + wxSize scrollbarSize = m_canvas->GetSize() - m_canvas->GetClientSize(); + wxSize sizeAdjusted = m_canvas->GetClientSize() - scrollbarSize; + + wxPoint dPos = posBefore - sizeAdjusted / 2; + + // screen position of crosshair after zoom + wxPoint newScreenPos = m_canvas->ToDeviceXY( GetCrossHairPosition() ); + wxPoint newCenter = m_canvas->ToLogicalXY( newScreenPos - dPos ); + + AdjustScrollBars( newCenter ); + + m_canvas->Refresh(); + m_canvas->Update(); +} + + +// Factor out the calculation portion of the various BestZoom() implementations. +// +// Note that like it's forerunners this routine has an intentional side-effect: it +// sets the scroll centre position. While I'm not happy about that, it's probably +// not worth fixing as its days are numbered (GAL canvases use a different method). +double EDA_DRAW_FRAME::bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre ) +{ + double bestzoom = std::max( sizeX * scaleFactor / (double) m_canvas->GetClientSize().x, + sizeY * scaleFactor / (double) m_canvas->GetClientSize().y ); + + // Take scrollbars into account + DSIZE scrollbarSize = m_canvas->GetSize() - m_canvas->GetClientSize(); + centre.x -= int( bestzoom * scrollbarSize.x / 2.0 ); + centre.y -= int( bestzoom * scrollbarSize.y / 2.0 ); + + SetScrollCenterPosition( centre ); + + return bestzoom; +} + + +void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer ) +{ + BASE_SCREEN* screen = GetScreen(); + + // Set the best zoom and get center point. + + // BestZoom() can compute an illegal zoom if the client window size + // is small, say because frame is not maximized. So use the clamping form + // of SetZoom(): + double bestzoom = BestZoom(); + screen->SetScalingFactor( bestzoom ); + + if( screen->m_FirstRedraw ) + SetCrossHairPosition( GetScrollCenterPosition() ); + + if( !IsGalCanvasActive() ) + RedrawScreen( GetScrollCenterPosition(), aWarpPointer ); + else + m_toolManager->RunAction( "common.Control.zoomFitScreen", true ); +} + + +void EDA_DRAW_FRAME::Window_Zoom( EDA_RECT& Rect ) +{ + // Compute the best zoom + Rect.Normalize(); + + wxSize size = m_canvas->GetClientSize(); + + // Use ceil to at least show the full rect + double scalex = (double) Rect.GetSize().x / size.x; + double bestscale = (double) Rect.GetSize().y / size.y; + + bestscale = std::max( bestscale, scalex ); + + GetScreen()->SetScalingFactor( bestscale ); + RedrawScreen( Rect.Centre(), true ); +} + + +void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event ) +{ + if( m_canvas == NULL ) + return; + + int id = event.GetId(); + bool zoom_at_cursor = false; + BASE_SCREEN* screen = GetScreen(); + wxPoint center = GetScrollCenterPosition(); + + if ( id == ID_KEY_ZOOM_IN ) + { + id = GetCanvas()->GetEnableZoomNoCenter() ? + ID_OFFCENTER_ZOOM_IN : ID_POPUP_ZOOM_IN; + } + else if ( id == ID_KEY_ZOOM_OUT ) + { + id = GetCanvas()->GetEnableZoomNoCenter() ? + ID_OFFCENTER_ZOOM_OUT : ID_POPUP_ZOOM_OUT; + } + + switch( id ) + { + case ID_OFFCENTER_ZOOM_IN: + center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); + + if( screen->SetPreviousZoom() ) + RedrawScreen2( center ); + break; + + case ID_POPUP_ZOOM_IN: + zoom_at_cursor = true; + center = GetCrossHairPosition(); + + // fall thru + case ID_VIEWER_ZOOM_IN: + case ID_ZOOM_IN: + if( screen->SetPreviousZoom() ) + RedrawScreen( center, zoom_at_cursor ); + break; + + case ID_OFFCENTER_ZOOM_OUT: + center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); + + if( screen->SetNextZoom() ) + RedrawScreen2( center ); + break; + + case ID_POPUP_ZOOM_OUT: + zoom_at_cursor = true; + center = GetCrossHairPosition(); + + // fall thru + case ID_VIEWER_ZOOM_OUT: + case ID_ZOOM_OUT: + if( screen->SetNextZoom() ) + RedrawScreen( center, zoom_at_cursor ); + break; + + case ID_VIEWER_ZOOM_REDRAW: + case ID_POPUP_ZOOM_REDRAW: + case ID_ZOOM_REDRAW: + m_canvas->Refresh(); + break; + + case ID_POPUP_ZOOM_CENTER: + center = GetCrossHairPosition(); + RedrawScreen( center, true ); + break; + + case ID_POPUP_ZOOM_PAGE: + case ID_VIEWER_ZOOM_PAGE: + case ID_ZOOM_PAGE: + Zoom_Automatique( false ); + break; + + case ID_POPUP_ZOOM_SELECT: + break; + + case ID_POPUP_CANCEL: + m_canvas->MoveCursorToCrossHair(); + break; + + default: + SetPresetZoom( id - ID_POPUP_ZOOM_LEVEL_START ); + } + + UpdateStatusBar(); +} + + +void EDA_DRAW_FRAME::SetNextZoom() +{ + GetScreen()->SetNextZoom(); +} + + +void EDA_DRAW_FRAME::SetPrevZoom() +{ + GetScreen()->SetPreviousZoom(); +} + + +void EDA_DRAW_FRAME::SetPresetZoom( int aIndex ) +{ + BASE_SCREEN* screen = GetScreen(); + + if( aIndex >= (int) screen->m_ZoomList.size() ) + { + wxLogDebug( wxT( "%s %d: index %d is outside the bounds of the zoom list." ), + __TFILE__, __LINE__, aIndex ); + return; + } + + if( m_zoomSelectBox ) + m_zoomSelectBox->SetSelection( aIndex ); + + if( screen->SetZoom( screen->m_ZoomList[aIndex] ) ) + RedrawScreen( GetScrollCenterPosition(), true ); + + UpdateStatusBar(); +} + + +void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu ) +{ + int maxZoomIds; + double zoom; + wxString msg; + BASE_SCREEN* screen = m_canvas->GetScreen(); + + msg = AddHotkeyName( _( "Center" ), m_hotkeysDescrList, HK_ZOOM_CENTER ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_CENTER, msg, KiBitmap( zoom_center_on_screen_xpm ) ); + msg = AddHotkeyName( _( "Zoom In" ), m_hotkeysDescrList, HK_ZOOM_IN ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_IN, msg, KiBitmap( zoom_in_xpm ) ); + msg = AddHotkeyName( _( "Zoom Out" ), m_hotkeysDescrList, HK_ZOOM_OUT ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_OUT, msg, KiBitmap( zoom_out_xpm ) ); + msg = AddHotkeyName( _( "Redraw View" ), m_hotkeysDescrList, HK_ZOOM_REDRAW ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_REDRAW, msg, KiBitmap( zoom_redraw_xpm ) ); + msg = AddHotkeyName( _( "Zoom to Fit" ), m_hotkeysDescrList, HK_ZOOM_AUTO ); + AddMenuItem( MasterMenu, ID_POPUP_ZOOM_PAGE, msg, KiBitmap( zoom_fit_in_page_xpm ) ); + + + wxMenu* zoom_choice = new wxMenu; + AddMenuItem( MasterMenu, zoom_choice, + ID_POPUP_ZOOM_SELECT, _( "Zoom" ), + KiBitmap( zoom_selection_xpm ) ); + + zoom = screen->GetZoom(); + maxZoomIds = ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START; + maxZoomIds = ( (size_t) maxZoomIds < screen->m_ZoomList.size() ) ? + maxZoomIds : screen->m_ZoomList.size(); + + // Populate zoom submenu. + for( int i = 0; i < maxZoomIds; i++ ) + { + msg.Printf( wxT( "%.2f" ), m_zoomLevelCoeff / screen->m_ZoomList[i] ); + + zoom_choice->Append( ID_POPUP_ZOOM_LEVEL_START + i, _( "Zoom: " ) + msg, + wxEmptyString, wxITEM_CHECK ); + if( zoom == screen->m_ZoomList[i] ) + zoom_choice->Check( ID_POPUP_ZOOM_LEVEL_START + i, true ); + } + + // Create grid submenu as required. + if( screen->GetGridCount() ) + { + wxMenu* gridMenu = new wxMenu; + AddMenuItem( MasterMenu, gridMenu, ID_POPUP_GRID_SELECT, + _( "Grid" ), KiBitmap( grid_select_xpm ) ); + + wxArrayString gridsList; + int icurr = screen->BuildGridsChoiceList( gridsList, GetUserUnits() != INCHES ); + + for( unsigned i = 0; i < gridsList.GetCount(); i++ ) + { + GRID_TYPE& grid = screen->GetGrid( i ); + gridMenu->Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK ); + + if( (int)i == icurr ) + gridMenu->Check( grid.m_CmdId, true ); + } + } + + MasterMenu->AppendSeparator(); + AddMenuItem( MasterMenu, ID_POPUP_CANCEL, _( "Close" ), KiBitmap( cancel_xpm ) ); +} + +static bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ); + +void EDA_DRAW_FRAME::CopyToClipboard( wxCommandEvent& event ) +{ + DrawPageOnClipboard( this ); + + if( event.GetId() == ID_GEN_COPY_BLOCK_TO_CLIPBOARD ) + { + if( GetScreen()->IsBlockActive() ) + m_canvas->SetCursor( wxCursor( (wxStockCursor) m_canvas->GetDefaultCursor() ) ); + + m_canvas->EndMouseCapture(); + } +} + + +/* copy the current page or block to the clipboard , + * to export drawings to other applications (word processing ...) + * This is not suitable for copy command within Eeschema or Pcbnew + */ +bool DrawPageOnClipboard( EDA_DRAW_FRAME* aFrame ) +{ + bool DrawBlock = false; + wxRect DrawArea; + BASE_SCREEN* screen = aFrame->GetCanvas()->GetScreen(); + + if( screen->IsBlockActive() ) + { + DrawBlock = true; + DrawArea.SetX( screen->m_BlockLocate.GetX() ); + DrawArea.SetY( screen->m_BlockLocate.GetY() ); + DrawArea.SetWidth( screen->m_BlockLocate.GetWidth() ); + DrawArea.SetHeight( screen->m_BlockLocate.GetHeight() ); + } + else + DrawArea.SetSize( aFrame->GetPageSizeIU() ); + + // Calculate a reasonable dc size, in pixels, and the dc scale to fit + // the drawings into the dc size + // scale is the ratio resolution (in PPI) / internal units + double ppi = 300; // Use 300 pixels per inch to create bitmap images on start + double inch2Iu = 1000.0 * (double) screen->MilsToIuScalar(); + double scale = ppi / inch2Iu; + + wxSize dcsize = DrawArea.GetSize(); + + int maxdim = std::max( dcsize.x, dcsize.y ); + // the max size in pixels of the bitmap used to byuild the sheet copy + const int maxbitmapsize = 3000; + + while( int( maxdim * scale ) > maxbitmapsize ) + { + ppi = ppi / 1.5; + scale = ppi / inch2Iu; + } + + dcsize.x *= scale; + dcsize.y *= scale; + + // Set draw offset, zoom... to values needed to draw in the memory DC + // after saving initial values: + wxPoint tmp_startvisu = screen->m_StartVisu; + double tmpzoom = screen->GetZoom(); + wxPoint old_org = screen->m_DrawOrg; + screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0; + screen->m_StartVisu.x = screen->m_StartVisu.y = 0; + + screen->SetZoom( 1 ); // we use zoom = 1 in draw functions. + + wxMemoryDC dc; + wxBitmap image( dcsize ); + dc.SelectObject( image ); + + EDA_RECT tmp = *aFrame->GetCanvas()->GetClipBox(); + GRResetPenAndBrush( &dc ); + GRForceBlackPen( false ); + screen->m_IsPrinting = true; + dc.SetUserScale( scale, scale ); + + aFrame->GetCanvas()->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), + wxSize( 0x7FFFFF0, 0x7FFFFF0 ) ) ); + + if( DrawBlock ) + { + dc.SetClippingRegion( DrawArea ); + } + + dc.Clear(); + aFrame->GetCanvas()->EraseScreen( &dc ); + const LSET allLayersMask = LSET().set(); + aFrame->PrintPage( &dc, allLayersMask, false ); + screen->m_IsPrinting = false; + aFrame->GetCanvas()->SetClipBox( tmp ); + + bool success = true; + + if( wxTheClipboard->Open() ) + { + // This data objects are held by the clipboard, + // so do not delete them in the app. + wxBitmapDataObject* clipbrd_data = new wxBitmapDataObject( image ); + wxTheClipboard->SetData( clipbrd_data ); + wxTheClipboard->Close(); + } + else + success = false; + + // Deselect Bitmap from DC in order to delete the MemoryDC safely + // without deleting the bitmap + dc.SelectObject( wxNullBitmap ); + + GRForceBlackPen( false ); + + screen->m_StartVisu = tmp_startvisu; + screen->m_DrawOrg = old_org; + screen->SetZoom( tmpzoom ); + + return success; +} + + +void DrawPageLayout( wxDC* aDC, EDA_RECT* aClipBox, + const PAGE_INFO& aPageInfo, + const wxString &aFullSheetName, + const wxString& aFileName, + TITLE_BLOCK& aTitleBlock, + int aSheetCount, int aSheetNumber, + int aPenWidth, double aScalar, + COLOR4D aColor, COLOR4D aAltColor, + const wxString& aSheetLayer ) +{ + WS_DRAW_ITEM_LIST drawList; + + drawList.SetPenSize( aPenWidth ); + drawList.SetMilsToIUfactor( aScalar ); + drawList.SetSheetNumber( aSheetNumber ); + drawList.SetSheetCount( aSheetCount ); + drawList.SetFileName( aFileName ); + drawList.SetSheetName( aFullSheetName ); + drawList.SetSheetLayer( aSheetLayer ); + + drawList.BuildWorkSheetGraphicList( aPageInfo, + aTitleBlock, aColor, aAltColor ); + + // Draw item list + drawList.Draw( aClipBox, aDC ); +} + + +void EDA_DRAW_FRAME::DrawWorkSheet( wxDC* aDC, BASE_SCREEN* aScreen, int aLineWidth, + double aScalar, const wxString &aFilename, + const wxString &aSheetLayer ) +{ + if( !m_showBorderAndTitleBlock ) + return; + + const PAGE_INFO& pageInfo = GetPageSettings(); + wxSize pageSize = pageInfo.GetSizeMils(); + + // if not printing, draw the page limits: + if( !aScreen->m_IsPrinting && m_showPageLimits ) + { + GRSetDrawMode( aDC, GR_COPY ); + GRRect( m_canvas->GetClipBox(), aDC, 0, 0, + pageSize.x * aScalar, pageSize.y * aScalar, aLineWidth, + m_drawBgColor == WHITE ? LIGHTGRAY : DARKDARKGRAY ); + } + + TITLE_BLOCK t_block = GetTitleBlock(); + COLOR4D color = COLOR4D( RED ); + + wxPoint origin = aDC->GetDeviceOrigin(); + + if( aScreen->m_IsPrinting && origin.y > 0 ) + { + aDC->SetDeviceOrigin( 0, 0 ); + aDC->SetAxisOrientation( true, false ); + } + + DrawPageLayout( aDC, m_canvas->GetClipBox(), pageInfo, + GetScreenDesc(), aFilename, t_block, + aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, + aLineWidth, aScalar, color, color, aSheetLayer ); + + if( aScreen->m_IsPrinting && origin.y > 0 ) + { + aDC->SetDeviceOrigin( origin.x, origin.y ); + aDC->SetAxisOrientation( true, true ); + } +} + + +wxString EDA_DRAW_FRAME::GetScreenDesc() const +{ + // Virtual function. In basic class, returns + // an empty string. + return wxEmptyString; +} + +const BOX2I EDA_DRAW_FRAME::GetDocumentExtents() const +{ + BOX2I rv; + rv.SetMaximum(); + return rv; +} diff --git a/common/draw_panel.cpp b/common/legacy_wx/eda_draw_panel.cpp similarity index 99% rename from common/draw_panel.cpp rename to common/legacy_wx/eda_draw_panel.cpp index 04fb68b6e1..585ba44693 100644 --- a/common/draw_panel.cpp +++ b/common/legacy_wx/eda_draw_panel.cpp @@ -682,7 +682,7 @@ void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC ) DrawGrid( DC ); // Draw axis - if( GetParent()->m_showAxis ) + if( GetParent()->GetShowAxis() ) { COLOR4D axis_color = COLOR4D( BLUE ); wxSize pageSize = GetParent()->GetPageSizeIU(); @@ -694,10 +694,10 @@ void EDA_DRAW_PANEL::DrawBackGround( wxDC* DC ) GRLine( &m_ClipBox, DC, -pageSize.x, 0, pageSize.x, 0, 0, axis_color ); } - if( GetParent()->m_showOriginAxis ) + if( GetParent()->GetShowOriginAxis() ) DrawAuxiliaryAxis( DC, GR_COPY ); - if( GetParent()->m_showGridAxis ) + if( GetParent()->GetShowGridAxis() ) DrawGridAxis( DC, GR_COPY, GetParent()->GetGridOrigin() ); } @@ -845,7 +845,7 @@ void EDA_DRAW_PANEL::DrawAuxiliaryAxis( wxDC* aDC, GR_DRAWMODE aDrawMode ) void EDA_DRAW_PANEL::DrawGridAxis( wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aGridOrigin ) { - if( !GetParent()->m_showGridAxis || ( !aGridOrigin.x && !aGridOrigin.y ) ) + if( !GetParent()->GetShowGridAxis() || ( !aGridOrigin.x && !aGridOrigin.y ) ) return; COLOR4D color = GetParent()->GetGridColor(); diff --git a/common/legacy_wx/other.cpp b/common/legacy_wx/other.cpp new file mode 100644 index 0000000000..9aba629141 --- /dev/null +++ b/common/legacy_wx/other.cpp @@ -0,0 +1,47 @@ +#include "fctsys.h" +#include "gr_basic.h" +#include "base_screen.h" +#include "common.h" +#include "macros.h" +#include "class_drawpanel.h" +#include "marker_base.h" +#include "dialog_display_info_HTML_base.h" + + +static const wxPoint MarkerShapeCorners[] = +{ + wxPoint( 0, 0 ), + wxPoint( 8, 1 ), + wxPoint( 4, 3 ), + wxPoint( 13, 8 ), + wxPoint( 9, 9 ), + wxPoint( 8, 13 ), + wxPoint( 3, 4 ), + wxPoint( 1, 8 ) +}; +const unsigned CORNERS_COUNT = DIM( MarkerShapeCorners ); + + + +void MARKER_BASE::DrawMarker( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, + const wxPoint& aOffset ) +{ + wxPoint corners[CORNERS_COUNT]; + + GRSetDrawMode( aDC, aDrawMode ); + + for( unsigned ii = 0; ii < CORNERS_COUNT; ii++ ) + { + corners[ii] = MarkerShapeCorners[ii]; + corners[ii].x *= m_ScalingFactor; + corners[ii].y *= m_ScalingFactor; + corners[ii] += m_Pos + aOffset; + } + + GRClosedPoly( aPanel->GetClipBox(), aDC, CORNERS_COUNT, corners, + true, // = Filled + 0, // outline width + m_Color, // outline color + m_Color // fill collor + ); +} diff --git a/common/marker_base.cpp b/common/marker_base.cpp index 8647abdc8a..1cb2007443 100644 --- a/common/marker_base.cpp +++ b/common/marker_base.cpp @@ -35,7 +35,6 @@ #include "base_screen.h" #include "common.h" #include "macros.h" -#include "class_drawpanel.h" #include "marker_base.h" #include "dialog_display_info_HTML_base.h" @@ -182,28 +181,6 @@ EDA_RECT MARKER_BASE::GetBoundingBoxMarker() const return EDA_RECT( m_Pos, realsize ); } -void MARKER_BASE::DrawMarker( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, - const wxPoint& aOffset ) -{ - wxPoint corners[CORNERS_COUNT]; - - GRSetDrawMode( aDC, aDrawMode ); - - for( unsigned ii = 0; ii < CORNERS_COUNT; ii++ ) - { - corners[ii] = MarkerShapeCorners[ii]; - corners[ii].x *= m_ScalingFactor; - corners[ii].y *= m_ScalingFactor; - corners[ii] += m_Pos + aOffset; - } - - GRClosedPoly( aPanel->GetClipBox(), aDC, CORNERS_COUNT, corners, - true, // = Filled - 0, // outline width - m_Color, // outline color - m_Color // fill collor - ); -} void MARKER_BASE::DisplayMarkerInfo( EDA_DRAW_FRAME* aFrame ) diff --git a/common/worksheet.cpp b/common/worksheet.cpp index 0e558daeb9..3ee478e393 100644 --- a/common/worksheet.cpp +++ b/common/worksheet.cpp @@ -42,86 +42,9 @@ #include + static const wxString productName = wxT( "KiCad E.D.A. " ); -void DrawPageLayout( wxDC* aDC, EDA_RECT* aClipBox, - const PAGE_INFO& aPageInfo, - const wxString &aFullSheetName, - const wxString& aFileName, - TITLE_BLOCK& aTitleBlock, - int aSheetCount, int aSheetNumber, - int aPenWidth, double aScalar, - COLOR4D aColor, COLOR4D aAltColor, - const wxString& aSheetLayer ) -{ - WS_DRAW_ITEM_LIST drawList; - - drawList.SetPenSize( aPenWidth ); - drawList.SetMilsToIUfactor( aScalar ); - drawList.SetSheetNumber( aSheetNumber ); - drawList.SetSheetCount( aSheetCount ); - drawList.SetFileName( aFileName ); - drawList.SetSheetName( aFullSheetName ); - drawList.SetSheetLayer( aSheetLayer ); - - drawList.BuildWorkSheetGraphicList( aPageInfo, - aTitleBlock, aColor, aAltColor ); - - // Draw item list - drawList.Draw( aClipBox, aDC ); -} - - -void EDA_DRAW_FRAME::DrawWorkSheet( wxDC* aDC, BASE_SCREEN* aScreen, int aLineWidth, - double aScalar, const wxString &aFilename, - const wxString &aSheetLayer ) -{ - if( !m_showBorderAndTitleBlock ) - return; - - const PAGE_INFO& pageInfo = GetPageSettings(); - wxSize pageSize = pageInfo.GetSizeMils(); - - // if not printing, draw the page limits: - if( !aScreen->m_IsPrinting && m_showPageLimits ) - { - GRSetDrawMode( aDC, GR_COPY ); - GRRect( m_canvas->GetClipBox(), aDC, 0, 0, - pageSize.x * aScalar, pageSize.y * aScalar, aLineWidth, - m_drawBgColor == WHITE ? LIGHTGRAY : DARKDARKGRAY ); - } - - TITLE_BLOCK t_block = GetTitleBlock(); - COLOR4D color = COLOR4D( RED ); - - wxPoint origin = aDC->GetDeviceOrigin(); - - if( aScreen->m_IsPrinting && origin.y > 0 ) - { - aDC->SetDeviceOrigin( 0, 0 ); - aDC->SetAxisOrientation( true, false ); - } - - DrawPageLayout( aDC, m_canvas->GetClipBox(), pageInfo, - GetScreenDesc(), aFilename, t_block, - aScreen->m_NumberOfScreens, aScreen->m_ScreenNumber, - aLineWidth, aScalar, color, color, aSheetLayer ); - - if( aScreen->m_IsPrinting && origin.y > 0 ) - { - aDC->SetDeviceOrigin( origin.x, origin.y ); - aDC->SetAxisOrientation( true, true ); - } -} - - -wxString EDA_DRAW_FRAME::GetScreenDesc() const -{ - // Virtual function. In basic class, returns - // an empty string. - return wxEmptyString; -} - // returns the full text corresponding to the aTextbase, // after replacing format symbols by the corresponding value wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase ) diff --git a/common/zoom.cpp b/common/zoom.cpp deleted file mode 100644 index 1b814bd804..0000000000 --- a/common/zoom.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 1992-2018 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 - */ - -/** - * @file zoom.cpp - */ - -/* - * Manage zoom, grid step, and auto crop. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -void EDA_DRAW_FRAME::RedrawScreen( const wxPoint& aCenterPoint, bool aWarpPointer ) -{ - if( IsGalCanvasActive() ) - return; - - AdjustScrollBars( aCenterPoint ); - - // Move the mouse cursor to the on grid graphic cursor position - if( aWarpPointer ) - m_canvas->MoveCursorToCrossHair(); - - m_canvas->Refresh(); - m_canvas->Update(); -} - - -void EDA_DRAW_FRAME::RedrawScreen2( const wxPoint& posBefore ) -{ - if( IsGalCanvasActive() ) - return; - - // Account for scrollbars (see EDA_DRAW_FRAME::AdjustScrollBars that takes - // in account scroolbars area to adjust scroll bars) - wxSize scrollbarSize = m_canvas->GetSize() - m_canvas->GetClientSize(); - wxSize sizeAdjusted = m_canvas->GetClientSize() - scrollbarSize; - - wxPoint dPos = posBefore - sizeAdjusted / 2; - - // screen position of crosshair after zoom - wxPoint newScreenPos = m_canvas->ToDeviceXY( GetCrossHairPosition() ); - wxPoint newCenter = m_canvas->ToLogicalXY( newScreenPos - dPos ); - - AdjustScrollBars( newCenter ); - - m_canvas->Refresh(); - m_canvas->Update(); -} - - -// Factor out the calculation portion of the various BestZoom() implementations. -// -// Note that like it's forerunners this routine has an intentional side-effect: it -// sets the scroll centre position. While I'm not happy about that, it's probably -// not worth fixing as its days are numbered (GAL canvases use a different method). -double EDA_DRAW_FRAME::bestZoom( double sizeX, double sizeY, double scaleFactor, wxPoint centre ) -{ - double bestzoom = std::max( sizeX * scaleFactor / (double) m_canvas->GetClientSize().x, - sizeY * scaleFactor / (double) m_canvas->GetClientSize().y ); - - // Take scrollbars into account - DSIZE scrollbarSize = m_canvas->GetSize() - m_canvas->GetClientSize(); - centre.x -= int( bestzoom * scrollbarSize.x / 2.0 ); - centre.y -= int( bestzoom * scrollbarSize.y / 2.0 ); - - SetScrollCenterPosition( centre ); - - return bestzoom; -} - - -void EDA_DRAW_FRAME::Zoom_Automatique( bool aWarpPointer ) -{ - BASE_SCREEN* screen = GetScreen(); - - if( !screen ) - return; - - // Set the best zoom and get center point. - - // BestZoom() can compute an illegal zoom if the client window size - // is small, say because frame is not maximized. So use the clamping form - // of SetZoom(): - double bestzoom = BestZoom(); - screen->SetScalingFactor( bestzoom ); - - if( screen->m_FirstRedraw ) - SetCrossHairPosition( GetScrollCenterPosition() ); - - if( !IsGalCanvasActive() ) - RedrawScreen( GetScrollCenterPosition(), aWarpPointer ); - else - m_toolManager->RunAction( "common.Control.zoomFitScreen", true ); -} - - -void EDA_DRAW_FRAME::Window_Zoom( EDA_RECT& Rect ) -{ - // Compute the best zoom - Rect.Normalize(); - - wxSize size = m_canvas->GetClientSize(); - - // Use ceil to at least show the full rect - double scalex = (double) Rect.GetSize().x / size.x; - double bestscale = (double) Rect.GetSize().y / size.y; - - bestscale = std::max( bestscale, scalex ); - - GetScreen()->SetScalingFactor( bestscale ); - RedrawScreen( Rect.Centre(), true ); -} - - -void EDA_DRAW_FRAME::OnZoom( wxCommandEvent& event ) -{ - if( m_canvas == NULL ) - return; - - int id = event.GetId(); - bool zoom_at_cursor = false; - BASE_SCREEN* screen = GetScreen(); - wxPoint center = GetScrollCenterPosition(); - - if ( id == ID_KEY_ZOOM_IN ) - { - id = GetCanvas()->GetEnableZoomNoCenter() ? - ID_OFFCENTER_ZOOM_IN : ID_POPUP_ZOOM_IN; - } - else if ( id == ID_KEY_ZOOM_OUT ) - { - id = GetCanvas()->GetEnableZoomNoCenter() ? - ID_OFFCENTER_ZOOM_OUT : ID_POPUP_ZOOM_OUT; - } - - switch( id ) - { - case ID_OFFCENTER_ZOOM_IN: - center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); - - if( screen->SetPreviousZoom() ) - RedrawScreen2( center ); - break; - - case ID_POPUP_ZOOM_IN: - zoom_at_cursor = true; - center = GetCrossHairPosition(); - - // fall thru - case ID_VIEWER_ZOOM_IN: - case ID_ZOOM_IN: - if( screen->SetPreviousZoom() ) - RedrawScreen( center, zoom_at_cursor ); - break; - - case ID_OFFCENTER_ZOOM_OUT: - center = m_canvas->ToDeviceXY( GetCrossHairPosition() ); - - if( screen->SetNextZoom() ) - RedrawScreen2( center ); - break; - - case ID_POPUP_ZOOM_OUT: - zoom_at_cursor = true; - center = GetCrossHairPosition(); - - // fall thru - case ID_VIEWER_ZOOM_OUT: - case ID_ZOOM_OUT: - if( screen->SetNextZoom() ) - RedrawScreen( center, zoom_at_cursor ); - break; - - case ID_VIEWER_ZOOM_REDRAW: - case ID_POPUP_ZOOM_REDRAW: - case ID_ZOOM_REDRAW: - m_canvas->Refresh(); - break; - - case ID_POPUP_ZOOM_CENTER: - center = GetCrossHairPosition(); - RedrawScreen( center, true ); - break; - - case ID_POPUP_ZOOM_PAGE: - case ID_VIEWER_ZOOM_PAGE: - case ID_ZOOM_PAGE: - Zoom_Automatique( false ); - break; - - case ID_POPUP_ZOOM_SELECT: - break; - - case ID_POPUP_CANCEL: - m_canvas->MoveCursorToCrossHair(); - break; - - default: - SetPresetZoom( id - ID_POPUP_ZOOM_LEVEL_START ); - } - - UpdateStatusBar(); -} - - -void EDA_DRAW_FRAME::SetNextZoom() -{ - GetScreen()->SetNextZoom(); -} - - -void EDA_DRAW_FRAME::SetPrevZoom() -{ - GetScreen()->SetPreviousZoom(); -} - - -void EDA_DRAW_FRAME::SetPresetZoom( int aIndex ) -{ - BASE_SCREEN* screen = GetScreen(); - - if( aIndex >= (int) screen->m_ZoomList.size() ) - { - wxLogDebug( wxT( "%s %d: index %d is outside the bounds of the zoom list." ), - __TFILE__, __LINE__, aIndex ); - return; - } - - if( m_zoomSelectBox ) - m_zoomSelectBox->SetSelection( aIndex ); - - if( screen->SetZoom( screen->m_ZoomList[aIndex] ) ) - RedrawScreen( GetScrollCenterPosition(), true ); - - UpdateStatusBar(); -} - - -void EDA_DRAW_FRAME::AddMenuZoomAndGrid( wxMenu* MasterMenu ) -{ - int maxZoomIds; - double zoom; - wxString msg; - BASE_SCREEN* screen = m_canvas->GetScreen(); - - msg = AddHotkeyName( _( "Center" ), m_hotkeysDescrList, HK_ZOOM_CENTER ); - AddMenuItem( MasterMenu, ID_POPUP_ZOOM_CENTER, msg, KiBitmap( zoom_center_on_screen_xpm ) ); - msg = AddHotkeyName( _( "Zoom In" ), m_hotkeysDescrList, HK_ZOOM_IN ); - AddMenuItem( MasterMenu, ID_POPUP_ZOOM_IN, msg, KiBitmap( zoom_in_xpm ) ); - msg = AddHotkeyName( _( "Zoom Out" ), m_hotkeysDescrList, HK_ZOOM_OUT ); - AddMenuItem( MasterMenu, ID_POPUP_ZOOM_OUT, msg, KiBitmap( zoom_out_xpm ) ); - msg = AddHotkeyName( _( "Redraw View" ), m_hotkeysDescrList, HK_ZOOM_REDRAW ); - AddMenuItem( MasterMenu, ID_POPUP_ZOOM_REDRAW, msg, KiBitmap( zoom_redraw_xpm ) ); - msg = AddHotkeyName( _( "Zoom to Fit" ), m_hotkeysDescrList, HK_ZOOM_AUTO ); - AddMenuItem( MasterMenu, ID_POPUP_ZOOM_PAGE, msg, KiBitmap( zoom_fit_in_page_xpm ) ); - - - wxMenu* zoom_choice = new wxMenu; - AddMenuItem( MasterMenu, zoom_choice, - ID_POPUP_ZOOM_SELECT, _( "Zoom" ), - KiBitmap( zoom_selection_xpm ) ); - - zoom = screen->GetZoom(); - maxZoomIds = ID_POPUP_ZOOM_LEVEL_END - ID_POPUP_ZOOM_LEVEL_START; - maxZoomIds = ( (size_t) maxZoomIds < screen->m_ZoomList.size() ) ? - maxZoomIds : screen->m_ZoomList.size(); - - // Populate zoom submenu. - for( int i = 0; i < maxZoomIds; i++ ) - { - msg.Printf( wxT( "%.2f" ), m_zoomLevelCoeff / screen->m_ZoomList[i] ); - - zoom_choice->Append( ID_POPUP_ZOOM_LEVEL_START + i, _( "Zoom: " ) + msg, - wxEmptyString, wxITEM_CHECK ); - if( zoom == screen->m_ZoomList[i] ) - zoom_choice->Check( ID_POPUP_ZOOM_LEVEL_START + i, true ); - } - - // Create grid submenu as required. - if( screen->GetGridCount() ) - { - wxMenu* gridMenu = new wxMenu; - AddMenuItem( MasterMenu, gridMenu, ID_POPUP_GRID_SELECT, - _( "Grid" ), KiBitmap( grid_select_xpm ) ); - - wxArrayString gridsList; - int icurr = screen->BuildGridsChoiceList( gridsList, GetUserUnits() != INCHES ); - - for( unsigned i = 0; i < gridsList.GetCount(); i++ ) - { - GRID_TYPE& grid = screen->GetGrid( i ); - gridMenu->Append( grid.m_CmdId, gridsList[i], wxEmptyString, wxITEM_CHECK ); - - if( (int)i == icurr ) - gridMenu->Check( grid.m_CmdId, true ); - } - } - - MasterMenu->AppendSeparator(); - AddMenuItem( MasterMenu, ID_POPUP_CANCEL, _( "Close" ), KiBitmap( cancel_xpm ) ); -} diff --git a/include/legacy_gal/class_drawpanel.h b/include/legacy_gal/class_drawpanel.h new file mode 100644 index 0000000000..667cebda63 --- /dev/null +++ b/include/legacy_gal/class_drawpanel.h @@ -0,0 +1,389 @@ +#ifndef __EDA_DRAW_PANEL_H +#define __EDA_DRAW_PANEL_H + +#include +#include +#include +#include + +/** + * Mouse capture callback function prototype. + */ + +class BASE_SCREEN; + +class EDA_DRAW_PANEL; + +typedef void ( *MOUSE_CAPTURE_CALLBACK )( EDA_DRAW_PANEL* aPanel, wxDC* aDC, + const wxPoint& aPosition, bool aErase ); + +/** + * End mouse capture callback function prototype. + */ +typedef void ( *END_MOUSE_CAPTURE_CALLBACK )( EDA_DRAW_PANEL* aPanel, wxDC* aDC ); + + +class EDA_DRAW_PANEL +{ +protected: + bool m_showCrossHair; ///< Indicate if cross hair is to be shown. + int m_cursorLevel; ///< Index for cursor redraw in XOR mode. + int m_scrollIncrementX; ///< X axis scroll increment in pixels per unit. + int m_scrollIncrementY; ///< Y axis scroll increment in pixels per unit. + + wxPoint m_CursorStartPos; ///< Used for testing the cursor movement. + wxPoint m_PanStartCenter; ///< Initial scroll center position when pan started + wxPoint m_PanStartEventPosition; ///< Initial position of mouse event when pan started + + wxPoint m_CursorClickPos; ///< Used for maintaining click position + wxTimer *m_ClickTimer; + + /// The drawing area used to redraw the screen which is usually the visible area + /// of the drawing in internal units. + EDA_RECT m_ClipBox; + + bool m_abortRequest; ///< Flag used to abort long commands. + + bool m_enableZoomNoCenter; ///< True to enable zooming around the crosshair instead of the center + bool m_enableMousewheelPan; ///< True to enable mousewheel panning by default. + + bool m_enableAutoPan; ///< True to enable automatic panning. + + bool m_requestAutoPan; ///< true to request an auto pan. Valid only when m_enableAutoPan = true. + + bool m_ignoreMouseEvents; ///< Ignore mouse events when true. + + /* Used to inhibit a response to a mouse left button release, after a double click + * (when releasing the left button at the end of the second click. Used in Eeschema + * to inhibit a mouse left release command when switching between hierarchical sheets + * on a double click. + */ + bool m_ignoreNextLeftButtonRelease; ///< Ignore the next mouse left button release when true. + + bool m_enableBlockCommands; ///< True enables block commands. + + /** + * Count the drag events. Used to filter mouse moves before starting a + * block command. A block command can be started only if + * MinDragEventCount > MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND in order to avoid + * spurious block commands. + */ + int m_minDragEventCount; + + /// True when drawing in mirror mode. Used by the draw arc function, because arcs + /// are oriented, and in mirror mode, orientations are reversed. + bool m_PrintIsMirrored; + + /// Mouse capture move callback function. + MOUSE_CAPTURE_CALLBACK m_mouseCaptureCallback; + + /// Abort mouse capture callback function. + END_MOUSE_CAPTURE_CALLBACK m_endMouseCaptureCallback; + + /// useful to avoid false start block in certain cases + /// (like switch from a sheet to another sheet + /// >= 0 (or >= n) if a block can start + int m_canStartBlock; + + int m_doubleClickInterval; + +public: + + EDA_DRAW_PANEL(){}; + virtual ~EDA_DRAW_PANEL(){}; + + /** + * Function GetDisplayOptions + * A way to pass info to draw functions. + * this is just an accessor to the GetDisplayOptions() parent frame function. + */ + virtual void* GetDisplayOptions() { printf("Unimplemented\n"); assert(false); return nullptr; }; + + virtual BASE_SCREEN* GetScreen() = 0; + + virtual EDA_DRAW_FRAME* GetParent() const = 0; + + //virtual void OnPaint( wxPaintEvent& event ); + + virtual EDA_RECT* GetClipBox() { return &m_ClipBox; } + + void SetClipBox( const EDA_RECT& aRect ) { m_ClipBox = aRect; } + + bool GetAbortRequest() const { return m_abortRequest; } + + void SetAbortRequest( bool aAbortRequest ) { m_abortRequest = aAbortRequest; } + + bool GetEnableMousewheelPan() const { return m_enableMousewheelPan; } + + virtual void SetEnableMousewheelPan( bool aEnable ) { m_enableMousewheelPan = aEnable; }; + + bool GetEnableZoomNoCenter() const { return m_enableZoomNoCenter; } + + virtual void SetEnableZoomNoCenter( bool aEnable ) { m_enableZoomNoCenter = aEnable; }; + + bool GetEnableAutoPan() const { return m_enableAutoPan; } + + virtual void SetEnableAutoPan( bool aEnable ) { m_enableAutoPan = aEnable; }; + + void SetAutoPanRequest( bool aEnable ) { m_requestAutoPan = aEnable; } + + void SetIgnoreMouseEvents( bool aIgnore ) { m_ignoreMouseEvents = aIgnore; } + + void SetIgnoreLeftButtonReleaseEvent( bool aIgnore ) { m_ignoreNextLeftButtonRelease = aIgnore; } + + void SetEnableBlockCommands( bool aEnable ) { m_enableBlockCommands = aEnable; } + + bool GetPrintMirrored() const { return m_PrintIsMirrored; } + void SetPrintMirrored( bool aMirror ) { m_PrintIsMirrored = aMirror; } + + void SetCanStartBlock( int aStartBlock ) { m_canStartBlock = aStartBlock; } + + /** + * Function DrawBackGround + * @param DC = current Device Context + * Draws (if allowed) : + * the grid + * X and Y axis + * X and Y auxiliary axis + */ + virtual void DrawBackGround( wxDC* DC ) { printf("Unimplemented\n"); }; + + /** + * Function DrawGrid + * draws a grid to \a aDC. + * @see m_ClipBox to determine the damaged area of the drawing to draw the grid. + * @see EDA_DRAW_FRAME::IsGridVisible() to determine if grid is shown. + * @see EDA_DRAW_FRAME::GetGridColor() for the color of the grid. + * @param aDC The device context to draw the grid. + */ + virtual void DrawGrid( wxDC* aDC ) { printf("Unimplemented\n"); }; + + /** + * Function DrawAuxiliaryAxis + * Draw the Auxiliary Axis, used in Pcbnew which as origin coordinates + * for gerber and excellon files + * @param aDC = current Device Context + * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) + */ + virtual void DrawAuxiliaryAxis( wxDC* aDC, GR_DRAWMODE aDrawMode ) { printf("Unimplemented\n");}; + + /** + * Function DrawGridAxis + * Draw on auxiliary axis, used in Pcbnew to show grid origin, when + * the grid origin is set by user, and is not (0,0) + * @param aDC = current Device Context + * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) + * @param aGridOrigin = the absolute coordinate of grid origin for snap. + */ + virtual void DrawGridAxis( wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aGridOrigin ) { printf("Unimplemented\n"); }; + + /** + * Function DeviceToLogical + * converts \a aRect from device to drawing (logical) coordinates. + *

+ * \a aRect must be in scrolled device units. + *

+ * @param aRect The rectangle to convert. + * @param aDC The device context used for the conversion. + * @return A rectangle converted to drawing units. + */ + virtual wxRect DeviceToLogical( const wxRect& aRect, wxDC& aDC ) { printf("Unimplemented\n");assert(false); return wxRect(); }; + + /* Mouse and keys events */ + + /** + * Function OnMouseWheel + * handles mouse wheel events. + *

+ * The mouse wheel is used to provide support for zooming and panning. This + * is accomplished by converting mouse wheel events in pseudo menu command + * events and sending them to the appropriate parent window event handler. + *

+ */ + + virtual void EraseScreen( wxDC* DC ) { printf("Unimplemented\n"); };; + + virtual void SetZoom( double mode ) { printf("Unimplemented\n"); };; + virtual double GetZoom() { printf("Unimplemented\n"); return 1.0; };; + + //virtual void SetGrid( const wxRealPoint& size ) { printf("Unimplemented\n"); };; + //virtual wxRealPoint GetGrid() { printf("Unimplemented\n"); return wxRealPoint(1.0, 1.0); };; + + + /** + * Function IsPointOnDisplay + * @param aPosition The position to test in logical (drawing) units. + * @return true if \a aPosition is visible on the screen. + * false if \a aPosition is not visible on the screen. + */ + virtual bool IsPointOnDisplay( const wxPoint& aPosition ) { printf("Unimplemented\n"); return false; };; + + /** + * Function SetClipBox + * sets the clip box in drawing (logical) units from \a aRect in device units. + *

+ * If \a aRect is NULL, then the entire visible area of the screen is used as the clip + * area. The clip box is used when drawing to determine which objects are not visible + * and do not need to be drawn. Note that this is not the same as setting the device + * context clipping with wxDC::SetClippingRegion(). This is the rectangle used by the + * drawing functions in gr_basic.cpp used to determine if the item to draw is off screen + * and therefore not drawn. + *

+ * @param aDC The device context use for drawing with the correct scale and + * offsets already configured. See DoPrepareDC(). + * @param aRect The clip rectangle in device units or NULL for the entire visible area + * of the screen. + */ + virtual void SetClipBox( wxDC& aDC, const wxRect* aRect = NULL ) { printf("Unimplemented\n"); };; + + virtual void ReDraw( wxDC* aDC, bool aEraseBackground = true ) { printf("Unimplemented\n"); };; + + /** + * Function RefreshDrawingRect + * redraws the contents of \a aRect in drawing units. \a aRect is converted to + * screen coordinates and wxWindow::RefreshRect() is called to repaint the region. + * @param aRect The rectangle to repaint. + * @param aEraseBackground Erases the background if true. + */ + virtual void RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground = true ) { printf("Unimplemented\n"); };; + + /// @copydoc wxWindow::Refresh() + //virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL ); + + /** + * Function GetScreenCenterLogicalPosition + * @return The current screen center position in logical (drawing) units. + */ + virtual wxPoint GetScreenCenterLogicalPosition() { printf("Unimplemented\n"); return wxPoint(0, 0); };; + + /** + * Function MoveCursorToCrossHair + * warps the cursor to the current cross hair position. + */ + virtual void MoveCursorToCrossHair() { printf("Unimplemented\n"); };; + + /** + * Function ToDeviceXY + * transforms logical to device coordinates + */ + virtual wxPoint ToDeviceXY( const wxPoint& pos ) { printf("Unimplemented\n"); return wxPoint(0, 0); };; + + /** + * Function ToLogicalXY + * transforms device to logical coordinates + */ + virtual wxPoint ToLogicalXY( const wxPoint& pos ) { printf("Unimplemented\n"); return wxPoint(0, 0); };; + + /** + * Function MoveCursor + * moves the mouse pointer to \a aPosition in logical (drawing) units. + * @param aPosition The position in logical units to move the cursor. + */ + virtual void MoveCursor( const wxPoint& aPosition ) { printf("Unimplemented\n"); };; + + /* Cursor functions */ + /** + * Function DrawCrossHair + * draws the user cross hair. + *

+ * The user cross hair is not the mouse cursor although they may be at the same screen + * position. The mouse cursor is still render by the OS. This is a drawn cross hair + * that is used to snap to grid when grid snapping is enabled. This is as an indicator + * to where the next user action will take place. + *

+ * @param aDC - the device context to draw the cursor + * @param aColor - the color to draw the cursor + */ + virtual void DrawCrossHair( wxDC* aDC=nullptr, COLOR4D aColor = COLOR4D::WHITE ) { printf("Unimplemented\n"); };; + + // Hide the cross hair. + virtual void CrossHairOff( wxDC* DC=nullptr ) { printf("Unimplemented\n"); };; + + // Show the cross hair. + virtual void CrossHairOn( wxDC* DC=nullptr ) { printf("Unimplemented\n"); };; + + /** + * Function SetMouseCapture + * sets the mouse capture and end mouse capture callbacks to \a aMouseCaptureCallback + * and \a aEndMouseCaptureCallback respectively. + */ + virtual void SetMouseCapture( MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback, + END_MOUSE_CAPTURE_CALLBACK aEndMouseCaptureCallback ) + { + m_mouseCaptureCallback = aMouseCaptureCallback; + m_endMouseCaptureCallback = aEndMouseCaptureCallback; + } + + + virtual void SetMouseCaptureCallback( MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback ) + { + m_mouseCaptureCallback = aMouseCaptureCallback; + } + + + /** + * Function EndMouseCapture + * ends mouse a capture. + * + * Check to see if the cursor is being managed for block or editing commands and release it. + * @param aId The command ID to restore or -1 to keep the current command ID. + * @param aCursorId The wxWidgets stock cursor ID to set the cursor to or -1 to keep the + * current cursor. + * @param aTitle The tool message to display in the status bar or wxEmptyString to clear + * the message. + * @param aCallEndFunc Call the abort mouse capture callback if true. + */ + virtual void EndMouseCapture( int aId = -1, int aCursorId = -1, + const wxString& aTitle = wxEmptyString, + bool aCallEndFunc = true ) { printf("Unimplemented\n"); assert(false); };; + + inline bool IsMouseCaptured() const { return m_mouseCaptureCallback != NULL; } + + /** + * Function CallMouseCapture + * calls the mouse capture callback. + * + * @param aDC A point to a wxDC object to perform any drawing upon. + * @param aPosition A referecnce to a wxPoint object containing the current cursor + * position. + * @param aErase True indicates the item being drawn should be erase before drawing + * it a \a aPosition. + */ + virtual void CallMouseCapture( wxDC* aDC, const wxPoint& aPosition, bool aErase ) { printf("Unimplemented\n"); assert(false); };; + + /** + * Function CallEndMouseCapture + * calls the end mouse capture callback. + * + * @param aDC A point to a wxDC object to perform any drawing upon. + */ + virtual void CallEndMouseCapture( wxDC* aDC ) { printf("Unimplemented\n"); assert(false); };; + + /** + * Function SetCurrentCursor + * Set the current cursor shape for drawpanel + */ + virtual void SetCurrentCursor( int aCursor ) {}; + virtual void SetCurrentCursor( const wxCursor& aCursor ) {}; + + /** + * Function GetDefaultCursor + * @return the default cursor shape + */ + //fixme-gal + virtual int GetDefaultCursor() const = 0; + + virtual void SetDefaultCursor() {}; + + /** + * Function GetCurrentCursor + * @return the current cursor shape, depending on the current selected tool + */ + virtual int GetCurrentCursor() const = 0; + + virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL ) {} + + virtual wxWindow* GetWindow() = 0; +}; + +#endif diff --git a/include/legacy_wx/class_drawpanel.h b/include/legacy_wx/class_drawpanel.h new file mode 100644 index 0000000000..fee2284f7c --- /dev/null +++ b/include/legacy_wx/class_drawpanel.h @@ -0,0 +1,508 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2011 Wayne Stambaugh + * Copyright (C) 1992-2018 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 + */ + +/** + * @file class_drawpanel.h: + * @brief EDA_DRAW_PANEL class definition. + */ + +#ifndef PANEL_WXSTRUCT_H +#define PANEL_WXSTRUCT_H + +#include +#include +#include + + +class BASE_SCREEN; +class PCB_SCREEN; + + +/** + * Mouse capture callback function prototype. + */ +typedef void ( *MOUSE_CAPTURE_CALLBACK )( EDA_DRAW_PANEL* aPanel, wxDC* aDC, + const wxPoint& aPosition, bool aErase ); + +/** + * End mouse capture callback function prototype. + */ +typedef void ( *END_MOUSE_CAPTURE_CALLBACK )( EDA_DRAW_PANEL* aPanel, wxDC* aDC ); + + +class EDA_DRAW_PANEL : public wxScrolledWindow +{ +private: + int m_currentCursor; ///< Current mouse cursor shape id. + int m_defaultCursor; ///< The default mouse cursor shape id. + bool m_showCrossHair; ///< Indicate if cross hair is to be shown. + int m_cursorLevel; ///< Index for cursor redraw in XOR mode. + int m_scrollIncrementX; ///< X axis scroll increment in pixels per unit. + int m_scrollIncrementY; ///< Y axis scroll increment in pixels per unit. + + wxPoint m_CursorStartPos; ///< Used for testing the cursor movement. + wxPoint m_PanStartCenter; ///< Initial scroll center position when pan started + wxPoint m_PanStartEventPosition; ///< Initial position of mouse event when pan started + + wxPoint m_CursorClickPos; ///< Used for maintaining click position + wxTimer *m_ClickTimer; + + /// The drawing area used to redraw the screen which is usually the visible area + /// of the drawing in internal units. + EDA_RECT m_ClipBox; + + bool m_abortRequest; ///< Flag used to abort long commands. + + bool m_enableZoomNoCenter; ///< True to enable zooming around the crosshair instead of the center + bool m_enableMousewheelPan; ///< True to enable mousewheel panning by default. + + bool m_enableAutoPan; ///< True to enable automatic panning. + + bool m_requestAutoPan; ///< true to request an auto pan. Valid only when m_enableAutoPan = true. + + bool m_ignoreMouseEvents; ///< Ignore mouse events when true. + + /* Used to inhibit a response to a mouse left button release, after a double click + * (when releasing the left button at the end of the second click. Used in Eeschema + * to inhibit a mouse left release command when switching between hierarchical sheets + * on a double click. + */ + bool m_ignoreNextLeftButtonRelease; ///< Ignore the next mouse left button release when true. + + bool m_enableBlockCommands; ///< True enables block commands. + + /** + * Count the drag events. Used to filter mouse moves before starting a + * block command. A block command can be started only if + * MinDragEventCount > MIN_DRAG_COUNT_FOR_START_BLOCK_COMMAND in order to avoid + * spurious block commands. + */ + int m_minDragEventCount; + + /// True when drawing in mirror mode. Used by the draw arc function, because arcs + /// are oriented, and in mirror mode, orientations are reversed. + bool m_PrintIsMirrored; + + /// Mouse capture move callback function. + MOUSE_CAPTURE_CALLBACK m_mouseCaptureCallback; + + /// Abort mouse capture callback function. + END_MOUSE_CAPTURE_CALLBACK m_endMouseCaptureCallback; + + /// useful to avoid false start block in certain cases + /// (like switch from a sheet to another sheet + /// >= 0 (or >= n) if a block can start + int m_canStartBlock; + + int m_doubleClickInterval; + +public: + + EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, const wxPoint& pos, const wxSize& size ); + ~EDA_DRAW_PANEL(); + + /** + * Function GetDisplayOptions + * A way to pass info to draw functions. + * this is just an accessor to the GetDisplayOptions() parent frame function. + */ + void* GetDisplayOptions(); + + BASE_SCREEN* GetScreen(); + + EDA_DRAW_FRAME* GetParent() const; + + void OnPaint( wxPaintEvent& event ); + + EDA_RECT* GetClipBox() { return &m_ClipBox; } + + void SetClipBox( const EDA_RECT& aRect ) { m_ClipBox = aRect; } + + bool GetAbortRequest() const { return m_abortRequest; } + + void SetAbortRequest( bool aAbortRequest ) { m_abortRequest = aAbortRequest; } + + bool GetEnableMousewheelPan() const { return m_enableMousewheelPan; } + + void SetEnableMousewheelPan( bool aEnable ); + + bool GetEnableZoomNoCenter() const { return m_enableZoomNoCenter; } + + void SetEnableZoomNoCenter( bool aEnable ); + + bool GetEnableAutoPan() const { return m_enableAutoPan; } + + void SetEnableAutoPan( bool aEnable ); + + void SetAutoPanRequest( bool aEnable ) { m_requestAutoPan = aEnable; } + + void SetIgnoreMouseEvents( bool aIgnore ) { m_ignoreMouseEvents = aIgnore; } + + void SetIgnoreLeftButtonReleaseEvent( bool aIgnore ) { m_ignoreNextLeftButtonRelease = aIgnore; } + + void SetEnableBlockCommands( bool aEnable ) { m_enableBlockCommands = aEnable; } + + bool GetPrintMirrored() const { return m_PrintIsMirrored; } + void SetPrintMirrored( bool aMirror ) { m_PrintIsMirrored = aMirror; } + + void SetCanStartBlock( int aStartBlock ) { m_canStartBlock = aStartBlock; } + + /** + * Function DrawBackGround + * @param DC = current Device Context + * Draws (if allowed) : + * the grid + * X and Y axis + * X and Y auxiliary axis + */ + void DrawBackGround( wxDC* DC ); + + /** + * Function DrawGrid + * draws a grid to \a aDC. + * @see m_ClipBox to determine the damaged area of the drawing to draw the grid. + * @see EDA_DRAW_FRAME::IsGridVisible() to determine if grid is shown. + * @see EDA_DRAW_FRAME::GetGridColor() for the color of the grid. + * @param aDC The device context to draw the grid. + */ + void DrawGrid( wxDC* aDC ); + + /** + * Function DrawAuxiliaryAxis + * Draw the Auxiliary Axis, used in Pcbnew which as origin coordinates + * for gerber and excellon files + * @param aDC = current Device Context + * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) + */ + void DrawAuxiliaryAxis( wxDC* aDC, GR_DRAWMODE aDrawMode ); + + /** + * Function DrawGridAxis + * Draw on auxiliary axis, used in Pcbnew to show grid origin, when + * the grid origin is set by user, and is not (0,0) + * @param aDC = current Device Context + * @param aDrawMode = draw mode (GR_COPY, GR_OR ..) + * @param aGridOrigin = the absolute coordinate of grid origin for snap. + */ + void DrawGridAxis( wxDC* aDC, GR_DRAWMODE aDrawMode, const wxPoint& aGridOrigin ); + + void OnEraseBackground( wxEraseEvent& event ) { } + + /** + * Function OnActivate + * handles window activation events. + *

+ * The member m_canStartBlock is initialize to avoid a block start command on activation + * (because a left mouse button can be pressed and no block command wanted. This happens + * when enter on a hierarchy sheet on double click. + *

+ */ + void OnActivate( wxActivateEvent& event ); + + /** + * Function OnTimer + * handle timer events + *

+ * The class will start a timer when a mouse-up event is handled. If a + * double-click event is not handled inside of a specified interval, + * the timer event will fire, causing the single-click event to be handled. + * Otherwise, the system will process the double-click. + */ + void OnTimer( wxTimerEvent& event ); + + /** + * Function DoPrepareDC + * sets up the device context \a aDC for drawing. + *

+ * This overrides wxScrolledWindow::DoPrepareDC() for setting up the the device context + * used for drawing. The scale factor and drawing logical offset are set and the base + * method is called to set the DC device origin (scroll bar position). This connects + * everything together to achieve the appropriate coordinate manipulation using wxDC + * LogicalToDeviceXXX and DeviceToLogixalXXX methods. This gets called automatically + * for a paint event. If you do any drawing outside the paint event, you must call + * DoPrepareDC manually. + *

+ * @param aDC The device context to prepare. + */ + virtual void DoPrepareDC( wxDC& aDC ) override; + + /** + * Function DeviceToLogical + * converts \a aRect from device to drawing (logical) coordinates. + *

+ * \a aRect must be in scrolled device units. + *

+ * @param aRect The rectangle to convert. + * @param aDC The device context used for the conversion. + * @return A rectangle converted to drawing units. + */ + wxRect DeviceToLogical( const wxRect& aRect, wxDC& aDC ); + + /* Mouse and keys events */ + + /** + * Function OnMouseWheel + * handles mouse wheel events. + *

+ * The mouse wheel is used to provide support for zooming and panning. This + * is accomplished by converting mouse wheel events in pseudo menu command + * events and sending them to the appropriate parent window event handler. + *

+ */ + void OnMouseWheel( wxMouseEvent& event ); +#if wxCHECK_VERSION( 3, 1, 0 ) || defined( USE_OSX_MAGNIFY_EVENT ) + void OnMagnify( wxMouseEvent& event ); +#endif + void OnMouseEvent( wxMouseEvent& event ); + void OnMouseEntering( wxMouseEvent& aEvent ); + void OnMouseLeaving( wxMouseEvent& event ); + void OnKeyEvent( wxKeyEvent& event ); + void OnCharHook( wxKeyEvent& event ); + + void OnPan( wxCommandEvent& event ); + + void EraseScreen( wxDC* DC ); + void OnScrollWin( wxCommandEvent& event ); + void OnScroll( wxScrollWinEvent& event ); + + void SetZoom( double mode ); + double GetZoom(); + + void SetGrid( const wxRealPoint& size ); + wxRealPoint GetGrid(); + + /** + * Function OnRightClick + * builds and displays a context menu on a right mouse button click. + * @return true if the context menu is shown, or false + */ + bool OnRightClick( wxMouseEvent& event ); + + /** + * Function IsPointOnDisplay + * @param aPosition The position to test in logical (drawing) units. + * @return true if \a aPosition is visible on the screen. + * false if \a aPosition is not visible on the screen. + */ + bool IsPointOnDisplay( const wxPoint& aPosition ); + + /** + * Function SetClipBox + * sets the clip box in drawing (logical) units from \a aRect in device units. + *

+ * If \a aRect is NULL, then the entire visible area of the screen is used as the clip + * area. The clip box is used when drawing to determine which objects are not visible + * and do not need to be drawn. Note that this is not the same as setting the device + * context clipping with wxDC::SetClippingRegion(). This is the rectangle used by the + * drawing functions in gr_basic.cpp used to determine if the item to draw is off screen + * and therefore not drawn. + *

+ * @param aDC The device context use for drawing with the correct scale and + * offsets already configured. See DoPrepareDC(). + * @param aRect The clip rectangle in device units or NULL for the entire visible area + * of the screen. + */ + void SetClipBox( wxDC& aDC, const wxRect* aRect = NULL ); + + void ReDraw( wxDC* aDC, bool aEraseBackground = true ); + + /** + * Function RefreshDrawingRect + * redraws the contents of \a aRect in drawing units. \a aRect is converted to + * screen coordinates and wxWindow::RefreshRect() is called to repaint the region. + * @param aRect The rectangle to repaint. + * @param aEraseBackground Erases the background if true. + */ + void RefreshDrawingRect( const EDA_RECT& aRect, bool aEraseBackground = true ); + + /// @copydoc wxWindow::Refresh() + virtual void Refresh( bool eraseBackground = true, const wxRect* rect = NULL ) override; + + /** + * Function GetScreenCenterLogicalPosition + * @return The current screen center position in logical (drawing) units. + */ + wxPoint GetScreenCenterLogicalPosition(); + + /** + * Function MoveCursorToCrossHair + * warps the cursor to the current cross hair position. + */ + void MoveCursorToCrossHair(); + + /** + * Function ToDeviceXY + * transforms logical to device coordinates + */ + wxPoint ToDeviceXY( const wxPoint& pos ); + + /** + * Function ToLogicalXY + * transforms device to logical coordinates + */ + wxPoint ToLogicalXY( const wxPoint& pos ); + + /** + * Function MoveCursor + * moves the mouse pointer to \a aPosition in logical (drawing) units. + * @param aPosition The position in logical units to move the cursor. + */ + void MoveCursor( const wxPoint& aPosition ); + + /* Cursor functions */ + /** + * Function DrawCrossHair + * draws the user cross hair. + *

+ * The user cross hair is not the mouse cursor although they may be at the same screen + * position. The mouse cursor is still render by the OS. This is a drawn cross hair + * that is used to snap to grid when grid snapping is enabled. This is as an indicator + * to where the next user action will take place. + *

+ * @param aDC - the device context to draw the cursor + * @param aColor - the color to draw the cursor + */ + void DrawCrossHair( wxDC* aDC, COLOR4D aColor = COLOR4D::WHITE ); + + // Hide the cross hair. + void CrossHairOff( wxDC* DC ); + + // Show the cross hair. + void CrossHairOn( wxDC* DC ); + + /** + * Function SetMouseCapture + * sets the mouse capture and end mouse capture callbacks to \a aMouseCaptureCallback + * and \a aEndMouseCaptureCallback respectively. + */ + void SetMouseCapture( MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback, + END_MOUSE_CAPTURE_CALLBACK aEndMouseCaptureCallback ) + { + m_mouseCaptureCallback = aMouseCaptureCallback; + m_endMouseCaptureCallback = aEndMouseCaptureCallback; + } + + + void SetMouseCaptureCallback( MOUSE_CAPTURE_CALLBACK aMouseCaptureCallback ) + { + m_mouseCaptureCallback = aMouseCaptureCallback; + } + + + /** + * Function EndMouseCapture + * ends mouse a capture. + * + * Check to see if the cursor is being managed for block or editing commands and release it. + * @param aId The command ID to restore or -1 to keep the current command ID. + * @param aCursorId The wxWidgets stock cursor ID to set the cursor to or -1 to keep the + * current cursor. + * @param aTitle The tool message to display in the status bar or wxEmptyString to clear + * the message. + * @param aCallEndFunc Call the abort mouse capture callback if true. + */ + void EndMouseCapture( int aId = -1, int aCursorId = -1, + const wxString& aTitle = wxEmptyString, + bool aCallEndFunc = true ); + + inline bool IsMouseCaptured() const { return m_mouseCaptureCallback != NULL; } + + /** + * Function CallMouseCapture + * calls the mouse capture callback. + * + * @param aDC A point to a wxDC object to perform any drawing upon. + * @param aPosition A referecnce to a wxPoint object containing the current cursor + * position. + * @param aErase True indicates the item being drawn should be erase before drawing + * it a \a aPosition. + */ + void CallMouseCapture( wxDC* aDC, const wxPoint& aPosition, bool aErase ); + + /** + * Function CallEndMouseCapture + * calls the end mouse capture callback. + * + * @param aDC A point to a wxDC object to perform any drawing upon. + */ + void CallEndMouseCapture( wxDC* aDC ); + + /** + * Function SetCurrentCursor + * Set the current cursor shape for drawpanel + */ + void SetCurrentCursor( int aCursor ) + { + m_currentCursor = aCursor; + SetCursor( (wxStockCursor) m_currentCursor ); + } + + /** + * Function GetDefaultCursor + * @return the default cursor shape + */ + int GetDefaultCursor() const { return m_defaultCursor; } + + /** + * Function GetCurrentCursor + * @return the current cursor shape, depending on the current selected tool + */ + int GetCurrentCursor() const { return m_currentCursor; } + + + DECLARE_EVENT_TABLE() +}; + + +/** + * Class EDA_CROSS_HAIR_MANAGER + * is used to hide the cross hair and restore it when the class goes out of scope. + */ +class EDA_CROSS_HAIR_MANAGER +{ +public: + EDA_CROSS_HAIR_MANAGER( EDA_DRAW_PANEL* aPanel, wxDC* aDC ) : + m_panel( aPanel ), + m_dc( aDC ) + { + if( aPanel && aDC ) + aPanel->CrossHairOff( aDC ); + } + + ~EDA_CROSS_HAIR_MANAGER() + { + if( m_panel && m_dc ) + m_panel->CrossHairOn( m_dc ); + } + +private: + EDA_DRAW_PANEL* m_panel; + wxDC* m_dc; + + DECLARE_NO_COPY_CLASS( EDA_CROSS_HAIR_MANAGER ) +}; + + +#endif /* #ifndef PANEL_WXSTRUCT_H */