Initial commit

- Basic main window
- Are you sure you want to exit modal
- Basic settings window
This commit is contained in:
blankie 2022-12-31 15:35:58 +07:00
commit 6632e58e61
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
10 changed files with 440 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.o
*.obj
logmeow
logmeow.exe

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "imgui"]
path = imgui
url = https://github.com/ocornut/imgui.git

91
Makefile Normal file
View File

@ -0,0 +1,91 @@
#
# Cross Platform Makefile
# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X
#
# You will need SDL2 (http://www.libsdl.org):
# Linux:
# apt-get install libsdl2-dev
# Mac OS X:
# brew install sdl2
# MSYS2:
# pacman -S mingw-w64-i686-SDL2
#
#CXX = g++
#CXX = clang++
EXE = logmeow
IMGUI_DIR = imgui
SOURCES = main.cpp config.cpp event_loop.cpp
SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui_draw.cpp $(IMGUI_DIR)/imgui_tables.cpp $(IMGUI_DIR)/imgui_widgets.cpp
SOURCES += $(IMGUI_DIR)/misc/cpp/imgui_stdlib.cpp $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
UNAME_S := $(shell uname -s)
LINUX_GL_LIBS = -lGL
CXXFLAGS = -std=c++11 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/misc/cpp -I$(IMGUI_DIR)/backends
CXXFLAGS += -g -Wall -Wformat
LIBS =
##---------------------------------------------------------------------
## OPENGL ES
##---------------------------------------------------------------------
## This assumes a GL ES library available in the system, e.g. libGLESv2.so
# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2
# LINUX_GL_LIBS = -lGLESv2
## If you're on a Raspberry Pi and want to use the legacy drivers,
## use the following instead:
# LINUX_GL_LIBS = -L/opt/vc/lib -lbrcmGLESv2
##---------------------------------------------------------------------
## BUILD FLAGS PER PLATFORM
##---------------------------------------------------------------------
ifeq ($(UNAME_S), Linux) #LINUX
ECHO_MESSAGE = "Linux"
LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs`
CXXFLAGS += `sdl2-config --cflags`
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(UNAME_S), Darwin) #APPLE
ECHO_MESSAGE = "Mac OS X"
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs`
LIBS += -L/usr/local/lib -L/opt/local/lib
CXXFLAGS += `sdl2-config --cflags`
CXXFLAGS += -I/usr/local/include -I/opt/local/include
CFLAGS = $(CXXFLAGS)
endif
ifeq ($(OS), Windows_NT)
ECHO_MESSAGE = "MinGW"
LIBS += -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2`
CXXFLAGS += `pkg-config --cflags sdl2`
CFLAGS = $(CXXFLAGS)
endif
##---------------------------------------------------------------------
## BUILD RULES
##---------------------------------------------------------------------
%.o:%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/misc/cpp/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
%.o:$(IMGUI_DIR)/backends/%.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $<
$(EXE): $(OBJS)
$(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS)
clean:
rm -f $(EXE) $(OBJS)

71
config.cpp Normal file
View File

@ -0,0 +1,71 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <fstream>
#include "config.h"
std::string get_config_path() {
const char* path;
path = getenv("XDG_CONFIG_HOME");
if (path) {
return std::string(path) + "/logmeow/config";
}
path = getenv("HOME");
if (path) {
return std::string(path) + "/.config/logmeow/config";
}
throw std::runtime_error("cannot find suitable config folder, please set XDG_CONFIG_HOME or HOME");
}
Config parse_config(FILE* file) {
size_t line_capacity_size = 128 * sizeof(char);
char* line = static_cast<char*>(malloc(line_capacity_size));
if (line == nullptr) {
throw std::bad_alloc();
}
Config config;
while (true) {
errno = 0;
if (getline(&line, &line_capacity_size, file) < 0) {
int errsv = errno;
free(line);
if (errsv == ENOMEM) {
throw std::bad_alloc();
} else if (errsv != 0) {
throw std::system_error(errsv, std::generic_category(), "getline()");
} else {
break;
}
}
if (line_capacity_size == 0 || line[0] == '\0' || line[0] == '#') {
continue;
}
if (char* newline = strchr(line, '\n')) {
*newline = '\0';
}
if (strncmp(line, "logcat_command=", 15 * sizeof(char)) == 0) {
config.logcat_command = &line[16];
} else {
std::invalid_argument e = std::invalid_argument(std::string("unknown config line: ") + line);
free(line);
throw e;
}
}
return config;
}
void write_config(std::ofstream& file, const Config& config) {
file << "# This is an auto-generated file, comments made will be lost\n"
<< "# This is a poor man's config file \"format\", there are only three legal lines:\n"
<< "# # a comment, only available at the start of a line\n"
<< "# (an empty line, no whitespace)\n"
<< "# key=value pairs, no spaces around the delimiter, and no unknown keys\n\n"
<< "logcat_command=" << config.logcat_command;
}

12
config.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <string>
#include <fstream>
struct Config {
std::string logcat_command;
};
std::string get_config_path();
Config parse_config(FILE* file);
void write_config(std::ofstream& file, const Config& config);

75
event_loop.cpp Normal file
View File

@ -0,0 +1,75 @@
#include <imgui.h>
#include <imgui_stdlib.h>
#include "config.h"
static inline void settings_window(Config& inactive_config, bool* show_settings_window) {
// by default, the settings window is a bit cramped
ImGui::SetNextWindowSize(ImVec2(575, 75), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Settings", show_settings_window)) {
ImGui::End();
return;
}
ImGui::Text("Persistence coming soon(tm)");
ImGui::InputTextWithHint("Logcat command", "adb logcat -Dv 'threadtime UTC epoch usec'", &inactive_config.logcat_command);
ImGui::End();
}
static inline void main_window(Config& active_config, Config& inactive_config, bool* show_demo_window,
bool* show_settings_window, bool* save_settings_when_settings_window_closed, bool* exit_requested_rev) {
if (!ImGui::Begin("LogMeow", exit_requested_rev)) {
ImGui::End();
return;
}
ImGui::Checkbox("Show Dear ImGui Demo Window", show_demo_window);
if (ImGui::Button("Settings")) {
if (!*show_settings_window) {
inactive_config = active_config;
}
*show_settings_window = true;
*save_settings_when_settings_window_closed = true;
}
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
static inline void exit_modal_if_necessary(bool* run_event_loop) {
if (ImGui::BeginPopupModal("Exit?", nullptr, ImGuiWindowFlags_NoResize)) {
ImGui::Text("Are you sure you want to exit?");
if (ImGui::Button("Yes", ImVec2(120, 0))) {
*run_event_loop = false;
}
ImGui::SameLine();
if (ImGui::Button("No", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
}
ImGui::SetItemDefaultFocus();
ImGui::EndPopup();
}
}
void event_loop(Config& active_config, bool* run_event_loop) {
static bool show_demo_window = false;
static bool show_settings_window = false;
static bool save_settings_when_settings_window_closed = false;
static bool exit_requested_rev = true;
static Config inactive_config;
if (show_demo_window) {
ImGui::ShowDemoWindow(&show_demo_window);
}
if (show_settings_window) {
settings_window(inactive_config, &show_settings_window);
} else if (save_settings_when_settings_window_closed) {
active_config = inactive_config;
}
if (!exit_requested_rev) {
ImGui::OpenPopup("Exit?");
exit_requested_rev = true;
}
exit_modal_if_necessary(run_event_loop);
main_window(active_config, inactive_config, &show_demo_window, &show_settings_window, &save_settings_when_settings_window_closed, &exit_requested_rev);
}

5
event_loop.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "config.h"
void event_loop(Config& config, bool* run_event_loop);

1
imgui Submodule

@ -0,0 +1 @@
Subproject commit e57871bb95faec757e51214bc0e1ae29b13258ab

20
imgui.ini Normal file
View File

@ -0,0 +1,20 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][LogMeow]
Pos=60,60
Size=339,94
Collapsed=0
[Window][Exit?]
Pos=549,324
Size=264,71
Collapsed=0
[Window][Settings]
Pos=88,228
Size=575,75
Collapsed=0

158
main.cpp Normal file
View File

@ -0,0 +1,158 @@
#include <cstdio>
#include <sys/stat.h>
#include <imgui.h>
#include <imgui_impl_sdl.h>
#include <imgui_impl_opengl3.h>
#include <SDL.h>
#if defined(IMGUI_IMPL_OPENGL_ES2)
#include <SDL_opengles2.h>
#else
#include <SDL_opengl.h>
#endif
#include "config.h"
#include "event_loop.h"
int main(int, char**)
{
Config config;
FILE* config_file = nullptr;
try {
config_file = fopen(get_config_path().c_str(), "r");
if (config_file) {
config = parse_config(config_file);
} else if (errno != ENOENT) {
perror("Failed to open config file");
return 1;
}
} catch (const std::exception& e) {
fprintf(stderr, "Failed to parse config: %s\n", e.what());
return 1;
}
if (config_file) {
if (fclose(config_file)) {
perror("Failed to close config file");
}
}
// Setup SDL
// (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
// depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to the latest version of SDL is recommended!)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return -1;
}
// Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
// GL ES 2.0 + GLSL 100
const char* glsl_version = "#version 100";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#elif defined(__APPLE__)
// GL 3.2 Core + GLSL 150
const char* glsl_version = "#version 150";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#else
// GL 3.0 + GLSL 130
const char* glsl_version = "#version 130";
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
// Create window with graphics context
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("LogMeow", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
SDL_GL_MakeCurrent(window, gl_context);
SDL_GL_SetSwapInterval(1); // Enable vsync
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup Platform/Renderer backends
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Main loop
bool run_event_loop = true;
while (run_event_loop)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT) {
run_event_loop = false;
} else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
run_event_loop = false;
}
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
event_loop(config, &run_event_loop);
// Rendering
ImGui::Render();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);
}
// Cleanup
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_GL_DeleteContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}