//===============================================================================
// Xe UI toolkit
//
// XePrimitive
//  Private header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-May-17 04:10:42
//
// Copyright (C) 1996-2026 by Gabor Nagy. All rights reserved.
//===============================================================================
#ifndef _XePrimitiveP_h
#define _XePrimitiveP_h

#include <Xe/BaseP.h>
#include <Xe/Primitive.h>


//================================================
// Common part of SetValues methods
//================================================
static inline XeChangeFlags Xe_SetValuesCommon(XeWidget PW, const XeChangeFlags PChangeFlags, void (*PGetPreferredSize)(XeWidget PW, XeWidgetGeometry* PGeo))
{
//const EBool  LDebug = EStr_Equal(PW->Parent->Name, "FontsHMatrixW");
//const EBool  LDebug = EStr_Equal(PW->Name, "FontSampleLabelW");
const EBool  LDebug = FALSE;
	XeChangeFlags  LChangeFlags = PChangeFlags;
	if(PChangeFlags & XeChgSIZE)
	{
		LChangeFlags |= XeChgLAYOUT;

		if(PW->SelfResizePolicyX || PW->SelfResizePolicyY)
		{
			XeWidgetGeometry  LGeo;PGetPreferredSize(PW, &LGeo);

// Check our SelfResizePolicy
//
/*
			if(LGeo.Size.X < PW->Size.X) { if((PW->SelfResizePolicyX & XeSHRINK) == 0) LGeo.Size.X = PW->Size.X; }
			else if(LGeo.Size.X > PW->Size.X) { if((PW->SelfResizePolicyX & XeGROW) == 0) LGeo.Size.X = PW->Size.X; }
			if(LGeo.Size.Y < PW->Size.Y) { if((PW->SelfResizePolicyY & XeSHRINK) == 0) LGeo.Size.Y = PW->Size.Y; }
			else if(LGeo.Size.Y > PW->Size.Y) { if((PW->SelfResizePolicyY & XeGROW) == 0) LGeo.Size.Y = PW->Size.Y; }
*/
			if(LGeo.Size.X < PW->PreferredSize.X) { if((PW->SelfResizePolicyX & XeSHRINK) == 0) LGeo.Size.X = PW->PreferredSize.X; }
			else if(LGeo.Size.X > PW->PreferredSize.X) { if((PW->SelfResizePolicyX & XeGROW) == 0) LGeo.Size.X = PW->PreferredSize.X; }
			if(LGeo.Size.Y < PW->PreferredSize.Y) { if((PW->SelfResizePolicyY & XeSHRINK) == 0) LGeo.Size.Y = PW->PreferredSize.Y; }
			else if(LGeo.Size.Y > PW->PreferredSize.Y) { if((PW->SelfResizePolicyY & XeGROW) == 0) LGeo.Size.Y = PW->PreferredSize.Y; }

if(LDebug)
{
	printf("%s() %s:%d  [%s%p%s:%s%s%s]  PrefSize %lld x %lld -> %lld x %lld\n",  __FUNCTION__, __FILE__, __LINE__,  ECodeCyan, PW, ECodeNormal,  ECodeGreen, PW->Name, ECodeNormal,  XY_sll(PW->PreferredSize), XY_sll(LGeo.Size));
	fflush(stdout);
}

			PW->PreferredSize = LGeo.Size;

			if(PW->Size.X != LGeo.Size.X || PW->Size.Y != LGeo.Size.Y)
			{
				PW->Size.X = LGeo.Size.X;PW->Size.Y = LGeo.Size.Y;

// If the size changes, Resize() will get called, so no need to do a Layout here. Also, if the size we set here is not approved by the parent,
// but the parent offers a compromise, our SetValuesAlmost() method will be called...
//
				LChangeFlags &= ~XeChgLAYOUT;
			}
			PW->PreferredSize = LGeo.Size;
		}
	}

	return(LChangeFlags);
}


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


typedef  void  (*XeWidgetRedrawProc)(XeWidget PW);

#define XePrimitiveClassCore\
 XeCoreClassCore

//================================
// Class record
//================================
typedef struct _XePrimitiveClassRec
{
	XePrimitiveClassCore;
} XePrimitiveClassRec;

extern XePrimitiveClassRec  _XePrimitiveWidget_class;


//================================
// Instance definition
//================================
// Instance part
//================================
typedef struct
{
// Resources
//
	XeWidget  TraverseLeft, TraverseRight, TraverseUp, TraverseDown;
	int       HighlightThickness, GapWidth;

	XeColor   ActiveColor;            // Background color used on mouse-over
	XeColor   GapColor;
	XeColor   HighlightColor;

// Internal variables
//
	EBool     HasKeyboardFocus;       // VisualInfo was NULL on initialize, so a new one was allocated
} XePrimitivePart;


//================================
// Instance record
//================================
typedef struct _XePrimitiveRec
{
	XeWidgetCore;
	XeBasePart       Base;
	XePrimitivePart  Primitive;
} XePrimitiveRec;



//================================================================================================
// Get the size of the arrow, used in CascadeButtons and ToggleButtons (when in a list header)
//================================================================================================
static inline int _ArrowSize(XePrimitiveWidget PEW, const int PSizeY)
{
	const int  LSizeY = PSizeY, LShadowThickness = PEW->Base.ShadowThickness;
	const int  LInnerSizeY = LSizeY - PEW->Primitive.HighlightThickness * 2 - PEW->Primitive.GapWidth * 2 - LShadowThickness * 2 - PEW->Base.MarginSize.Y * 2 - PEW->Base.MarginTop - PEW->Base.MarginBottom;
	const int  LArowSizeX = (int)((float)LInnerSizeY * 0.42);

	return(LArowSizeX);
}

//========================================
// Draw arrow on the right
//========================================
static inline void _DrawArrow(XePrimitiveWidget PEW, EpImage* PCacheImage,  const int POffsetX, const int PArrowY,  const int PArrowWidth, const int PArrowLength, const int PDirection, EcRGBAu8Color PColor)
{
	const int  LSizeX = Xe_SizeX(PEW), LShadowThickness = PEW->Base.ShadowThickness;
	int        LArrowSizeX = 0, LArrowSizeY = 0;

	if(PArrowWidth > 0)
	{
		int  LArrowX = 0;

		switch(PDirection)
		{
			case XeLEFT:   LArrowX = LShadowThickness + PEW->Base.MarginSize.X + PEW->Base.MarginLeft - 1;LArrowSizeX = PArrowLength;LArrowSizeY = PArrowWidth;break;
			case XeRIGHT:  LArrowX = LSizeX - LShadowThickness - PArrowLength - PEW->Base.MarginSize.X - PEW->Base.MarginRight + POffsetX;LArrowSizeX = PArrowLength;LArrowSizeY = PArrowWidth; break;
			case XeUP:
			case XeDOWN:
				LArrowX = LSizeX - LShadowThickness - PEW->Base.MarginRight - PEW->Base.MarginSize.X - PArrowWidth;LArrowSizeX = PArrowWidth; LArrowSizeY = PArrowLength;
			break;
		}

		if(PCacheImage && _Xe_Theme)
		{
			XeImageDrawArrowRGBA8(PCacheImage,  LArrowX, PArrowY,  LArrowSizeX, LArrowSizeY,  PDirection, PColor);
		}
	}
}


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
} // Close scope of 'extern "C"' declaration
#endif

#endif // _XePrimitiveP_h
