commit 5fa4a39867a3e777b134eef8c98a62497daed9a0
Author: david.sorber <david.sorber@jacobs.com>
Date:   Fri Feb 23 16:07:09 2024 -0500

    Hasty WIP commit.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 506709e..f1cb994 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 3.22)
-PROJECT("test_gui")
+PROJECT("pwmgr")
 CMAKE_POLICY(SET CMP0054 NEW)
 
 # This is a neat trick to prevent in source builds
@@ -85,6 +85,7 @@ MESSAGE(STATUS "SDL2 include path: ${SDL2_INCLUDE_DIRS}")
 ################################################################################
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/imgui)
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/backend)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/)
 
 
 ################################################################################
@@ -103,19 +104,20 @@ SET(backend_sources
     ${CMAKE_CURRENT_SOURCE_DIR}/src/backend/imgui_impl_sdlrenderer2.cpp
 )
 
+SET(code_sources
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/Catalog.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/CatalogItem.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
+
 
 ################################################################################
-# Target: example
+# Target: pwmgr
 ################################################################################
 
-SET(example_sources
-    ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
-)
-
-ADD_EXECUTABLE(example
+ADD_EXECUTABLE(pwmgr
     ${imgui_sources}
     ${backend_sources}
-    ${example_sources})
+    ${code_sources})
 
-TARGET_INCLUDE_DIRECTORIES(example PUBLIC ${SDL2_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(example ${SDL2_LIBRARIES})
\ No newline at end of file
+TARGET_INCLUDE_DIRECTORIES(pwmgr PUBLIC ${SDL2_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(pwmgr ${SDL2_LIBRARIES})
diff --git a/src/Catalog.cc b/src/Catalog.cc
new file mode 100644
index 0000000..d162341
--- /dev/null
+++ b/src/Catalog.cc
@@ -0,0 +1,56 @@
+#include <algorithm>
+
+#include "Catalog.h"
+
+Catalog::Catalog()
+{
+    // Temporarily fill the catalog with some test data
+    /*
+        {"Target", "baranovich@gmail.com\nF-B-3-7"},
+        {"United", "david.sorber@gmail.com\nF-B-3-7"},
+        {"Pepco", "david.sorber@gmail.com\nNZ-98-O"},
+        {"Washington Gas", "baranovich@gmail.com\nS-N-718"}
+     */
+    m_catalog.push_back({"Target", "baranovich@gmail.com\nF-B-3-7"});
+    m_catalog.push_back({"United", "david.sorber@gmail.com\nF-B-3-7"});
+    m_catalog.push_back({"Pepco", "david.sorber@gmail.com\nNZ-98-O"});
+    m_catalog.push_back({"Washington Gas", "baranovich@gmail.com\nS-N-718"});
+
+    // Sort the catalog (A -> Z) for display purposes
+    std::sort(
+        m_catalog.begin(),
+        m_catalog.end(),
+        [](auto const& lhs, auto const& rhs)
+        {
+            return lhs.getLcKey() < rhs.getLcKey();
+        });
+
+}
+
+Catalog::~Catalog()
+{
+}
+
+void Catalog::setAllVisible()
+{
+    for (auto& item : m_catalog)
+    {
+        item.setVisibilty(true);
+    }
+}
+
+void Catalog::filter(const std::string& criteria)
+{
+    // TODO: would be nice if there were a more efficient way to do this
+    for (auto& item : m_catalog)
+    {
+        if (item.match(criteria))
+        {
+            item.setVisibilty(true);
+        }
+        else
+        {
+            item.setVisibilty(false);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Catalog.h b/src/Catalog.h
new file mode 100644
index 0000000..93b0995
--- /dev/null
+++ b/src/Catalog.h
@@ -0,0 +1,42 @@
+#ifndef __CATALOG_H__
+#define __CATALOG_H__
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "CatalogItem.h"
+
+
+class Catalog
+{
+public:
+
+    Catalog();
+
+    ~Catalog();
+
+    inline std::vector<CatalogItem>::iterator begin()
+    {
+        return m_catalog.begin();
+    }
+
+    inline std::vector<CatalogItem>::iterator end()
+    {
+        return m_catalog.end();
+    }
+
+    void setAllVisible();
+
+    void filter(const std::string& criteria);
+
+
+
+private:
+
+    std::vector<CatalogItem> m_catalog;
+
+};
+
+
+#endif // __CATALOG_H__
\ No newline at end of file
diff --git a/src/CatalogItem.cc b/src/CatalogItem.cc
new file mode 100644
index 0000000..c5a6dc6
--- /dev/null
+++ b/src/CatalogItem.cc
@@ -0,0 +1,27 @@
+#include "CatalogItem.h"
+
+CatalogItem::CatalogItem(const std::string& key, const std::string& value)
+    : m_key(key),
+      m_keyLower(key),
+      m_value(value),
+      m_visible(true)
+{
+    // Create lowercase version of the key's value
+    for (uint32_t idx = 0; idx < m_keyLower.size(); ++idx)
+    {
+        if ((m_keyLower.at(idx) >= 'A') && (m_keyLower.at(idx) <= 'Z'))
+        {
+            m_keyLower.at(idx) = (m_keyLower.at(idx) | 32);
+        }
+    }
+}
+
+CatalogItem::~CatalogItem()
+{
+
+}
+
+bool CatalogItem::match(const std::string& criteria)
+{
+    return m_keyLower.find(criteria) != std::string::npos;
+}
\ No newline at end of file
diff --git a/src/CatalogItem.h b/src/CatalogItem.h
new file mode 100644
index 0000000..74d9eeb
--- /dev/null
+++ b/src/CatalogItem.h
@@ -0,0 +1,69 @@
+#ifndef __CATALOGITEM_H__
+#define __CATALOGITEM_H__
+
+#include <cstdint>
+#include <string>
+
+
+class CatalogItem
+{
+public:
+
+    CatalogItem(const std::string& key, const std::string& value);
+
+    ~CatalogItem();
+
+    inline const std::string& getKey() const
+    {
+        return m_key;
+    }
+
+    inline const std::string& getLcKey() const
+    {
+        return m_keyLower;
+    }
+
+    inline const std::string& getValue() const
+    {
+        return m_value;
+    }
+
+    /**
+     * Should this CatalogItem be visible
+     * @return
+     */
+    inline bool visible() const
+    {
+        return m_visible;
+    }
+
+    /**
+     * Set CatalogItem visibility based on parameter
+     * @param vis
+     */
+    inline void setVisibilty(bool vis)
+    {
+        m_visible = vis;
+    }
+
+
+    /**
+     * Return true if the specified criteria matches the key
+     * @param criteria
+     * @return
+     */
+    bool match(const std::string& criteria);
+
+
+private:
+
+    std::string m_key;
+    std::string m_keyLower;
+    std::string m_value;
+
+    bool m_visible;
+
+};
+
+
+#endif // __CATALOGITEM_H__
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 6eb92d3..6e0a2ca 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -15,6 +15,8 @@
 #include <cstdio>
 #include <cstdint>
 #include <iostream>
+//#include <ostream>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -24,18 +26,56 @@
 #include "imgui_impl_sdl2.h"
 #include "imgui_impl_sdlrenderer2.h"
 
+#include "Catalog.h"
+
 
 #if !SDL_VERSION_ATLEAST(2,0,17)
 #error This backend requires SDL 2.0.17+ because of SDL_RenderGeometry() function
 #endif
 
+const std::string APP_NAME("pwmgr");
+
+const std::string VERSION("v0.0.1");
+
+const std::string BOLD{"\033[1m"};
+const std::string ENDC{"\033[0m"};
+const std::string RED{"\033[31m"};
+const std::string YELLOW{"\033[33m"};
+const std::string PURPLE{"\033[35m"};
+const std::string LBLUE{"\033[1;34m"};
+const std::string UP_ONE = "\033[1A";
+
+
+#define ERROR_MSG       BOLD << RED << "ERROR: " << ENDC
+
+Catalog catalog;
+
+
+static ImGuiInputTextFlags MULTILINE_TEXT_FLAGS = ImGuiInputTextFlags_AllowTabInput;
+
+int catalogFilterCallback(ImGuiInputTextCallbackData* data)
+{
+    if (data->BufTextLen > 0)
+    {
+        std::cout << "BUFFER: " << data->Buf << std::endl;
+        catalog.filter(data->Buf);
+    }
+    else
+    {
+        catalog.setAllVisible();
+    }
+
+    return 0;
+}
+
 // Main code
 int main(int argc, char** argv)
 {
     // Setup SDL
     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
     {
-        printf("Error: %s\n", SDL_GetError());
+        std::cerr << BOLD << RED << "ERROR: " << ENDC << SDL_GetError() << "\n"
+                  << std::endl;
         return -1;
     }
 
@@ -46,13 +86,13 @@ int main(int argc, char** argv)
 
     // Create window with SDL_Renderer graphics context
     SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
-    SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+SDL_Renderer example",
+    SDL_Window* window = SDL_CreateWindow(APP_NAME.c_str(),
                                           SDL_WINDOWPOS_CENTERED,
                                           SDL_WINDOWPOS_CENTERED,
                                           1280, 720, window_flags);
     if (window == nullptr)
     {
-        printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
+        std::cerr << ERROR_MSG << SDL_GetError();
         return -1;
     }
 
@@ -80,7 +120,7 @@ int main(int argc, char** argv)
 //    ImGui::StyleColorsLight();
 
     ImGuiStyle& style = ImGui::GetStyle();
-    style.ScaleAllSizes(4.0);
+    style.ScaleAllSizes(2.0);
 
     // Setup Platform/Renderer backends
     ImGui_ImplSDL2_InitForSDLRenderer(window, renderer);
@@ -164,34 +204,20 @@ int main(int argc, char** argv)
         ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
 #endif
         ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
-        ImGui::Begin("ere i am jh", nullptr,
-//                     ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize |
+        ImGui::Begin("inner window", nullptr,
                      ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_MenuBar);
 
+
         ImGui::PushFont(font);
         {
-            static float f = 0.0f;
-            static uint32_t counter = 0;
-            static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
-            static char text[1024 * 16] =
-                    "/*\n"
-                    " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
-                    " the hexadecimal encoding of one offending instruction,\n"
-                    " more formally, the invalid operand with locked CMPXCHG8B\n"
-                    " instruction bug, is a design flaw in the majority of\n"
-                    " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
-                    " processors (all in the P5 microarchitecture).\n"
-                    "*/\n\n"
-                    "label:\n"
-                    "\tlock cmpxchg8b eax\n";
-
-            // Menubar
+            //---[Menu bar]-----------------------------------------------------
             if (ImGui::BeginMenuBar())
             {
                 if (ImGui::BeginMenu("File"))
                 {
                     if (ImGui::MenuItem("Close", "Ctrl+W"))
                     {
+                        std::cerr << ERROR_MSG << "Closing it out" << std::endl;
                         done = true;
                     }
                     ImGui::EndMenu();
@@ -199,68 +225,72 @@ int main(int argc, char** argv)
                 ImGui::EndMenuBar();
             }
 
-            // Display some text (you can use a format strings too)
-            ImGui::Text("This is some useful text.");
-
-            // Edit bools storing our window open/close state
-            ImGui::Checkbox("Demo Window", &show_demo_window);
-            ImGui::Checkbox("Another Window", &show_another_window);
-
-            // Edit 1 float using a slider from 0.0f to 1.0f
-            ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
+            //---[Left side]----------------------------------------------------
+            static int selected = 0;
+            {
+                ImGui::BeginChild("left_pane", ImVec2(150, 0),
+                                  ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX);
 
-            // Edit 3 floats representing a color
-            ImGui::ColorEdit3("clear color", (float*)&clear_color);
+                for (auto& iter : catalog)
+                {
+                    if (iter.visible() &&
+                        ImGui::CollapsingHeader(iter.getKey().c_str()))
+                    {
+//                        ImGui::Text("%s", iter.second.c_str());
+                        ImGui::InputTextMultiline(
+                            iter.getLcKey().c_str(),
+                            const_cast<char*>(iter.getValue().c_str()),
+                             iter.getValue().size(),
+                             ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 4),
+                            MULTILINE_TEXT_FLAGS);
+                    }
+                }
 
-            // Buttons return true when clicked (most widgets return true when
-            // edited/activated)
-            if (ImGui::Button("Button"))
-            {
-                counter++;
+                ImGui::EndChild();
             }
             ImGui::SameLine();
-            ImGui::Text("counter = %d", counter);
 
-            ImGui::Text("Application average %.3f ms/frame (%.1f FPS)",
-                        1000.0f / io.Framerate, io.Framerate);
+            //---[Right side]---------------------------------------------------
+            {
+                ImGui::BeginGroup();
+                ImGui::BeginChild("item view",
+                                  ImVec2(0, -ImGui::GetFrameHeightWithSpacing()));
 
-            std::vector<std::string> list{"foo", "bar", "qux"};
 
-            for (auto& iter : list)
-            {
-                if (ImGui::CollapsingHeader(iter.c_str()))
+//                ImGui::Text("MyObject: %d", selected);
+                char str0[128]{};
+                ImGui::InputText("Filter", str0,
+                                 IM_ARRAYSIZE(str0),
+                                 ImGuiInputTextFlags_CallbackEdit,
+                                 catalogFilterCallback);
+
+                ImGui::Separator();
+                if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
                 {
-                    ImGui::Text("This is a label. Yes it is.");
+                    if (ImGui::BeginTabItem("Description"))
+                    {
+                        ImGui::TextWrapped(
+                        "Lorem ipsum dolor sit amet, consectetur adipiscing "
+                        "elit, sed do eiusmod tempor incididunt ut labore et"
+                        " dolore magna aliqua. ");
+                        ImGui::EndTabItem();
+                    }
+
+                    if (ImGui::BeginTabItem("Details"))
+                    {
+                        ImGui::Text("ID: 0123456789");
+                        ImGui::EndTabItem();
+                    }
+                    ImGui::EndTabBar();
                 }
-            }
+                ImGui::EndChild();
 
-            if (ImGui::CollapsingHeader("Configuration"))
-            {
-                ImGui::InputTextMultiline("##source", text,
-                                          IM_ARRAYSIZE(text),
-                                          ImVec2(-FLT_MIN,
-                                                 ImGui::GetTextLineHeight() *
-                                                 8),
-                                          flags);
-            }
-            if (ImGui::CollapsingHeader("Bojo"))
-            {
-                ImGui::Text("F.ART");
-            }
-        }
+                if (ImGui::Button("Revert")) {}
+                ImGui::SameLine();
 
-        // 3. Show another simple window.
-        if (show_another_window)
-        {
-            // Pass a pointer to our bool variable (the window will have a
-            // closing button that will clear the bool when clicked)
-            ImGui::Begin("Another Window", &show_another_window);
-            ImGui::Text("Hello from another window!");
-            if (ImGui::Button("Close Me"))
-            {
-                show_another_window = false;
+                if (ImGui::Button("Save")) {}
+                ImGui::EndGroup();
             }
-            ImGui::End();
         }
 
         ImGui::PopFont();
@@ -274,10 +304,7 @@ int main(int argc, char** argv)
                            io.DisplayFramebufferScale.x,
                            io.DisplayFramebufferScale.y);
         SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
-//                               (uint8_t)(clear_color.x * 255),
-//                               (uint8_t)(clear_color.y * 255),
-//                               (uint8_t)(clear_color.z * 255),
-//                               (uint8_t)(clear_color.w * 255));
+
         SDL_RenderClear(renderer);
         ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData());
         SDL_RenderPresent(renderer);
