28#include <wx/splitter.h>
29#include <wx/stattext.h>
30#include <wx/stc/stc.h>
51 for(
const std::vector<KICAD_DIFF::SCENE_SHAPE>* shapes :
57 BOX2I box = shapes->front().bbox;
63 int padX =
static_cast<int>( minSide - box.
GetWidth() ) / 2;
64 int padY =
static_cast<int>( minSide - box.
GetHeight() ) / 2;
65 box.
Inflate( std::max( 0, padX ), std::max( 0, padY ) );
73std::string readAll(
const wxString& aFile )
78 std::ifstream in( aFile.fn_str(), std::ios::binary );
79 return std::string( ( std::istreambuf_iterator<char>( in ) ), std::istreambuf_iterator<char>() );
83struct FILE_DIFF_RESULT
86 std::unique_ptr<GIT_DIFF_WORKSPACE> workspace;
88 std::vector<KIGIT::TEXT_DIFF_LINE> textLines;
107 wxBoxSizer* sizer =
new wxBoxSizer( wxVERTICAL );
110 m_note =
new wxStaticText(
this, wxID_ANY, wxEmptyString );
111 m_canvasSplitter =
new wxSplitterWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
112 wxSP_LIVE_UPDATE | wxSP_3DSASH );
115 m_textDiff =
new wxStyledTextCtrl(
this, wxID_ANY );
119 m_legend =
new wxBoxSizer( wxHORIZONTAL );
121 for(
const auto& [colour, label] : { std::make_pair( theme.
added,
_(
"Added" ) ),
122 std::make_pair( theme.
removed,
_(
"Removed" ) ),
123 std::make_pair( theme.
modified,
_(
"Modified" ) ) } )
125 wxPanel* swatch =
new wxPanel(
this, wxID_ANY, wxDefaultPosition, FromDIP( wxSize( 12, 12 ) ) );
126 swatch->SetBackgroundColour( colour.ToColour() );
127 m_legend->Add( swatch, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 4 );
128 m_legend->Add(
new wxStaticText(
this, wxID_ANY, label ), 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 16 );
131 sizer->Add(
m_note, 0, wxEXPAND | wxALL, 4 );
133 sizer->Add(
m_legend, 0, wxLEFT | wxTOP, 4 );
161 const wxString& aBeforeLabel,
const wxString& aAfterLabel )
163 showNote(
_(
"Loading comparison..." ) );
165 auto result = std::make_shared<FILE_DIFF_RESULT>();
166 result->sides.error =
_(
"Could not compare this file." );
172 result->workspace = std::make_unique<GIT_DIFF_WORKSPACE>();
174 if( !
result->workspace->IsOk() )
176 result->sides.error =
_(
"Could not create a temporary directory for the diff." );
180 if( !aMaterialize( aCommon, *
result->workspace,
result->sides ) )
185 std::string before = readAll(
result->sides.before );
186 std::string after = readAll(
result->sides.after );
190 result->sides.error =
_(
"This is not a plain text file, so there is no comparison to show." );
200 [
this,
result, aSession, aBeforeLabel, aAfterLabel]()
202 if(
m_frame->Prj().GetGitCommon() != aSession )
220 m_note->SetLabel( aNote );
223 GetSizer()->Show(
m_legend,
false );
230 const wxString& aBeforeLabel,
const wxString& aAfterLabel )
239 showNote(
_(
"Double click the file to open its comparison." ) );
252 GetSizer()->Show(
m_legend,
false );
258 const wxString& aAfter,
const wxString& aBeforeLabel,
259 const wxString& aAfterLabel )
283 std::optional<BOX2I> focus = firstChangeBox( scene, aKind );
312 if( frame->GetCanvas() )
313 backend = frame->GetCanvas()->GetBackend();
319 wxBoxSizer* sizer =
new wxBoxSizer( wxVERTICAL );
321 *aLabel =
new wxStaticText( side, wxID_ANY, wxEmptyString );
324 sizer->Add( *aLabel, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 4 );
325 sizer->Add( *aCanvas, 1, wxEXPAND );
326 side->SetSizer( sizer );
367 auto onInput = [
this, aLead, aFollower]( wxMouseEvent& aEvent )
372 [
this, aLead, aFollower]()
390 aLead->Bind( wxEVT_MOTION, onInput );
391 aLead->Bind( wxEVT_MOUSEWHEEL, onInput );
392 aLead->Bind( wxEVT_MAGNIFY, onInput );
393 aLead->Bind( wxEVT_LEFT_UP, onInput );
394 aLead->Bind( wxEVT_MIDDLE_UP, onInput );
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
The base frame for deriving all KiCad main window classes.
The base class for create windows for drawing purpose.
static constexpr GAL_TYPE GAL_FALLBACK
virtual KIGFX::VIEW * GetView() const
Return a pointer to the KIGFX::VIEW instance used in the panel.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
std::function< bool(KIGIT_COMMON &, GIT_DIFF_WORKSPACE &, GIT_FILE_SIDES &)> MATERIALIZE
Writes the two sides on a worker with the session's action lock held.
wxStyledTextCtrl * m_textDiff
KIGIT_QUERY m_query
A newer file selection discards any materialization still running for the previous one.
void showDiff(const GIT_FILE_SIDES &aSides, const std::vector< KIGIT::TEXT_DIFF_LINE > &aTextLines, const wxString &aBeforeLabel, const wxString &aAfterLabel)
GIT_FILE_DIFF_AREA(wxWindow *aParent, EDA_BASE_FRAME *aFrame)
void followCanvas(WIDGET_DIFF_CANVAS *aLead, WIDGET_DIFF_CANVAS *aFollower)
Give aFollower the view of aLead, so panning or zooming one moves both.
~GIT_FILE_DIFF_AREA() override
bool showDrawingDiff(KICAD_DIFF::DOC_KIND aKind, const wxString &aBefore, const wxString &aAfter, const wxString &aBeforeLabel, const wxString &aAfterLabel)
void showTextDiff(const std::vector< KIGIT::TEXT_DIFF_LINE > &aLines)
std::unique_ptr< KICAD_DIFF::DIFF_CANVAS_CONTEXT > m_diffContext
The documents the two canvases draw, held by the kiface that loaded them.
WIDGET_DIFF_CANVAS * m_afterCanvas
wxStaticText * m_beforeLabel
wxSplitterWindow * m_canvasSplitter
void ShowFile(const std::shared_ptr< KIGIT_COMMON > &aSession, const MATERIALIZE &aMaterialize, const wxString &aBeforeLabel, const wxString &aAfterLabel)
Compare the two sides aMaterialize writes out, or show its reason instead.
void showNote(const wxString &aNote)
void ensureCanvases()
The two drawing canvases exist only while a drawing is compared.
WIDGET_DIFF_CANVAS * m_beforeCanvas
wxStaticText * m_afterLabel
void Clear()
Drop the documents and the drawing canvases.
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
virtual void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 })
Set the scaling factor, zooming around a given anchor point.
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
The project's git session.
A wrapper for reporting to a wxString object.
void FillTextDiffControl(wxStyledTextCtrl *aCtrl, const std::vector< KIGIT::TEXT_DIFF_LINE > &aLines)
Fill aCtrl with a line diff, added and removed lines in the diff colours, and make it read only.
DIFF_SCENE BuildScene(const DOCUMENT_DIFF &aDiff, const DIFF_COLOR_THEME &aTheme)
Build a DIFF_SCENE from a DOCUMENT_DIFF, populating the shape lists and computing the union bbox.
SIDE_BY_SIDE_SCENES SplitSceneBySide(const DIFF_SCENE &aScene)
const EDA_IU_SCALE & IuScaleForDocKind(DOC_KIND aKind)
Internal-unit scale a document kind's coordinates are expressed in.
std::unique_ptr< DIFF_CANVAS_CONTEXT > DispatchAttachDiffCanvases(KIWAY &aKiway, DOC_KIND aKind, const wxString &aFileA, const wxString &aFileB, WIDGET_DIFF_CANVAS &aBefore, WIDGET_DIFF_CANVAS &aAfter, DOCUMENT_DIFF &aDiff, REPORTER *aReporter)
Diff two files in the owning kiface through its KIFACE_ATTACH_DIFF_CANVASES export.
DOC_KIND
Document type a diff/merge entry point should route to, derived from a file path's extension.
std::vector< wxString > SplitTextLines(const std::string &aContent)
Tolerates CRLF endings and content that is not valid UTF-8.
bool TextLooksBinary(const std::string &aContent)
std::vector< TEXT_DIFF_LINE > BuildTextDiff(const std::vector< wxString > &aOld, const std::vector< wxString > &aNew)
Every line of both sides appears once. There are no hunks and nothing is elided.
constexpr int mmToIU(double mm) const
The two sides of one file, written out for a comparison.
KICAD_DIFF::DOC_KIND kind
wxString before
Empty when the file did not exist on that side.
Diff colors with defaults for light backgrounds.
std::vector< SCENE_SHAPE > modifiedShapes
std::vector< SCENE_SHAPE > addedShapes
DOC_KIND docKind
Source document type.
std::vector< SCENE_SHAPE > removedShapes
The full set of changes between two parsed documents of one type.
The two halves of a side by side view.
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.