diff --git a/file/CMakeLists.txt b/file/CMakeLists.txt index e0b552014a..b1d9b09122 100644 --- a/file/CMakeLists.txt +++ b/file/CMakeLists.txt @@ -2,7 +2,8 @@ set(SRCS easy_file.cpp chunk_file.cpp zip_read.cpp - file_util.cpp) + file_util.cpp + dialog.cpp) set(SRCS ${SRCS}) diff --git a/file/dialog.cpp b/file/dialog.cpp new file mode 100644 index 0000000000..c2b0565c3c --- /dev/null +++ b/file/dialog.cpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +#include "file/dialog.h" + +bool OpenFileDialog(const char *title, const char *extension, std::string *filename); +bool SaveFileDialog(const char *title, const char *extension, std::string *filename); diff --git a/file/dialog.h b/file/dialog.h new file mode 100644 index 0000000000..bbf5abd252 --- /dev/null +++ b/file/dialog.h @@ -0,0 +1,73 @@ +#pragma once + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include + +// For desktop operating systems only. Stubbed out on Android. +// Simplified as this will only be used in utilities / temp code. +// An false returned means cancel; +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); + + of.lpstrFilter = "All files (*.*)\0*.*\0\0"; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + + of.nMaxFile = 511; + + of.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + if (!GetOpenFileName(&of)) return false; + *filename = of.lpstrFile; + return true; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + OPENFILENAME of; + memset(&of, 0, sizeof(of)); + char buffer[512] = {0}; + of.lStructSize = sizeof(OPENFILENAME); + of.hInstance = 0; + of.hwndOwner = GetActiveWindow(); + + of.lpstrFilter = "All files (*.*)\0*.*\0\0"; + of.lpstrDefExt = extension; + of.lpstrFile = buffer; + + of.nMaxFile = 511; + + of.Flags = OFN_HIDEREADONLY; + if (!GetSaveFileName(&of)) + return false; + *filename = of.lpstrFile; + return true; +} + +#else + +#include +#include "base/basictypes.h" + +bool OpenFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for OpenFileDialog, not present on this platform."); + return false; +} + +bool SaveFileDialog(const char *title, const char *extension, std::string *filename) +{ + ELOG("Asked for SaveFileDialog, not present on this platform."); + return false; +} + +#endif \ No newline at end of file diff --git a/file/file_util.cpp b/file/file_util.cpp index f18d78a95c..4200dbc551 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -12,7 +12,7 @@ #include "file/file_util.h" #include -bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) +bool writeStringToFile(bool text_file, const std::string &str, const char *filename) { FILE *f = fopen(filename, text_file ? "w" : "wb"); if (!f) diff --git a/native.vcxproj b/native.vcxproj index 867891b517..39ef385443 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -107,6 +107,7 @@ + @@ -155,6 +156,7 @@ true + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 2c9e258425..fa24d4ac78 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -150,6 +150,9 @@ midi + + file + @@ -269,6 +272,9 @@ midi + + file + diff --git a/ui/ui.cpp b/ui/ui.cpp index 68efbb0d49..e4a8b50217 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -122,6 +122,50 @@ int UIButton(int id, int x, int y, int w, const char *text, int button_align) { return clicked; } +int UIImageButton(int id, int x, int y, int w, int image, int button_align) { + const int h = 64; + if (button_align & ALIGN_HCENTER) x -= w / 2; + if (button_align & ALIGN_VCENTER) y -= h / 2; + if (button_align & ALIGN_RIGHT) x -= w; + if (button_align & ALIGN_BOTTOMRIGHT) y -= h; + + // Check whether the button should be hot, use a generous margin for touch ease + if (UIRegionHit(x, y, w, h, 8)) { + uistate.hotitem = id; + if (uistate.activeitem == 0 && uistate.mousedown) + uistate.activeitem = id; + } + + // Render button + + int txOffset = 0; + if (uistate.hotitem == id) { + if (uistate.activeitem == id) { + // Button is both 'hot' and 'active' + txOffset = 2; + } else { + // Button is merely 'hot' + } + } else { + // button is not hot, but it may be active + } + ui_draw2d.DrawImage2GridH(themeButtonImage, x, y, x + w); + ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER); + + int clicked = 0; + // If button is hot and active, but mouse button is not + // down, the user must have clicked the button. + if (uistate.mousedown == 0 && + uistate.hotitem == id && + uistate.activeitem == id) { + clicked = 1; + } + + uistate.lastwidget = id; + return clicked; +} + + int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) { const int h = 64; float tw, th;