task editor

This commit is contained in:
2023-03-17 19:25:03 +01:00
parent 42930e7d5e
commit 132d493dc6
4 changed files with 185 additions and 30 deletions

View File

@@ -83,6 +83,7 @@ public:
time_t hoverTargetDay = 0;
TimerData timerData{};
std::mutex timerMutex{};
bool lighthouseProcActive = false;
//ApplicationData(const ApplicationData&) = delete;
//ApplicationData& operator=(const ApplicationData&) = delete;

View File

@@ -94,6 +94,9 @@ void init(DrawData& drawData, ApplicationData& appData)
iconFontPath.append("\\remixicon.ttf");
io.Fonts->AddFontFromFileTTF(iconFontPath.c_str(), 14.0f, &icons_config, icons_ranges);
// style
loadUiStyle();
// Start timer thread
std::thread timerThread(updateTimer, std::ref(appData));
timerThread.detach();
@@ -108,6 +111,8 @@ void init(DrawData& drawData, ApplicationData& appData)
void draw(DrawData& drawData, ApplicationData& appData)
{
const float panelGap = 0.f;
justDocked = false;
appData.hoverTargetType = HoverTargetType::HOVER_TARGET_NONE;
@@ -127,7 +132,7 @@ void draw(DrawData& drawData, ApplicationData& appData)
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
customYCursor += checklistWindow(appData, std::format(" {} Checklist", ICON_CHECK_FILL).c_str()).y;
customYCursor += 5.;
customYCursor += panelGap;
// Timer
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
@@ -138,13 +143,13 @@ void draw(DrawData& drawData, ApplicationData& appData)
ImGui::SetNextWindowPos(ImVec2(viewportSize.x / 2.f, customYCursor));
ImGui::SetNextWindowSize(ImVec2(viewportSize.x / 2.f, 0));
customYCursor += baseStationWindow(appData).y;
customYCursor += 5.;
customYCursor += panelGap;
// Playback Devices
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
ImGui::SetNextWindowSize(ImVec2(viewportSize.x, 0));
customYCursor += audioDeviceWindow(appData, appData.audioData->playbackDevices, std::format(" {} Playback", ICON_HEADPHONE_FILL).c_str()).y;
customYCursor += 5.;
customYCursor += panelGap;
// Recording devices
ImGui::SetNextWindowPos(ImVec2(0, customYCursor));
@@ -179,6 +184,12 @@ void cleanup(DrawData& drawData, ApplicationData& appData)
cleanupShell(drawData);
}
float getButtonWidth(const char* label)
{
ImVec2 labelSize = ImGui::CalcTextSize(label);
return labelSize.x + ImGui::GetStyle().FramePadding.x * 2.f;
}
ImVec2 menuBar(DrawData& drawData, ApplicationData& appData)
{
ImVec2 size{};
@@ -219,7 +230,7 @@ ImVec2 menuBar(DrawData& drawData, ApplicationData& appData)
{
ImVec2 availableSpace = ImGui::GetContentRegionAvail();
ImVec2 cursorPos = ImGui::GetCursorPos();
ImGui::SetCursorPosX(cursorPos.x + availableSpace.x - 47.);
ImGui::SetCursorPosX(cursorPos.x + availableSpace.x - getButtonWidth(ICON_SUBTRACT_FILL) * 2.f);
if (ImGui::SmallButton(ICON_SUBTRACT_FILL))
{
@@ -270,7 +281,7 @@ bool windowHeaderButton(const char* id)
ImVec2 windowMax = ImGui::GetWindowContentRegionMax();
ImGui::PopClipRect();
ImGui::SetCursorPos({ windowMax.x - 20.f, tempPos.y - 28.f });
ImGui::SetCursorPos({ windowMax.x - getButtonWidth(ICON_CLOSE_FILL), tempPos.y - 30.f});
bool result = ImGui::SmallButton(id);
ImGui::PushClipRect(tempRect.Min, tempRect.Max, false);
@@ -441,11 +452,11 @@ ImVec2 timerWindow(DrawData& drawData, ApplicationData& appData)
{
if (timerData.timerHasNotified)
{
formatTime(timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
timerText = std::format("Ended at {}", timeStr);
}
else
{
formatTime(timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
timerText = std::format("Ended at {}", timeStr);
}
else
{
formatTime(appData.timerData.timerStartTimestamp + std::chrono::seconds((int)appData.settings.timerDuration), timeStr, sizeof(timeStr));
timerText = std::format("Ends at {}", timeStr);
}
@@ -531,12 +542,18 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
std::vector<time_t>& taskDates = appData.settings.tasks[taskName];
bool taskDone = std::any_of(taskDates.begin(), taskDates.end(), selectedDayMatcher);
bool highlightButton = false;
std::string hoverText = "";
if (taskDates.size() > 0)
{
time_t mostRecentDoneDate = *std::max_element(taskDates.begin(), taskDates.end());
double timeDiffSeconds = difftime(today, getDayStartOf(mostRecentDoneDate));
int timeDiffDays = timeDiffSeconds / (60 * 60 * 24);
highlightButton = timeDiffDays > appData.checklistHighlightDurationDays;
hoverText = std::format("{}", timeDiffDays);
}
time_t mostRecentDoneDate = *std::max_element(taskDates.begin(), taskDates.end());
double timeDiffSeconds = difftime(today, getDayStartOf(mostRecentDoneDate));
int timeDiffDays = timeDiffSeconds / (60 * 60 * 24);
bool highlightButton = timeDiffDays > appData.checklistHighlightDurationDays;
if (highlightButton)
{
ImGui::PushStyleColor(ImGuiCol_FrameBg, { .5f, .2f, .15f, 0.54f });
@@ -545,7 +562,8 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
}
ImVec2 beforeCheckbox = ImGui::GetCursorScreenPos();
if (ImGui::Checkbox(taskName.c_str(), &taskDone))
std::string checkboxText = std::format("{}##taskcheck{}", taskName.c_str(), taskName.c_str());
if (ImGui::Checkbox(checkboxText.c_str(), &taskDone))
{
if (taskDone)
{
@@ -563,11 +581,10 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
ImGui::PopStyleColor(3);
ImVec2 afterCheckbox = ImGui::GetCursorScreenPos();
std::string dayText = std::format("{}", timeDiffDays);
float textWidth = ImGui::CalcTextSize(dayText.c_str()).x;
float textWidth = ImGui::CalcTextSize(hoverText.c_str()).x;
ImGui::SetCursorScreenPos({ beforeCheckbox.x + ImGui::GetFrameHeight() / 2.f - textWidth / 2.f, beforeCheckbox.y });
ImGui::PushStyleColor(ImGuiCol_Text, { 1.f, 1.f, 1.f, 1.f });
ImGui::Text(dayText.c_str());
ImGui::Text(hoverText.c_str());
ImGui::PopStyleColor();
ImGui::SetCursorScreenPos(afterCheckbox);
}
@@ -575,9 +592,37 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
if (ImGui::BeginPopup(SETTINGS_POPUP_NAME))
{
ImGui::Text("Task Highlight Duration");
ImGui::SameLine();
ImGui::PushItemWidth(75.f);
ImGui::DragInt("Task highlight duration", &appData.checklistHighlightDurationDays, .05f, 1, 7, "%d days");
ImGui::DragInt("##taskduration", &appData.checklistHighlightDurationDays, .05f, 1, 7, "%d days");
ImGui::PopItemWidth();
ImGui::Text("Tasks");
auto taskIterator = appData.settings.taskNames.begin();
while (taskIterator != appData.settings.taskNames.end())
{
size_t taskIndex = taskIterator - appData.settings.taskNames.begin();
std::string& taskName = *taskIterator;
taskName.reserve(128);
ImGui::InputText(std::format("##taskinput{}", taskIndex).c_str(), taskName.data(), taskName.capacity());
ImGui::SameLine();
if (ImGui::SmallButton(std::format("{}##deltask{}", ICON_CLOSE_FILL, taskIndex).c_str()))
{
taskIterator = appData.settings.taskNames.erase(taskIterator);
}
else
{
taskIterator++;
}
}
if (ImGui::Button(ICON_ADD_FILL))
{
appData.settings.taskNames.push_back("");
}
ImGui::EndPopup();
}
}
@@ -587,8 +632,21 @@ ImVec2 checklistWindow(ApplicationData& appData, const char* title)
return size;
}
void startBaseStationProc(const char* args, DWORD flags = 0)
void startBaseStationProc(ApplicationData& appData, const char* args, DWORD flags = 0)
{
if (appData.lighthouseProcActive) return;
appData.lighthouseProcActive = true;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
HANDLE exeOutWrite;
HANDLE exeOutRead;
CreatePipe(&exeOutRead, &exeOutWrite, &saAttr, 0);
SetHandleInformation(exeOutRead, HANDLE_FLAG_INHERIT, 0);
// additional information
STARTUPINFOA si;
PROCESS_INFORMATION pi;
@@ -596,14 +654,33 @@ void startBaseStationProc(const char* args, DWORD flags = 0)
// set the size of the structures
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.hStdOutput = exeOutWrite;
si.dwFlags = STARTF_USESTDHANDLES;
ZeroMemory(&pi, sizeof(pi));
// start the program up
CreateProcessA("lighthouse-v2-manager.exe", const_cast<LPSTR>(args), NULL, NULL, FALSE, flags, NULL, NULL, &si, &pi);
CreateProcessA("lighthouse-v2-manager.exe", const_cast<LPSTR>(args), NULL, NULL, true, flags, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
for (;;)
{
constexpr size_t BUFFER_SIZE = 4096;
char readBuffer[BUFFER_SIZE]{};
DWORD readCount = 0;
bool readSuccess = ReadFile(exeOutRead, readBuffer, BUFFER_SIZE, &readCount, NULL);
if (!readSuccess || readCount == 0) break;
std::cout << readBuffer << std::endl;
}
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(exeOutWrite);
CloseHandle(exeOutRead);
appData.lighthouseProcActive = false;
}
ImVec2 baseStationWindow(ApplicationData& appData)
@@ -623,7 +700,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
params.append(" ");
params.append(mac.c_str());
}
startBaseStationProc(params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
startBaseStationProc(appData, params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
}
ImGui::SameLine();
if (ImGui::Button("Shutdown"))
@@ -634,7 +711,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
params.append(" ");
params.append(mac.c_str());
}
startBaseStationProc(params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
startBaseStationProc(appData, params.c_str(), appData.settings.baseStationShowConsole ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW);
}
}
@@ -643,7 +720,7 @@ ImVec2 baseStationWindow(ApplicationData& appData)
ImGui::Checkbox("Show Console", &appData.settings.baseStationShowConsole);
if (ImGui::Button("Search"))
{
startBaseStationProc("discover");
startBaseStationProc(appData, "discover");
// TODO: parse stuff (annoying)
}
ImGui::Text(std::format("Known: {}", appData.settings.baseStationMacAdresses.size()).c_str());
@@ -664,11 +741,12 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector<AudioDevice>& dev
ImGui::OpenPopup(SETTINGS_POPUP_NAME);
}
if (ImGui::BeginTable("DeviceTable", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings))
if (ImGui::BeginTable("DeviceTable", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_NoSavedSettings))
{
ImGui::TableSetupColumn("Devices", ImGuiTableColumnFlags_WidthStretch, 3.);
ImGui::TableSetupColumn("Volume", ImGuiTableColumnFlags_WidthStretch, 1.);
ImGui::TableSetupColumn("Defaults", ImGuiTableColumnFlags_WidthFixed, 55.);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, getButtonWidth(ICON_MUSIC_2_FILL));
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, getButtonWidth(ICON_PHONE_FILL));
ImGui::TableHeadersRow();
for (auto& dev : deviceList)
@@ -756,22 +834,31 @@ ImVec2 audioDeviceWindow(ApplicationData& appData, std::vector<AudioDevice>& dev
}
// Defaults
const float circleSize = 5.f;
ImGui::TableNextColumn();
if (dev.state == DEVICE_STATE_ACTIVE)
{
if (dev.isDefaultConsole)
{
drawCircle(5, IM_COL32(50, 50, 222, 255));
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + getButtonWidth(ICON_MUSIC_2_FILL) / 2.f - circleSize);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 4.f);
drawCircle(circleSize, IM_COL32(50, 50, 222, 255));
}
if (customButton("bn_d_", deviceIdUtf8.c_str(), ICON_MUSIC_2_FILL, !dev.isDefaultConsole))
{
setDefaultAudioDevice(*appData.audioData, dev.id.c_str(), ERole::eConsole);
}
}
ImGui::SameLine();
ImGui::TableNextColumn();
if (dev.state == DEVICE_STATE_ACTIVE)
{
if (dev.isDefaultCommunication)
{
drawCircle(5, IM_COL32(222, 50, 50, 255));
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + getButtonWidth(ICON_PHONE_FILL) / 2.f - circleSize);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 4.f);
drawCircle(circleSize, IM_COL32(222, 50, 50, 255));
}
if (customButton("bn_c_", deviceIdUtf8.c_str(), ICON_PHONE_FILL, !dev.isDefaultCommunication))
{

View File

@@ -172,3 +172,68 @@ void setAutostart(bool newValue)
if (isError(hr, "Failed to delete autostart key: ")) return;
}
}
void loadUiStyle()
{
ImGuiStyle& style = ImGui::GetStyle();
style.WindowPadding = { 6.f, 8.f };
style.FramePadding = { 8.f, 4.f };
style.ItemSpacing = { 4.f, 4.f };
style.WindowRounding = 4.f;
style.GrabRounding = 2.f;
ImVec4* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.07f, 0.09f, 0.99f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.04f, 0.07f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_FrameBg] = ImVec4(0.02f, 0.01f, 0.01f, 0.54f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.98f, 0.36f, 0.36f, 0.40f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.60f, 0.41f, 0.41f, 0.67f);
colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.48f, 0.16f, 0.16f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.02f, 0.02f, 0.02f, 0.51f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.06f, 0.05f, 0.06f, 0.99f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.98f, 0.61f, 0.26f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.88f, 0.38f, 0.24f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.98f, 0.41f, 0.26f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.04f, 0.01f, 0.03f, 0.73f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.28f, 0.14f, 0.23f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.47f, 0.23f, 0.39f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.46f, 0.19f, 0.12f, 0.67f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.69f, 0.29f, 0.19f, 0.80f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.98f, 0.41f, 0.26f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.45f, 0.43f, 0.50f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.75f, 0.24f, 0.10f, 0.78f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.75f, 0.24f, 0.10f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.98f, 0.41f, 0.26f, 0.20f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.98f, 0.41f, 0.26f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.98f, 0.41f, 0.26f, 0.95f);
colors[ImGuiCol_Tab] = ImVec4(0.09f, 0.02f, 0.07f, 0.86f);
colors[ImGuiCol_TabHovered] = ImVec4(0.28f, 0.15f, 0.24f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.37f, 0.14f, 0.29f, 1.00f);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.15f, 0.09f, 0.07f, 0.97f);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.42f, 0.20f, 0.14f, 1.00f);
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f);
colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
}

View File

@@ -17,3 +17,5 @@ void settingsWriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTex
void applySettings(DrawData& drawData, ApplicationData& appData);
void updateDocked(DrawData& drawData, ApplicationData& appData);
void setAutostart(bool newValue);
void loadUiStyle();