/* 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__ typedef struct UIContainer UIContainer; #define UIContainer_superclass UIElement #include "uitoolkit/UIElement.h" #include #define UICONTAINER_MOUSE_BUTTON_NUMBER_RESPONSE_COUNT 5 #define UICONTAINER_MENU_ACTION_NUMBER_RESPONSE_COUNT 3 #define UICONTAINER_KEY_RESPONSE_COUNT_MAX 8 #define UICONTAINER_FOCUS_NONE ((unsigned int) -1) struct UIContainer_element { UIElement * element; bool owned; }; struct UIContainer_keyDownTarget { UIElement * element; unsigned int keyCode; }; #define UIContainer_ivars \ UIElement_ivars \ \ Vector2f innerRelativeOrigin; \ 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]; \ struct UIContainer_keyDownTarget lastKeyDownTargets[UICONTAINER_KEY_RESPONSE_COUNT_MAX]; \ 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 (* insertElement)(self_type * self, unsigned int insertIndex, compat_type(UIElement *) element, bool takeOwnership); \ void (* removeElement)(self_type * self, compat_type(UIElement *) element); \ void (* removeElementAtIndex)(self_type * self, unsigned int removeIndex); \ void (* removeAllElements)(self_type * self); \ void (* reorderElement)(self_type * self, unsigned int fromIndex, unsigned int toIndex); \ unsigned int (* getElementIndex)(self_type * self, compat_type(UIElement *) element); \ 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); \ void (* resetMouseDownTargets)(self_type * self); \ Rect4f (* getChildBoundsUnion)(self_type * self); \ void (* autosize)(self_type * self); stemobject_declare(UIContainer) // outerRelativeOrigin determines which direction the visible portion of this container extends from its position. // innerRelativeOrigin determines which corner of the container contents are anchored to. For example, if // innerRelativeOrigin is set to VECTOR2f(0, 1), contained element x and y coordinates will start at {0, 0} in the // upper left corner, with positive x values running to the right, and negative y values running downward. // If clipContents is true, elements extending beyond the container's bounds will be clipped. UIContainer * UIContainer_create(Vector2f position, Vector2f outerRelativeOrigin, Vector2f innerRelativeOrigin, Vector2f size, bool clipContents, UIAppearance appearance); bool UIContainer_init(UIContainer * self, Vector2f position, Vector2f outerRelativeOrigin, Vector2f innerRelativeOrigin, Vector2f size, bool clipContents, UIAppearance appearance); void UIContainer_dispose(UIContainer * self); void UIContainer_addElement(UIContainer * self, compat_type(UIElement *) element, bool takeOwnership); void UIContainer_insertElement(UIContainer * self, unsigned int insertIndex, compat_type(UIElement *) element, bool takeOwnership); void UIContainer_removeElement(UIContainer * self, compat_type(UIElement *) element); void UIContainer_removeElementAtIndex(UIContainer * self, unsigned int removeIndex); void UIContainer_removeAllElements(UIContainer * self); void UIContainer_reorderElement(UIContainer * self, unsigned int fromIndex, unsigned int toIndex); bool UIContainer_containsElement(UIContainer * self, compat_type(UIElement *) element); unsigned int UIContainer_getElementIndex(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); void UIContainer_resetMouseDownTargets(UIContainer * self); Rect4f UIContainer_getChildBoundsUnion(UIContainer * self); void UIContainer_autosize(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); bool UIContainer_mouseLeave(UIContainer * self, unsigned int modifiers, double referenceTime); UIEventResponse UIContainer_scrollWheel(UIContainer * self, float x, float y, int scrollDeltaX, int scrollDeltaY, unsigned int buttonMask, 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, bool finalTargetOnly); 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); void UIContainer_autoconnect(UIContainer * self, bool connectAtEnds, bool recursive); void UIContainer_autoconnectWithParent(UIContainer * self, UIElement ** ioFirstElement, UIElement ** ioLastElement, bool recursive); #endif