/* Copyright (c) 2018 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #ifndef __UIContainer_H__ #define __UIContainer_H__ #ifdef __cplusplus extern "C" { #endif typedef struct UIContainer UIContainer; #define UIContainer_superclass UIElement #include "uitoolkit/UIElement.h" #include #define UICONTAINER_MOUSE_BUTTON_NUMBER_RESPONSE_COUNT 3 #define UICONTAINER_MENU_ACTION_NUMBER_RESPONSE_COUNT 3 #define UICONTAINER_FOCUS_NONE ((unsigned int) -1) #define UICONTAINER_NO_CENTER VECTOR2f(INFINITY, INFINITY) #define UICONTAINER_SIZE_AUTO VECTOR2f(INFINITY, INFINITY) struct UIContainer_element { UIElement * element; bool owned; }; #define UIContainer_ivars \ UIElement_ivars \ \ Vector2f size; \ bool clipContents; \ bool hitTestSelf; \ unsigned int elementCount; \ unsigned int private_ivar(elementAllocatedCount); \ struct UIContainer_element * elements; \ unsigned int focusedElementIndex; \ Vector2f lastMousePosition; \ Vector2f mousePositionAtMouseDown; \ UIElement * lastMouseDownTargets[UICONTAINER_MOUSE_BUTTON_NUMBER_RESPONSE_COUNT]; \ UIElement * lastKeyDownTarget; \ UIElement * lastMenuDirectionTargets[UI_DIRECTION_COUNT]; \ UIElement * lastMenuActionTargets[UICONTAINER_MENU_ACTION_NUMBER_RESPONSE_COUNT]; #define UIContainer_vtable(self_type) \ UIElement_vtable(self_type) \ \ void (* addElement)(self_type * self, compat_type(UIElement *) element, bool takeOwnership); \ void (* removeElement)(self_type * self, compat_type(UIElement *) element); \ void (* removeAllElements)(self_type * self); \ unsigned int (* getElementCountWithTag)(self_type * self, int tag); \ UIElement * (* getElementWithTagAtIndex)(self_type * self, int tag, unsigned int elementIndex); \ void (* enumerateElementsWithTag)(self_type * self, int tag, bool (* callback)(UIElement * element, void * context), void * context); \ Vector2f (* getContentOffset)(self_type * self); \ void (* resetMouseDownTargets)(self_type * self); stemobject_declare(UIContainer) // relativeOrigin can be UICONTAINER_NO_CENTER to allow elements to be offset relative to position with no adjustment // size can be UICONTAINER_SIZE_AUTO to calculate the total bounds of children and use that as the container's bounds. // Note that UICONTAINER_SIZE_AUTO will cause elements to be fit tightly, so offsets on all four sides are negated. // If clipContents is true and size is not UICONTAINER_SIZE_AUTO, elements extending beyond the container's bounds will be clipped. UIContainer * UIContainer_create(Vector2f position, Vector2f relativeOrigin, Vector2f size, bool clipContents, UIAppearance appearance); bool UIContainer_init(UIContainer * self, Vector2f position, Vector2f relativeOrigin, Vector2f size, bool clipContents, UIAppearance appearance); void UIContainer_dispose(UIContainer * self); void UIContainer_addElement(UIContainer * self, compat_type(UIElement *) element, bool takeOwnership); void UIContainer_removeElement(UIContainer * self, compat_type(UIElement *) element); void UIContainer_removeAllElements(UIContainer * self); bool UIContainer_containsElement(UIContainer * self, compat_type(UIElement *) element); void UIContainer_enumerateElements(UIContainer * self, UIElement_enumerationCallback callback, void * context); unsigned int UIContainer_getElementCountWithTag(UIContainer * self, int tag); UIElement * UIContainer_getElementWithTagAtIndex(UIContainer * self, int tag, unsigned int index); void UIContainer_enumerateElementsWithTag(UIContainer * self, int tag, bool (* callback)(UIElement * element, void * context), void * context); Vector2f UIContainer_getContentOffset(UIContainer * self); void UIContainer_resetMouseDownTargets(UIContainer * self); bool UIContainer_hitTest(UIContainer * self, float x, float y, UIHitTestType type, int * outPriority, bool * outForwardNext); void UIContainer_hitTestList(UIContainer * self, float x, float y, UIHitTestType type, int priorityOffset, UIHitTestResultIO * resultIO); UIEventResponse UIContainer_mouseDown(UIContainer * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, bool isFinalTarget, double referenceTime); bool UIContainer_mouseUp(UIContainer * self, unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifiers, double referenceTime); bool UIContainer_mouseMoved(UIContainer * self, float x, float y, float deltaX, float deltaY, unsigned int modifiers, double referenceTime); bool UIContainer_mouseDragged(UIContainer * self, unsigned int buttonMask, float x, float y, float deltaX, float deltaY, unsigned int modifiers, double referenceTime); UIEventResponse UIContainer_scrollWheel(UIContainer * self, float x, float y, int deltaX, int deltaY, unsigned int modifiers, bool isFinalTarget, double referenceTime); UIEventResponse UIContainer_keyDown(UIContainer * self, unsigned int charCode, unsigned int keyCode, unsigned int modifiers, bool isRepeat, bool isFinalTarget, double referenceTime); bool UIContainer_keyUp(UIContainer * self, unsigned int keyCode, unsigned int modifiers, double referenceTime); bool UIContainer_keyModifiersChanged(UIContainer * self, unsigned int modifiers, unsigned int lastModifiers, double referenceTime); bool UIContainer_menuActionDown(UIContainer * self, unsigned int actionNumber, bool isRepeat, double referenceTime); bool UIContainer_menuActionUp(UIContainer * self, unsigned int actionNumber, double referenceTime); bool UIContainer_menuDirectionDown(UIContainer * self, UINavigationDirection direction, bool isRepeat, double referenceTime); bool UIContainer_menuDirectionUp(UIContainer * self, UINavigationDirection direction, double referenceTime); bool UIContainer_setFocusedElement(UIContainer * self, compat_type(UIElement *) element, compat_type(UIElement *) fromElement, UINavigationDirection directionFromElement); UIElement * UIContainer_getFocusedElement(UIContainer * self); bool UIContainer_acceptsFocus(UIContainer * self); Rect4f UIContainer_getBounds(UIContainer * self); Rect4f UIContainer_getFocusBounds(UIContainer * self); Vector2f UIContainer_getRelativeOffset(UIContainer * self); bool UIContainer_ignoreClipForHitTest(UIContainer * self, UIHitTestType type); Rect4f UIContainer_getClipBounds(UIContainer * self); void UIContainer_draw(UIContainer * self, Vector2f offset, UIDrawingInterface * drawingInterface, VertexIO * vertexIO); void UIContainer_listRenderables(UIContainer * self, RenderableIO * renderableIO, int drawOrderOffset, Rect4i clipBounds); bool UIContainer_needsRedraw(UIContainer * self); ShellCursorID UIContainer_getCursorAtPosition(UIContainer * self, float x, float y); // Calls UIElement_connect() with bidirectional UI_NEXT for every element that returns true from shouldAutoconnect(). // If connectAtEnds is true, the first and last elements will be connected to each other. void UIContainer_autoconnectElements(compat_type(UIContainer *) self, bool connectAtEnds); #ifdef __cplusplus } #endif #endif