Add saving and loading
This commit is contained in:
parent
8b0efde52a
commit
c1f798be7a
@ -1,5 +1,5 @@
|
|||||||
# Mainspring app CMakeLists.txt
|
# Mainspring app CMakeLists.txt
|
||||||
add_executable(Mainspring WIN32 "src/main.cpp" "src/pch.h" "src/Application.h" "src/Application.cpp" "resource.rc" "src/resources.h")
|
add_executable(Mainspring WIN32 "src/main.cpp" "src/pch.h" "src/Application.h" "src/Application.cpp" "resource.rc" "src/resources.h" "src/utility.h" "src/utility.cpp")
|
||||||
|
|
||||||
set_property(TARGET Mainspring PROPERTY CXX_STANDARD 20)
|
set_property(TARGET Mainspring PROPERTY CXX_STANDARD 20)
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ IDR_MENUMAIN MENU
|
|||||||
BEGIN
|
BEGIN
|
||||||
POPUP "&File"
|
POPUP "&File"
|
||||||
BEGIN
|
BEGIN
|
||||||
MENUITEM "&New Time\tCtrl+N" ID_FILE_NEW
|
MENUITEM "&Reset\tCtrl+R" ID_FILE_RESET
|
||||||
MENUITEM "&Save Time\tCtrl+S" ID_FILE_SAVE
|
MENUITEM "&Save Time\tCtrl+S" ID_FILE_SAVE
|
||||||
MENUITEM "Save Time &As...\tCtrl+Shift+S" ID_FILE_SAVEAS
|
MENUITEM "Save Time &As...\tCtrl+Shift+S" ID_FILE_SAVEAS
|
||||||
MENUITEM "&Open Time\tCtrl+O" ID_FILE_OPEN
|
MENUITEM "&Open Time\tCtrl+O" ID_FILE_OPEN
|
||||||
@ -23,19 +23,19 @@ BEGIN
|
|||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_DIALOGMAIN DIALOGEX 0, 0, 175, 70
|
IDD_DIALOGMAIN DIALOGEX 0, 0, 200, 70
|
||||||
STYLE WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_SETFONT
|
STYLE WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | DS_SETFONT
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
MENU IDR_MENUMAIN
|
MENU IDR_MENUMAIN
|
||||||
BEGIN
|
BEGIN
|
||||||
CTEXT "APPNAME", IDC_STATICTITLE, 30, 0, 115, 20, SS_CENTERIMAGE
|
CTEXT "APPNAME", IDC_STATICTITLE, 0, 0, 200, 20, SS_CENTERIMAGE
|
||||||
CTEXT "TIME", IDC_STATICTIME, 8, 20, 158, 28, SS_CENTERIMAGE | SS_SUNKEN
|
CTEXT "TIME", IDC_STATICTIME, 8, 20, 184, 28, SS_CENTERIMAGE | SS_SUNKEN
|
||||||
DEFPUSHBUTTON "STARTPAUSE" IDC_BUTTONSTARTPAUSE, 63, 53, 50, 15
|
DEFPUSHBUTTON "STARTPAUSE" IDC_BUTTONSTARTPAUSE, 75, 53, 50, 15
|
||||||
END
|
END
|
||||||
|
|
||||||
IDA_ACCELMAIN ACCELERATORS
|
IDA_ACCELMAIN ACCELERATORS
|
||||||
BEGIN
|
BEGIN
|
||||||
"N", ID_FILE_NEW, CONTROL, VIRTKEY
|
"R", ID_FILE_RESET, CONTROL, VIRTKEY
|
||||||
"S", ID_FILE_SAVE, CONTROL, VIRTKEY
|
"S", ID_FILE_SAVE, CONTROL, VIRTKEY
|
||||||
"S", ID_FILE_SAVEAS, CONTROL, SHIFT, VIRTKEY
|
"S", ID_FILE_SAVEAS, CONTROL, SHIFT, VIRTKEY
|
||||||
"O", ID_FILE_OPEN, CONTROL, VIRTKEY
|
"O", ID_FILE_OPEN, CONTROL, VIRTKEY
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
// Define timer IDs
|
||||||
|
#define IDT_UPDATEAPP 1
|
||||||
|
#define IDT_SAVEDTEXT 2
|
||||||
|
|
||||||
// Define window message to update the timer display
|
// Define window message to update the timer display
|
||||||
#define WM_UPDATEAPP WM_USER + 1
|
#define WM_UPDATEAPP WM_USER + 1
|
||||||
@ -15,9 +20,13 @@ namespace mainspring {
|
|||||||
Application::Application(const char* appName, const char* appVersion)
|
Application::Application(const char* appName, const char* appVersion)
|
||||||
: m_appName(appName)
|
: m_appName(appName)
|
||||||
, m_appVersion(appVersion)
|
, m_appVersion(appVersion)
|
||||||
|
, m_dlg()
|
||||||
, m_timing(false)
|
, m_timing(false)
|
||||||
, m_startpauseButtonPressed(false)
|
, m_startpauseButtonPressed(false)
|
||||||
, m_elapsedSaved()
|
, m_elapsedSaved()
|
||||||
|
, m_startTime()
|
||||||
|
, m_file()
|
||||||
|
, m_showSavedText(false)
|
||||||
{
|
{
|
||||||
std::cout << std::format("{} {}\n", m_appName, m_appVersion);
|
std::cout << std::format("{} {}\n", m_appName, m_appVersion);
|
||||||
}
|
}
|
||||||
@ -25,14 +34,14 @@ namespace mainspring {
|
|||||||
void Application::run() {
|
void Application::run() {
|
||||||
// Read last time here
|
// Read last time here
|
||||||
|
|
||||||
HWND dlg = CreateDialogParam(nullptr, MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(this));
|
m_dlg = CreateDialogParam(nullptr, MAKEINTRESOURCE(IDD_DIALOGMAIN), nullptr, reinterpret_cast<DLGPROC>(mainDlgProc), reinterpret_cast<LPARAM>(this));
|
||||||
|
|
||||||
HACCEL hAccel = LoadAccelerators(GetModuleHandle(NULL), MAKEINTRESOURCE(IDA_ACCELMAIN));
|
HACCEL hAccel = LoadAccelerators(GetModuleHandle(NULL), MAKEINTRESOURCE(IDA_ACCELMAIN));
|
||||||
MSG msg = {};
|
MSG msg = {};
|
||||||
ShowWindow(dlg, SW_SHOW);
|
ShowWindow(m_dlg, SW_SHOW);
|
||||||
while (GetMessage(&msg, nullptr, 0, 0))
|
while (GetMessage(&msg, nullptr, 0, 0))
|
||||||
if (!TranslateAccelerator(dlg, hAccel, &msg))
|
if (!TranslateAccelerator(m_dlg, hAccel, &msg))
|
||||||
IsDialogMessage(dlg, &msg);
|
IsDialogMessage(m_dlg, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
BOOL CALLBACK Application::mainDlgProc(HWND dlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||||
@ -52,7 +61,6 @@ namespace mainspring {
|
|||||||
GetMonitorInfo(MonitorFromPoint(cursor, MONITOR_DEFAULTTONEAREST), &mi);
|
GetMonitorInfo(MonitorFromPoint(cursor, MONITOR_DEFAULTTONEAREST), &mi);
|
||||||
SetWindowPos(dlg, nullptr, mi.rcMonitor.left + 100, mi.rcMonitor.top + 100, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
SetWindowPos(dlg, nullptr, mi.rcMonitor.left + 100, mi.rcMonitor.top + 100, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
||||||
|
|
||||||
SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName);
|
|
||||||
LOGFONT lFont = {};
|
LOGFONT lFont = {};
|
||||||
lFont.lfHeight = 30;
|
lFont.lfHeight = 30;
|
||||||
HFONT titleFont = CreateFontIndirect(&lFont);
|
HFONT titleFont = CreateFontIndirect(&lFont);
|
||||||
@ -64,7 +72,7 @@ namespace mainspring {
|
|||||||
SendMessage(GetDlgItem(dlg, IDC_STATICTIME), WM_SETFONT, reinterpret_cast<WPARAM>(timeFont), NULL);
|
SendMessage(GetDlgItem(dlg, IDC_STATICTIME), WM_SETFONT, reinterpret_cast<WPARAM>(timeFont), NULL);
|
||||||
|
|
||||||
SendMessage(dlg, WM_UPDATEAPP, NULL, NULL);
|
SendMessage(dlg, WM_UPDATEAPP, NULL, NULL);
|
||||||
SetTimer(dlg, 1, 50, nullptr);
|
SetTimer(dlg, IDT_UPDATEAPP, 50, nullptr);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -75,23 +83,29 @@ namespace mainspring {
|
|||||||
app->m_startpauseButtonPressed = true;
|
app->m_startpauseButtonPressed = true;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
case ID_FILE_NEW: {
|
case ID_FILE_RESET: {
|
||||||
std::cout << std::format("New!\n");
|
if (!app->m_file.empty())
|
||||||
|
app->save();
|
||||||
|
|
||||||
|
app->reset();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ID_FILE_SAVE: {
|
case ID_FILE_SAVE: {
|
||||||
std::cout << std::format("Save!\n");
|
app->save();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ID_FILE_SAVEAS: {
|
case ID_FILE_SAVEAS: {
|
||||||
std::cout << std::format("Save As!\n");
|
app->save(true);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ID_FILE_OPEN: {
|
case ID_FILE_OPEN: {
|
||||||
std::cout << std::format("Open!\n");
|
if (!app->m_file.empty())
|
||||||
|
app->save();
|
||||||
|
|
||||||
|
app->open();
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,9 +122,20 @@ namespace mainspring {
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
|
switch (wParam) {
|
||||||
|
case IDT_UPDATEAPP:
|
||||||
SendMessage(dlg, WM_UPDATEAPP, NULL, NULL);
|
SendMessage(dlg, WM_UPDATEAPP, NULL, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
case IDT_SAVEDTEXT:
|
||||||
|
app->m_showSavedText = false;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
case WM_UPDATEAPP: {
|
case WM_UPDATEAPP: {
|
||||||
if (app->m_startpauseButtonPressed) {
|
if (app->m_startpauseButtonPressed) {
|
||||||
app->m_startpauseButtonPressed = false;
|
app->m_startpauseButtonPressed = false;
|
||||||
@ -123,22 +148,33 @@ namespace mainspring {
|
|||||||
app->m_timing = !app->m_timing;
|
app->m_timing = !app->m_timing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (app->m_showSavedText)
|
||||||
|
SetDlgItemText(dlg, IDC_STATICTITLE, "Saved!");
|
||||||
|
|
||||||
|
else if (!app->m_file.empty()) {
|
||||||
|
std::string filename = app->m_file.substr(app->m_file.find_last_of('\\') + 1);
|
||||||
|
SetDlgItemText(dlg, IDC_STATICTITLE, filename.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetDlgItemText(dlg, IDC_STATICTITLE, app->m_appName);
|
||||||
|
|
||||||
if (app->m_timing)
|
if (app->m_timing)
|
||||||
SetDlgItemText(dlg, IDC_BUTTONSTARTPAUSE, "Pause");
|
SetDlgItemText(dlg, IDC_BUTTONSTARTPAUSE, "Pause");
|
||||||
else
|
else
|
||||||
SetDlgItemText(dlg, IDC_BUTTONSTARTPAUSE, !app->m_elapsedSaved ? "Start" : "Resume");
|
SetDlgItemText(dlg, IDC_BUTTONSTARTPAUSE, !app->m_elapsedSaved ? "Start" : "Resume");
|
||||||
|
|
||||||
|
|
||||||
Seconds totalTime = app->m_elapsedSaved + app->getElapsed();
|
Seconds totalTime = app->m_elapsedSaved + app->getElapsed();
|
||||||
|
|
||||||
uint32_t hr = totalTime / (3600), min = totalTime % (3600) / 60, sec = totalTime % 60;
|
uint32_t hr = totalTime / (3600), min = totalTime % (3600) / 60, sec = totalTime % 60;
|
||||||
SetDlgItemText(dlg, IDC_STATICTIME, std::format("{:02}:{:02}:{:02}", hr, min, sec).c_str());
|
SetDlgItemText(dlg, IDC_STATICTIME, std::format("{:03}:{:02}:{:02}", hr, min, sec).c_str());
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
// TODO: Ask to / save time here
|
if (!app->m_file.empty())
|
||||||
|
app->save();
|
||||||
|
|
||||||
KillTimer(dlg, 1);
|
KillTimer(dlg, 1);
|
||||||
DestroyWindow(dlg);
|
DestroyWindow(dlg);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -157,4 +193,57 @@ namespace mainspring {
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::reset() {
|
||||||
|
m_timing = false;
|
||||||
|
m_elapsedSaved = 0;
|
||||||
|
m_file.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::save(bool saveas) {
|
||||||
|
if (m_file.empty() || saveas) {
|
||||||
|
OPENFILENAME ofn = {};
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hwndOwner = m_dlg;
|
||||||
|
ofn.lpstrFilter = "Mainspring Time File (*.mspring)\0*.mspring\0\0";
|
||||||
|
ofn.lpstrDefExt = "mspring";
|
||||||
|
char fileBuf[MAX_PATH] = {};
|
||||||
|
ofn.lpstrFile = fileBuf;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
ofn.Flags = OFN_OVERWRITEPROMPT;
|
||||||
|
|
||||||
|
if (GetSaveFileName(&ofn))
|
||||||
|
m_file = fileBuf;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Seconds totalTime = m_elapsedSaved + getElapsed();
|
||||||
|
std::string saveData = std::to_string(totalTime);
|
||||||
|
writeFile(m_file.c_str(), saveData);
|
||||||
|
m_showSavedText = true;
|
||||||
|
SetTimer(m_dlg, IDT_SAVEDTEXT, 3000, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::open() {
|
||||||
|
OPENFILENAME ofn = {};
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hwndOwner = m_dlg;
|
||||||
|
ofn.lpstrFilter = "Mainspring Time File (*.mspring)\0*.mspring\0\0";
|
||||||
|
ofn.lpstrDefExt = "mspring";
|
||||||
|
char fileBuf[MAX_PATH] = {};
|
||||||
|
ofn.lpstrFile = fileBuf;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
||||||
|
|
||||||
|
if (GetOpenFileName(&ofn))
|
||||||
|
m_file = fileBuf;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string openData;
|
||||||
|
if (readFile(m_file.c_str(), openData))
|
||||||
|
// Update status text;
|
||||||
|
m_elapsedSaved = std::stoull(openData);
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,13 +17,21 @@ namespace mainspring {
|
|||||||
|
|
||||||
Seconds getElapsed(); // Gets the current timing session time
|
Seconds getElapsed(); // Gets the current timing session time
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
void save(bool saveas = false);
|
||||||
|
void open();
|
||||||
|
|
||||||
const char* m_appName;
|
const char* m_appName;
|
||||||
const char* m_appVersion;
|
const char* m_appVersion;
|
||||||
|
|
||||||
// Current "Time" (state of the app)
|
HWND m_dlg;
|
||||||
|
|
||||||
|
// Current state of the app
|
||||||
bool m_timing; // Currently timing?
|
bool m_timing; // Currently timing?
|
||||||
bool m_startpauseButtonPressed; // Was the start / pause button pressed?
|
bool m_startpauseButtonPressed; // Was the start / pause button pressed?
|
||||||
Seconds m_elapsedSaved; // Time saved
|
Seconds m_elapsedSaved; // Time saved
|
||||||
TimePoint m_startTime; // When the current timing session was started
|
TimePoint m_startTime; // When the current timing session was started
|
||||||
|
std::string m_file; // Current time file path
|
||||||
|
bool m_showSavedText; // Save confirmation
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -12,3 +12,4 @@
|
|||||||
// Windows
|
// Windows
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <commdlg.h>
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
#define IDR_MENUMAIN 301
|
#define IDR_MENUMAIN 301
|
||||||
#define ID_FILE_NEW 302
|
#define ID_FILE_RESET 302
|
||||||
#define ID_FILE_SAVE 303
|
#define ID_FILE_SAVE 303
|
||||||
#define ID_FILE_SAVEAS 304
|
#define ID_FILE_SAVEAS 304
|
||||||
#define ID_FILE_OPEN 305
|
#define ID_FILE_OPEN 305
|
||||||
|
26
Mainspring/src/utility.cpp
Normal file
26
Mainspring/src/utility.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Utility implementation
|
||||||
|
#include "pch.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
namespace mainspring {
|
||||||
|
bool readFile(const char* filename, std::string& out) {
|
||||||
|
std::ifstream fileStream(filename, std::ios::binary | std::ios::ate);
|
||||||
|
if (!fileStream.is_open())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t fileSize = fileStream.tellg();
|
||||||
|
fileStream.seekg(0);
|
||||||
|
out.resize(fileSize);
|
||||||
|
fileStream.read(out.data(), fileSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writeFile(const char* filename, const std::string& in) {
|
||||||
|
std::ofstream fileStream(filename, std::ios::binary | std::ios::trunc);
|
||||||
|
if (!fileStream.is_open())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fileStream << in;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
6
Mainspring/src/utility.h
Normal file
6
Mainspring/src/utility.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Utility header
|
||||||
|
|
||||||
|
namespace mainspring {
|
||||||
|
bool readFile(const char* filename, std::string& out);
|
||||||
|
bool writeFile(const char* filename, const std::string& in);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user