diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce290b3..6c6a4aa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -164,6 +164,7 @@ if(APPLE)
MACOSX_BUNDLE_SHORT_VERSION_STRING "${CSV_EXPLORER_VERSION}"
MACOSX_BUNDLE_BUNDLE_VERSION "${CSV_EXPLORER_VERSION}"
MACOSX_BUNDLE_ICON_FILE "csv-explorer.icns"
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in"
)
set_source_files_properties(${CSV_EXPLORER_BUNDLE_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
set_source_files_properties(${CSV_EXPLORER_WINDOW_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
diff --git a/Info.plist.in b/Info.plist.in
new file mode 100644
index 0000000..1e1ecfc
--- /dev/null
+++ b/Info.plist.in
@@ -0,0 +1,43 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${MACOSX_BUNDLE_EXECUTABLE_NAME}
+ CFBundleIconFile
+ ${MACOSX_BUNDLE_ICON_FILE}
+ CFBundleIdentifier
+ ${MACOSX_BUNDLE_GUI_IDENTIFIER}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${MACOSX_BUNDLE_BUNDLE_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ ${MACOSX_BUNDLE_SHORT_VERSION_STRING}
+ CFBundleVersion
+ ${MACOSX_BUNDLE_BUNDLE_VERSION}
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeExtensions
+
+ csv
+
+ CFBundleTypeName
+ Comma-Separated Values File
+ CFBundleTypeRole
+ Editor
+ LSHandlerRank
+ Owner
+ LSItemContentTypes
+
+ public.comma-separated-values-text
+
+
+
+
+
diff --git a/src/main.cpp b/src/main.cpp
index 02a0c90..eb44551 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,9 +13,21 @@ class CsvExplorerApp : public wxApp {
}
auto* frame = CreateMainFrame(initialFile);
+ SetTopWindow(frame);
frame->Show();
return true;
}
+
+#ifdef __WXOSX__
+ void MacOpenFile(const wxString& fileName) override {
+ wxFrame* frame = wxDynamicCast(GetTopWindow(), wxFrame);
+ if (!frame) {
+ return;
+ }
+
+ OpenFileInMainFrame(frame, fileName);
+ }
+#endif
};
wxIMPLEMENT_APP(CsvExplorerApp);
diff --git a/src/main_frame.cpp b/src/main_frame.cpp
index 4e3eca8..6262c6e 100644
--- a/src/main_frame.cpp
+++ b/src/main_frame.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
@@ -133,19 +134,42 @@ class MainFrame : public wxFrame {
public:
explicit MainFrame(const wxString& initialFile)
: wxFrame(nullptr, wxID_ANY, CSV_EXPLORER_NAME, wxDefaultPosition, wxSize(900, 600)) {
+ SetDropTarget(new CsvFileDropTarget(*this));
BuildMenuBar();
BuildAccelerators();
BuildGrid();
BuildStatusBar();
ApplyWindowIcon();
if (!initialFile.IsEmpty()) {
- OpenFile(initialFile);
+ OpenDocumentFile(initialFile);
} else {
CreateNewFile();
}
}
+ bool OpenDocumentFile(const wxString& path) {
+ if (!ConfirmDirtyFileAction()) {
+ return false;
+ }
+
+ OpenFile(path);
+ return !m_currentFile.IsEmpty() && m_currentFile == path;
+ }
+
private:
+ class CsvFileDropTarget final : public wxFileDropTarget {
+ public:
+ explicit CsvFileDropTarget(MainFrame& frame)
+ : m_frame(frame) {}
+
+ bool OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames) override {
+ return m_frame.HandleDroppedFiles(filenames);
+ }
+
+ private:
+ MainFrame& m_frame;
+ };
+
void BuildMenuBar() {
auto* fileMenu = new wxMenu();
fileMenu->Append(wxID_NEW, "&New\tCtrl+N");
@@ -170,9 +194,9 @@ class MainFrame : public wxFrame {
editMenu->AppendSeparator();
auto* goToMenu = new wxMenu();
#ifdef __WXOSX__
- goToMenu->Append(ID_GO_TO_FIRST, "Go to &First\tCmd+Up");
- goToMenu->Append(ID_GO_TO_LAST, "Go to &Last\tCmd+Down");
- goToMenu->Append(ID_GO_TO_ROW, "Go to &Row...\tCmd+G");
+ goToMenu->Append(ID_GO_TO_FIRST, "Go to &First\tCtrl+Up");
+ goToMenu->Append(ID_GO_TO_LAST, "Go to &Last\tCtrl+Down");
+ goToMenu->Append(ID_GO_TO_ROW, "Go to &Row...\tCtrl+G");
#else
goToMenu->Append(ID_GO_TO_FIRST, "Go to &First\tCtrl+Home");
goToMenu->Append(ID_GO_TO_LAST, "Go to &Last\tCtrl+End");
@@ -214,6 +238,8 @@ class MainFrame : public wxFrame {
m_grid->Bind(wxEVT_CHAR_HOOK, &MainFrame::OnGridCharHook, this);
m_grid->Bind(wxEVT_SIZE, &MainFrame::OnGridResized, this);
m_grid->GetGridWindow()->Bind(wxEVT_LEFT_DCLICK, &MainFrame::OnGridWindowLeftDClick, this);
+ m_grid->SetDropTarget(new CsvFileDropTarget(*this));
+ m_grid->GetGridWindow()->SetDropTarget(new CsvFileDropTarget(*this));
m_headerEditor = new wxTextCtrl(
m_grid->GetGridColLabelWindow(),
@@ -691,6 +717,14 @@ class MainFrame : public wxFrame {
ResizeToCsvContent();
}
+ bool HandleDroppedFiles(const wxArrayString& filenames) {
+ if (!IsEffectivelyEmptyDocument() || filenames.empty()) {
+ return false;
+ }
+
+ return OpenDocumentFile(filenames[0]);
+ }
+
void ResizeToCsvContent() {
if (!m_grid || m_rows.empty() || GetColumnCount() == 0) {
return;
@@ -1349,3 +1383,12 @@ wxEND_EVENT_TABLE()
wxFrame* CreateMainFrame(const wxString& initialFile) {
return new MainFrame(initialFile);
}
+
+bool OpenFileInMainFrame(wxFrame* frame, const wxString& path) {
+ auto* mainFrame = dynamic_cast(frame);
+ if (!mainFrame) {
+ return false;
+ }
+
+ return mainFrame->OpenDocumentFile(path);
+}
diff --git a/src/main_frame.h b/src/main_frame.h
index 8a5e368..4bc34ff 100644
--- a/src/main_frame.h
+++ b/src/main_frame.h
@@ -4,3 +4,4 @@ class wxFrame;
class wxString;
wxFrame* CreateMainFrame(const wxString& initialFile);
+bool OpenFileInMainFrame(wxFrame* frame, const wxString& path);