From 9d5f07c882e1270783c5d89b3c25e7c160a48d6b Mon Sep 17 00:00:00 2001
From: Odilitime <janesmith@airmail.cc>
Date: Tue, 22 Aug 2017 04:28:52 -0700
Subject: [PATCH] onMouseOut relay, cursor property, don't rely on window
 global/use win property, updateMouse(), renderComponentType()

---
 src/graphics/components/MultiComponent.cpp | 123 ++++++++++++++++-----
 src/graphics/components/MultiComponent.h   |  22 +++-
 2 files changed, 117 insertions(+), 28 deletions(-)

diff --git a/src/graphics/components/MultiComponent.cpp b/src/graphics/components/MultiComponent.cpp
index b9d209da..177c1e78 100644
--- a/src/graphics/components/MultiComponent.cpp
+++ b/src/graphics/components/MultiComponent.cpp
@@ -1,7 +1,10 @@
 #include "MultiComponent.h"
-#include "DocumentComponent.h"
 #include <iostream>
 
+#include "DocumentComponent.h"
+#include "TabbedComponent.h"
+#include "AnimeComponent.h"
+
 MultiComponent::MultiComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight) {
     
     // take our space (for parent picking)
@@ -13,35 +16,25 @@ MultiComponent::MultiComponent(const float rawX, const float rawY, const float r
     // not really needed but nothing else sets this
     windowWidth = passedWindowWidth;
     windowHeight = passedWindowHeight;
+    
+    // we need a mouseout to mouseout our hovercomponent
+    onMouseout=[this]() {
+        if (this->hoverComponent && this->hoverComponent->onMouseout) {
+            this->hoverComponent->onMouseout();
+        }
+        // select nothing
+        this->hoverComponent = nullptr;
+    };
         
     onMousemove=[this](int passedX, int passedY) {
-        // set hover component
-        static int lx = 0;
-        static int ly = 0;
         //std::cout << "MultiComponent::MultiComponent:onMousemove - at " << passedX << "," << passedY << std::endl;
-        if (lx == passedX && ly == passedY) {
+        if (this->cursorX == passedX && this->cursorY == passedY) {
             return;
         }
-        lx = passedX;
-        ly = passedY;
+        this->cursorX = passedX;
+        this->cursorY = passedY;
         //std::cout << "MultiComponent::MultiComponent:onMousemove - size " << this->windowWidth << "," << this->windowHeight << std::endl;
-        // we need to make pX/pY relative to this component?
-        this->hoverComponent = this->searchComponentTree(this->rootComponent, passedX, passedY);
-        if (this->hoverComponent) {
-            //std::cout << "MultiComponent::MultiComponent:onMousemove - hovering over " << typeOfComponent(this->hoverComponent) << " component" << std::endl;
-            if (this->hoverComponent->onMousemove) {
-                // this could communicate the cursor to use
-                this->hoverComponent->onMousemove(passedX, passedY);
-            } else {
-            if (this->hoverComponent->onClick) {
-                glfwSetCursor(this->win->window, this->win->cursorHand);
-            } else {
-                glfwSetCursor(this->win->window, this->win->cursorIbeam);
-            }
-            }
-        } else {
-            glfwSetCursor(this->win->window, this->win->cursorArrow);
-        }
+        this->updateMouse();
     };
     onMousedown=[this](int passedX, int passedY) {
         //std::cout << "MultiComponent left press" << std::endl;
@@ -90,11 +83,13 @@ MultiComponent::MultiComponent(const float rawX, const float rawY, const float r
                 // ok we can't communicate through the component
                 //std::cout << "unloaded2 " << this->parent->unloaded << std::endl;
                 // we can through the window global
-                //std::cout << "win unloaded focus: " << window->focusedComponent << std::endl;
-                //std::cout << "win unloaded hover: " << window->hoverComponent << std::endl;
+                //std::cout << "window unloaded focus: " << window->focusedComponent << std::endl;
+                //std::cout << "window unloaded hover: " << window->hoverComponent << std::endl;
+                //std::cout << "win unloaded focus: " << this->win->focusedComponent << std::endl;
+                //std::cout << "win unloaded hover: " << this->win->hoverComponent << std::endl;
             }
             // make sure we weren't unloaded by last click and check for additional events
-            if (window->hoverComponent != nullptr && this->focusedComponent->onClick) {
+            if (this->win->focusedComponent != nullptr && this->focusedComponent->onClick) {
                 //std::cout << "click event" << std::endl;
                 this->focusedComponent->onClick();
             }
@@ -158,6 +153,36 @@ MultiComponent::MultiComponent(const float rawX, const float rawY, const float r
     };
 }
 
+// update component hover (need to call on component change)
+void MultiComponent::updateMouse() {
+    // do we need to make pX/pY relative to this component? no, we just made the picking system take mouse coordinates
+    std::shared_ptr<Component> newHover = this->searchComponentTree(this->rootComponent, this->cursorX, this->cursorY);
+    if (newHover != this->hoverComponent) {
+        if (this->hoverComponent && this->hoverComponent->onMouseout) {
+            this->hoverComponent->onMouseout();
+        }
+        if (newHover && newHover->onMouseover) {
+            newHover->onMouseover();
+        }
+        this->hoverComponent = newHover;
+    }
+    if (this->hoverComponent) {
+        //std::cout << "MultiComponent::MultiComponent:onMousemove - hovering over " << typeOfComponent(this->hoverComponent) << " component" << std::endl;
+        if (this->hoverComponent->onMousemove) {
+            // this could communicate the cursor to use
+            this->hoverComponent->onMousemove(this->cursorX, this->cursorY);
+        } else {
+            if (this->hoverComponent->onClick) {
+                glfwSetCursor(this->win->window, this->win->cursorHand);
+            } else {
+                glfwSetCursor(this->win->window, this->win->cursorIbeam);
+            }
+        }
+    } else {
+        glfwSetCursor(this->win->window, this->win->cursorArrow);
+    }    
+}
+
 //#include "ComponentBuilder.h"
 
 void MultiComponent::resize(const int passedWindowWidth, const int passedWindowHeight) {
@@ -266,6 +291,50 @@ void MultiComponent::renderBoxComponents(std::shared_ptr<Component> component) {
     }
 }
 
+void MultiComponent::renderComponentType(std::string str, std::shared_ptr<Component> component) {
+    if (!component) {
+        std::cout << "Window::renderComponentType - got null passed" << std::endl;
+        return;
+    }
+    if (typeOfComponent(component) == str) {
+        // how slow is this?
+        if (str == "doc") {
+            DocumentComponent *docComponent = dynamic_cast<DocumentComponent*>(component.get());
+            docComponent->render();
+        } else if (str =="tab") {
+            TabbedComponent *pTabComponent = dynamic_cast<TabbedComponent*>(component.get());
+            pTabComponent->render();
+        } else if (str =="text") {
+            TextComponent *textComponent = dynamic_cast<TextComponent*>(component.get());
+            textComponent->render();
+        } else if (str =="input") {
+            InputComponent *inputComponent = dynamic_cast<InputComponent*>(component.get());
+            inputComponent->render();
+        } else if (str =="anime") {
+            AnimeComponent *animeComponent = dynamic_cast<AnimeComponent*>(component.get());
+            animeComponent->render();
+        } else if (str =="box") {
+            //AnimeComponent *animeComponent = dynamic_cast<AnimeComponent*>(component.get());
+            //if (!animeComponent) {
+            BoxComponent *boxComponent = dynamic_cast<BoxComponent*>(component.get());
+            boxComponent->render();
+            //}
+        } else {
+            std::cout << "Unknown type " << str << std::endl;
+        }
+        //} else {
+        //std::cout << "type: " << typeOfComponent(component) << "!=" << str << std::endl;
+    }
+    // is this needed?
+    if (component->children.empty()) {
+        return;
+    }
+    for (std::shared_ptr<Component> &child : component->children) {
+        this->renderComponentType(str, child);
+    }
+}
+
+
 // used for picking
 std::shared_ptr<Component> MultiComponent::searchComponentTree(const std::shared_ptr<Component> &component, const int passedX, const int passedY) {
     if (component->children.empty()) {
diff --git a/src/graphics/components/MultiComponent.h b/src/graphics/components/MultiComponent.h
index 6c1ca812..9cba4faa 100644
--- a/src/graphics/components/MultiComponent.h
+++ b/src/graphics/components/MultiComponent.h
@@ -11,16 +11,32 @@
 // this component is not scrollable
 class MultiComponent : public Component {
 public:
+    //
+    // Methods
+    //
+
     MultiComponent(const float rawX, const float rawY, const float rawWidth, const float rawHeight, const int passedWindowWidth, const int passedWindowHeight);
+    void updateMouse();
     void render();
     void renderComponents(std::shared_ptr<Component> component);
     void renderDocumentComponents(std::shared_ptr<Component> component);
     void renderBoxComponents(std::shared_ptr<Component> component);
+    void renderComponentType(std::string str, std::shared_ptr<Component> component);
     void resize(const int passedWindowWidth, const int passedWindowHeight);
     std::shared_ptr<Component> searchComponentTree(const std::shared_ptr<Component> &component, const int passedX, const int passedY);
-    std::vector<std::shared_ptr<Component>> layers;
+    
+    //
+    // Properties
+    //
+    
+    // layers will replace rootComponent
+    std::vector<std::shared_ptr<Component>> layers; // each layer's root component
     std::shared_ptr<Component> rootComponent = std::make_shared<Component>();
+    
+    // handle to signal that a redraw is needed, and access to shader programs
     Window *win;
+    
+    // tabbed coordinate system?
     bool tabbed = false;
 
     // we'll need a way to pass events down and up
@@ -28,6 +44,10 @@ public:
     // we'll need searchComponentTree for picking
     std::shared_ptr<Component> hoverComponent = nullptr;
     std::shared_ptr<Component> focusedComponent = nullptr;
+
+    // if the component tree changes, we'll need these to recalculate hoverComponent
+    double cursorX = 0;
+    double cursorY = 0;
 };
 
 extern const std::unique_ptr<Window> window;
-- 
GitLab