IceBoarding@freebasic

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: IceBoarding@freebasic

Post by fxm »

In an inheritance structure, it is not necessary to explicitly call the default base type constructor from the first line of the derived type constructor. The chaining of default constructors is implicitly done by the compiler.
Reserve the first line of a constructor to call a base constructor when passing parameters.

Same remark for the destructor: the destructors are also implicitly chained by compiler.

On the other hand, the syntax for the first constructor line to call a base constructor is:
Base.Constructor(parameters)
Base(parameters)

otherwise, the default constructor will be also called.
('Base()' in first line is useless, but even if you request it, the default constructor will not be called two times)

In your code above, the base constructors / destructors are called multiple times for one only object to construct!
Last edited by fxm on Dec 19, 2015 19:49, edited 2 times in total.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: IceBoarding@freebasic

Post by fxm »

fxm wrote:.....otherwise, infinite call loop and then overflow stack!
dkl,

Many bugs occur by overflowing of stack.
In that case there is no runtime error message, even when compiling with option '-exx'.
With this compiler option (or another) for debugging, could is possible that compiler adds some code to detect that the stack will overflow?
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

fxm wrote:In an inheritance structure, it is not necessary to explicitly call the default base type constructor from the first line of the derived type constructor. The chaining of default constructors is implicitly done by the compiler.
Reserve the first line of a constructor to call a base constructor when passing parameters.
Thanks I was not sure. Indeed IDMINI constructor was called many times (I've put constructor counter to watch this). Corrected now however (edited in the last code).

I find this very interesting finally to use inheritance, it's much cleaner and it breaks the complexity.

However, I dont see what kind of stack overflow it can induce. I think I'm missing some indepth mechanism.
Oh yes, thanks again for watching this, I was calling recursively a property -> which is bad here. I wouldn't have called that stackoverflow (for in my head recursivity is more talkative), but yes this is surely an undetected bug, even via -exx. A warning in the case of the property to prevent unwanted recursive calls would also help (even if in some cases it is possible to want some recursion after all if something ensures loop ending).
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: IceBoarding@freebasic

Post by fxm »

Code: Select all

destructor RECTANGLEMINI()
    'IDMINI base destruction
    BASE.destructor()
end destructor 'RECTANGLEMINI default explicit constructor
'.....
destructor FOCUSABLEMINI()
    BASE.destructor()
end destructor 'FOCUSABLEMINI default explicit destructor
No still correction (see my post http://www.freebasic.net/forum/viewtopi ... 28#p214528)!
(the RECTANGLEMINI destructor is called 2 times and the IDMINI destructor is called 4 times!)
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

fxm wrote: (the RECTANGLEMINI destructor is called 2 times and the IDMINI destructor is called 4 times!)
Missed that, but corrected now and I've expanded a little the code in the same scheme (posted below for testing if needed). Clearly using inheritance allows great reusability and easy maintenance since things are very modular, but the design time is quite longer since udt are more numerous and come each time with at least some structural code.

About focus, for I'll still have to deal with this after code reshaping, I have to provide something to compute the set of focusable rectangles, or conversely the set of overlapping ones. Maybe I should add a picture? Whatever I'll probably use arrays of RECTANGLEMINI for that.

Code: Select all

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.

'______________________________________________
'>>                                          <<
'>>  INFOMINI->                              <<
'>>     RECTANGLEMINI->                      <<
'>>        OVERABLEMINI->                    <<
'>>           CLICKABLEMINI->                <<
'>>              FOCUSABLEMINI->             <<
'>>                         BUTTON           <<
'______________________________________________
'>>  INFOMINI->                              <<
'>>     RECTANGLEMINI->                      <<
'>>        OVERABLEMINI->                    <<
'>>           CLICKABLEMINI->                <<
'>>              FOCUSABLEMINI->             <<
'>>                DRAGGABLEMINI->           <<
'>>                     GUIRECTANGLE->       <<
'>>                         DYNAMICBENCH     <<
'>>                            ..<BUTTON>    <<
'______________________________________________
'>>   FBAPPLICATION->                        <<
'>>            ICEBOARD                      <<
'>>              ..<DYNAMICBENCH>            <<
'______________________________________________


#include once "fbgfx.bi"

'                                  ------------
'                                  INFOMINI UDT
'                                  ------------
type INFOMINI extends OBJECT
	enum _HIERARCHYLEVEL
		_rootLevel		= -1
		_nonRootLevel	= -0
	end enum '_HIERARCHYLEVEL
	declare constructor()
	declare destructor()
	'
	declare operator cast() as string
	declare property HierarchyLevel() as _HIERARCHYLEVEL
	declare property HierarchyLevel(byval as _HIERARCHYLEVEL)
	declare property InfoMiniIndex() as integer
	declare property InfoMiniIndex(byval as integer)
	declare function RefreshInfoMini() as string
	'
	declare property MiniId() as string
	declare property MiniId(byval as string)
	declare property MiniInfoCount() as integer
	declare property MiniInfo(as integer) as string
	declare property MiniInfo(as integer, byval as string)
	public:
		as string			_miniInfo(any)
	private:
	declare property ConstructionIndex() as integer
	declare property ConstructionIndex(byval as integer)
	declare property DestructionIndex() as integer
	declare property DestructionIndex(byval as integer)
	static as integer		constructionCount
	static as integer		deconstructionCount
		as string			_miniId
		as _HIERARCHYLEVEL	_hierarchyPosition
		as integer			_infoMiniIndex
		as integer			_constructionIndex
		as integer			_destructionIndex
end type 'INFOMINI XT OBJECT
dim as integer	INFOMINI.constructionCount	=> 0
dim as integer	INFOMINI.deconstructionCount	=> 0
constructor INFOMINI()
	THIS._hierarchyPosition	=> _
					INFOMINI._HIERARCHYLEVEL._rootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	INFOMINI.constructionCount+=> 1
	THIS._constructionIndex	 => INFOMINI.constructionCount
	THIS._miniId			 => "id"& _ 
								INFOMINI.constructionCount &"/"& _ 
								TIME &"_"& _ 
								DATE &"_"
end constructor 'INFOMINI default explicit constructor
destructor INFOMINI()
	THIS._miniInfo(0)		=> "destructed"
	THIS._destructionIndex	=> INFOMINI.constructionCount
	INFOMINI.constructionCount	-= 1
	INFOMINI.deconstructionCount	+=> 1
end destructor 'INFOMINI default explicit destructor
operator INFOMINI.cast() as string
	dim as string	stringReturnValue
	stringReturnValue	= "<INFOMINI>"& _
						  "cons"& THIS.ConstructionIndex & _ 
						  "des"& THIS.DestructionIndex & _ 
						  chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(INFOMINI)
property INFOMINI.HierarchyLevel() as _HIERARCHYLEVEL
	'---->
	return THIS._hierarchyPosition
end property 'get _HIERARCHYLEVEL:=INFOMINI.HierarchyLevel
property INFOMINI.HierarchyLevel(byval SetValue as _HIERARCHYLEVEL)
	THIS._hierarchyPosition = SetValue
end property 'set INFOMINI.HierarchyLevel(val_HIERARCHYLEVEL)
property INFOMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=INFOMINI.InfoMiniIndex
property INFOMINI.InfoMiniIndex(byval SetValue as integer)
	THIS._infoMiniIndex	= SetValue
end property 'set DMINI.InfoMiniIndex(valINT)
function INFOMINI.RefreshInfoMini() as string
	' ''block below wont compile even if called only if had meaning
	/'
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	'/
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=INFOMINI.RefreshInfoMini()
property INFOMINI.MiniId() as string
	'---->
	return THIS._miniId
end property 'get STR:=INFOMINI.MiniId
property INFOMINI.MiniId(byval SetValue as string)
	THIS._miniId = SetValue
end property 'set INFOMINI.MiniId(valSTR)
property INFOMINI.MiniInfoCount() as integer
	'---->
	return ( uBound(THIS._miniInfo) - lBound(THIS._miniInfo) + 1 )
end property 'get INT:=INFOMINI.MiniInfoCount
property INFOMINI.MiniInfo(Index as integer) as string
	'todo: add bound check!!
	'---->
	return THIS._miniInfo(Index)
end property 'get STR:=INFOMINI.MiniInfo(INDEX)
property INFOMINI.MiniInfo(Index as integer, byval SetValue as string)
	'todo: add bound check!!
	THIS._miniInfo(Index) = SetValue
end property 'set INFOMINI.MiniInfo(INDEX,valSTR)
property INFOMINI.ConstructionIndex() as integer
	'---->
	return THIS._constructionIndex
end property 'get INT:=INFOMINI.ConstructionIndex
property INFOMINI.ConstructionIndex(byval SetValue as integer)
	THIS._constructionIndex = SetValue
end property 'set INFOMINI.ConstructionIndex(valINT)
property INFOMINI.DestructionIndex() as integer
	'---->
	return THIS._destructionIndex
end property 'get INT:=INFOMINI.DestructionIndex
property INFOMINI.DestructionIndex(byval SetValue as integer)
	THIS._destructionIndex = SetValue
end property 'set INFOMINI.DestructionIndex(valINT)


'                             -----------------
'                             RECTANGLEMINI UDT
'                             -----------------
type RECTANGLEMINI extends INFOMINI
	declare constructor()
	enum _CONSTRUCTORENTRYMODE
		_bottomRightCornerXYwidthHeight		= -2
		_topLeftCornerXYbottomRightCornerXY	= -1
		_topLeftCornerXYwidthHeight			= -0
		_random								= +1
	end enum '_CONSTRUCTORENTRYMODE
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string
	declare sub ShowIdMini()
	declare sub ShowInfoMini()
	'
	declare property TopLeftCornerX() as integer
	declare property TopLeftCornerX(byval as integer)
	declare property TopLeftCornerY() as integer
	declare property TopLeftCornerY(byval as integer)
	declare property RectangleWidth() as integer
	declare property RectangleWidth(byval as integer)
	declare property RectangleHeight() as integer
	declare property RectangleHeight(byval as integer)
	declare property BottomRightCornerX() as integer
	declare property BottomRightCornerX(byval as integer)
	declare property BottomRightCornerY() as integer
	declare property BottomRightCornerY(byval as integer)
	declare sub DrawRectangleMini()
	private:
		as integer		_infoMiniIndex
		as integer		_topLeftCornerX
		as integer		_topLeftCornerY
		as integer		_width
		as integer		_height
end type 'RECTANGLEMINI XT INFOMINI
constructor RECTANGLEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	dim as integer	scrW, scrH
	screenInfo		scrW, scrH
	with THIS
		._topLeftCornerX	=> scrW\3
		._topLeftCornerY	=> scrH\3
		._width				=> scrW\3
		._height			=> scrH\3
	end with 'THIS
end constructor 'RECTANGLEMINI default explicit constructor
destructor RECTANGLEMINI()
	'
end destructor 'RECTANGLEMINI default explicit constructor
operator RECTANGLEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<RECTANGLEMINI>"& _ 
						"tlcX:"& THIS.TopLeftCornerX & _ 
						"..tlcY:"& THIS.TopLeftCornerY & _ 
						"..W:"& THIS.RectangleWidth & _ 
						"..H:"& THIS.RectangleHeight & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(RECTANGLEMINI)
property RECTANGLEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=RECTANGLEMINI.InfoMiniIndex
function RECTANGLEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=RECTANGLEMINI.RefreshInfoMini()
sub RECTANGLEMINI.ShowIdMini()
	draw string (THIS.TopLeftCornerX, THIS.TopLeftCornerY), _ 
				":ShowId:"& BASE.MiniId
end sub 'RECTANGLEMINI.ShowIdMini()
sub RECTANGLEMINI.ShowInfoMini()
	for index as integer = 0 to THIS.MiniInfoCount - 1
		draw string (THIS.TopLeftCornerX, THIS.TopLeftCornerY + 12 + 12*index), _ 
					":ShowInfo:"& BASE.MiniInfo(index)
	next index
end sub 'RECTANGLEMINI.ShowInfoMini()
property RECTANGLEMINI.TopLeftCornerX() as integer
	'---->
	return THIS._topLeftCornerX
end property 'get INT:=RECTANGLEMINI.TopLeftCornerX
property RECTANGLEMINI.TopLeftCornerX(byval SetValue as integer)
	THIS._topLeftCornerX = SetValue
end property 'set RECTANGLEMINI.TopLeftCornerX(valINT)
property RECTANGLEMINI.TopLeftCornerY() as integer
	'---->
	return THIS._topLeftCornerY
end property 'get INT:=RECTANGLEMINI.TopLeftCornerY
property RECTANGLEMINI.TopLeftCornerY(byval SetValue as integer)
	THIS._topLeftCornerY = SetValue
end property 'set RECTANGLEMINI.TopLeftCornerY(valINT)
property RECTANGLEMINI.RectangleWidth() as integer
	'---->
	return THIS._width
end property 'get INT:=RECTANGLEMINI.RectangleWidth
property RECTANGLEMINI.RectangleWidth(byval SetValue as integer)
	THIS._width = SetValue
end property 'set RECTANGLEMINI.RectangleWidth(valINT)
property RECTANGLEMINI.RectangleHeight() as integer
	'---->
	return THIS._height
end property 'get INT:=RectangleHeight
property RECTANGLEMINI.RectangleHeight(byval SetValue as integer)
	THIS._height = SetValue
end property 'set RECTANGLEMINI.RectangleHeight(valINT)
property RECTANGLEMINI.BottomRightCornerX() as integer
	'---->
	return ( THIS.TopLeftCornerX + THIS._width - 1 )
end property 'get INT:=RECTANGLEMINI.BottomRightCornerX
property RECTANGLEMINI.BottomRightCornerX(byval SetValue as integer)
	THIS.TopLeftCornerX = SetValue - THIS._width + 1
end property 'set RECTANGLEMINI.BottomRightCornerX(valINT)
property RECTANGLEMINI.BottomRightCornerY() as integer
	'---->
	return ( THIS.TopLeftCornerY + THIS._height - 1 )
end property 'get INT:=RECTANGLEMINI.BottomRightCornerY
property RECTANGLEMINI.BottomRightCornerY(byval SetValue as integer)
	THIS.TopLeftCornerY = SetValue - THIS._height + 1
end property 'set RECTANGLEMINI.BottomRightCornerY(valINT)
sub RECTANGLEMINI.DrawRectangleMini()
	with THIS
		line (.TopLeftCornerX, .TopLeftCornerY) - _ 
			 (.BottomRightCornerX, .BottomRightCornerY), _ 
			 rgb(200,200,250), _ 
			 bf
		for k as double = 0 to 1 step 0.05
			line (.TopLeftCornerX + k*(.BottomRightCornerX - .TopLeftCornerX), .BottomRightCornerY) - _ 
				 (.BottomRightCornerX, .BottomRightCornerY - k*(.BottomRightCornerY - .TopLeftCornerY)), _ 
				 rgb(200,100,100)
		next k
	end with 'THIS
end sub 'RECTANGLEMINI.DrawRectangleMini()


'                                 -------------
'                                 MOUSEMINI UDT
'                                 -------------
type MOUSEMINI extends RECTANGLEMINI
	declare constructor()
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string
	'
	declare property MouseErrorCode() as integer
	declare property GMX()		as integer
	declare property GMY()		as integer
	declare property MouseOut()	as boolean
	declare property MouseOut(byval as boolean)
	declare property GMWhl()	as integer
	declare property GMBtn()	as integer
	declare property GMClp()	as integer
	declare function TestMouse() as integer
	private:
		as integer		_infoMiniIndex
		as integer		_getMouseErrorResult
		as integer		_gmX
		as integer		_gmY
		as boolean		_mouseOutOfBound
		as integer		_gmWheel
		as integer		_gmBtn
		as integer		_gmClipStatus
end type 'MOUSEMINI XT RECTANGLEMINI
constructor MOUSEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	THIS.TestMouse()
end constructor 'MOUSEMINI default explicit constructor
destructor MOUSEMINI()
	'
end destructor 'MOUSEMINI default explicit destructor
operator MOUSEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<MOUSEMINI>"& _ 
						"gmX:"& THIS.GMX & _ 
						"..gmY:"& THIS.GMY & _ 
						"..gmW:"& THIS.GMWhl & _ 
						"..gmB:"& THIS.GMBtn & _ 
						"..gmC:"& THIS.GMClp & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(MOUSEMINI)
property MOUSEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=MOUSEMINI.InfoMiniIndex
function MOUSEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=MOUSEMINI.RefreshInfoMini()
property MOUSEMINI.MouseErrorCode() as integer
	'---->
	return THIS._getMouseErrorResult
end property 'INT:=MOUSEMINI.MouseErrorCode
property MOUSEMINI.GMX() as integer
	'---->
	return THIS._gmX
end property 'get INT:=MOUSEMINI.GMX
property MOUSEMINI.GMY() as integer
	'---->
	return THIS._gmY
end property 'get INT:=MOUSEMINI.GMY
property MOUSEMINI.MouseOut() as boolean
	'---->
	return THIS._mouseOutOfBound
end property 'get BOOL:=MOUSEMINI.MouseOut
property MOUSEMINI.MouseOut(byval SetValue as boolean)
	THIS._mouseOutOfBound = SetValue
end property 'set MOUSEMINI.MouseOut(valBOOL)
property MOUSEMINI.GMWhl() as integer
	'---->
	return THIS._gmWheel
end property 'get INT:=MOUSEMINI.GMWhl
property MOUSEMINI.GMBtn() as integer
	'---->
	return THIS._gmBtn
end property 'get INT:=MOUSEMINI.GMBtn
property MOUSEMINI.GMClp() as integer
	'---->
	return THIS._gmClipStatus
end property 'get INT:=MOUSEMINI.GMClp
function MOUSEMINI.TestMouse() as integer
	with THIS
		._getMouseErrorResult => _ 
			getMouse (._gmX, _ 
					 ._gmY, _ 
					 ._gmWheel, _ 
					 ._gmBtn, _ 
					 ._gmClipStatus)
	end with 'THIS
	'
	if THIS._gmX=-1 and THIS._gmY=-1 then
		THIS.MouseOut = TRUE
	else
		THIS.MouseOut = FALSE
	end if
	'---->
	return THIS.MouseErrorCode
end function 'INT:=MOUSEMINI.TestMouse()


'                              ----------------
'                              OVERABLEMINI UDT
'                              ----------------
type OVERABLEMINI extends MOUSEMINI
	declare constructor()
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string
	'
	declare property MouseOver() as boolean
	declare property MouseOver(byval as boolean)
	declare function TestMouseOver() as boolean
	private:
		as integer		_infoMiniIndex
		as boolean		_mouseOver
end type 'OVERABLEMINI XT MOUSEMINI
constructor OVERABLEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	THIS._mouseOver	=> FALSE
end constructor 'OVERABLEMINI default explicit constructor
destructor OVERABLEMINI()
	'
end destructor 'OVERABLEMINI default explicit destructor
operator OVERABLEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<OVERABLEMINI>"& _
						THIS.TestMouseOver & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(OVERABLEMINI)
property OVERABLEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=OVERABLEMINI.InfoMiniIndex
function OVERABLEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=OVERABLEMINI.RefreshInfoMini()
property OVERABLEMINI.MouseOver() as boolean
	'---->
	return THIS._mouseOver
end property 'get BOOL:=OVERABLEMINI.MouseOver
property OVERABLEMINI.MouseOver(byval SetValue as boolean)
	THIS._mouseOver = SetValue
end property 'set OVERABLEMINI.MouseOver(valBOOL)
function OVERABLEMINI.TestMouseOver() as boolean
	THIS.TestMouse()
	'
	if THIS.GMX>=THIS.TopLeftCornerX		and _ 
	   THIS.GMY>=THIS.TopLeftCornerY		and _ 
	   THIS.GMX<=THIS.BottomRightCornerX	and _ 
	   THIS.GMY<=THIS.BottomRightCornerY	then
		if THIS.MouseOver=FALSE then THIS.MouseOver = TRUE
	else
		if THIS.MouseOver=TRUE then THIS.MouseOver = FALSE
	end if
	'
	'---->
	return THIS.MouseOver
end function 'BOOL:=OVERABLEMINI.TestMouseOver


'                             -----------------
'                             CLICKABLEMINI UDT
'                             -----------------
type CLICKABLEMINI extends OVERABLEMINI
	declare constructor()
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string	
	'
	declare property MouseClick() as boolean
	declare property MouseClick(byval as boolean)
	declare function TestMouseClick() as boolean
	private:
		as integer		_infoMiniIndex
		as boolean		_mouseClick
end type 'CLICKABLEMINI XT OVERABLEMINI
constructor CLICKABLEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	THIS._mouseClick	=> FALSE
end constructor 'CLICKABLEMINI default explicit constructor
destructor CLICKABLEMINI()
	'
end destructor 'CLICKABLEMINI default explicit destructor
operator CLICKABLEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<CLICKABLEMINI>"& _
						THIS.TestMouseClick() & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(CLICKABLEMINI)
property CLICKABLEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=CLICKABLEMINI.InfoMiniIndex
function CLICKABLEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=CLICKABLEMINI.RefreshInfoMini()
property CLICKABLEMINI.MouseClick() as boolean
	'---->
	return THIS._mouseClick
end property 'get BOOL:=CLICKABLEMINI.MouseOver
property CLICKABLEMINI.MouseClick(byval SetValue as boolean)
	THIS._mouseClick = SetValue
end property 'set CLICKABLEMINI.MouseOver(valBOOL)
function CLICKABLEMINI.TestMouseClick() as boolean
	if THIS.TestMouseOver() then
		if THIS.GMBtn=+1 then
			if THIS.MouseClick=FALSE then THIS.MouseClick = TRUE
		else
			if THIS.MouseClick=TRUE then THIS.MouseClick = FALSE
		end if
	else
		if THIS.MouseClick=TRUE then THIS.MouseClick = FALSE
	end if
	'
	'---->
	return THIS.MouseClick
end function 'BOOL:=CLICKABLEMINI.TestMouseClick()


'                             -----------------
'                             FOCUSABLEMINI UDT
'                             -----------------
type FOCUSABLEMINI extends CLICKABLEMINI
	declare constructor()
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string	
	'
	declare property ZOrder() as integer
	declare property ZOrder(byval as integer)
	declare property IsRequestingFocus() as boolean
	declare property IsRequestingFocus(byval as boolean)
	declare property IsGrantedSubFocus() as boolean
	declare property IsGrantedSubFocus(byval as boolean)
	declare function TestForFocusRequest() as boolean
	private:
		as integer		_infoMiniIndex
		as integer		_zOrder
		as boolean		_isResquestingFocus
		as boolean		_isGrantedSubFocus
end type 'FOCUSABLEMINI XT CLICKABLEMINI
constructor FOCUSABLEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	with THIS
		._zOrder				=> -1
		._isResquestingFocus	=> FALSE
		._isGrantedSubFocus		=> FALSE
	end with 'THIS
end constructor 'FOCUSABLEMINI default explicit constructor
destructor FOCUSABLEMINI()
	'
end destructor 'FOCUSABLEMINI default explicit destructor
operator FOCUSABLEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<FOCUSABLEMINI>"& _
						"subfocus::"& THIS.IsGrantedSubFocus & _ 
						"..zOrder:"& THIS.ZOrder & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(FOCUSABLEMINI)
property FOCUSABLEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=FOCUSABLEMINI.InfoMiniIndex
function FOCUSABLEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=FOCUSABLEMINI.RefreshInfoMini()
property FOCUSABLEMINI.ZOrder() as integer
	'---->
	return THIS._zOrder
end property 'get INT:=FOCUSABLEMINI.ZOrder
property FOCUSABLEMINI.ZOrder(byval SetValue as integer)
	THIS._zOrder = SetValue
end property 'set FOCUSABLEMINI.ZOrder(valINT)
property FOCUSABLEMINI.IsRequestingFocus() as boolean
	'---->
	return THIS._isResquestingFocus
end property 'get BOOL:=FOCUSABLEMINI.IsRequestingFocus
property FOCUSABLEMINI.IsRequestingFocus(byval SetValue as boolean)
	THIS._isResquestingFocus = SetValue
end property 'set FOCUSABLEMINI.IsRequestingFocus(valBOOL)
property FOCUSABLEMINI.IsGrantedSubFocus() as boolean
	'---->
	return THIS._isGrantedSubFocus
end property 'get BOOL:=FOCUSABLEMINI.IsGrantedSubFocus
property FOCUSABLEMINI.IsGrantedSubFocus(byval SetValue as boolean)
	THIS._isGrantedSubFocus = SetValue
end property 'set FOCUSABLEMINI.IsGrantedSubFocus(valBOOL)
function FOCUSABLEMINI.TestForFocusRequest() as boolean
	'
	'for now only mouseClick could be request for focus
	if THIS.MouseClick then 
		if THIS.IsRequestingFocus=FALSE then THIS.IsRequestingFocus = TRUE
	else
		if THIS.IsRequestingFocus=TRUE then THIS.IsRequestingFocus = FALSE
	end if
	'
	'---->
	return THIS.IsRequestingFocus
end function 'BOOL:=FOCUSABLEMINI.TestForFocusRequest()


'                             -----------------
'                             DRAGGABLEMINI UDT
'                             -----------------
type DRAGGABLEMINI extends FOCUSABLEMINI
	declare constructor()
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string	
	'
	declare property MouseDrag() as boolean
	declare property MouseDrag(byval as boolean)
	declare function TestMouseDrag() as boolean
	declare sub DrawDragContourTrack()
	private:
		as integer		_infoMiniIndex
		as boolean		_mouseDrag
		as integer		_xAtDragTime
		as integer		_yAtDragTime
		as integer		_xDragOffsetFixedValue
		as integer		_yDragOffsetFixedValue
		as boolean		_markedAsTemporaryNonDraggable
		as integer					_draggableMiniFamillyCurrentMemberIndex
	static as integer				draggableMiniFamillyMemberCount
	static as DRAGGABLEMINI ptr		draggableMiniFamillyArrayOfPtr(any)
end type 'DRAGGABLEMINI XT FOCUSABLEMINI
dim as integer				DRAGGABLEMINI.draggableMiniFamillyMemberCount
dim as DRAGGABLEMINI ptr	DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr(any)
constructor DRAGGABLEMINI()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	DRAGGABLEMINI.draggableMiniFamillyMemberCount	+=> 1
	THIS._draggableMiniFamillyCurrentMemberIndex	 => _ 
								DRAGGABLEMINI.draggableMiniFamillyMemberCount - 1
	redim preserve _ 
	DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
								DRAGGABLEMINI.draggableMiniFamillyMemberCount - 1)
	DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
								uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr))	=> @THIS
	'
	with THIS
		._mouseDrag				=> FALSE
		._xDragOffsetFixedValue	=> ._xAtDragTime - .TopLeftCornerX
		._yDragOffsetFixedValue	=> ._yAtDragTime - .TopLeftCornerY
		._markedAsTemporaryNonDraggable	=> FALSE
	end with 'THIS
end constructor 'DRAGGABLEMINI default explicit constructor
destructor DRAGGABLEMINI()
	DRAGGABLEMINI.draggableMiniFamillyMemberCount -= 1
	select case DRAGGABLEMINI.draggableMiniFamillyMemberCount
		case is<=0
			erase DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr
		case else
			swap DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
								THIS._draggableMiniFamillyCurrentMemberIndex), _ 
				 DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
				 				uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr))
			redim preserve _ 
			DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
								uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr) - 1)
	end select 'DRAGGABLEMINI.rectangleFamillyMemberCount
	'
   	for index as integer = 0 to uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr)
  		DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr( _ 
  													 index)-> _ 
  													 _draggableMiniFamillyCurrentMemberIndex = _ 
  													 index
   	next index
end destructor 'DRAGGABLEMINI default explicit destructor
operator DRAGGABLEMINI.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<DRAGGABLEMINI>"& _
						THIS.TestMouseDrag() & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(DRAGGABLEMINI)
property DRAGGABLEMINI.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=DRAGGABLEMINI.InfoMiniIndex
function DRAGGABLEMINI.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=DRAGGABLEMINI.RefreshInfoMini()
property DRAGGABLEMINI.MouseDrag() as boolean
	'---->
	return THIS._mouseDrag
end property 'get BOOL:=DRAGGABLEMINI.MouseDrag
property DRAGGABLEMINI.MouseDrag(byval SetValue as boolean)
	THIS._mouseDrag = SetValue
end property 'set DRAGGABLEMINI.MouseDrag(valBOOL)
function DRAGGABLEMINI.TestMouseDrag() as boolean
	if THIS._mouseDrag=TRUE	then
		THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
		THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
	end if
	'
	with THIS
		if .TestMouseClick() then
			if not(._markedAsTemporaryNonDraggable) and _ 
			   ._mouseDrag=FALSE					then
			   	for index as integer = 0 to uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr)
			   		if index<>._draggableMiniFamillyCurrentMemberIndex then
			   			DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr(index)-> _ 
			   									_markedAsTemporaryNonDraggable = TRUE
			   		else
			   			THIS._markedAsTemporaryNonDraggable = FALSE
			   		end if
			   	next index
				._xAtDragTime = gmX
				._yAtDragTime = gmY
				._xDragOffsetFixedValue = ._xAtDragTime - .TopLeftCornerX
				._yDragOffsetFixedValue = ._yAtDragTime - .TopLeftCornerY
				._mouseDrag = TRUE
			end if
		else
			if ._mouseDrag=TRUE		then	
				._mouseDrag		= FALSE
			   	for index as integer = 0 to uBound(DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr)
			   		if index<>._draggableMiniFamillyCurrentMemberIndex then
			   			DRAGGABLEMINI.draggableMiniFamillyArrayOfPtr(index)-> _ 
			   										_markedAsTemporaryNonDraggable = FALSE
			   		end if
			   	next index
			end if
		end if		
	end with 'THIS	
	'---->
	return THIS.MouseDrag
end function 'BOOL:=DRAGGABLEMINI.TestMouseClick()
sub DRAGGABLEMINI.DrawDragContourTrack()
	if THIS.TestMouseDrag() then 
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			 rgb(240,090,120), _ 
			 b		
	end if
end sub 'DRAGGABLEMINI.DrawDragContourTrack()


'                              ----------------
'                              GUIRECTANGLE UDT
'                              ----------------
type GUIRECTANGLE extends DRAGGABLEMINI
	declare constructor()
	declare constructor(byval as _CONSTRUCTORENTRYMODE= _ 
								 _CONSTRUCTORENTRYMODE._topLeftCornerXYwidthHeight, _ 
						byval as integer, _ 
						byval as integer, _
						byval as integer, _
						byval as integer)
	declare destructor()
	declare operator cast() as string
	declare property InfoMiniIndex() as integer
	declare function RefreshInfoMini() as string
	'
	declare property ClickEnabled() as boolean
	declare property ClickEnabled(byval as boolean)
	declare property DragEnabled() as boolean
	declare property DragEnabled(byval as boolean)
	declare property BackgroundColor() as ulong
	declare property BackgroundColor(byval as ulong)
	declare property ForegroundColor() as ulong
	declare property ForegroundColor(byval as ulong)
	declare property OnMouseOverColor() as ulong
	declare property OnMouseOverColor(byval as ulong)
	declare property OnMouseClickColor() as ulong
	declare property OnMouseClickColor(byval as ulong)
	declare property OnMouseDragColor() as ulong
	declare property OnMouseDragColor(byval as ulong)
	declare property FocusableMiniArrayCount() as integer
	declare sub DrawRectangleContour()
	declare sub DrawRectangleInnerArea()
	declare sub DrawFocusableMiniSubElement()
		'note: focusableMiniArray must be built by the owner (see ICEBENCH):
		as integer				_focusableMiniArrayCount
		as FOCUSABLEMINI ptr	_focusableMiniArrayOfPtr(any)
	private:
		as integer				_infoMiniIndex
		as boolean				_clickEnabled
		as boolean				_dragEnabled
		as ulong				_bckgColor
		as ulong				_fgndColor
		as ulong				_onMouseOverColor
		as ulong				_onMouseClickColor
		as ulong				_onMouseDragColor
end type 'RECTANGLEMINI XT DRAGGABLEMINI
constructor GUIRECTANGLE()
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	with THIS
		._focusableMiniArrayCount	=> uBound(._focusableMiniArrayOfPtr) + 1
		._clickEnabled				=> TRUE
		._dragEnabled				=> TRUE
		._bckgColor			=> rgb(080,080,080)
		._fgndColor			=> rgb(240,240,190)
		._onMouseOverColor	=> rgb(120,080,120)
		._onMouseClickColor	=> rgb(080,080,120)
		._onMouseDragColor	=> rgb(080,080,120)
	end with 'THIS
end constructor 'GUIRECTANGLE default explicit constructor
constructor GUIRECTANGLE(byval Mode as RECTANGLEMINI._CONSTRUCTORENTRYMODE= _ 
			RECTANGLEMINI._CONSTRUCTORENTRYMODE._topLeftCornerXYwidthHeight, _ 
						 byval Arg1 as integer, _ 
						 byval Arg2 as integer, _
						 byval Arg3 as integer, _
						 byval Arg4 as integer)
	THIS.HierarchyLevel	=> _
			INFOMINI._HIERARCHYLEVEL._nonRootLevel
	THIS._infoMiniIndex	=> uBound(THIS._miniInfo) + 1
	redim preserve _ 
			THIS._miniInfo(uBound(THIS._miniInfo) + 1)
	THIS.RefreshInfoMini()
	'
	select case Mode
		case RECTANGLEMINI._CONSTRUCTORENTRYMODE._topLeftCornerXYwidthHeight
			THIS.TopLeftCornerX		=> Arg1
			THIS.TopLeftCornerY		=> Arg2
			THIS.RectangleWidth		=> Arg3
			THIS.RectangleHeight	=> Arg4
		case RECTANGLEMINI._CONSTRUCTORENTRYMODE._topLeftCornerXYbottomRightCornerXY
			THIS.TopLeftCornerX		=> Arg1
			THIS.TopLeftCornerY		=> Arg2
			THIS.BottomRightCornerX	=> Arg3
			THIS.BottomRightCornerY	=> Arg4
		case RECTANGLEMINI._CONSTRUCTORENTRYMODE._bottomRightCornerXYwidthHeight
			THIS.TopLeftCornerX		=> Arg1 - Arg3 + 1
			THIS.TopLeftCornerX		=> Arg2 - Arg4 + 1
			THIS.RectangleWidth		=> Arg3
			THIS.RectangleHeight	=> Arg4
		case _random
			dim as integer	scrW, scrH
			screenInfo		scrW, scrH
			randomize TIMER
			THIS.TopLeftCornerX		=> scrW\4 + rnd()*scrW\3
			THIS.TopLeftCornerY		=> scrH\4 + rnd()*scrH\3
			THIS.RectangleWidth		=> scrW\4 + rnd()*scrW\6
			THIS.RectangleHeight	=> scrH\4 + rnd()*scrH\6
		case else
			dim as integer	scrW, scrH
			screenInfo		scrW, scrH
			THIS.TopLeftCornerX		=> scrW\3
			THIS.TopLeftCornerY		=> scrH\3
			THIS.RectangleWidth		=> scrW\3
			THIS.RectangleHeight	=> scrH\3
	end select 'Mode
	'
	with THIS
		._focusableMiniArrayCount	=> uBound(._focusableMiniArrayOfPtr) + 1
		._clickEnabled				=> TRUE
		._dragEnabled				=> TRUE
		._bckgColor			=> rgb(080,080,080)
		._fgndColor			=> rgb(240,240,190)
		._onMouseOverColor	=> rgb(120,080,120)
		._onMouseClickColor	=> rgb(080,080,120)
		._onMouseDragColor	=> rgb(080,080,120)
	end with 'THIS
end constructor 'GUIRECTANGLE(valRECTANGLEMINI_CONSTRUCTORENTRYMODE[0],{valINT}*4)
destructor GUIRECTANGLE()
	'
end destructor 'GUIRECTANGLE default explicit destructor
operator GUIRECTANGLE.cast() as string
	dim as string	stringReturnValue => ""
	stringReturnValue =	"<GUIRECTANGLE>"& _
						"clickEnabled::"& THIS._clickEnabled & _ 
						"..dragEnabled:"& THIS._dragEnabled & _ 
						chr(10) & chr(13)
	'---->
	return stringReturnValue
end operator 'STR:=cast(GUIRECTANGLE)
property GUIRECTANGLE.InfoMiniIndex() as integer
	'---->
	return THIS._infoMiniIndex
end property 'get INT:=GUIRECTANGLE.InfoMiniIndex
function GUIRECTANGLE.RefreshInfoMini() as string
	if THIS.HierarchyLevel<>INFOMINI._HIERARCHYLEVEL._rootLevel then
		BASE.MiniInfo(BASE.InfoMiniIndex)	=> BASE.RefreshInfoMini()
	end if
	THIS._miniInfo(THIS.InfoMiniIndex)	=> THIS
	'---->
	return THIS
end function 'STR:=GUIRECTANGLE.RefreshInfoMini()
property GUIRECTANGLE.ClickEnabled() as boolean
	'---->
	return THIS._clickEnabled
end property 'get BOOL:=GUIRECTANGLE.ClickEnabled
property GUIRECTANGLE.ClickEnabled(byval SetValue as boolean)
	THIS._clickEnabled = SetValue
end property 'GUIRECTANGLE.ClickEnabled(valBOOL)
property GUIRECTANGLE.DragEnabled() as boolean
	'---->
	return THIS._dragEnabled
end property 'get BOOL:=GUIRECTANGLE.DragEnabled
property GUIRECTANGLE.DragEnabled(byval SetValue as boolean)
	THIS._dragEnabled = SetValue
end property 'GUIRECTANGLE.DragEnabled(byval as boolean)
property GUIRECTANGLE.BackgroundColor() as ulong
	'---->
	return THIS._bckgColor
end property 'get ULNG:=GUIRECTANGLE.BackgroundColor
property GUIRECTANGLE.BackgroundColor(byval SetValue as ulong)
	THIS._bckgColor = SetValue
end property ' set GUIRECTANGLE.BackgroundColor(valULNG)
property GUIRECTANGLE.ForegroundColor() as ulong
	'---->
	return THIS._fgndColor
end property 'get ULNG:=GUIRECTANGLE.ForegroundColor
property GUIRECTANGLE.ForegroundColor(byval SetValue as ulong)
	THIS._fgndColor = SetValue
end property 'set GUIRECTANGLE.ForegroundColor(valULNG)
property GUIRECTANGLE.OnMouseOverColor() as ulong
	'---->
	return THIS._onMouseOverColor
end property 'get ULNG:=GUIRECTANGLE.OnMouseOverColor
property GUIRECTANGLE.OnMouseOverColor(byval SetValue as ulong)
	THIS._onMouseOverColor = SetValue
end property 'set GUIRECTANGLE.OnMouseOverColor(valULNG)
property GUIRECTANGLE.OnMouseClickColor() as ulong
	'---->
	return THIS._onMouseClickColor
end property 'get ULNG:=GUIRECTANGLE.OnMouseClickColor
property GUIRECTANGLE.OnMouseClickColor(byval SetValue as ulong)
	THIS._onMouseClickColor = SetValue
end property 'set GUIRECTANGLE.OnMouseClickColor(valULNG)
property GUIRECTANGLE.OnMouseDragColor() as ulong
	'---->
	return THIS._onMouseDragColor
end property 'get ULNG:=GUIRECTANGLE.OnMouseDragColor
property GUIRECTANGLE.OnMouseDragColor(byval SetValue as ulong)
	THIS._onMouseDragColor = SetValue
end property 'set GUIRECTANGLE.OnMouseDragColor(valULNG)
property GUIRECTANGLE.FocusableMiniArrayCount() as integer
	'---->
	return ( uBound(THIS._focusableMiniArrayOfPtr) + 1 )
end property 'get INT:=GUIRECTANGLE.FocusableMiniArrayCount
sub GUIRECTANGLE.DrawRectangleContour()
	if THIS.TestMouseDrag() then 
		line (THIS.TopLeftCornerX - 3, THIS.TopLeftCornerY - 3)- _ 
			 (THIS.BottomRightCornerX + 3, THIS.BottomRightCornerY + 3), _ 
			  THIS.OnMouseDragColor, _ 
			 bf
	elseif THIS.TestMouseClick() then 
		line (THIS.TopLeftCornerX - 2, THIS.TopLeftCornerY - 2)- _ 
			 (THIS.BottomRightCornerX + 2, THIS.BottomRightCornerY + 2), _ 
			  THIS.OnMouseClickColor, _ 
			 bf
	elseif THIS.TestMouseOver() then 
		line (THIS.TopLeftCornerX - 1, THIS.TopLeftCornerY - 1)- _ 
			 (THIS.BottomRightCornerX + 1, THIS.BottomRightCornerY + 1), _ 
			  THIS.OnMouseOverColor, _ 
			 bf
	else
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			  THIS.BackgroundColor, _ 
			 bf
	end if
end sub 'GUIRECTANGLE.DrawRectangleContour()
sub GUIRECTANGLE.DrawRectangleInnerArea()
	if THIS.TestMouseDrag() then 
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			  THIS.OnMouseDragColor, _ 
			 bf
	elseif THIS.TestMouseClick() then 
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			  THIS.OnMouseClickColor, _ 
			 bf
	elseif THIS.TestMouseOver() then 
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			  THIS.OnMouseOverColor, _ 
			 bf
	else
		line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
			 (THIS.BottomRightCornerX, THIS.BottomRightCornerY), _ 
			  THIS.BackgroundColor, _ 
			 bf
	end if
end sub 'GUIRECTANGLE.DrawRectangleInnerArea()
sub GUIRECTANGLE.DrawFocusableMiniSubElement()
	for index as integer = 0 to THIS.FocusableMiniArrayCount
		THIS._focusableMiniArrayOfPtr(index)->DrawRectangleMini()
	next index
end sub 'GUIRECTANGLE.DrawFocusableMiniSubElement()


'                              ----------------
'                              DYNAMICBENCH UDT
'                              ----------------
type DYNAMICBENCH extends GUIRECTANGLE
	declare constructor()
	declare destructor()
	declare property CumulatedHeight() as integer
	declare sub RefreshBench()
	declare sub DrawBench()
		'as integer			_borderThickness
		'as integer			_bodySurfaceHeight
		'as boolean			_hasHeadBar
		'as boolean			_hasFootBar
		'as integer			_headBarHeight
		'as integer			_footBarHeight
		'as GUIRECTANGLE		_headBar
		'as GUIRECTANGLE		_footBar
		'as GUIRECTANGLE		_arrayOfBorder(3)
		'as GUIRECTANGLE		_arrayOfCorner(3)
		'as integer			_arrayOfPositionX(8)
		'as integer			_arrayOfPositionY(8)
end type 'DYNAMICBENCH XT GUIRECTANGLE
constructor DYNAMICBENCH()
	'
end constructor 'DYNAMICBENCH default explicit constructor


'                             -----------------
'                             FBAPPLICATION UDT
'                             -----------------
type FBAPPLICATION extends OBJECT
	declare property CurrentDirectory() as string
	private:
		as string	_currentDir
end type 'FBAPPLICATION XT OBJECT
property FBAPPLICATION.CurrentDirectory() as string
	'---->
	return curdir()
end property 'get STR:=FBAPPLICATION.CurrentDirectory


'                                  ------------
'                                  ICEBOARD UDT
'                                  ------------
type ICEBOARD extends FBAPPLICATION
	declare constructor()
	declare destructor()
	declare property BoardWidth()		as integer
	declare property BoardHeight()		as integer
	declare property BenchCount()		as integer
	declare property ZOrder(as integer) as integer
	declare function AddBench(byval as DYNAMICBENCH) _ 
										as integer
	declare function CreateBench()	as DYNAMICBENCH
	declare sub DrawBench()
	static as integer			constructionCounter
		as integer				_width
		as integer				_height
		as integer				_ownedBenchCount
		as DYNAMICBENCH ptr		_arrayOfBench(any)
end type 'ICEBOARD XT FBAPPLICATION
dim as integer ICEBOARD.constructionCounter	=> 0
constructor ICEBOARD()
	if ICEBOARD.constructionCounter>0 then 
		THIS.destructor()
	else 
		ICEBOARD.constructionCounter +=> 1
	end if
	'
	dim as integer deskTopW
	dim as integer deskTopH
	screenInfo deskTopW, deskTopH
	'
	THIS._width		=> desktopW - 200
	THIS._height	=> desktopH - 200
	screenRes THIS._width, _ 
	          THIS._height, _ 
	          32, _ 
	          1, _ 
	          fb.GFX_SHAPED_WINDOW
	color ,rgba(255,0,255,0)	
end constructor 'ICEBOARD default explicit constructor
destructor ICEBOARD()
	'
end destructor 'ICEBOARD default explicit destructor
property ICEBOARD.BoardWidth() as integer
	'---->
	return THIS._width
end property 'get INT:=ICEBOARD.BoardWidth
property ICEBOARD.BoardHeight() as integer
	'---->
	return THIS._height
end property 'get INT:=ICEBOARD.BoardHeight
property ICEBOARD.BenchCount() as integer
	'---->
	return ( (uBound(THIS._arrayOfBench) - _ 
			  lBound(THIS._arrayOfBench)) + _ 
			  1 )
end property 'get INT:=ICEBOARD.BenchCount
property ICEBOARD.ZOrder(Index as integer) as integer
	if Index>=lBound(THIS._arrayOfBench) and _
	   Index<=lBound(THIS._arrayOfBench) then
			'---->
			return THIS._arrayOfBench(Index)->ZOrder
	else
			'---->
			return log(-1)
	end if
end property 'get INT:=ZOrder(INDEX)
function ICEBOARD.AddBench(byval Bnc as DYNAMICBENCH) as integer
	'
end function 'INT:=ICEBOARD.AddBench(valDYNAMICBENCH)
function ICEBOARD.CreateBench() as DYNAMICBENCH
	'
end function 'BENCH:=ICEBOARD.CreateBench() 

sub ICEBOARD.DrawBench()
	'
end sub 'ICEBOARD.DrawBench()



'----------------------------------------------
'------------------------------------------MAIN

'--------------------------------INITIALIZATION
dim as integer deskTopW
dim as integer deskTopH
screenInfo deskTopW, deskTopH

screenRes desktopW, _ 
          desktopH, _ 
          32, _ 
          1, _ 
          fb.GFX_SHAPED_WINDOW + _ 
          fb.GFX_ALWAYS_ON_TOP
color ,rgba(255,0,255,0)

'dim as FOCUSABLEMINI	fcsMini
'dim as DRAGGABLEMINI	dgbMini
dim as GUIRECTANGLE		guiRect => _ 
						GUIRECTANGLE(,100,100,100,100)
dim as GUIRECTANGLE		guiRec2 => _ 
						GUIRECTANGLE(cast(RECTANGLEMINI._CONSTRUCTORENTRYMODE,1),0,0,0,0)

'-------------------------------------MAIN LOOP
do
	screenLock
		cls
			/'
			'focusable object
			fcsMini.DrawRectangleMini()
			fcsMini.RefreshInfoMini()
			fcsMini.ShowIdMini()
			fcsMini.ShowInfoMini()		
			'
			'draggable object
			dgbMini.DrawRectangleMini()
			dgbMini.DrawDragContourTrack()
			dgbMini.RefreshInfoMini()
			dgbMini.ShowIdMini()
			dgbMini.ShowInfoMini()
			'/
			'gui rectangle
			guiRect.DrawRectangleContour()
			guiRect.RefreshInfoMini()
			guiRect.ShowInfoMini()
			'
			guiRec2.DrawRectangleContour()
			guiRec2.RefreshInfoMini()
			guiRec2.ShowInfoMini()
	screenUnlock

	sleep 15
loop until inkey=chr(27)

'----------------------------------FINALIZATION

sleep
end 0

'[you've reached the end of the freebasic file]
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

I've switched a little on the focus mechanism. I've discovered that it's more complicated than it seems to be at least for me.
I don't know the good academic solution, so I've started developping a way to handle visible parts of windows.
Here the principle of how AREA and related stuff works:
Image
The demo below gives a clear insight of the concept. However if someone knows where to get documentation about best praxis around this programming point, I would enjoy learn it.

Code: Select all

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.

#include "fbgfx.bi"

'                                 -------------
'                                 RECTANGLE UDT
'                                 -------------
type RECTANGLE extends OBJECT
	declare constructor()
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	declare sub InitializeRectangle overload(byval as long=-1, _ 
											 byval as long=-1)
	declare sub InitializeRectangle(byval as long, _ 
									byval as long, _ 
									byval as long, _ 
									byval as long)
	declare destructor()
	declare sub FinalizeRectangle()
	'
	declare property Xi()	as long
	declare property Xi(byval as long)
	declare property Yi()	as long
	declare property Yi(byval as long)
	declare property W()	as long
	declare property W(byval as long)
	declare property H()	as long
	declare property H(byval as long)
	declare property Xf()	as long
	declare property Xf(byval as long)
	declare property Yf()	as long
	declare property Yf(byval as long)
	declare property TopLeftCornerX()		as long
	declare property TopLeftCornerX(byval 	as long)
	declare property TopLeftCornerY()		as long
	declare property TopLeftCornerY(byval 	as long)
	declare property RectangleWidth()		as long
	declare property RectangleWidth(byval 	as long)
	declare property RectangleHeight()		as long
	declare property RectangleHeight(byval 	as long)
	declare property BottomRightCornerX()		as long
	declare property BottomRightCornerX(byval 	as long)
	declare property BottomRightCornerY()		as long
	declare property BottomRightCornerY(byval 	as long)
	declare sub DrawRectangle()
	private:
		as long						_topLeftCornerX
		as long						_topLeftCornerY
		as long						_rectangleWidth
		as long						_rectangleHeight
		'
		as long						_maxWidth
		as long						_maxHeight
end type 'RECTANGLE <-- OBJECT
'->file to be saved as "RECTANGLE.imp.bas"

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.
'.implementation of RECTANGLE UDT..............

'inheritance lineage:
'RECTANGLE <-- OBJECT
constructor RECTANGLE()
	BASE()
	THIS.InitializeRectangle()
end constructor 'RECTANGLE default explicit constructor
constructor RECTANGLE(byval MaxW	as long, _ 
					  byval MaxH	as long)
	BASE()
	if maxW>0 then THIS._maxWidth	=> MaxW
	if maxH>0 then THIS._maxHeight	=> MaxH
	THIS.InitializeRectangle(THIS._maxWidth, _ 
							 THIS._maxHeight)
end constructor 'RECTANGLE(valLNG,valLNG)
constructor RECTANGLE(byval TCLX	as long, _ 
					  byval TCLY	as long, _ 
					  byval Wid		as long, _ 
					  byval Hei		as long)
	BASE()
	THIS.InitializeRectangle(TCLX,TCLY,Wid,Hei)
end constructor 'RECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub RECTANGLE.InitializeRectangle(byval MaxW as long=-1, _ 
								  byval MaxH as long=-1)
	dim as integer	scrW, scrH
	screenInfo		scrW, scrH
	if MaxW<=0 then
		with THIS
			._topLeftCornerX	=> scrW\3
			._rectangleWidth	=> scrW\3
		end with 'THIS
	else
		with THIS
			._topLeftCornerY	=> MaxH\3
			._rectangleHeight	=> MaxH\3
		end with 'THIS		
	end if
	if MaxH<=0 then
		with THIS
			._topLeftCornerY	=> scrH\3
			._rectangleHeight	=> scrH\3
		end with 'THIS
	else
		with THIS
			._topLeftCornerY	=> MaxH\3
			._rectangleHeight	=> MaxH\3
		end with 'THIS		
	end if
end sub 'RECTANGLE.InitializeRectangle(valLNG[-1],valLNG[-1])
sub RECTANGLE.InitializeRectangle(byval TCLX	as long, _ 
								  byval TCLY	as long, _ 
								  byval Wid		as long, _ 
								  byval Hei		as long)
	with THIS
		._topLeftCornerX	=> TCLX
		._topLeftCornerY	=> TCLY
		._rectangleWidth	=> Wid
		._rectangleHeight	=> Hei
	end with 'THIS
end sub 'RECTANGLE.InitializeRectangle(valLNG,valLNG,valLNG,valLNG)
destructor RECTANGLE()
	'
end destructor 'RECTANGLE default explicit destructor
sub RECTANGLE.FinalizeRectangle()
	THIS.destructor()
end sub 'RECTANGLE.FinalizeRectangle()
property RECTANGLE.Xi() as long
	'---->
	return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.Xi
property RECTANGLE.Xi(byval SetValue as long)
	THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.Xi(valLNG)
property RECTANGLE.Yi() as long
	'---->
	return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.Yi
property RECTANGLE.Yi(byval SetValue as long)
	THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.Yi(valLNG)
property RECTANGLE.W()	as long
	'---->
	return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.W
property RECTANGLE.W(byval SetValue as long)
	THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.W(valLNG)
property RECTANGLE.H()	as long
	'---->
	return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.H
property RECTANGLE.H(byval SetValue as long)
	THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.H(valLNG)
property RECTANGLE.Xf() as long
	'---->
	return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.Xf
property RECTANGLE.Xf(byval SetValue as long)
	if SetValue<THIS._topLeftCornerX then
		THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
		THIS._topLeftCornerX = SetValue
	else
		THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
	end if
end property 'set RECTANGLE.Xf(valLNG)
property RECTANGLE.Yf() as long
	'---->
	return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.Yf
property RECTANGLE.Yf(byval SetValue as long)
	if SetValue<THIS._topLeftCornerY then
		THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
		THIS._topLeftCornerY = SetValue
	else
		THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
	end if
end property 'set RECTANGLE.Yf(valLNG)
property RECTANGLE.TopLeftCornerX()	as long
	'---->
	return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.TopLeftCornerX
property RECTANGLE.TopLeftCornerX(byval SetValue as long)
	THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.TopLeftCornerX(valLNG)
property RECTANGLE.TopLeftCornerY()	as long
	'---->
	return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.TopLeftCornerY
property RECTANGLE.TopLeftCornerY(byval SetValue as long)
	THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.TopLeftCornerY(valLNG)
property RECTANGLE.RectangleWidth()	as long
	'---->
	return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.RectangleWidth
property RECTANGLE.RectangleWidth(byval SetValue as long)
	THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.RectangleWidth(valLNG)
property RECTANGLE.RectangleHeight() as long
	'---->
	return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.RectangleHeight
property RECTANGLE.RectangleHeight(byval SetValue as long)
	THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.RectangleHeight(valLNG)
property RECTANGLE.BottomRightCornerX()	as long
	'---->
	return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerX
property RECTANGLE.BottomRightCornerX(byval SetValue as long)
	if SetValue<THIS._topLeftCornerX then
		THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
		THIS._topLeftCornerX = SetValue
	else
		THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
	end if
end property 'set RECTANGLE.BottomRightCornerX(valLNG)
property RECTANGLE.BottomRightCornerY()	as long
	'---->
	return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerY
property RECTANGLE.BottomRightCornerY(byval SetValue as long)
	if SetValue<THIS._topLeftCornerY then
		THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
		THIS._topLeftCornerY = SetValue
	else
		THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
	end if
end property 'RECTANGLE.BottomRightCornerY(valLNG)
sub RECTANGLE.DrawRectangle()
	static as byte		switcher	=> +1
	static as double	startTime	=> 00
	dim as double	currentTime		=> TIMER()
	dim as double	timeInterval	=> 0.65
	if ( (currentTime - startTime)>timeInterval ) then
		switcher *= -1
		startTime = TIMER()
	end if
	if switcher=+1 then
		with THIS
			line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _ 
				 (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _ 
				  THIS._topLeftCornerY + THIS._rectangleHeight - 1), _ 
				  rgb(200,150,150), _
				  b, _ 
				  &b0000111100001111

		end with 'THIS		
	else 
		with THIS
			line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _ 
				 (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _ 
				  THIS._topLeftCornerY + THIS._rectangleHeight - 1), _ 
				  rgb(200,150,150), _
				  b, _ 
				  &b1111000011110000
		end with 'THIS			
	end if
end sub 'RECTANGLE.DrawRectangle()	


'                      ------------------------
'                      RECTANGLESIDESEGMENT UDT
'                      ------------------------
type RECTANGLESIDESEGMENT extends RECTANGLE
	declare constructor()
	declare constructor(byval as RECTANGLE ptr)
	declare sub InitializeRectangleSideSegment()
	declare destructor()
	enum _RELATIVEPOSITION
		_vout	= -5
		_vcover	= -4
		_vbot	= -3
		_vmid	= -2
		_vtop	= -1
		_none	= +0
		_hlef	= +1
		_hmid	= +2
		_hrig	= +3
		_hcover	= +4
		_hout	= +5
	end enum '_RELATIVEPOSITION
	declare property Xi()	as long
	declare property Xi(byval as long)
	declare property Yi()	as long
	declare property Yi(byval as long)
	declare property W()	as long
	declare property W(byval as long)
	declare property H()	as long
	declare property H(byval as long)
	declare property Xf()	as long
	declare property Xf(byval as long)
	declare property Yf()	as long
	declare property Yf(byval as long)
	declare property XHi()	as long
	declare property XHi(byval as long)
	declare property YHi()	as long
	declare property YHi(byval as long)
	declare property XHf()	as long
	declare property XHf(byval as long)
	declare property YHf()	as long
	declare property YHf(byval as long)
	declare property XVi()	as long
	declare property XVi(byval as long)
	declare property YVi()	as long
	declare property YVi(byval as long)
	declare property XVf()	as long
	declare property XVf(byval as long)
	declare property YVf()	as long
	declare property YVf(byval as long)
	declare property HorizontalPositionComparisonResult()	as _RELATIVEPOSITION
	declare property VerticalPositionComparisonResult()		as _RELATIVEPOSITION
	declare sub EnterRectangleForSideComparison(byval as RECTANGLE ptr)
	declare sub EnterSideSegmentForSideComparison(byval as RECTANGLESIDESEGMENT ptr)
	declare function CompareForHside()	as _RELATIVEPOSITION
	declare function CompareForVside() 	as _RELATIVEPOSITION
	declare sub VisualizeComparison()
		as RECTANGLE ptr			_comparedToRectanglePtr
		as RECTANGLESIDESEGMENT ptr	_comparedToRectangleSideSegmentPtr ''note: no more in use
	private:
		as long						_xHi
		as long						_yHi
		as long						_xHf
		as long						_yHf
		as long						_xVi
		as long						_yVi
		as long						_xVf
		as long						_yVf
	enum _HVORIENTATION
		_vertical	= -1
		_none		= -0
		_horizontal	= +1
	end enum '_HVORIENTATION
		as _HVORIENTATION		_comparisonOrientation
		as _RELATIVEPOSITION	_positionComparisonResult(1 to 2)
end type 'RECTANGLESIDESEGMENT <-- RECTANGLE <-- OBJECT


'                                      --------
'                                      AREA UDT
'                                      --------
type AREA extends OBJECT
	declare constructor()
	declare constructor(() as RECTANGLE ptr)
	declare destructor()
	declare property RectangleCount() as long
	declare function AddRectangle overload(byval as RECTANGLE) as long
	declare function AddRectangle(byval as RECTANGLE ptr) as long
	declare sub ReduceRectangleArray()
	declare sub VisualizeArea()
		as long						_rectangleCount
		as RECTANGLE				_arrayOfRectangle(any)
end type 'AREA <-- OBJECT


'                              Geometry OPERATOR
'                              -----------------
declare operator - (byref as RECTANGLE, _ 
				   	byref as RECTANGLE) _ 
				   	as AREA

declare operator + (byref as RECTANGLE, _ 
					byref as AREA) _ 
					as AREA

declare operator + (byref as AREA, _ 
					byref as AREA) _ 
					as AREA

declare operator - (byref as RECTANGLE, _ 
				   	byref as AREA) _ 
				   	as AREA

'dev. note: 
'below operator not implemented (will ever be?)
declare operator -(byref as AREA, byref as AREA) _ 
										as AREA

'->file to be saved as "AREA.imp.bas"

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.
'.implementation of RECTANGLESIDESEGMENT UDT...
'.implementation of AREA UDT...................
'.implementation of TRACKABLEAREA UDT..........
'.implementation of Geometry OPERATOR..........


type SIDESEG as RECTANGLESIDESEGMENT
'inheritance lineage:
'RECTANGLESIDESEGMENT <-- RECTANGLE <-- OBJECT
'                      RECTANGLESIDESEGMENT IMP
'                      ------------------------
constructor SIDESEG()
	BASE()
	'
	THIS.InitializeRectangleSideSegment()
	THIS.EnterSideSegmentForSideComparison(@THIS)
	THIS._positionComparisonResult(1)	=> THIS.CompareForHside()
	THIS._positionComparisonResult(2)	=> THIS.CompareForVside()
end constructor 'SIDESEG default explicit constructor
constructor SIDESEG(byval CompareToRectanglePointer as RECTANGLE ptr)
	BASE()
	'
	THIS.InitializeRectangleSideSegment()

	'note: line below questionning......................
	THIS._comparedToRectangleSideSegmentPtr = new SIDESEG

	THIS.EnterRectangleForSideComparison(CompareToRectanglePointer)
	THIS.CompareForHside()
	THIS.CompareForVside()
end constructor 'SIDESEG(valRECTANGLE_PTR)
sub SIDESEG.InitializeRectangleSideSegment()
	with THIS
		'horizontal side segment
		._xHi	=> .Xi
		._yHi	=> .Yi
		._xHf	=> .Xf
		._yHf	=> .Yi
	end with 'THIS
	with THIS
		'vertical side segment
		._xVi	=> .Xi
		._yVi	=> .Yi
		._xVf	=> .Xi
		._yVf	=> .Yf
	end with 'THIS
end sub 'SIDESEG.InitializeRectangleSideSegment()
destructor SIDESEG()
	'delete THIS._comparedToRectangleSideSegmentPtr
end destructor 'SIDESEG default explicit destructor
property SIDESEG.Xi()	as long
	'---->
	return BASE.Xi
end property 'get LNG:=SIDESEG.Xi
property SIDESEG.Xi(byval SetValue as long)
	BASE.Xi = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.Xi(valLNG)
property SIDESEG.Yi()	as long
	'---->
	return BASE.Yi
end property 'get LNG:=SIDESEG.Yi
property SIDESEG.Yi(byval SetValue as long)
	BASE.Yi = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.Yi(valLNG)
property SIDESEG.W() as long
	'---->
	return BASE.W
end property 'get LNG:=SIDESEG.W
property SIDESEG.W(byval SetValue as long)
	BASE.W = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.W(valLNG)
property SIDESEG.H() as long
	'---->
	return BASE.H
end property 'get LNG:=SIDESEG.H
property SIDESEG.H(byval SetValue as long)
	BASE.H = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.H(valLNG)
property SIDESEG.Xf()	as long
	'---->
	return BASE.Xf
end property 'get LNG:=SIDESEG.Xf
property SIDESEG.Xf(byval SetValue as long)
	BASE.Yi = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.Xf(valLNG)
property SIDESEG.Yf()	as long
	'---->
	return BASE.Yf
end property 'get LNG:=SIDESEG.Yf
property SIDESEG.Yf(byval SetValue as long)
	BASE.Yf = SetValue
	THIS.InitializeRectangleSideSegment()
end property 'set SIDESEG.Yf(valLNG)
property SIDESEG.XHi()	as long
	'---->
	return THIS._xHi
end property 'get LNG:=SIDESEG.XHi
property SIDESEG.XHi(byval SetValue as long)
	THIS._xHi	= SetValue
	BASE.Xi		= SetValue
end property 'set SIDESEG.XHi(valLNG)
property SIDESEG.YHi()	as long
	'---->
	return THIS._yHi
end property 'get LNG:=SIDESEG.YHi
property SIDESEG.YHi(byval SetValue as long)
	THIS._yHi = SetValue
	BASE.Yi   = SetValue
end property 'set SIDESEG.YHi(valLNG)
property SIDESEG.XHf()	as long
	'---->
	return THIS._xHf
end property 'get LNG:=SIDESEG.XHf
property SIDESEG.XHf(byval SetValue as long)
	THIS._xHf = SetValue
	BASE.Xf   = SetValue
end property 'set SIDESEG.XHf(valLNG)
property SIDESEG.YHf()	as long
	'---->
	return THIS._yHf
end property 'get LNG:=SIDESEG.YHf
property SIDESEG.YHf(byval SetValue as long)
	THIS._yHf = SetValue
	BASE.Yi   = SetValue
end property 'set SIDESEG.YHf(valLNG)
property SIDESEG.XVi()	as long
	'---->
	return THIS._xVi
end property 'get LNG:=SIDESEG.XVi
property SIDESEG.XVi(byval SetValue as long)
	THIS._xVi = SetValue
	BASE.Xi   = SetValue
end property 'set SIDESEG.XVi(valLNG)
property SIDESEG.YVi()	as long
	'---->
	return THIS._yVi
end property 'get LNG:=SIDESEG.YVi
property SIDESEG.YVi(byval SetValue as long)
	THIS._yVi = SetValue
	BASE.Yi   = SetValue
end property 'set SIDESEG.YVi(valLNG)
property SIDESEG.XVf()	as long
	'---->
	return THIS._xVf
end property 'get LNG:=SIDESEG.XVf
property SIDESEG.XVf(byval SetValue as long)
	THIS._xVf = SetValue
	BASE. Xi  = SetValue
end property 'set SIDESEG.XVf(valLNG)
property SIDESEG.YVf()	as long
	'---->
	return THIS._yVf
end property 'get LNG:=SIDESEG.YVf
property SIDESEG.YVf(byval SetValue as long)
	THIS._yVf = SetValue
	BASE.Yf   = SetValue
end property 'set SIDESEG.YVf(valLNG)
property SIDESEG.HorizontalPositionComparisonResult() as _RELATIVEPOSITION
	'---->
	return THIS._positionComparisonResult(1)
end property 'get SIDESEG_RELATIVEPOSITION:=SIDESEG.HorizontalPositionComparisonResult
property SIDESEG.VerticalPositionComparisonResult() as _RELATIVEPOSITION
	'---->
	return THIS._positionComparisonResult(2)
end property 'get SIDESEG_RELATIVEPOSITION:=SIDESEG.VerticalPositionComparisonResult
sub SIDESEG.EnterRectangleForSideComparison(byval RectanglePointer as RECTANGLE ptr)
	THIS._comparedToRectanglePtr			= RectanglePointer
end sub 'SIDESEG.EnterRectangleForSideComparison(valRECTANGLE_PTR)
sub SIDESEG.EnterSideSegmentForSideComparison(byval SideSegPointer as SIDESEG ptr)
	'dev.note: not tested - related constructor removed
	'--------------------------------------------------
	THIS._comparedToRectangleSideSegmentPtr = SideSegPointer
	THIS._comparedToRectanglePtr			= @RECTANGLE(*SideSegPointer)
end sub 'SIDESEG.EnterSideSegmentForSideComparison(valSIDESEG_PTR)
function SIDESEG.CompareForHside()	as SIDESEG._RELATIVEPOSITION
	dim as SIDESEG._RELATIVEPOSITION	returnPosition
	'security check for null pointer
	if THIS._comparedToRectangleSideSegmentPtr=0 then
		returnPosition = SIDESEG._RELATIVEPOSITION._none
		'---->
		return returnPosition
	end if
	'           _____________________________           
	'                       cover                       
	' _________ _________ _________ _________ _________ 
	'   out        left      mid      right     out     
	'                +------------------+               
	'                I                  F               
	if _
			THIS._comparedToRectanglePtr->Xi<=THIS._xHi	and _
			THIS._comparedToRectanglePtr->Xf>=THIS._xHf	then
		returnPosition = SIDESEG._RELATIVEPOSITION._hcover
	elseif _
			THIS._comparedToRectanglePtr->Xi>=THIS._xHf	and _
			THIS._comparedToRectanglePtr->Xf<=THIS._xHi	then
		returnPosition = SIDESEG._RELATIVEPOSITION._hcover
	elseif _ 
			THIS._comparedToRectanglePtr->Xi<=THIS._xHi	and _
			THIS._comparedToRectanglePtr->Xf<THIS._xHf		and _
			THIS._comparedToRectanglePtr->Xf>THIS._xHi		then
		returnPosition = SIDESEG._RELATIVEPOSITION._hlef
	elseif _ 
			THIS._comparedToRectanglePtr->Xi>THIS._xHi		and _
			THIS._comparedToRectanglePtr->Xi<THIS._xHf		and _
			THIS._comparedToRectanglePtr->Xf>=THIS._xHf	then
		returnPosition = SIDESEG._RELATIVEPOSITION._hrig
	elseif _ 
			THIS._comparedToRectanglePtr->Xi>THIS._xHi		and _
			THIS._comparedToRectanglePtr->Xi<THIS._xHf		and _
			THIS._comparedToRectanglePtr->Xf<THIS._xHf		and _
			THIS._comparedToRectanglePtr->Xf>THIS._xHi		then
		returnPosition = SIDESEG._RELATIVEPOSITION._hmid
	else
		returnPosition = SIDESEG._RELATIVEPOSITION._hout
	end if
	'
	THIS._positionComparisonResult(1) = returnPosition
	'---->
	return returnPosition
end function 'SIDESEG._RELATIVEPOSITION:=SIDESEG.CompareForHside()
function SIDESEG.CompareForVside() 	as SIDESEG._RELATIVEPOSITION
	dim as SIDESEG._RELATIVEPOSITION	returnPosition
	'security check for null pointer
	if THIS._comparedToRectangleSideSegmentPtr=0 then
		returnPosition = SIDESEG._RELATIVEPOSITION._none
		'---->
		return returnPosition
	end if
	'            
	'        !    
	'       t!   !
	'       o!   !
	'   I+  p!   !
	'    :   !   !
	'    :       !
	'    :   !  c!
	'    :  m!  o!
	'    :  i!  v!
	'    :  d!  e!
	'    :   !  r!
	'    :       !
	'    :   !   !
	'   F+  b!   !
	'       o!   !
	'       t!   !
	'        !    
	'             
	if _
			THIS._comparedToRectanglePtr->Yi<=THIS._yVi	and _
			THIS._comparedToRectanglePtr->Yf>=THIS._yVf	then
		returnPosition = SIDESEG._RELATIVEPOSITION._vcover
	elseif _
			THIS._comparedToRectanglePtr->Yi>=THIS._yVf	and _
			THIS._comparedToRectanglePtr->Yf<=THIS._yVi	then
		returnPosition = SIDESEG._RELATIVEPOSITION._vcover
	elseif _ 
			THIS._comparedToRectanglePtr->Yi<=THIS._yVi	and _
			THIS._comparedToRectanglePtr->Yf<THIS._yVf		and _
			THIS._comparedToRectanglePtr->Yf>THIS._yVi		then
		returnPosition = SIDESEG._RELATIVEPOSITION._vtop
	elseif _ 
			THIS._comparedToRectanglePtr->Yi>THIS._yVi		and _
			THIS._comparedToRectanglePtr->Yi<THIS._yVf		and _
			THIS._comparedToRectanglePtr->Yf>=THIS._yVf	then
		returnPosition = SIDESEG._RELATIVEPOSITION._vbot
	elseif _ 
			THIS._comparedToRectanglePtr->Yi>THIS._yVi		and _
			THIS._comparedToRectanglePtr->Yi<THIS._yVf		and _
			THIS._comparedToRectanglePtr->Yf<THIS._yVf		and _
			THIS._comparedToRectanglePtr->Yf>THIS._yVi		then
		returnPosition = SIDESEG._RELATIVEPOSITION._vmid
	else
		returnPosition = SIDESEG._RELATIVEPOSITION._vout
	end if
	'
	THIS._positionComparisonResult(2) = returnPosition
	'---->
	return returnPosition
end function 'SIDESEG._RELATIVEPOSITION:=SIDESEG.CompareForVside()
sub SIDESEG.VisualizeComparison()
	THIS._comparedToRectanglePtr->DrawRectangle()
	THIS.DrawRectangle()
	draw string (THIS.Xi,THIS.Yi), "ref rectangle"
	'
	dim as string	relativeHsidePositionInfo
	dim as string	relativeVsidePositionInfo
	select case THIS.HorizontalPositionComparisonResult
		case SIDESEG._RELATIVEPOSITION._hcover
			relativeHsidePositionInfo = "reference horizontal side masked"
		case SIDESEG._RELATIVEPOSITION._hlef
			relativeHsidePositionInfo = "left of the horizontal side masked"
		case SIDESEG._RELATIVEPOSITION._hmid
			relativeHsidePositionInfo = "mid of the horizontal side masked"
		case SIDESEG._RELATIVEPOSITION._hrig
			relativeHsidePositionInfo = "right of the horizontal side masked"
		case else 'hout
			relativeHsidePositionInfo = "no horizontal intersection"
	end select
	select case THIS.VerticalPositionComparisonResult
		case SIDESEG._RELATIVEPOSITION._vcover
			relativeVsidePositionInfo = "reference vertical side masked"
		case SIDESEG._RELATIVEPOSITION._vtop
			relativeVsidePositionInfo = "top of the vertical side masked"
		case SIDESEG._RELATIVEPOSITION._vmid
			relativeVsidePositionInfo = "mid of the vertical side masked"
		case SIDESEG._RELATIVEPOSITION._vbot
			relativeVsidePositionInfo = "bot of the vertical side masked"
		case else 'vout
			relativeVsidePositionInfo = "no vertical intersection"
	end select
	'
	print relativeHsidePositionInfo
	print relativeVsidePositionInfo
end sub 'SIDESEG.VisualizeComparison()


'inheritance lineage:
'AREA <-- OBJECT
'                                      AREA IMP
'                                      --------
constructor AREA()
	BASE()
end constructor 'AREA default explicit constructor
constructor AREA(RectangleArrayOfPtr() as RECTANGLE ptr)
	BASE()
	'
	for index as long = lBound(RectangleArrayOfPtr) to uBound(RectangleArrayOfPtr)
		THIS.AddRectangle(RectangleArrayOfPtr(index))
	next index
end constructor 'AREA(refRECTANGLE_PTR())
destructor AREA()
	'
end destructor 'AREA default explicit destructor
property AREA.RectangleCount() as long
	'---->
	return ( uBound(THIS._arrayOfRectangle) - _ 
			 lBound(THIS._arrayOfRectangle) _ 
			 + 1 )
end property 'get LNG:=AREA.RectangleCount
function AREA.AddRectangle overload(byval R as RECTANGLE) as long
	with THIS
		._rectangleCount += 1
		redim preserve ._arrayOfRectangle(uBound(._arrayOfRectangle) + 1)
		._arrayOfRectangle(uBound(._arrayOfRectangle)) = R
	end with 'THIS
	'
	'---->
	return THIS._rectangleCount
end function 'OVERLOAD LNG:=AREA.AddRectangle(valRECTANGLE)
function AREA.AddRectangle(byval RectanglePointer as RECTANGLE ptr) as long
	if RectanglePointer=0 then
		'---->
		return THIS._rectangleCount
	end if
	'
	with THIS
		._rectangleCount += 1
		redim preserve ._arrayOfRectangle(uBound(._arrayOfRectangle) + 1)
		._arrayOfRectangle(uBound(._arrayOfRectangle)) = *RectanglePointer
	end with 'THIS
	'
	'---->
	return THIS._rectangleCount
end function 'OVERLOAD LNG:=AREA.AddRectangle(valRECTANGLE_PTR)
sub AREA.ReduceRectangleArray()	
	dim as long		m
	dim as long		n
	dim as boolean	hasToExit => FALSE
	'
	if THIS.RectangleCount<=1 then exit sub
	'
	dim as long		initialRectangleCount
	do	'test for right side to left side possible fusion
		initialRectangleCount = THIS.RectangleCount
		'
		for n=0 to (THIS.RectangleCount - 1)
			for m=0 to (THIS.RectangleCount - 1)
				if n<>m																and _
				   THIS._arrayOfRectangle(n).Xf=THIS._arrayOfRectangle(m).Xi		and _
				   THIS._arrayOfRectangle(n).Yi=THIS._arrayOfRectangle(m).Yi		and _
				   THIS._arrayOfRectangle(n).Yf=THIS._arrayOfRectangle(m).Yf		then
						'replace old n index rectangle by new fusionned one
						THIS._arrayOfRectangle(n).InitializeRectangle(THIS._arrayOfRectangle(n).Xi, _ 
																	  THIS._arrayOfRectangle(n).Yi, _ 
							(THIS._arrayOfRectangle(m).Xf - THIS._arrayOfRectangle(n).Xi + 1), _ 
							(THIS._arrayOfRectangle(m).Yf - THIS._arrayOfRectangle(n).Yi + 1))
						'erase old m index rectangle
						swap THIS._arrayOfRectangle(m), THIS._arrayOfRectangle(uBound(THIS._arrayOfRectangle))
						redim preserve THIS._arrayOfRectangle(uBound(THIS._arrayOfRectangle) - 1)
						hasToExit = TRUE
						exit for
				end if
			next m
			if hasToExit then exit for
		next n
		hasToExit = FALSE
		if THIS.RectangleCount<=1 then exit sub
	loop until ( (THIS.RectangleCount - initialRectangleCount)=0 )
	'
	do	'test for bottom side to top side possible fusion
		initialRectangleCount = THIS.RectangleCount
		'
		for n=0 to (THIS.RectangleCount - 1)
			for m=0 to (THIS.RectangleCount - 1)
				if n<>m																and _
				   THIS._arrayOfRectangle(n).Xi=THIS._arrayOfRectangle(m).Xi		and _
				   THIS._arrayOfRectangle(n).Xf=THIS._arrayOfRectangle(m).Xf		and _
				   THIS._arrayOfRectangle(n).Yf=THIS._arrayOfRectangle(m).Yi		then
						'replace old n index rectangle by new fusionned one
						THIS._arrayOfRectangle(n).InitializeRectangle(THIS._arrayOfRectangle(n).Xi, _ 
																	  THIS._arrayOfRectangle(n).Yi, _ 
							(THIS._arrayOfRectangle(m).Xf - THIS._arrayOfRectangle(n).Xi + 1), _ 
							(THIS._arrayOfRectangle(m).Yf - THIS._arrayOfRectangle(n).Yi + 1))
						'erase old m index rectangle
						swap THIS._arrayOfRectangle(m), THIS._arrayOfRectangle(uBound(THIS._arrayOfRectangle))
						redim preserve THIS._arrayOfRectangle(uBound(THIS._arrayOfRectangle) - 1)
						hasToExit = TRUE
						exit for
				end if
			next m
			if hasToExit then exit for
		next n
		hasToExit = FALSE
		if THIS.RectangleCount<=1 then exit sub	
	loop until  ( (THIS.RectangleCount - initialRectangleCount)=0 )
end sub 'AREA.ReduceRectangleArray()
sub AREA.VisualizeArea()
	for index as long = 0 to uBound(THIS._arrayOfRectangle)
		THIS._arrayOfRectangle(index).DrawRectangle()
		draw string (THIS._arrayOfRectangle(index).Xi, _ 
					 THIS._arrayOfRectangle(index).Yi), _ 
					 str(index)
	next index
end sub 'AREA.VisualizeArea()


'                              Geometry OP. IMP.
'                              -----------------
operator - (byref R1 as RECTANGLE, byref R2 as RECTANGLE) as AREA
	dim as AREA	resultArea
	'
	dim as SIDESEG	testRSS	=> SIDESEG(@R2)
	testRSS.Xi	=> R1.Xi
	testRSS.Yi	=> R1.Yi
	testRSS.W	=> R1.W
	testRSS.H	=> R1.H
	testRSS.CompareForHside()
	testRSS.CompareForVside()
	'
	if _	 'case 01/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hmid		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vmid		then 
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/8
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/8
				testRect.Xi = R2.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/8
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 4/8
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 5/8
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 6/8
				testRect.Xi = R2.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 7/8
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 8/8
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 02/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hcover	and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vcover		then 	
			resultArea._rectangleCount = 0
			erase resultArea._arrayOfRectangle
	elseif _ 'case 03/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hcover	and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vtop		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/1
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 04/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hlef		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vcover		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/1
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 05/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hcover	and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vmid		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/2
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 06/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hmid		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vcover		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/2
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 07/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hcover	and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vbot		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/1
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 08/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hrig		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vcover		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/1
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 09/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hlef		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vtop		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/3
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 3/3
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 10/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hrig		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vtop		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/3
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R2.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 3/3
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 11/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hrig		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vbot		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/3
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R2.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/3
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 12/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hlef		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vbot		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/3
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/2
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/3
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 13/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hlef		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vmid		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/5
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/5
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/5
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 4/5
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 5/5
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 14/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hmid		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vtop		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/5
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 2/5
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			'rectangle 3/5
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 4/5
				testRect.Xi = R2.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 5/5
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 15/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hrig		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vmid		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/5
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/5
				testRect.Xi = R2.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/5
				testRect.Xi = R2.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 4/5
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yf
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 5/5
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	elseif _ 'case 16/17
		testRSS.HorizontalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._hmid		and _
		testRSS.VerticalPositionComparisonResult=SIDESEG._RELATIVEPOSITION._vbot		then 	
			dim as RECTANGLE	testRect
			with resultArea
			'rectangle 1/5
				testRect.Xi = R1.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 2/5
				testRect.Xi = R2.Xi
				testRect.Yi = R1.Yi
				testRect.Xf = R2.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 3/5
				testRect.Xi = R2.Xf
				testRect.Yi = R1.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R2.Yi
				.AddRectangle(@testRect)
			'rectangle 4/5
				testRect.Xi = R2.Xf
				testRect.Yi = R2.Yi
				testRect.Xf = R1.Xf
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			'rectangle 5/5
				testRect.Xi = R1.Xi
				testRect.Yi = R2.Yi
				testRect.Xf = R2.Xi
				testRect.Yf = R1.Yf
				.AddRectangle(@testRect)
			end with 'resultArea
	else _	'case 17/17 (17/36 but remaining states are all out)
			'case out
			resultArea._rectangleCount = 1
			redim resultArea._arrayOfRectangle(resultArea._rectangleCount - 1)
			resultArea._arrayOfRectangle(0) = R1
	end if
	'
	resultArea.ReduceRectangleArray()
	'---->
	return resultArea
end operator 'AREA:=(RECTANGLE - RECTANGLE)

operator + (byref R as RECTANGLE, A as AREA) as AREA
	dim as AREA	resultArea	=> A
	'
	resultArea.AddRectangle(R)
	'---->
	return resultArea
end operator 'AREA:=(AREA - AREA)

operator + (byref A1 as AREA, A2 as AREA) as AREA
	'dev.note:
	'not taking account of overlapping initial states
	'that would have required analysis+clean-up
	'shouldn't occure in this context however (....?)
	dim as AREA	resultArea
	'
	select case ( A2.RectangleCount < A1.RectangleCount )
		case TRUE
			resultArea => A1
			for index as long = 1 to  A2.RectangleCount
				resultArea.AddRectangle(A2._arrayOfRectangle(index - 1))
			next index
		case else
			resultArea => A2
			for index as long = 1 to  A1.RectangleCount
				resultArea.AddRectangle(A1._arrayOfRectangle(index - 1))
			next index
	end select '( A2.RectangleCount < A1.RectangleCount )
	'
	resultArea.ReduceRectangleArray()
	'---->
	return resultArea
end operator 'AREA:=(AREA - AREA)

'***********************************************
'****impotant test needed for below operator****
'***********************************************
operator - (byref R as RECTANGLE, byref MaskArea as AREA) as AREA
	dim as AREA	resultArea
	dim as AREA	temporaryArea
	dim as long	i, j
	'
	temporaryArea.AddRectangle(R)
	for i = 0 to (temporaryArea.RectangleCount - 1)
		for j = 0 to (MaskArea.RectangleCount - 1)
			temporaryArea = temporaryArea._arrayOfRectangle(i) - MaskArea._arrayOfRectangle(j)
			resultArea += temporaryArea 
			resultArea.ReduceRectangleArray()
		next j
	next i
	'---->
	return resultArea
end operator 'AREA:=( RECTANGLE - RECTANGLE() )

'todo-->
operator -(byref A1 as AREA, byref A2 as AREA) as AREA
	dim as AREA	resultArea
	'
	'**********
	'***TODO***
	'**********
	'
	resultArea.ReduceRectangleArray()
	'---->
	return resultArea
end operator 'AREA:=(AREA - AREA)


'                        ----------------------
'                        DRAGGABLERECTANGLE UDT
'                        ----------------------
type DRAGGABLERECTANGLE extends RECTANGLE
	declare constructor()
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	declare sub InitializeDraggableRectangle()
	declare destructor()
	declare sub TestDraggableRectangleForMouse()
	declare sub DrawDraggableRectangle()
		as ulong			_bckgColor
		as ulong			_fgndColor
		as boolean			_mouseOver
		as boolean			_mouseClick
		as boolean			_mouseDrag
		as ulong			_onMouseOverBckgColor
		as ulong			_onMouseClickBckgColor
		as ulong			_onMouseDragBckgColor
		'
		as boolean			_clickEnabled
		as boolean			_dragEnabled
	enum _DRAGAXISCONSTRAINT
		_yOnly	= -2
		_xOnly	= -1
		_noAxis	= -0
		_xy		= +1
	end enum '_DRAGAXISCONSTRAINT	
	as _DRAGAXISCONSTRAINT	_dragAxis
		as integer			_xAtDragTime
		as integer			_yAtDragTime
		as integer			_xDragOffsetFixedValue
		as integer			_yDragOffsetFixedValue
		as boolean			_markedAsTemporaryNonDraggable
		as integer						_draggableFamillyCurrentMemberIndex	
	static as integer					draggableFamillyMemberCount
	static as DRAGGABLERECTANGLE ptr	draggableFamillyArrayOfPtr(any)
end type 'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
dim as integer					DRAGGABLERECTANGLE.draggableFamillyMemberCount
dim as DRAGGABLERECTANGLE ptr	DRAGGABLERECTANGLE.draggableFamillyArrayOfPtr(any)
'->file to be saved as "DRAGGABLERECTANGLE.imp.bas"

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.
'.implementation of DRAGGABLERECTANGLE UDT.....

type DR as DRAGGABLERECTANGLE
'inheritance lineage:
'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor DRAGGABLERECTANGLE()
	BASE()
	THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE default explicit constructor
constructor DRAGGABLERECTANGLE(byval MaxW	as long, _ 
							   byval MaxH	as long)
	BASE()
	THIS.InitializeRectangle(MaxW, MaxH)
	THIS.InitializeDraggableRectangle()
end constructor 'RECTANGLE(valLNG,valLNG)
constructor DRAGGABLERECTANGLE(byval TCLX	as long, _ 
							   byval TCLY	as long, _ 
							   byval W		as long, _ 
							   byval H		as long)
	BASE()
	THIS.InitializeRectangle(TCLX, TCLY, W, H)
	THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub DRAGGABLERECTANGLE.InitializeDraggableRectangle()
	'-constructor routine-
	DR.draggableFamillyMemberCount				+=> 1
	THIS._draggableFamillyCurrentMemberIndex	 => DR.draggableFamillyMemberCount - 1
	redim preserve DR.draggableFamillyArrayOfPtr(DR.draggableFamillyMemberCount - 1)
	DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))	=> @THIS
	'
	with THIS
		._bckgColor					=> rgb(080,080,080)
		._fgndColor					=> rgb(240,240,190)
		._onMouseOverBckgColor		=> rgb(120,080,120)
		._onMouseClickBckgColor		=> rgb(080,120,080)
		._onMouseDragBckgColor		=> rgb(080,080,120)
		._clickEnabled		=> TRUE
		._dragEnabled		=> TRUE
		._mouseOver			=> FALSE
		._mouseClick		=> FALSE
		._mouseDrag			=> FALSE
		._dragAxis			=> DR._DRAGAXISCONSTRAINT._xy
		._xDragOffsetFixedValue	=> ._xAtDragTime - .TopLeftCornerX
		._yDragOffsetFixedValue	=> ._yAtDragTime - .TopLeftCornerY
		._markedAsTemporaryNonDraggable	=> FALSE
	end with 'THIS
end sub 'DRAGGABLERECTANGLE.InitializeDraggableRectangle()
destructor DRAGGABLERECTANGLE()
	DR.draggableFamillyMemberCount -= 1
	'
	select case DR.draggableFamillyMemberCount
		case is<=0
			erase DR.draggableFamillyArrayOfPtr
		case else
			swap DR.draggableFamillyArrayOfPtr(THIS._draggableFamillyCurrentMemberIndex), _ 
				 DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))
			redim preserve _ 
			DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr) - 1)
	end select 'DR.rectangleFamillyMemberCount
	'
   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
  		DR.draggableFamillyArrayOfPtr(index)->_draggableFamillyCurrentMemberIndex = index
   	next index
   	'
   	THIS._draggableFamillyCurrentMemberIndex = -1
   	'
	THIS.FinalizeRectangle()
end destructor 'DRAGGABLERECTANGLE default explicit destructor
sub DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
	if THIS._draggableFamillyCurrentMemberIndex=-1 then
		'index of object that should have been destroyed
		exit sub
	end if
	'
	dim as integer gmX, gmY, gmBtn1
	getMouse gmX, gmY, , gmBtn1
	'
	if THIS._mouseDrag=TRUE	and _ 
	   cBool(gmX>=0)		and _ 
	   cBool(gmY>=0)		then
		select case THIS._dragAxis
			case DR._DRAGAXISCONSTRAINT._xOnly
				THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
			case DR._DRAGAXISCONSTRAINT._yOnly
				THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
			case DR._DRAGAXISCONSTRAINT._noAxis
				'no assignement required
			case else 
				'_xy (+1)
				THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
				THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
		end select 'THIS._dragAxis
	end if
	'
	with THIS
		if gmX>=.TopLeftCornerX						and _ 
		   gmX<(.TopLeftCornerX + .RectangleWidth)	and _ 
		   gmY>=.TopLeftCornerY						and _ 
		   gmY<(.TopLeftCornerY + .RectangleHeight)	then
			if ._mouseOver=FALSE then ._mouseOver = TRUE
			if (._clickEnabled and cBool(gmBtn1=+1)) then
				if ._mouseClick=FALSE then 
					._mouseClick = TRUE
					if not(._markedAsTemporaryNonDraggable) and _ 
					   ._dragEnabled 						and _ 
					   ._mouseDrag=FALSE 					then
					   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
					   		if index<>._draggableFamillyCurrentMemberIndex then
					   			DR.draggableFamillyArrayOfPtr(index)-> _ 
					   								_markedAsTemporaryNonDraggable = TRUE
					   		else
					   			THIS._markedAsTemporaryNonDraggable = FALSE
					   		end if
					   	next index
						._xAtDragTime = gmX
						._yAtDragTime = gmY
						._xDragOffsetFixedValue = ._xAtDragTime - .TopLeftCornerX
						._yDragOffsetFixedValue = ._yAtDragTime - .TopLeftCornerY
						._mouseDrag = TRUE
					end if
				end if
			else
				if ._mouseClick=TRUE then ._mouseClick	= FALSE
				if ._mouseDrag=TRUE then
					._mouseDrag	= FALSE
				   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
				   		if index<>._draggableFamillyCurrentMemberIndex then
				   			DR.draggableFamillyArrayOfPtr(index)-> _ 
				   					_markedAsTemporaryNonDraggable = FALSE
				   		end if
				   	next index					
				end if
			end if
		else
			if ._mouseOver=TRUE		then	._mouseOver		= FALSE
			if ._mouseClick=TRUE	then	._mouseClick	= FALSE
			if ._mouseDrag=TRUE		then	
				._mouseDrag		= FALSE
			   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
			   		if index<>._draggableFamillyCurrentMemberIndex then
			   			DR.draggableFamillyArrayOfPtr(index)-> _ 
			   					_markedAsTemporaryNonDraggable = FALSE
			   		end if
			   	next index
			end if
		end if		
	end with 'THIS	
end sub 'DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
sub DRAGGABLERECTANGLE.DrawDraggableRectangle()
	if THIS._draggableFamillyCurrentMemberIndex=-1 then
		'index of object that should have been destroyed
		exit sub
	end if
	'
	THIS.TestDraggableRectangleForMouse()
	'
	line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
		 (THIS.TopLeftCornerX + THIS.RectangleWidth, _ 
		  THIS.TopLeftCornerY + THIS.RectangleHeight), _ 
		 THIS._bckgColor, _ 
		 bf
	line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
		 (THIS.TopLeftCornerX + THIS.RectangleWidth, _ 
		  THIS.TopLeftCornerY + THIS.RectangleHeight), _ 
		 rgb(090,090,120), _ 
		 b
end sub 'DRAGGABLERECTANGLE.DrawDraggableRectangle()


'==============================================
'==============================================
'----------------------------------------------
'------------------------------------------MAIN

'--------------------------------INITIALIZATION
screenRes 600,480,32

dim as DRAGGABLERECTANGLE	testDrag	=> DRAGGABLERECTANGLE(40,45,120,90)
'in this demo testDrag is the mask rectangle

''''''''dim as RECTANGLESIDESEGMENT	testSideSeg	=> RECTANGLESIDESEGMENT()
dim as RECTANGLESIDESEGMENT	testSideSeg	=> RECTANGLESIDESEGMENT(@testDrag)
testSideSeg.Xi => 250
testSideSeg.Yi => 120
testSideSeg.W  => 165
testSideSeg.H  => 240

dim as AREA		testArea
testArea = RECTANGLE(testSideSeg) - RECTANGLE(testDrag)
'format:: AREA := RECT - MASK 

dim as AREA	Ptr				areaObjectPtr
dim as AREA					areaCopyForInitializatorFix
areaCopyForInitializatorFix	=> AREA(testArea)
areaObjectPtr	=> new (@testArea) AREA
*areaObjectPtr	=> RECTANGLE(testSideSeg) - RECTANGLE(testDrag)

'dev.note: 
'clone mechanism not tested yet with dim byref


'-------------------------------------MAIN LOOP
color rgb(0,220,220)
do
	screenLock
		cls
            ? "rectangle masking one other"
            ? "and resultant visible areas"
            ? "<DRAG> the grey mask"
            ? "<ESC> to leave out"
			testDrag.DrawDraggableRectangle()
		
			*areaObjectPtr = RECTANGLE(testSideSeg) - RECTANGLE(testDrag)
			areaObjectPtr ->VisualizeArea()
	screenUnlock

	sleep 25
loop until inkey=chr(27)

'----------------------------------FINALIZATION

sleep
end 0


'[you've reached the end of the freebasic file]
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

Unuseful overhead finally the previous affair of ractangle area computing. Here things work with classical mouse tests, yet in the correct order.
I had to split the below code. Maybe should I consider hosting in a third-party website in the future. Whatever this important update comes split in 2 parts. Sorry for the disturbance.

Code: Select all

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.
'----------------------------------------------
'gnu-like public domain small windowing utility
'weblink:
'----------------------------------------------

'----------------------------------------------
'.declaration of XY UDT........................
'.implementation of XY UDT.....................
'.declaration of RECTANGLE UDT.................
'.implementation of RECTANGLE UDT..............
'.declaration of DRAGGABLERECTANGLE UDT........
'.implementation of DRAGGABLERECTANGLE UDT.....
'.declaration of RESIZABLERECTANGLE UDT........
'.implementation of RESIZABLERECTANGLE UDT.....
'.declaration of ICEBENCH UDT..................
'.implementation of ICEBENCH UDT...............
'.declaration of ICEBOARD UDT..................
'.implementation of ICEBOARD UDT...............
'----------------------------------------------

'>missing features at current scheduler:       
'----------------------------------------------
'>a quit button (!)                            
'>make bench object parentable container       

'>1st test result:                             
'----------------------------------------------
'>compiled fine under fb1.04 windowsXP32       
'>nothing to signal at run-time (runs smoothy) 

'>known bugs/mostly unexplained at present day:
'----------------------------------------------
'screen is blank flashing at application start 
'______________________________________________
'left and top resizers has weird behaviour     
'______________________________________________
'corner resizers lose too easily focus         
'______________________________________________
'there is code mistake with top resizing border
'______________________________________________
'there is a weird issue with focus flip while  
'a top level bench is crossing a low level one 
'a certain way -                               
'suspected mouse test at resizer object ...    
'______________________________________________
'the mouseover test at IceBoard mousetest      
'doesnt release properly when mouseover nothing
'______________________________________________
'and probably much  more!                      

'>please for bug reporting/remarks/suggestion  
'>visit fb.net link at head of this file       
'>sorry for long preamble, thanks folks, enjoy!
'>.............happy new year!.................


#include once "fbgfx.bi"


'                                        ------
'                                        XY UDT
'                                        ------
type XY
	'small udt utility to pass (X,Y) argument
	'in procedure in more (?) readable way ..
	declare constructor()
	declare constructor(byval as long, byval as long)
		as long		_x
		as long		_y	
end type 'XY
constructor XY()
	'
end constructor 'XY default explicit constructor
constructor XY(byval X as long, byval Y as long)
	this._x	=> X
	this._y	=> Y
end constructor 'XY default explicit constructor


'                                 -------------
'                                 RECTANGLE UDT
'                                 -------------
type RECTANGLE extends OBJECT
	declare constructor()
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	declare sub InitializeRectangle overload(byval as long=-1, _ 
											 byval as long=-1)
	declare sub InitializeRectangle(byval as long, _ 
									byval as long, _ 
									byval as long, _ 
									byval as long)
	declare destructor()
	declare sub FinalizeRectangle()
	'
	declare property Xi()	as long
	declare property Xi(byval as long)
	declare property Yi()	as long
	declare property Yi(byval as long)
	declare property W()	as long
	declare property W(byval as long)
	declare property H()	as long
	declare property H(byval as long)
	declare property Xf()	as long
	declare property Xf(byval as long)
	declare property Yf()	as long
	declare property Yf(byval as long)
	declare property TopLeftCornerX()		as long
	declare property TopLeftCornerX(byval 	as long)
	declare property TopLeftCornerY()		as long
	declare property TopLeftCornerY(byval 	as long)
	declare property RectangleWidth()		as long
	declare property RectangleWidth(byval 	as long)
	declare property RectangleHeight()		as long
	declare property RectangleHeight(byval 	as long)
	declare property BottomRightCornerX()		as long
	declare property BottomRightCornerX(byval 	as long)
	declare property BottomRightCornerY()		as long
	declare property BottomRightCornerY(byval 	as long)
	declare sub DrawRectangle()
	declare sub DrawRectangleAsFlatBackground()
	private:
		as long						_topLeftCornerX
		as long						_topLeftCornerY
		as long						_rectangleWidth
		as long						_rectangleHeight
		'
		as long						_maxWidth
		as long						_maxHeight
end type 'RECTANGLE <-- OBJECT
'inheritance lineage:
'RECTANGLE <-- OBJECT
constructor RECTANGLE()
	BASE()
	THIS.InitializeRectangle()
end constructor 'RECTANGLE default explicit constructor
constructor RECTANGLE(byval MaxW	as long, _ 
					  byval MaxH	as long)
	'dev.note: very specific usage initializer
	'		   can't remember its use ........
	BASE()
	if maxW>0 then THIS._maxWidth	=> MaxW
	if maxH>0 then THIS._maxHeight	=> MaxH
	THIS.InitializeRectangle(THIS._maxWidth, _ 
							 THIS._maxHeight)
end constructor 'RECTANGLE(valLNG,valLNG)
constructor RECTANGLE(byval TCLX	as long, _ 
					  byval TCLY	as long, _ 
					  byval Wid		as long, _ 
					  byval Hei		as long)
	BASE()
	THIS.InitializeRectangle(TCLX,TCLY,Wid,Hei)
end constructor 'RECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub RECTANGLE.InitializeRectangle(byval MaxW as long=-1, _ 
								  byval MaxH as long=-1)
	'dev.note: very specific usage initializer
	dim as integer	scrW, scrH
	screenInfo		scrW, scrH
	if MaxW<=0 then
		with THIS
			._topLeftCornerX	=> scrW\3
			._rectangleWidth	=> scrW\3
		end with 'THIS
	else
		with THIS
			._topLeftCornerY	=> MaxH\3
			._rectangleHeight	=> MaxH\3
		end with 'THIS		
	end if
	if MaxH<=0 then
		with THIS
			._topLeftCornerY	=> scrH\3
			._rectangleHeight	=> scrH\3
		end with 'THIS
	else
		with THIS
			._topLeftCornerY	=> MaxH\3
			._rectangleHeight	=> MaxH\3
		end with 'THIS		
	end if
end sub 'RECTANGLE.InitializeRectangle(valLNG[-1],valLNG[-1])
sub RECTANGLE.InitializeRectangle(byval TCLX	as long, _ 
								  byval TCLY	as long, _ 
								  byval Wid		as long, _ 
								  byval Hei		as long)
	with THIS
		._topLeftCornerX	=> TCLX
		._topLeftCornerY	=> TCLY
		._rectangleWidth	=> Wid
		._rectangleHeight	=> Hei
	end with 'THIS
end sub 'RECTANGLE.InitializeRectangle(valLNG,valLNG,valLNG,valLNG)
destructor RECTANGLE()
	'
end destructor 'RECTANGLE default explicit destructor
sub RECTANGLE.FinalizeRectangle()
	THIS.destructor()
end sub 'RECTANGLE.FinalizeRectangle()
property RECTANGLE.Xi() as long
	'---->
	return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.Xi
property RECTANGLE.Xi(byval SetValue as long)
	THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.Xi(valLNG)
property RECTANGLE.Yi() as long
	'---->
	return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.Yi
property RECTANGLE.Yi(byval SetValue as long)
	THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.Yi(valLNG)
property RECTANGLE.W()	as long
	'---->
	return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.W
property RECTANGLE.W(byval SetValue as long)
	THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.W(valLNG)
property RECTANGLE.H()	as long
	'---->
	return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.H
property RECTANGLE.H(byval SetValue as long)
	THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.H(valLNG)
property RECTANGLE.Xf() as long
	'---->
	return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.Xf
property RECTANGLE.Xf(byval SetValue as long)
	if SetValue<THIS._topLeftCornerX then
		THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
		THIS._topLeftCornerX = SetValue
	else
		THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
	end if
end property 'set RECTANGLE.Xf(valLNG)
property RECTANGLE.Yf() as long
	'---->
	return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.Yf
property RECTANGLE.Yf(byval SetValue as long)
	if SetValue<THIS._topLeftCornerY then
		THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
		THIS._topLeftCornerY = SetValue
	else
		THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
	end if
end property 'set RECTANGLE.Yf(valLNG)
property RECTANGLE.TopLeftCornerX()	as long
	'---->
	return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.TopLeftCornerX
property RECTANGLE.TopLeftCornerX(byval SetValue as long)
	THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.TopLeftCornerX(valLNG)
property RECTANGLE.TopLeftCornerY()	as long
	'---->
	return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.TopLeftCornerY
property RECTANGLE.TopLeftCornerY(byval SetValue as long)
	THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.TopLeftCornerY(valLNG)
property RECTANGLE.RectangleWidth()	as long
	'---->
	return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.RectangleWidth
property RECTANGLE.RectangleWidth(byval SetValue as long)
	THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.RectangleWidth(valLNG)
property RECTANGLE.RectangleHeight() as long
	'---->
	return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.RectangleHeight
property RECTANGLE.RectangleHeight(byval SetValue as long)
	THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.RectangleHeight(valLNG)
property RECTANGLE.BottomRightCornerX()	as long
	'---->
	return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerX
property RECTANGLE.BottomRightCornerX(byval SetValue as long)
	if SetValue<THIS._topLeftCornerX then
		THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
		THIS._topLeftCornerX = SetValue
	else
		THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
	end if
end property 'set RECTANGLE.BottomRightCornerX(valLNG)
property RECTANGLE.BottomRightCornerY()	as long
	'---->
	return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerY
property RECTANGLE.BottomRightCornerY(byval SetValue as long)
	if SetValue<THIS._topLeftCornerY then
		THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
		THIS._topLeftCornerY = SetValue
	else
		THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
	end if
end property 'RECTANGLE.BottomRightCornerY(valLNG)
sub RECTANGLE.DrawRectangle()
	static as byte		switcher	=> +1
	static as double	startTime	=> 00
	dim as double	currentTime		=> TIMER()
	dim as double	timeInterval	=> 0.65
	if ( (currentTime - startTime)>timeInterval ) then
		switcher *= -1
		startTime = TIMER()
	end if
	if switcher=+1 then
		with THIS
			line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _ 
				 (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _ 
				  THIS._topLeftCornerY + THIS._rectangleHeight - 1), _ 
				  rgb(200,150,150), _
				  b, _ 
				  &b0000111100001111
		end with 'THIS		
	else 
		with THIS
			line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _ 
				 (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _ 
				  THIS._topLeftCornerY + THIS._rectangleHeight - 1), _ 
				  rgb(200,150,150), _
				  b, _ 
				  &b1111000011110000
		end with 'THIS			
	end if
end sub 'RECTANGLE.DrawRectangle()	
sub RECTANGLE.DrawRectangleAsFlatBackground()
	with THIS
		line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _ 
			 (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _ 
			  THIS._topLeftCornerY + THIS._rectangleHeight - 1), _ 
			  rgb(100,100,120), _
			  bf, _ 
			  &b0000111100001111
	end with 'THIS	
end sub 'RECTANGLE.DrawRectangleAsFlatBackground()


'                        ----------------------
'                        DRAGGABLERECTANGLE UDT
'                        ----------------------
type DRAGGABLERECTANGLE extends RECTANGLE
	declare constructor()
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	declare sub InitializeDraggableRectangle()
	declare destructor()
	declare sub TestDraggableRectangleForMouse()
	declare sub DrawDraggableRectangle()
	declare sub DrawSilentlyDraggableRectangle()
		as ulong			_bckgColor
		as ulong			_fgndColor
		as boolean			_mouseOver
		as boolean			_mouseClick
		as boolean			_mouseDrag
		as ulong			_onMouseOverBckgColor
		as ulong			_onMouseClickBckgColor
		as ulong			_onMouseDragBckgColor
		'
		as boolean			_clickEnabled
		as boolean			_dragEnabled
	enum _DRAGAXISCONSTRAINT
		_yOnly	= -2
		_xOnly	= -1
		_noAxis	= -0
		_xy		= +1
	end enum '_DRAGAXISCONSTRAINT	
	as _DRAGAXISCONSTRAINT	_dragAxis
		as integer			_xAtDragTime
		as integer			_yAtDragTime
		as integer			_xDragOffsetFixedValue
		as integer			_yDragOffsetFixedValue
		as boolean			_markedAsTemporaryNonDraggable
		as integer						_draggableFamillyCurrentMemberIndex	
	static as integer					draggableFamillyMemberCount
	static as DRAGGABLERECTANGLE ptr	draggableFamillyArrayOfPtr(any)
end type 'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
dim as integer					DRAGGABLERECTANGLE.draggableFamillyMemberCount
dim as DRAGGABLERECTANGLE ptr	DRAGGABLERECTANGLE.draggableFamillyArrayOfPtr(any)
type DR as DRAGGABLERECTANGLE
'inheritance lineage:
'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor DRAGGABLERECTANGLE()
	BASE()
	THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE default explicit constructor
constructor DRAGGABLERECTANGLE(byval MaxW	as long, _ 
							   byval MaxH	as long)
	BASE()
	THIS.InitializeRectangle(MaxW, MaxH)
	THIS.InitializeDraggableRectangle()
end constructor 'RECTANGLE(valLNG,valLNG)
constructor DRAGGABLERECTANGLE(byval TCLX	as long, _ 
							   byval TCLY	as long, _ 
							   byval Wid	as long, _ 
							   byval Hei	as long)
	BASE()
	THIS.InitializeRectangle(TCLX, TCLY, Wid, Hei)
	THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub DRAGGABLERECTANGLE.InitializeDraggableRectangle()
	'-constructor subroutine-
	DR.draggableFamillyMemberCount				+=> 1
	THIS._draggableFamillyCurrentMemberIndex	 => DR.draggableFamillyMemberCount - 1
	redim preserve DR.draggableFamillyArrayOfPtr(DR.draggableFamillyMemberCount - 1)
	DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))	=> @THIS
	'
	with THIS
		._bckgColor					=> rgb(080,080,080)
		._fgndColor					=> rgb(240,240,190)
		._onMouseOverBckgColor		=> rgb(120,080,120)
		._onMouseClickBckgColor		=> rgb(080,120,080)
		._onMouseDragBckgColor		=> rgb(080,080,120)
		._clickEnabled		=> TRUE
		._dragEnabled		=> TRUE
		._mouseOver			=> FALSE
		._mouseClick		=> FALSE
		._mouseDrag			=> FALSE
		._dragAxis			=> DR._DRAGAXISCONSTRAINT._xy
		._xDragOffsetFixedValue	=> ._xAtDragTime - .TopLeftCornerX
		._yDragOffsetFixedValue	=> ._yAtDragTime - .TopLeftCornerY
		._markedAsTemporaryNonDraggable	=> FALSE
	end with 'THIS
end sub 'DRAGGABLERECTANGLE.InitializeDraggableRectangle()
destructor DRAGGABLERECTANGLE()
	DR.draggableFamillyMemberCount -= 1
	'
	select case DR.draggableFamillyMemberCount
		case is<=0
			erase DR.draggableFamillyArrayOfPtr
		case else
			swap DR.draggableFamillyArrayOfPtr(THIS._draggableFamillyCurrentMemberIndex), _ 
				 DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))
			redim preserve _ 
			DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr) - 1)
	end select 'DR.rectangleFamillyMemberCount
	'
   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
  		DR.draggableFamillyArrayOfPtr(index)->_draggableFamillyCurrentMemberIndex = index
   	next index
   	'
   	THIS._draggableFamillyCurrentMemberIndex = -1
   	'
	THIS.FinalizeRectangle()
end destructor 'DRAGGABLERECTANGLE default explicit destructor
sub DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
	if THIS._draggableFamillyCurrentMemberIndex=-1 then
		'index of object that should have been destroyed
		exit sub
	end if
	'
	dim as integer gmX, gmY, gmBtn1
	getMouse gmX, gmY, , gmBtn1
	'
	if cBool(gmBtn1<>+1) and THIS._mouseDrag=TRUE then
		':TODO:
		'finalize DRAG to ensure correct final placement
	end if
	'
	if THIS._mouseDrag=TRUE	and _ 
	   cBool(gmX>=0)		and _ 
	   cBool(gmY>=0)		then
		select case THIS._dragAxis
			case DR._DRAGAXISCONSTRAINT._xOnly
				THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
			case DR._DRAGAXISCONSTRAINT._yOnly
				THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
			case DR._DRAGAXISCONSTRAINT._noAxis
				'no assignement required
			case else 
				'_xy (+1)
				THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
				THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
		end select 'THIS._dragAxis
	end if
	'
	with THIS
		if gmX>=.TopLeftCornerX						and _ 
		   gmX<(.TopLeftCornerX + .RectangleWidth)	and _ 
		   gmY>=.TopLeftCornerY						and _ 
		   gmY<(.TopLeftCornerY + .RectangleHeight)	then
			if ._mouseOver=FALSE then ._mouseOver = TRUE
			if (._clickEnabled and cBool(gmBtn1=+1)) then
				if ._mouseClick=FALSE then 
					._mouseClick = TRUE
					if not(._markedAsTemporaryNonDraggable) and _ 
					   ._dragEnabled 						and _ 
					   ._mouseDrag=FALSE 					then
					   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
					   		if index<>._draggableFamillyCurrentMemberIndex then
					   			DR.draggableFamillyArrayOfPtr(index)-> _ 
					   								_markedAsTemporaryNonDraggable = TRUE
					   		else
					   			THIS._markedAsTemporaryNonDraggable = FALSE
					   		end if
					   	next index
						._xAtDragTime = gmX
						._yAtDragTime = gmY
						._xDragOffsetFixedValue = ._xAtDragTime - .TopLeftCornerX
						._yDragOffsetFixedValue = ._yAtDragTime - .TopLeftCornerY
						._mouseDrag = TRUE
					end if
				end if
			else
				if ._mouseClick=TRUE then ._mouseClick	= FALSE
				if ._mouseDrag=TRUE then
					._mouseDrag	= FALSE
				   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
				   		if index<>._draggableFamillyCurrentMemberIndex then
				   			DR.draggableFamillyArrayOfPtr(index)-> _ 
				   					_markedAsTemporaryNonDraggable = FALSE
				   		end if
				   	next index					
				end if
			end if
		else
			if ._mouseOver=TRUE		then	._mouseOver		= FALSE
			if ._mouseClick=TRUE	then	._mouseClick	= FALSE
			if ._mouseDrag=TRUE		then	
				._mouseDrag		= FALSE
			   	for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
			   		if index<>._draggableFamillyCurrentMemberIndex then
			   			DR.draggableFamillyArrayOfPtr(index)-> _ 
			   					_markedAsTemporaryNonDraggable = FALSE
			   		end if
			   	next index
			end if
		end if		
	end with 'THIS	
end sub 'DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
sub DRAGGABLERECTANGLE.DrawDraggableRectangle()
	if THIS._draggableFamillyCurrentMemberIndex=-1 then
		'index of object that should have been destroyed
		exit sub
	end if
	'
	THIS.TestDraggableRectangleForMouse()
	'
	line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
		 (THIS.TopLeftCornerX + THIS.RectangleWidth - 1, _ 
		  THIS.TopLeftCornerY + THIS.RectangleHeight - 1), _ 
		 THIS._bckgColor, _ 
		 bf
	line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _ 
		 (THIS.TopLeftCornerX + THIS.RectangleWidth - 1, _ 
		  THIS.TopLeftCornerY + THIS.RectangleHeight - 1), _ 
		 rgb(090,090,120), _ 
		 b
end sub 'DRAGGABLERECTANGLE.DrawDraggableRectangle()
sub DRAGGABLERECTANGLE.DrawSilentlyDraggableRectangle()
	if THIS._draggableFamillyCurrentMemberIndex=-1 then
		'index of object that should have been destroyed
		exit sub
	end if
	'
	THIS.TestDraggableRectangleForMouse()
	'
	line (THIS.TopLeftCornerX + 2, THIS.TopLeftCornerY + 2)- _ 
		 (THIS.TopLeftCornerX + THIS.RectangleWidth - 1 - 2, _ 
		  THIS.TopLeftCornerY + THIS.RectangleHeight - 1 - 2), _ 
		 rgb(090,090,120), _ 
		 b
end sub 'DRAGGABLERECTANGLE.DrawSilentlyDraggableRectangle()

'end of part1 -> please join part2 to this before compiling
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

Code: Select all

'part2 -> to join to previous code

'                        ----------------------
'                        RESIZABLERECTANGLE UDT
'                        ----------------------
type RESIZABLERECTANGLE extends DRAGGABLERECTANGLE
	declare constructor()
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	declare sub InitializeResizableRectangle()
	declare destructor()
	declare property TLCXanchored() as boolean
	declare property TLCX() as long
	declare property TLCX(byval as long)
	declare property TLCYanchored() as boolean
	declare property TLCY() as long
	declare property TLCY(byval as long)
	declare property TRCXanchored() as boolean
	declare property TRCX() as long
	declare property TRCX(byval as long)
	declare property TRCYanchored() as boolean
	declare property TRCY() as long
	declare property TRCY(byval as long)
	declare property BRCXanchored() as boolean
	declare property BRCX() as long
	declare property BRCX(byval as long)
	declare property BRCYanchored() as boolean
	declare property BRCY() as long
	declare property BRCY(byval as long)
	declare property BLCXanchored() as boolean
	declare property BLCX() as long
	declare property BLCX(byval as long)
	declare property BLCYanchored() as boolean
	declare property BLCY() as long
	declare property BLCY(byval as long)
	declare property Thckns() as long
	declare property Thckns(byval as long)
	declare property MouseOverAnyBoundary() as boolean
	declare property MouseClickAnyBoundary() as boolean
	declare property AnchorCount() as long
	declare sub ResetAnchorList()
	enum _ANCHORPOINT
		_allCorner			= +0
		_topLeftCorner		= +1
		_topRightCorner		= +2
		_bottomRightCorner	= +3
		_bottomLeftCorner	= +4
	end enum '_ANCHORPOINT
	declare function IsAnchor(byval as _ANCHORPOINT) as boolean
	declare sub AddAnchor(byval as _ANCHORPOINT=_ANCHORPOINT._allCorner)
	enum _FILLBOXOPTION
		_contour	= -1
		_fill		= -0
	end enum '_FILLBOXOPTION
	declare sub DrawThickContourElement overload(byval as long, _ 
												 byval as long, _ 
												 byval as long, _ 
												 byval as long, _ 
												 byval as ulong, _ 
												 byval as _FILLBOXOPTION=_FILLBOXOPTION._fill)
	declare sub DrawThickContourElement(byval as XY, _ 
										byval as XY, _ 
										byval as ulong, _ 
										byval as _FILLBOXOPTION=_FILLBOXOPTION._fill)
	declare sub RefreshAnchorArray()
	declare sub SetResizeTimeInitialOffset()
	declare sub TranslateCornerCoordinate(byval as long=0, _ 
										  byval as long=0)
	declare sub TestResizableRectangleForMouse()
	declare sub DrawResizableRectangle()
		as long				_borderThickness
		as boolean			_resizeEnabled
		as boolean			_resizeStarted
		as long				_xAtResizeTime
		as long				_yAtResizeTime
		as long				_tlcXoffsetAtResizeTime
		as long				_tlcYoffsetAtResizeTime
		as long				_trcXoffsetAtResizeTime
		as long				_trcYoffsetAtResizeTime
		as long				_brcXoffsetAtResizeTime
		as long				_brcYoffsetAtResizeTime
		as long				_blcXoffsetAtResizeTime
		as long				_blcYoffsetAtResizeTime
		as boolean			_mouseOverLeftBorder
		as boolean			_mouseOverTopBorder
		as boolean			_mouseOverRightBorder
		as boolean			_mouseOverBottomBorder
		as boolean			_mouseOverTopLeftCorner
		as boolean			_mouseOverTopRightCorner
		as boolean			_mouseOverBottomRightCorner
		as boolean			_mouseOverBottomLeftCorner
		as boolean			_mouseClickLeftBorder
		as boolean			_mouseClickTopBorder
		as boolean			_mouseClickRightBorder
		as boolean			_mouseClickBottomBorder
		as boolean			_mouseClickTopLeftCorner
		as boolean			_mouseClickTopRightCorner
		as boolean			_mouseClickBottomRightCorner
		as boolean			_mouseClickBottomLeftCorner
	private:
		as boolean			_mouseOverBoundary
		as boolean			_mouseClickBoundary
		as long				_anchorPointCount
		as _ANCHORPOINT		_anchorArray(any)
end type 'RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
type RSZ as RESIZABLERECTANGLE
'inheritance lineage:
'RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor RESIZABLERECTANGLE()
	BASE()
	THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE default explicit constructor
constructor RESIZABLERECTANGLE(byval MaxW	as long, _ 
							   byval MaxH	as long)
	BASE(MaxW,MaxH)
	THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE(valLNG, valLNG)
constructor RESIZABLERECTANGLE(byval TCLX	as long, _ 
							   byval TCLY	as long, _ 
							   byval Wid	as long, _ 
							   byval Hei	as long)
	BASE(TCLX,TCLY,Wid,Hei)
	THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE(valLNG, valLNG, valLNG, valLNG)
sub RESIZABLERECTANGLE.InitializeResizableRectangle()
	with THIS
		._borderThickness				=> 6
		._resizeEnabled					=> TRUE
		._mouseOverLeftBorder			=> FALSE
		._mouseOverTopBorder			=> FALSE
		._mouseOverRightBorder			=> FALSE
		._mouseOverBottomBorder			=> FALSE
		._mouseOverTopLeftCorner		=> FALSE
		._mouseOverTopRightCorner		=> FALSE
		._mouseOverBottomRightCorner	=> FALSE
		._mouseOverBottomLeftCorner		=> FALSE
		._mouseClickLeftBorder			=> FALSE
		._mouseClickTopBorder			=> FALSE
		._mouseClickRightBorder			=> FALSE
		._mouseClickBottomBorder		=> FALSE
		._mouseClickTopLeftCorner		=> FALSE
		._mouseClickTopRightCorner		=> FALSE
		._mouseClickBottomRightCorner	=> FALSE
		._mouseClickBottomLeftCorner	=> FALSE
	end with 'THIS
	THIS._mouseOverBoundary				=> FALSE
	THIS._mouseClickBoundary			=> FALSE
	THIS.ResetAnchorList()
end sub 'RESIZABLERECTANGLE.InitializeResizableRectangle()
destructor RESIZABLERECTANGLE()
	'
end destructor 'RESIZABLERECTANGLE default explicit destructor
property RESIZABLERECTANGLE.TLCXanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)		or _
	   THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)	or _
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.TLCXanchored
property RESIZABLERECTANGLE.TLCX() as long
	'---->
	return THIS.Xi
end property 'get LNG:=RESIZABLERECTANGLE.TLCX
property RESIZABLERECTANGLE.TLCX(byval SetValue as long)
	if not THIS.TLCXanchored	then
		THIS.W	= THIS.W - (SetValue - THIS.Xi + 1*sgn(SetValue - THIS.Xi))
		THIS.Xi = SetValue 
	end if
end property 'set RESIZABLERECTANGLE.TLCX(valLNG)
property RESIZABLERECTANGLE.TLCYanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)		then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.TLCYanchored
property RESIZABLERECTANGLE.TLCY() as long
	'---->
	return THIS.Yi
end property 'get LNG:=RESIZABLERECTANGLE.TLCY
property RESIZABLERECTANGLE.TLCY(byval SetValue as long)
	if not THIS.TLCYanchored then
		THIS.H	= THIS.H - (SetValue - THIS.Yi + 1*sgn(SetValue - THIS.Xi))
		THIS.Yi = SetValue
	end if
end property 'set RESIZABLERECTANGLE.TLCY(valLNG)
property RESIZABLERECTANGLE.TRCXanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)		or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.TRCXanchored
property RESIZABLERECTANGLE.TRCX() as long
	'---->
	return THIS.Xf
end property 'get LNG:=RESIZABLERECTANGLE.TRCX
property RESIZABLERECTANGLE.TRCX(byval SetValue as long)
	if not THIS.TRCXanchored then
		THIS.Xf = SetValue
	end if
end property 'set RESIZABLERECTANGLE.TRCX(valLNG)
property RESIZABLERECTANGLE.TRCYanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)		then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.TRCYanchored
property RESIZABLERECTANGLE.TRCY() as long
	'---->
	return THIS.Yi
end property 'get LNG:=RESIZABLERECTANGLE.TRCY
property RESIZABLERECTANGLE.TRCY(byval SetValue as long)
	if not THIS.TRCYanchored then
		THIS.Yi = SetValue
	end if
end property 'set RESIZABLERECTANGLE.TRCY(valLNG)
property RESIZABLERECTANGLE.BRCXanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)		or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.BRCXanchored
property RESIZABLERECTANGLE.BRCX() as long
	'---->
	return THIS.Xf
end property 'get LNG:=RESIZABLERECTANGLE.BRCX
property RESIZABLERECTANGLE.BRCX(byval SetValue as long)
	if not THIS.BRCXanchored then
		THIS.Xf = SetValue
	end if
end property 'set RESIZABLERECTANGLE.BRCX(valLNG)
property RESIZABLERECTANGLE.BRCYanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.BRCYanchored
property RESIZABLERECTANGLE.BRCY() as long
	'---->
	return THIS.Yf
end property 'get LNG:=RESIZABLERECTANGLE.BRCY
property RESIZABLERECTANGLE.BRCY(byval SetValue as long)
	if not THIS.BRCYanchored then
		THIS.Yf = SetValue
	end if
end property 'set RESIZABLERECTANGLE.BRCY(valLNG)
property RESIZABLERECTANGLE.BLCXanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)		or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.BLCXanchored
property RESIZABLERECTANGLE.BLCX() as long
	'---->
	return THIS.Xi
end property 'get LNG:=RESIZABLERECTANGLE.BLCX
property RESIZABLERECTANGLE.BLCX(byval SetValue as long)
	if not THIS.BLCXanchored then
		THIS.Xi = SetValue
	end if
end property 'set RESIZABLERECTANGLE.BLCX(valLNG)
property RESIZABLERECTANGLE.BLCYanchored() as boolean
	if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)	or _ 
	   THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)			then
		'---->
		return TRUE
	else
		'---->
		return FALSE
	end if
end property 'get BOOL:=RESIZABLERECTANGLE.BLCYanchored
property RESIZABLERECTANGLE.BLCY() as long
	'---->
	return THIS.Yf
end property 'get LNG:=RESIZABLERECTANGLE.BLCY
property RESIZABLERECTANGLE.BLCY(byval SetValue as long)
	if not THIS.BLCYanchored then
		THIS.Yf = SetValue
	end if
end property 'set RESIZABLERECTANGLE.BLCY(valLNG)
property RESIZABLERECTANGLE.Thckns() as long
	'---->
	return THIS._borderThickness
end property 'get LNG:=RESIZABLERECTANGLE.Thckns
property RESIZABLERECTANGLE.Thckns(byval SetValue as long)
	THIS._borderThickness = SetValue
end property 'set RESIZABLERECTANGLE.Thckns(valLNG)
property RESIZABLERECTANGLE.MouseOverAnyBoundary() as boolean
	THIS._mouseOverBoundary = FALSE
	if 	THIS._mouseOverLeftBorder			orElse _
		THIS._mouseOverTopBorder			orElse _
		THIS._mouseOverRightBorder			orElse _
		THIS._mouseOverBottomBorder			orElse _
		THIS._mouseOverTopLeftCorner		orElse _
		THIS._mouseOverTopRightCorner		orElse _
		THIS._mouseOverBottomRightCorner	orElse _
		THIS._mouseOverBottomLeftCorner		then
			THIS._mouseOverBoundary = TRUE
	end if
	'---->
	return THIS._mouseOverBoundary
end property 'BOOL:=RESIZABLERECTANGLE.MouseOverAnyBoundary
property RESIZABLERECTANGLE.MouseClickAnyBoundary() as boolean
	THIS._mouseClickBoundary = FALSE
	if 	THIS._mouseClickLeftBorder			orElse _
		THIS._mouseClickTopBorder			orElse _
		THIS._mouseClickRightBorder			orElse _
		THIS._mouseClickBottomBorder		orElse _
		THIS._mouseClickTopLeftCorner		orElse _
		THIS._mouseClickTopRightCorner		orElse _
		THIS._mouseClickBottomRightCorner	orElse _
		THIS._mouseClickBottomLeftCorner	then	
			THIS._mouseClickBoundary = TRUE
	end if
	'---->
	return THIS._mouseClickBoundary
end property 'BOOL:=RESIZABLERECTANGLE.MouseClickAnyBoundary
property RESIZABLERECTANGLE.AnchorCount() as long
	THIS._anchorPointCount	= uBound(THIS._anchorArray) + 1
	'---->
	return THIS._anchorPointCount
end property 'LNG:=RESIZABLERECTANGLE.AnchorPointCount
sub RESIZABLERECTANGLE.ResetAnchorList()
	'free anchor array
	erase THIS._anchorArray
end sub 'RESIZABLERECTANGLE.ResetAnchorList()
function RESIZABLERECTANGLE.IsAnchor(byval Corner as RESIZABLERECTANGLE._ANCHORPOINT) as boolean
	'search anchor array for corner candidate
	for index as integer = 0 to (THIS.AnchorCount - 1)
		if THIS._anchorArray(index)=Corner then 
			'--->
			return TRUE
		end if
	next index
	'---->
	return FALSE
end function 'BOOL:=RESIZABLERECTANGLE.IsAnchor(valRESIZABLERECTANGLE._ANCHORPOINT)
sub RESIZABLERECTANGLE.AddAnchor(byval CornerSet as RSZ._ANCHORPOINT=RSZ._ANCHORPOINT._allCorner)
	if CornerSet=RSZ._ANCHORPOINT._allCorner then
		THIS.ResetAnchorList()
		redim THIS._anchorArray(3)
		THIS._anchorArray(0)	= RSZ._ANCHORPOINT._topLeftCorner
		THIS._anchorArray(1)	= RSZ._ANCHORPOINT._topRightCorner
		THIS._anchorArray(2)	= RSZ._ANCHORPOINT._bottomRightCorner
		THIS._anchorArray(3)	= RSZ._ANCHORPOINT._bottomLeftCorner
	else
		if not THIS.IsAnchor(CornerSet) then
			redim preserve THIS._anchorArray(uBound(THIS._anchorArray) + 1)
			THIS._anchorArray(uBound(THIS._anchorArray)) = CornerSet
		end if
	end if	
end sub  'RESIZABLERECTANGLE.AddAnchor(valRESIZABLERECTANGLE_ANCHORPOINT[0])
sub RESIZABLERECTANGLE.DrawThickContourElement(byval X1 as long, _ 
											   byval Y1 as long, _ 
											   byval X2 as long, _ 
											   byval Y2 as long, _ 
											   byval C	as ulong, _ 
											   byval FO	as RSZ._FILLBOXOPTION=RSZ._FILLBOXOPTION._fill)
	select case FO
		case RESIZABLERECTANGLE._FILLBOXOPTION._contour
			line (X1, Y1)-(X2, Y2), C, b
		case else '_FILLBOXOPTION._fill
			line (X1, Y1)-(X2, Y2), C, bf
	end select 'FO
end sub 'RESIZABLERECTANGLE.DrawThickContourElement({valLNG}*4,valULNG,val_FILLBOXOPTION[0])
sub RESIZABLERECTANGLE.DrawThickContourElement(byval XY1 as XY, _ 
											   byval XY2 as XY, _ 
											   byval C	as ulong, _ 
											   byval FO	as RSZ._FILLBOXOPTION=RSZ._FILLBOXOPTION._fill)
	select case FO
		case RESIZABLERECTANGLE._FILLBOXOPTION._contour
			line (XY1._x, XY1._y)-(XY2._x, XY2._y), C, b
		case else '_FILLBOXOPTION._fill
			line (XY1._x, XY1._y)-(XY2._x, XY2._y), C, bf
	end select 'FO
end sub 'RESIZABLERECTANGLE.DrawThickContourElement({valXY}*2,valULNG,val_FILLBOXOPTION[0])
sub RESIZABLERECTANGLE.RefreshAnchorArray()
	if THIS._mouseClickLeftBorder then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
	elseif THIS._mouseClickTopBorder			then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
	elseif THIS._mouseClickRightBorder			then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
	elseif THIS._mouseClickBottomBorder			then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
		THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
	elseif THIS._mouseClickTopLeftCorner		then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
	elseif THIS._mouseClickTopRightCorner		then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
	elseif THIS._mouseClickBottomRightCorner	then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
	elseif THIS._mouseClickBottomLeftCorner		then
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
	else
		THIS.ResetAnchorList()
		THIS.AddAnchor(RSZ._ANCHORPOINT._allCorner)
	end if
end sub 'RESIZABLERECTANGLE.RefreshAnchorArray()
sub RESIZABLERECTANGLE.SetResizeTimeInitialOffset()
	THIS._tlcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.TLCX
	THIS._tlcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.TLCY
	'
	THIS._trcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.TRCX
	THIS._trcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.TRCY
	'
	THIS._brcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.BRCX
	THIS._brcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.BRCY
	'
	THIS._blcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.BLCX
	THIS._blcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.BLCY
end sub '
sub RESIZABLERECTANGLE.TranslateCornerCoordinate(byval DX as long=0, _ 
												 byval DY as long=0)
	THIS.TLCX	= THIS.TLCX + DX/2
	THIS.TLCY	= THIS.TLCY + DY/2
	'
	THIS.TRCX	= THIS.TRCX + DX/2
	THIS.TRCY	= THIS.TRCY + DY/2
	'
	THIS.BRCX	= THIS.BRCX + DX/2
	THIS.BRCY	= THIS.BRCY + DY/2
	'
	THIS.BLCX	= THIS.BLCX + DX/2
	THIS.BLCY	= THIS.BLCY + DY/2
end sub 'RESIZABLERECTANGLE.TranslateCornerCoordinate({valLNG[0]}*2)
sub RESIZABLERECTANGLE.TestResizableRectangleForMouse()
	dim as integer gmX, gmY, gmBtn1
	getMouse gmX, gmY, , gmBtn1
	'
	'set resize event status
	if THIS._resizeEnabled											and _
	   THIS.MouseClickAnyBoundary									and _ 
	   cBool(THIS._xAtResizeTime<>gmX or THIS._yAtResizeTime<>gmY)	then 
		if THIS._resizeStarted=FALSE then 
			THIS._resizeStarted = TRUE
			THIS.RefreshAnchorArray()
		end if
	else
		if THIS._resizeStarted=TRUE then 
			THIS._resizeStarted = FALSE
		end if
	end if
	if THIS._resizeStarted=TRUE then
		THIS.TranslateCornerCoordinate(gmX - THIS._xAtResizeTime, _ 
									   gmY - THIS._yAtResizeTime)
		THIS._xAtResizeTime = gmX
		THIS._yAtResizeTime = gmY
		exit sub
	end if
	'test mouse @LeftBorder
	if gmX>=THIS.Xi					and _
	   gmX<=(THIS.Xi + THIS.Thckns)	and _
	   gmY>=(THIS.Yi + THIS.Thckns)	and _
	   gmY<=(THIS.Yf - THIS.Thckns)	then
		if THIS._mouseOverLeftBorder=FALSE then THIS._mouseOverLeftBorder = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickLeftBorder=FALSE then 
				THIS._mouseClickLeftBorder = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickLeftBorder=TRUE then THIS._mouseClickLeftBorder = FALSE
		end if
	else
		if THIS._mouseOverLeftBorder=TRUE then THIS._mouseOverLeftBorder = FALSE
		if THIS._mouseClickLeftBorder=TRUE then THIS._mouseClickLeftBorder = FALSE   
	end if
	'test mouse @TopBorder
	if gmX>=(THIS.Xi + THIS.Thckns)	and _
	   gmX<=(THIS.Xf - THIS.Thckns)	and _
	   gmY>=THIS.Yi					and _
	   gmY<=(THIS.Yi + THIS.Thckns)	then
		if THIS._mouseOverTopBorder=FALSE then THIS._mouseOverTopBorder = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickTopBorder=FALSE then 
				THIS._mouseClickTopBorder = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickTopBorder=TRUE then THIS._mouseClickTopBorder = FALSE
		end if
	else
		if THIS._mouseOverTopBorder=TRUE then THIS._mouseOverTopBorder = FALSE
		if THIS._mouseClickTopBorder=TRUE then THIS._mouseClickTopBorder = FALSE
	end if
	'test mouse @RightBorder
	if gmX>=(THIS.Xf - THIS.Thckns)	and _
	   gmX<=THIS.Xf					and _
	   gmY>=(THIS.Yi + THIS.Thckns)	and _
	   gmY<=(THIS.Yf - THIS.Thckns)	then
		if THIS._mouseOverRightBorder=FALSE then THIS._mouseOverRightBorder = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickRightBorder=FALSE then 
				THIS._mouseClickRightBorder = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickRightBorder=TRUE then THIS._mouseClickRightBorder = FALSE
		end if
	else
		if THIS._mouseOverRightBorder=TRUE then THIS._mouseOverRightBorder = FALSE
		if THIS._mouseClickRightBorder=TRUE then THIS._mouseClickRightBorder = FALSE   
	end if
	'test mouse @BottomBorder
	if gmX>=(THIS.Xi + THIS.Thckns)	and _
	   gmX<=(THIS.Xf - THIS.Thckns)	and _
	   gmY>=(THIS.Yf - THIS.Thckns)	and _
	   gmY<=THIS.Yf					then
		if THIS._mouseOverBottomBorder=FALSE then THIS._mouseOverBottomBorder = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickBottomBorder=FALSE then
				THIS._mouseClickBottomBorder = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickBottomBorder=TRUE then THIS._mouseClickBottomBorder = FALSE
		end if
	else
		if THIS._mouseOverBottomBorder=TRUE then THIS._mouseOverBottomBorder = FALSE
		if THIS._mouseClickBottomBorder=TRUE then THIS._mouseClickBottomBorder = FALSE    
	end if
	'test mouse @TopLeftCorner
	if gmX>=THIS.Xi					and _
	   gmX<(THIS.Xi + THIS.Thckns)	and _
	   gmY>=THIS.Yi					and _
	   gmY<(THIS.Yi + THIS.Thckns)	then
		if THIS._mouseOverTopLeftCorner=FALSE then THIS._mouseOverTopLeftCorner = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickTopLeftCorner=FALSE then
				THIS._mouseClickTopLeftCorner = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickTopLeftCorner=TRUE then THIS._mouseClickTopLeftCorner = FALSE
		end if
	else
		if THIS._mouseOverTopLeftCorner=TRUE then THIS._mouseOverTopLeftCorner = FALSE	
		if THIS._mouseClickTopLeftCorner=TRUE then THIS._mouseClickTopLeftCorner = FALSE   
	end if
	'test mouse @TopRightCorner
	if gmX>(THIS.Xf - THIS.Thckns)	and _
	   gmX<=THIS.Xf					and _
	   gmY>=THIS.Yi					and _
	   gmY<(THIS.Yi + THIS.Thckns)	then
		if THIS._mouseOverTopRightCorner=FALSE then THIS._mouseOverTopRightCorner = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickTopRightCorner=FALSE then
				THIS._mouseClickTopRightCorner = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickTopRightCorner=TRUE then THIS._mouseClickTopRightCorner = FALSE
		end if
	else
		if THIS._mouseOverTopRightCorner=TRUE then THIS._mouseOverTopRightCorner = FALSE
		if THIS._mouseClickTopRightCorner=TRUE then THIS._mouseClickTopRightCorner = FALSE   
	end if
	'test mouse @BottomRightCorner
	if gmX>(THIS.Xf - THIS.Thckns)	and _
	   gmX<=THIS.Xf					and _
	   gmY>(THIS.Yf - THIS.Thckns)	and _
	   gmY<=THIS.Yf				 	then
		if THIS._mouseOverBottomRightCorner=FALSE then THIS._mouseOverBottomRightCorner = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickBottomRightCorner=FALSE then
				THIS._mouseClickBottomRightCorner = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickBottomRightCorner=TRUE then THIS._mouseClickBottomRightCorner = FALSE
		end if
	else
		if THIS._mouseOverBottomRightCorner=TRUE then THIS._mouseOverBottomRightCorner = FALSE
		if THIS._mouseClickBottomRightCorner=TRUE then THIS._mouseClickBottomRightCorner = FALSE  
	end if
	'test mouse @BottomLeftCorner
	if gmX>=THIS.Xi					and _
	   gmX<(THIS.Xi + THIS.Thckns)	and _
	   gmY>(THIS.Yf - THIS.Thckns)	and _
	   gmY<=THIS.Yf				 	then
		if THIS._mouseOverBottomLeftCorner=FALSE then THIS._mouseOverBottomLeftCorner = TRUE
		if gmBtn1=+1 then
			if THIS._mouseClickBottomLeftCorner=FALSE then
				THIS._mouseClickBottomLeftCorner = TRUE
				if not THIS._resizeStarted then
					THIS._xAtResizeTime = gmX
					THIS._yAtResizeTime = gmY
					THIS.SetResizeTimeInitialOffset()
				end if
			end if
		else
			if THIS._mouseClickBottomLeftCorner=TRUE then THIS._mouseClickBottomLeftCorner = FALSE
		end if
	else
		if THIS._mouseOverBottomLeftCorner=TRUE then THIS._mouseOverBottomLeftCorner = FALSE
		if THIS._mouseClickBottomLeftCorner=TRUE then THIS._mouseClickBottomLeftCorner = FALSE   
	end if
	'
end sub 'RESIZABLERECTANGLE.TestResizableRectangleForMouse()
sub RESIZABLERECTANGLE.DrawResizableRectangle()
	THIS.TestResizableRectangleForMouse()
	'
	'preamble->
	/'
		? "resize started="; THIS._resizeStarted
		? "TLCXanchored="; THIS.TLCXanchored
		? "TLCYanchored="; THIS.TLCYanchored
		? "TRCXanchored="; THIS.TRCXanchored
		? "TRCYanchored="; THIS.TRCYanchored
		? "BRCXanchored="; THIS.BRCXanchored
		? "BRCYanchored="; THIS.BRCYanchored
		? "BLCXanchored="; THIS.BLCXanchored
		? "BLCYanchored="; THIS.BLCYanchored
		THIS.DrawRectangle()
		if THIS._dragEnabled then
			THIS.DrawDraggableRectangle()
		end if
	'/
	'
	'draw left border
	if THIS._mouseClickLeftBorder then
		THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yi + THIS.Thckns)), _ 
							 XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
							 rgb(220,100,100), _
							 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverLeftBorder then
		THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yi + THIS.Thckns)), _ 
							 XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
							 rgb(200,120,150), _
							 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY(THIS.Xi, (THIS.Yi + THIS.Thckns)), _ 
								 XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw top border
	if THIS._mouseClickTopBorder then
		THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi - 1), _ 
									 XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverTopBorder then
		THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi - 1), _ 
									 XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi), _ 
								 XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw right border
	if THIS._mouseClickRightBorder then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _ 
									 XY(THIS.Xf + 1, (THIS.Yf - THIS.Thckns)), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverRightBorder then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _ 
									 XY(THIS.Xf + 1, (THIS.Yf - THIS.Thckns)), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _ 
								 XY(THIS.Xf, (THIS.Yf - THIS.Thckns)), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw bottom border
	if THIS._mouseClickBottomBorder then
		THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
									 XY((THIS.Xf - THIS.Thckns), THIS.Yf + 1), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverBottomBorder then
		THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
									 XY((THIS.Xf - THIS.Thckns), THIS.Yf + 1), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
								 XY((THIS.Xf - THIS.Thckns), THIS.Yf), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw top left corner
	if THIS._mouseClickTopLeftCorner then
		THIS.DrawThickContourElement(XY(THIS.Xi - 2, THIS.Yi - 2), _ 
									 XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverTopLeftCorner then
		THIS.DrawThickContourElement(XY(THIS.Xi - 2, THIS.Yi - 2), _ 
									 XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY(THIS.Xi - 1, THIS.Yi - 1), _ 
								 XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw top right corner
	if THIS._mouseClickTopRightCorner then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 2), _ 
									 XY(THIS.Xf	+ 2, (THIS.Yi + THIS.Thckns)), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverTopRightCorner then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 2), _ 
									 XY(THIS.Xf	+ 2, (THIS.Yi + THIS.Thckns)), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 1), _ 
								 XY(THIS.Xf	+ 1, (THIS.Yi + THIS.Thckns)), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw bottom right corner
	if THIS._mouseClickBottomRightCorner then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
									 XY(THIS.Xf	+ 2, THIS.Yf + 2), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverBottomRightCorner then
		THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
									 XY(THIS.Xf	+ 2, THIS.Yf + 2), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _ 
								 XY(THIS.Xf	+ 1, THIS.Yf + 1), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
	'draw bottom left corner
	if THIS._mouseClickBottomLeftCorner then
		THIS.DrawThickContourElement(XY(THIS.Xi - 2, (THIS.Yf - THIS.Thckns)), _ 
									 XY((THIS.Xi + THIS.Thckns), THIS.Yf + 2), _
									 rgb(220,100,100), _
									 RSZ._FILLBOXOPTION._fill)
	elseif THIS._mouseOverBottomLeftCorner then
		THIS.DrawThickContourElement(XY(THIS.Xi - 2, (THIS.Yf - THIS.Thckns)), _ 
									 XY((THIS.Xi + THIS.Thckns), THIS.Yf + 2), _
									 rgb(200,120,150), _
									 RSZ._FILLBOXOPTION._fill)
	end if
	THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yf - THIS.Thckns)), _ 
								 XY((THIS.Xi + THIS.Thckns), THIS.Yf + 1), _
								 rgb(180,180,130), _
								 RSZ._FILLBOXOPTION._contour)
end sub 'RESIZABLERECTANGLE.DrawResizableRectangle()


type ICEBENCH extends RESIZABLERECTANGLE
	declare constructor()
	/'
:TODO:
	declare constructor(byval as long, _ 
						byval as long)
	declare constructor(byval as long, _ 
						byval as long, _ 
						byval as long, _ 
						byval as long)
	'/
	declare sub InitializeIceBench()
	declare destructor()
	declare property AdjustedTitleToFitBar() as string
	declare property DraggableZoneXi() as long
	declare property DraggableZoneYi() as long
	declare property DraggableZoneXf() as long
	declare property DraggableZoneYf() as long
	declare property HasBoardFocus() as boolean
	declare property HasBoardFocus(byval as boolean)
	declare property DragEnabled() as boolean
	declare property DragEnabled(byval as boolean)
	declare property ResizeEnabled() as boolean
	declare property ResizeEnabled(byval as boolean)
	declare sub TestIceBenchForMouse()
	declare sub DrawIceBench()
		as long				_zOrder
		as string			_titleBarTitle
		as RECTANGLE		_draggableZone
		as long				_draggableZoneXi
		as long				_draggableZoneYi
		as long				_draggableZoneXf
		as long				_draggableZoneYf
		as boolean			_hasBoardFocus
		as boolean			_mouseOverVisibleArea
		as boolean			_mouseClickVisibleArea
		as boolean			_mouseOverDraggableSubFrame
		as boolean			_mouseClickDraggableSubFrame
		as boolean			_mouseOverResizableBoundary
		as boolean			_mouseClickResizableBoundary
end type 'ICEBENCH <-- RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor ICEBENCH()
	BASE()
	'
	THIS.InitializeIceBench()
end constructor 'ICEBENCH default explicit constructor
sub ICEBENCH.InitializeIceBench()
	with THIS
		._titleBarTitle					=> ".."
		.DragEnabled					=> FALSE
		.ResizeEnabled					=> TRUE
		._draggableZone.Xi				=> .DraggableZoneXi
		._draggableZone.Yi				=> .DraggableZoneYi
		._draggableZone.Xf				=> .DraggableZoneXf
		._draggableZone.Yf				=> .DraggableZoneYf
		._hasBoardFocus					=> FALSE
		._mouseOverVisibleArea			=> FALSE
		._mouseClickVisibleArea			=> FALSE
		._mouseOverDraggableSubFrame	=> FALSE
		._mouseClickDraggableSubFrame	=> FALSE
		._mouseOverResizableBoundary	=> FALSE
		._mouseClickResizableBoundary	=> FALSE
		.Thckns							=> 12
	end with 'THIS
end sub 'ICEBENCH.InitializeIceBench()
destructor ICEBENCH()
	'
end destructor 'ICEBENCH default explicit destructor
property ICEBENCH.AdjustedTitleToFitBar() as string
	dim as string	stringResult
	stringResult = THIS._titleBarTitle
	'---->
	return stringResult
end property 'get STR:=ICEBENCH.AdjustedTitleToFitBar
property ICEBENCH.DraggableZoneXi() as long
	THIS._draggableZoneXi = THIS.Xi + THIS.Thckns
	'---->
	return THIS._draggableZoneXi
end property 'get LNG:=ICEBENCH.DraggableZoneXi
property ICEBENCH.DraggableZoneYi() as long
	THIS._draggableZoneYi = THIS.Yi + THIS.Thckns
	'---->
	return THIS._draggableZoneYi
end property 'get LNG:=ICEBENCH.DraggableZoneYi
property ICEBENCH.DraggableZoneXf() as long
	THIS._draggableZoneXf = THIS.Xf - THIS.Thckns
	'---->
	return THIS._draggableZoneXf
end property 'get LNG:=ICEBENCH.DraggableZoneXf
property ICEBENCH.DraggableZoneYf as long
	THIS._draggableZoneYf = THIS.Yi + THIS.Thckns + 24
	'---->
	return THIS._draggableZoneYf
end property 'get LNG:=ICEBENCH.DraggableZoneYf
property ICEBENCH.HasBoardFocus() as boolean
	'---->
	return THIS._hasBoardFocus
end property 'get BOOL:=ICEBENCH.HasBoardFocus
property ICEBENCH.HasBoardFocus(byval SetValue as boolean)
	THIS._hasBoardFocus = SetValue
end property 'set ICEBENCH.HasBoardFocus(valBOOL)
property ICEBENCH.DragEnabled() as boolean
	if not THIS.HasBoardFocus then THIS._dragEnabled = FALSE
	'---->
	return THIS._dragEnabled
end property 'get BOOL:=ICEBENCH.DragEnabled
property ICEBENCH.DragEnabled(byval SetValue as boolean)
	THIS._dragEnabled = SetValue
end property 'set ICEBENCH.DragEnabled(valBOOL)
property ICEBENCH.ResizeEnabled() as boolean
	if not THIS.HasBoardFocus then THIS._resizeEnabled = FALSE
	'---->
	return THIS._resizeEnabled
end property 'get BOOL:=ICEBENCH.ResizeEnabled
property ICEBENCH.ResizeEnabled(byval SetValue as boolean)
	THIS._resizeEnabled = SetValue
end property 'set ICEBENCH.ResizeEnabled(valBOOL)
sub ICEBENCH.TestIceBenchForMouse()
	dim as integer gmX, gmY, gmBtn1
	getMouse gmX, gmY, , gmBtn1
	'
	if gmX>THIS.DraggableZoneXi		and _ 
	   gmX<THIS.DraggableZoneXf		and _ 
	   gmY>THIS.DraggableZoneYi		and _ 
	   gmY<THIS.DraggableZoneYf		then
		if THIS.DragEnabled=FALSE then THIS.DragEnabled = TRUE
	else
		if THIS.DragEnabled=TRUE then THIS.DragEnabled = FALSE
	end if
	'
end sub 'ICEBENCH.TestIceBenchForMouse()
sub ICEBENCH.DrawIceBench()
	THIS.TestIceBenchForMouse()
	if THIS.DragEnabled then
		'just calling the prop.
	end if
	if THIS.ResizeEnabled then
		'just calling the prop.
	end if
	if THIS._resizeStarted then 
		THIS.DragEnabled = FALSE
	end if
	if not THIS.HasBoardFocus then
		THIS.Thckns = 0
		'dev.note: check for redundancy! late addition:
		THIS.ResizeEnabled = FALSE
	else
		THIS.Thckns = 10
		'dev.note: check for redundancy! late addition:
		THIS.ResizeEnabled = TRUE
	end if
	'
	THIS.DrawRectangleAsFlatBackground()
	THIS.DrawSilentlyDraggableRectangle()
	THIS._draggableZone.Xi				= THIS.DraggableZoneXi
	THIS._draggableZone.Yi				= THIS.DraggableZoneYi
	THIS._draggableZone.Xf				= THIS.DraggableZoneXf
	THIS._draggableZone.Yf				= THIS.DraggableZoneYf
	THIS._draggableZone.DrawRectangle()
	THIS.DrawResizableRectangle()
	draw string (THIS._draggableZone.Xi + 4, _ 
				 THIS._draggableZone.Yi + 4), _ 
				 THIS.AdjustedTitleToFitBar, _ 
				 rgb(200,200,155)
end sub 'ICEBENCH.DrawIceBench()


'                                  ------------
'                                  ICEBOARD UDT
'                                  ------------
type ICEBOARD
	declare constructor()
	declare destructor()
	declare property IBenchCount() as long
	declare property IBenchZOrderAtIndex(Index as long) as long
	declare function IsIceBenchRegistred(byval as ICEBENCH ptr) as boolean
	declare sub AddIceBench(byval as ICEBENCH ptr)
	declare function GrantFocusToIceBenchAtIndex(byval as long) as long
	declare function TestIBenchArrayForMouseOverAtIndex(byval as long, _ 
														byval as long, _ 
														byval as long) _ 
														as boolean
	declare sub TestIceBoardForMouse()
	declare sub DrawIceBoard()
		as long				_benchCount
		as ICEBENCH ptr		_arrayOfIBenchPtr(any)
end type 'ICEBOARD
constructor ICEBOARD()
	dim as long deskTopW
	dim as long deskTopH
	screenInfo deskTopW, deskTopH
	'
	screenRes desktopW, _ 
	          desktopH, _ 
	          32, _ 
	          1, _ 
	          fb.GFX_SHAPED_WINDOW
	color ,rgba(255,0,255,0)	
end constructor 'ICEBOARD default explicit constructor
destructor ICEBOARD()
	'
end destructor 'ICEBOARD default explicit detructor
property ICEBOARD.IBenchCount() as long
	'---->
	return ( (uBound(THIS._arrayOfIBenchPtr) - _ 
			  lBound(THIS._arrayOfIBenchPtr)) + _ 
			  1 )
end property 'get LNG:=ICEBOARD.IBenchCount()
property ICEBOARD.IBenchZOrderAtIndex(Index as long) as long
	if Index>=lBound(THIS._arrayOfIBenchPtr) and _
	   Index<=uBound(THIS._arrayOfIBenchPtr) then
			'---->
			return THIS._arrayOfIBenchPtr(Index)->_zOrder
	else
			'---->
			return log(-1)
	end if
end property 'get LNG:=IBenchZOrderAtIndex(LNG_INDEX)
function ICEBOARD.IsIceBenchRegistred(byval IBenchPtr as ICEBENCH ptr) as boolean
	dim as boolean	returnValue	=> FALSE
	for index as long = 0 to uBound(THIS._arrayOfIBenchPtr)
		if IBenchPtr=THIS._arrayOfIBenchPtr(index) then
			returnValue = TRUE
			exit for
		end if
	next index
	'---->
	return returnValue
end function 'BOOL:=ICEBOARD.IsIceBenchRegistred(valICEBENCH_PTR)
sub ICEBOARD.AddIceBench(byval IBenchPtr as ICEBENCH ptr)
	if THIS.IsIceBenchRegistred(IBenchPtr)	or _ 
	   cBool(IBenchPtr=0)					then
		exit sub
	else
		if uBound(THIS._arrayOfIBenchPtr)>=0 then
			THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->HasBoardFocus = _ 
																				FALSE
		end if
		redim preserve THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr) + 1)
		THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr)) => IBenchPtr
		THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->HasBoardFocus => TRUE
		THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_zOrder => _ 
													uBound(THIS._arrayOfIBenchPtr)
	end if
end sub 'ICEBOARD.AddIceBench(valICEBENCH_PTR)
function ICEBOARD.GrantFocusToIceBenchAtIndex(byval Index as long) as long
	if Index>=lBound(THIS._arrayOfIBenchPtr) and _
	   Index<=uBound(THIS._arrayOfIBenchPtr) then
			THIS._arrayOfIBenchPtr(Index)->HasBoardFocus = TRUE
			if Index<>uBound(THIS._arrayOfIBenchPtr) then
				swap THIS._arrayOfIBenchPtr(Index), _ 
					 THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))	
				for localIndex as long = 0 to uBound(THIS._arrayOfIBenchPtr) - 1
					THIS._arrayOfIBenchPtr(Index)->HasBoardFocus = FALSE
			THIS._arrayOfIBenchPtr(Index)->_dragEnabled = FALSE
			THIS._arrayOfIBenchPtr(Index)->_resizeStarted = FALSE
				next localIndex
			end if
			'todo:
			'rearrange according to previous zOrder (not just swap)
			'---->
			return +0
	else
			'---->
			return +1
	end if
end function 'LNG:=ICEBOARD.GrantFocusToIceBenchAtIndex(valLNG)
function ICEBOARD.TestIBenchArrayForMouseOverAtIndex(byval Index	as long, _ 
													 byval GMX		as long, _ 
													 byval GMY		as long) _ 
																	as boolean
	dim as boolean	returnValue	=> FALSE
	if GMX>=THIS._arrayOfIBenchPtr(Index)->Xi	and _
	   GMX<=THIS._arrayOfIBenchPtr(Index)->Xf	and _
	   GMY>=THIS._arrayOfIBenchPtr(Index)->Yi	and _
	   GMY<=THIS._arrayOfIBenchPtr(Index)->Yf	then
	    ? Index
	    ? THIS._arrayOfIBenchPtr(0)->HasBoardFocus
	    ? THIS._arrayOfIBenchPtr(1)->HasBoardFocus
		? THIS._arrayOfIBenchPtr(Index)->Xi
		? THIS._arrayOfIBenchPtr(Index)->Xf
		? THIS._arrayOfIBenchPtr(Index)->Yi
		? THIS._arrayOfIBenchPtr(Index)->Yf
		returnValue = TRUE
	end if
	'---->
	return returnValue
end function 'BOOL:=ICEBOARD.TestIBenchArrayForMouseOverAtIndex({valLNG}*3)
sub ICEBOARD.TestIceBoardForMouse()
	'
	'dev.note: 
	'this below to prevent sudden weird partial focus flip (partial) while moving
	'unfortunately that doesn't work...
	if THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_dragEnabled		or _
	   THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_resizeStarted	then
	   	exit sub
	end if
	'
	dim as integer gmX, gmY, gmBtn1
	getMouse gmX, gmY, , gmBtn1	
	'
	dim as long	index
	for index = (THIS.IBenchCount - 1) to 0 step -1
		if THIS.TestIBenchArrayForMouseOverAtIndex(index, gmX, gmY) then exit for
	next index
	if index<0 then
		exit sub
	else
		if gmBtn1=+1 then 
			THIS.GrantFocusToIceBenchAtIndex(index)
		end if
	end if
end sub 'ICEBOARD.TestIceBoardForMouse()
sub ICEBOARD.DrawIceBoard()
	dim as long deskTopW
	dim as long deskTopH
	screenInfo deskTopW, deskTopH
	'non-priotary todo: check&update if desktop changed
	'
	for row as long = 200\8 to (desktopH - 200)\8
		for col as long = 200\8 to (desktopW - 200)\8
			locate row, col, 0 : ? ".";
		next col
	next row
	locate (desktopH - 200)\8, 200\8 : 	? "development version"
	'
	THIS.TestIceBoardForMouse()
	'
	for index as long = 0 to uBound(THIS._arrayOfIBenchPtr)
		THIS._arrayOfIBenchPtr(index)->DrawIceBench()
	next index
end sub 'ICEBOARD.DrawIceBoard()


'----------------------------------------------
'------------------------------------------MAIN

'--------------------------------INITIALIZATION
'screenRes 600,480,32
'color rgb(0,220,220), rgb(080,080,120)

dim as ICEBENCH	testIBench1
dim as ICEBENCH	testIBench2
dim as ICEBENCH	testIBench3

dim as ICEBOARD	testIBoard
testIBoard.AddIceBench(@testIBench1)
testIBoard.AddIceBench(@testIBench2)
testIBoard.AddIceBench(@testIBench3)


'-------------------------------------MAIN LOOP
color rgb(100,220,220)
do
	screenLock
		cls
			testIBoard.DrawIceBoard()
	screenUnlock

	sleep 25
loop until inkey=chr(27)

'----------------------------------FINALIZATION

sleep
end 0


'[you've reached the end of the freebasic file]
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

Sorry to refresh a little the oldies. It wasn't compiling in win64, so I made some corrections and this works again now (tested on win10 64):

Code: Select all

'program purpose: .............................
'.developpment around ICEBOARDING in freebasic.
'----------------------------------------------
'gnu-like public domain small windowing utility
'weblink:
'----------------------------------------------

'----------------------------------------------
'.declaration of XY UDT........................
'.implementation of XY UDT.....................
'.declaration of RECTANGLE UDT.................
'.implementation of RECTANGLE UDT..............
'.declaration of DRAGGABLERECTANGLE UDT........
'.implementation of DRAGGABLERECTANGLE UDT.....
'.declaration of RESIZABLERECTANGLE UDT........
'.implementation of RESIZABLERECTANGLE UDT.....
'.declaration of ICEBENCH UDT..................
'.implementation of ICEBENCH UDT...............
'.declaration of ICEBOARD UDT..................
'.implementation of ICEBOARD UDT...............
'----------------------------------------------

'>missing features at current scheduler:       
'----------------------------------------------
'>a quit button (!)                           
'>make bench object parentable container       

'>1st test result:                             
'----------------------------------------------
'>compiled fine under fb1.04 windowsXP32       
'>nothing to signal at run-time (runs smoothy)

'>known bugs/mostly unexplained at present day:
'----------------------------------------------
'screen is blank flashing at application start
'______________________________________________
'left and top resizers has weird behaviour     
'______________________________________________
'corner resizers lose too easily focus         
'______________________________________________
'there is code mistake with top resizing border
'______________________________________________
'there is a weird issue with focus flip while 
'a top level bench is crossing a low level one
'a certain way -                               
'suspected mouse test at resizer object ...   
'______________________________________________
'the mouseover test at IceBoard mousetest     
'doesnt release properly when mouseover nothing
'______________________________________________
'and probably much  more!                     

'>please for bug reporting/remarks/suggestion 
'>visit fb.net link at head of this file       
'>sorry for long preamble, thanks folks, enjoy!
'>.............happy new year!.................


#include once "fbgfx.bi"


'                                        ------
'                                        XY UDT
'                                        ------
type XY
   'small udt utility to pass (X,Y) argument
   'in procedure in more (?) readable way ..
   declare constructor()
   declare constructor(byval as long, byval as long)
      as long      _x
      as long      _y   
end type 'XY
constructor XY()
   '
end constructor 'XY default explicit constructor
constructor XY(byval X as long, byval Y as long)
   this._x   => X
   this._y   => Y
end constructor 'XY default explicit constructor


'                                 -------------
'                                 RECTANGLE UDT
'                                 -------------
type RECTANGLE extends OBJECT
   declare constructor()
   declare constructor(byval as long, _
                  byval as long)
   declare constructor(byval as long, _
                  byval as long, _
                  byval as long, _
                  byval as long)
   declare sub InitializeRectangle overload(byval as long=-1, _
                                  byval as long=-1)
   declare sub InitializeRectangle(byval as long, _
                           byval as long, _
                           byval as long, _
                           byval as long)
   declare destructor()
   declare sub FinalizeRectangle()
   '
   declare property Xi()   as long
   declare property Xi(byval as long)
   declare property Yi()   as long
   declare property Yi(byval as long)
   declare property W()   as long
   declare property W(byval as long)
   declare property H()   as long
   declare property H(byval as long)
   declare property Xf()   as long
   declare property Xf(byval as long)
   declare property Yf()   as long
   declare property Yf(byval as long)
   declare property TopLeftCornerX()      as long
   declare property TopLeftCornerX(byval    as long)
   declare property TopLeftCornerY()      as long
   declare property TopLeftCornerY(byval    as long)
   declare property RectangleWidth()      as long
   declare property RectangleWidth(byval    as long)
   declare property RectangleHeight()      as long
   declare property RectangleHeight(byval    as long)
   declare property BottomRightCornerX()      as long
   declare property BottomRightCornerX(byval    as long)
   declare property BottomRightCornerY()      as long
   declare property BottomRightCornerY(byval    as long)
   declare sub DrawRectangle()
   declare sub DrawRectangleAsFlatBackground()
   private:
      as long                  _topLeftCornerX
      as long                  _topLeftCornerY
      as long                  _rectangleWidth
      as long                  _rectangleHeight
      '
      as long                  _maxWidth
      as long                  _maxHeight
end type 'RECTANGLE <-- OBJECT
'inheritance lineage:
'RECTANGLE <-- OBJECT
constructor RECTANGLE()
   BASE()
   THIS.InitializeRectangle()
end constructor 'RECTANGLE default explicit constructor
constructor RECTANGLE(byval MaxW   as long, _
                 byval MaxH   as long)
   'dev.note: very specific usage initializer
   '         can't remember its use ........
   BASE()
   if maxW>0 then THIS._maxWidth   => MaxW
   if maxH>0 then THIS._maxHeight   => MaxH
   THIS.InitializeRectangle(THIS._maxWidth, _
                      THIS._maxHeight)
end constructor 'RECTANGLE(valLNG,valLNG)
constructor RECTANGLE(byval TCLX   as long, _
                 byval TCLY   as long, _
                 byval Wid      as long, _
                 byval Hei      as long)
   BASE()
   THIS.InitializeRectangle(TCLX,TCLY,Wid,Hei)
end constructor 'RECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub RECTANGLE.InitializeRectangle(byval MaxW as long=-1, _
                          byval MaxH as long=-1)
   'dev.note: very specific usage initializer
   dim as integer   scrW, scrH
   screenInfo      scrW, scrH
   if MaxW<=0 then
      with THIS
         ._topLeftCornerX   => scrW\3
         ._rectangleWidth   => scrW\3
      end with 'THIS
   else
      with THIS
         ._topLeftCornerY   => MaxH\3
         ._rectangleHeight   => MaxH\3
      end with 'THIS      
   end if
   if MaxH<=0 then
      with THIS
         ._topLeftCornerY   => scrH\3
         ._rectangleHeight   => scrH\3
      end with 'THIS
   else
      with THIS
         ._topLeftCornerY   => MaxH\3
         ._rectangleHeight   => MaxH\3
      end with 'THIS      
   end if
end sub 'RECTANGLE.InitializeRectangle(valLNG[-1],valLNG[-1])
sub RECTANGLE.InitializeRectangle(byval TCLX   as long, _
                          byval TCLY   as long, _
                          byval Wid      as long, _
                          byval Hei      as long)
   with THIS
      ._topLeftCornerX   => TCLX
      ._topLeftCornerY   => TCLY
      ._rectangleWidth   => Wid
      ._rectangleHeight   => Hei
   end with 'THIS
end sub 'RECTANGLE.InitializeRectangle(valLNG,valLNG,valLNG,valLNG)
destructor RECTANGLE()
   '
end destructor 'RECTANGLE default explicit destructor
sub RECTANGLE.FinalizeRectangle()
   THIS.destructor()
end sub 'RECTANGLE.FinalizeRectangle()
property RECTANGLE.Xi() as long
   '---->
   return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.Xi
property RECTANGLE.Xi(byval SetValue as long)
   THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.Xi(valLNG)
property RECTANGLE.Yi() as long
   '---->
   return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.Yi
property RECTANGLE.Yi(byval SetValue as long)
   THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.Yi(valLNG)
property RECTANGLE.W()   as long
   '---->
   return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.W
property RECTANGLE.W(byval SetValue as long)
   THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.W(valLNG)
property RECTANGLE.H()   as long
   '---->
   return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.H
property RECTANGLE.H(byval SetValue as long)
   THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.H(valLNG)
property RECTANGLE.Xf() as long
   '---->
   return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.Xf
property RECTANGLE.Xf(byval SetValue as long)
   if SetValue<THIS._topLeftCornerX then
      THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
      THIS._topLeftCornerX = SetValue
   else
      THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
   end if
end property 'set RECTANGLE.Xf(valLNG)
property RECTANGLE.Yf() as long
   '---->
   return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.Yf
property RECTANGLE.Yf(byval SetValue as long)
   if SetValue<THIS._topLeftCornerY then
      THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
      THIS._topLeftCornerY = SetValue
   else
      THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
   end if
end property 'set RECTANGLE.Yf(valLNG)
property RECTANGLE.TopLeftCornerX()   as long
   '---->
   return THIS._topLeftCornerX
end property 'get LNG:=RECTANGLE.TopLeftCornerX
property RECTANGLE.TopLeftCornerX(byval SetValue as long)
   THIS._topLeftCornerX = SetValue
end property 'set RECTANGLE.TopLeftCornerX(valLNG)
property RECTANGLE.TopLeftCornerY()   as long
   '---->
   return THIS._topLeftCornerY
end property 'get LNG:=RECTANGLE.TopLeftCornerY
property RECTANGLE.TopLeftCornerY(byval SetValue as long)
   THIS._topLeftCornerY = SetValue
end property 'set RECTANGLE.TopLeftCornerY(valLNG)
property RECTANGLE.RectangleWidth()   as long
   '---->
   return THIS._rectangleWidth
end property 'get LNG:=RECTANGLE.RectangleWidth
property RECTANGLE.RectangleWidth(byval SetValue as long)
   THIS._rectangleWidth = SetValue
end property 'set RECTANGLE.RectangleWidth(valLNG)
property RECTANGLE.RectangleHeight() as long
   '---->
   return THIS._rectangleHeight
end property 'get LNG:=RECTANGLE.RectangleHeight
property RECTANGLE.RectangleHeight(byval SetValue as long)
   THIS._rectangleHeight = SetValue
end property 'set RECTANGLE.RectangleHeight(valLNG)
property RECTANGLE.BottomRightCornerX()   as long
   '---->
   return ( THIS._topLeftCornerX + THIS._rectangleWidth - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerX
property RECTANGLE.BottomRightCornerX(byval SetValue as long)
   if SetValue<THIS._topLeftCornerX then
      THIS._rectangleWidth = THIS._topLeftCornerX - SetValue + 1
      THIS._topLeftCornerX = SetValue
   else
      THIS._rectangleWidth = SetValue - THIS._topLeftCornerX + 1
   end if
end property 'set RECTANGLE.BottomRightCornerX(valLNG)
property RECTANGLE.BottomRightCornerY()   as long
   '---->
   return ( THIS._topLeftCornerY + THIS._rectangleHeight - 1 )
end property 'get LNG:=RECTANGLE.BottomRightCornerY
property RECTANGLE.BottomRightCornerY(byval SetValue as long)
   if SetValue<THIS._topLeftCornerY then
      THIS._rectangleHeight = THIS._topLeftCornerY - SetValue + 1
      THIS._topLeftCornerY = SetValue
   else
      THIS._rectangleHeight = SetValue - THIS._topLeftCornerY + 1
   end if
end property 'RECTANGLE.BottomRightCornerY(valLNG)
sub RECTANGLE.DrawRectangle()
   static as byte      switcher   => +1
   static as double   startTime   => 00
   dim as double   currentTime      => TIMER()
   dim as double   timeInterval   => 0.65
   if ( (currentTime - startTime)>timeInterval ) then
      switcher *= -1
      startTime = TIMER()
   end if
   if switcher=+1 then
      with THIS
         line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _
             (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _
              THIS._topLeftCornerY + THIS._rectangleHeight - 1), _
              rgb(200,150,150), _
              b, _
              &b0000111100001111
      end with 'THIS      
   else
      with THIS
         line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _
             (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _
              THIS._topLeftCornerY + THIS._rectangleHeight - 1), _
              rgb(200,150,150), _
              b, _
              &b1111000011110000
      end with 'THIS         
   end if
end sub 'RECTANGLE.DrawRectangle()   
sub RECTANGLE.DrawRectangleAsFlatBackground()
   with THIS
      line (THIS._topLeftCornerX, THIS._topLeftCornerY)- _
          (THIS._topLeftCornerX + THIS._rectangleWidth - 1, _
           THIS._topLeftCornerY + THIS._rectangleHeight - 1), _
           rgb(100,100,120), _
           bf, _
           &b0000111100001111
   end with 'THIS   
end sub 'RECTANGLE.DrawRectangleAsFlatBackground()


'                        ----------------------
'                        DRAGGABLERECTANGLE UDT
'                        ----------------------
type DRAGGABLERECTANGLE extends RECTANGLE
   declare constructor()
   declare constructor(byval as long, _
                  byval as long)
   declare constructor(byval as long, _
                  byval as long, _
                  byval as long, _
                  byval as long)
   declare sub InitializeDraggableRectangle()
   declare destructor()
   declare sub TestDraggableRectangleForMouse()
   declare sub DrawDraggableRectangle()
   declare sub DrawSilentlyDraggableRectangle()
      as ulong         _bckgColor
      as ulong         _fgndColor
      as boolean         _mouseOver
      as boolean         _mouseClick
      as boolean         _mouseDrag
      as ulong         _onMouseOverBckgColor
      as ulong         _onMouseClickBckgColor
      as ulong         _onMouseDragBckgColor
      '
      as boolean         _clickEnabled
      as boolean         _dragEnabled
   enum _DRAGAXISCONSTRAINT
      _yOnly   = -2
      _xOnly   = -1
      _noAxis   = -0
      _xy      = +1
   end enum '_DRAGAXISCONSTRAINT   
   as _DRAGAXISCONSTRAINT   _dragAxis
      as integer         _xAtDragTime
      as integer         _yAtDragTime
      as integer         _xDragOffsetFixedValue
      as integer         _yDragOffsetFixedValue
      as boolean         _markedAsTemporaryNonDraggable
      as integer                  _draggableFamillyCurrentMemberIndex   
   static as integer               draggableFamillyMemberCount
   static as DRAGGABLERECTANGLE ptr   draggableFamillyArrayOfPtr(any)
end type 'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
dim as integer               DRAGGABLERECTANGLE.draggableFamillyMemberCount
dim as DRAGGABLERECTANGLE ptr   DRAGGABLERECTANGLE.draggableFamillyArrayOfPtr(any)
type DR as DRAGGABLERECTANGLE
'inheritance lineage:
'DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor DRAGGABLERECTANGLE()
   BASE()
   THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE default explicit constructor
constructor DRAGGABLERECTANGLE(byval MaxW   as long, _
                        byval MaxH   as long)
   BASE()
   THIS.InitializeRectangle(MaxW, MaxH)
   THIS.InitializeDraggableRectangle()
end constructor 'RECTANGLE(valLNG,valLNG)
constructor DRAGGABLERECTANGLE(byval TCLX   as long, _
                        byval TCLY   as long, _
                        byval Wid   as long, _
                        byval Hei   as long)
   BASE()
   THIS.InitializeRectangle(TCLX, TCLY, Wid, Hei)
   THIS.InitializeDraggableRectangle()
end constructor 'DRAGGABLERECTANGLE(valLNG,valLNG,valLNG,valLNG)
sub DRAGGABLERECTANGLE.InitializeDraggableRectangle()
   '-constructor subroutine-
   DR.draggableFamillyMemberCount            +=> 1
   THIS._draggableFamillyCurrentMemberIndex    => DR.draggableFamillyMemberCount - 1
   redim preserve DR.draggableFamillyArrayOfPtr(DR.draggableFamillyMemberCount - 1)
   DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))   => @THIS
   '
   with THIS
      ._bckgColor               => rgb(080,080,080)
      ._fgndColor               => rgb(240,240,190)
      ._onMouseOverBckgColor      => rgb(120,080,120)
      ._onMouseClickBckgColor      => rgb(080,120,080)
      ._onMouseDragBckgColor      => rgb(080,080,120)
      ._clickEnabled      => TRUE
      ._dragEnabled      => TRUE
      ._mouseOver         => FALSE
      ._mouseClick      => FALSE
      ._mouseDrag         => FALSE
      ._dragAxis         => DR._DRAGAXISCONSTRAINT._xy
      ._xDragOffsetFixedValue   => ._xAtDragTime - .TopLeftCornerX
      ._yDragOffsetFixedValue   => ._yAtDragTime - .TopLeftCornerY
      ._markedAsTemporaryNonDraggable   => FALSE
   end with 'THIS
end sub 'DRAGGABLERECTANGLE.InitializeDraggableRectangle()
destructor DRAGGABLERECTANGLE()
   DR.draggableFamillyMemberCount -= 1
   '
   select case DR.draggableFamillyMemberCount
      case is<=0
         erase DR.draggableFamillyArrayOfPtr
      case else
         swap DR.draggableFamillyArrayOfPtr(THIS._draggableFamillyCurrentMemberIndex), _
             DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr))
         redim preserve _
         DR.draggableFamillyArrayOfPtr(uBound(DR.draggableFamillyArrayOfPtr) - 1)
   end select 'DR.rectangleFamillyMemberCount
   '
      for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
        DR.draggableFamillyArrayOfPtr(index)->_draggableFamillyCurrentMemberIndex = index
      next index
      '
      THIS._draggableFamillyCurrentMemberIndex = -1
      '
   THIS.FinalizeRectangle()
end destructor 'DRAGGABLERECTANGLE default explicit destructor
sub DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
   if THIS._draggableFamillyCurrentMemberIndex=-1 then
      'index of object that should have been destroyed
      exit sub
   end if
   '
   dim as integer gmX, gmY, gmBtn1
   getMouse gmX, gmY, , gmBtn1
   '
   if cBool(gmBtn1<>+1) and THIS._mouseDrag=TRUE then
      ':TODO:
      'finalize DRAG to ensure correct final placement
   end if
   '
   if THIS._mouseDrag=TRUE   and _
      cBool(gmX>=0)      and _
      cBool(gmY>=0)      then
      select case THIS._dragAxis
         case DR._DRAGAXISCONSTRAINT._xOnly
            THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
         case DR._DRAGAXISCONSTRAINT._yOnly
            THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
         case DR._DRAGAXISCONSTRAINT._noAxis
            'no assignement required
         case else
            '_xy (+1)
            THIS.TopLeftCornerX = gmX - THIS._xDragOffsetFixedValue
            THIS.TopLeftCornerY = gmY - THIS._yDragOffsetFixedValue
      end select 'THIS._dragAxis
   end if
   '
   with THIS
      if gmX>=.TopLeftCornerX                  and _
         gmX<(.TopLeftCornerX + .RectangleWidth)   and _
         gmY>=.TopLeftCornerY                  and _
         gmY<(.TopLeftCornerY + .RectangleHeight)   then
         if ._mouseOver=FALSE then ._mouseOver = TRUE
         if (._clickEnabled and cBool(gmBtn1=+1)) then
            if ._mouseClick=FALSE then
               ._mouseClick = TRUE
               if not(._markedAsTemporaryNonDraggable) and _
                  ._dragEnabled                   and _
                  ._mouseDrag=FALSE                then
                     for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
                        if index<>._draggableFamillyCurrentMemberIndex then
                           DR.draggableFamillyArrayOfPtr(index)-> _
                                          _markedAsTemporaryNonDraggable = TRUE
                        else
                           THIS._markedAsTemporaryNonDraggable = FALSE
                        end if
                     next index
                  ._xAtDragTime = gmX
                  ._yAtDragTime = gmY
                  ._xDragOffsetFixedValue = ._xAtDragTime - .TopLeftCornerX
                  ._yDragOffsetFixedValue = ._yAtDragTime - .TopLeftCornerY
                  ._mouseDrag = TRUE
               end if
            end if
         else
            if ._mouseClick=TRUE then ._mouseClick   = FALSE
            if ._mouseDrag=TRUE then
               ._mouseDrag   = FALSE
                  for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
                     if index<>._draggableFamillyCurrentMemberIndex then
                        DR.draggableFamillyArrayOfPtr(index)-> _
                              _markedAsTemporaryNonDraggable = FALSE
                     end if
                  next index               
            end if
         end if
      else
         if ._mouseOver=TRUE      then   ._mouseOver      = FALSE
         if ._mouseClick=TRUE   then   ._mouseClick   = FALSE
         if ._mouseDrag=TRUE      then   
            ._mouseDrag      = FALSE
               for index as integer = 0 to uBound(DR.draggableFamillyArrayOfPtr)
                  if index<>._draggableFamillyCurrentMemberIndex then
                     DR.draggableFamillyArrayOfPtr(index)-> _
                           _markedAsTemporaryNonDraggable = FALSE
                  end if
               next index
         end if
      end if      
   end with 'THIS   
end sub 'DRAGGABLERECTANGLE.TestDraggableRectangleForMouse()
sub DRAGGABLERECTANGLE.DrawDraggableRectangle()
   if THIS._draggableFamillyCurrentMemberIndex=-1 then
      'index of object that should have been destroyed
      exit sub
   end if
   '
   THIS.TestDraggableRectangleForMouse()
   '
   line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _
       (THIS.TopLeftCornerX + THIS.RectangleWidth - 1, _
        THIS.TopLeftCornerY + THIS.RectangleHeight - 1), _
       THIS._bckgColor, _
       bf
   line (THIS.TopLeftCornerX, THIS.TopLeftCornerY)- _
       (THIS.TopLeftCornerX + THIS.RectangleWidth - 1, _
        THIS.TopLeftCornerY + THIS.RectangleHeight - 1), _
       rgb(090,090,120), _
       b
end sub 'DRAGGABLERECTANGLE.DrawDraggableRectangle()
sub DRAGGABLERECTANGLE.DrawSilentlyDraggableRectangle()
   if THIS._draggableFamillyCurrentMemberIndex=-1 then
      'index of object that should have been destroyed
      exit sub
   end if
   '
   THIS.TestDraggableRectangleForMouse()
   '
   line (THIS.TopLeftCornerX + 2, THIS.TopLeftCornerY + 2)- _
       (THIS.TopLeftCornerX + THIS.RectangleWidth - 1 - 2, _
        THIS.TopLeftCornerY + THIS.RectangleHeight - 1 - 2), _
       rgb(090,090,120), _
       b
end sub 'DRAGGABLERECTANGLE.DrawSilentlyDraggableRectangle()

'end of part1 -> please join part2 to this before compiling
Tourist Trap
Posts: 2958
Joined: Jun 02, 2015 16:24

Re: IceBoarding@freebasic

Post by Tourist Trap »

Part2, with the small corrections... thanks (working now on 1.06 win10, 64 as said above)

Code: Select all

'part2 -> to join to previous code

'                        ----------------------
'                        RESIZABLERECTANGLE UDT
'                        ----------------------
type RESIZABLERECTANGLE extends DRAGGABLERECTANGLE
   declare constructor()
   declare constructor(byval as long, _
                  byval as long)
   declare constructor(byval as long, _
                  byval as long, _
                  byval as long, _
                  byval as long)
   declare sub InitializeResizableRectangle()
   declare destructor()
   declare property TLCXanchored() as boolean
   declare property TLCX() as long
   declare property TLCX(byval as long)
   declare property TLCYanchored() as boolean
   declare property TLCY() as long
   declare property TLCY(byval as long)
   declare property TRCXanchored() as boolean
   declare property TRCX() as long
   declare property TRCX(byval as long)
   declare property TRCYanchored() as boolean
   declare property TRCY() as long
   declare property TRCY(byval as long)
   declare property BRCXanchored() as boolean
   declare property BRCX() as long
   declare property BRCX(byval as long)
   declare property BRCYanchored() as boolean
   declare property BRCY() as long
   declare property BRCY(byval as long)
   declare property BLCXanchored() as boolean
   declare property BLCX() as long
   declare property BLCX(byval as long)
   declare property BLCYanchored() as boolean
   declare property BLCY() as long
   declare property BLCY(byval as long)
   declare property Thckns() as long
   declare property Thckns(byval as long)
   declare property MouseOverAnyBoundary() as boolean
   declare property MouseClickAnyBoundary() as boolean
   declare property AnchorCount() as long
   declare sub ResetAnchorList()
   enum _ANCHORPOINT
      _allCorner         = +0
      _topLeftCorner      = +1
      _topRightCorner      = +2
      _bottomRightCorner   = +3
      _bottomLeftCorner   = +4
   end enum '_ANCHORPOINT
   declare function IsAnchor(byval as _ANCHORPOINT) as boolean
   declare sub AddAnchor(byval as _ANCHORPOINT=_ANCHORPOINT._allCorner)
   enum _FILLBOXOPTION
      _contour   = -1
      _fill      = -0
   end enum '_FILLBOXOPTION
   declare sub DrawThickContourElement overload(byval as long, _
                                     byval as long, _
                                     byval as long, _
                                     byval as long, _
                                     byval as ulong, _
                                     byval as _FILLBOXOPTION=_FILLBOXOPTION._fill)
   declare sub DrawThickContourElement(byval as XY, _
                              byval as XY, _
                              byval as ulong, _
                              byval as _FILLBOXOPTION=_FILLBOXOPTION._fill)
   declare sub RefreshAnchorArray()
   declare sub SetResizeTimeInitialOffset()
   declare sub TranslateCornerCoordinate(byval as long=0, _
                                byval as long=0)
   declare sub TestResizableRectangleForMouse()
   declare sub DrawResizableRectangle()
      as long            _borderThickness
      as boolean         _resizeEnabled
      as boolean         _resizeStarted
      as long            _xAtResizeTime
      as long            _yAtResizeTime
      as long            _tlcXoffsetAtResizeTime
      as long            _tlcYoffsetAtResizeTime
      as long            _trcXoffsetAtResizeTime
      as long            _trcYoffsetAtResizeTime
      as long            _brcXoffsetAtResizeTime
      as long            _brcYoffsetAtResizeTime
      as long            _blcXoffsetAtResizeTime
      as long            _blcYoffsetAtResizeTime
      as boolean         _mouseOverLeftBorder
      as boolean         _mouseOverTopBorder
      as boolean         _mouseOverRightBorder
      as boolean         _mouseOverBottomBorder
      as boolean         _mouseOverTopLeftCorner
      as boolean         _mouseOverTopRightCorner
      as boolean         _mouseOverBottomRightCorner
      as boolean         _mouseOverBottomLeftCorner
      as boolean         _mouseClickLeftBorder
      as boolean         _mouseClickTopBorder
      as boolean         _mouseClickRightBorder
      as boolean         _mouseClickBottomBorder
      as boolean         _mouseClickTopLeftCorner
      as boolean         _mouseClickTopRightCorner
      as boolean         _mouseClickBottomRightCorner
      as boolean         _mouseClickBottomLeftCorner
   private:
      as boolean         _mouseOverBoundary
      as boolean         _mouseClickBoundary
      as long            _anchorPointCount
      as _ANCHORPOINT      _anchorArray(any)
end type 'RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
type RSZ as RESIZABLERECTANGLE
'inheritance lineage:
'RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor RESIZABLERECTANGLE()
   BASE()
   THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE default explicit constructor
constructor RESIZABLERECTANGLE(byval MaxW   as long, _
                        byval MaxH   as long)
   BASE(MaxW,MaxH)
   THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE(valLNG, valLNG)
constructor RESIZABLERECTANGLE(byval TCLX   as long, _
                        byval TCLY   as long, _
                        byval Wid   as long, _
                        byval Hei   as long)
   BASE(TCLX,TCLY,Wid,Hei)
   THIS.InitializeResizableRectangle()
end constructor 'RESIZABLERECTANGLE(valLNG, valLNG, valLNG, valLNG)
sub RESIZABLERECTANGLE.InitializeResizableRectangle()
   with THIS
      ._borderThickness            => 6
      ._resizeEnabled               => TRUE
      ._mouseOverLeftBorder         => FALSE
      ._mouseOverTopBorder         => FALSE
      ._mouseOverRightBorder         => FALSE
      ._mouseOverBottomBorder         => FALSE
      ._mouseOverTopLeftCorner      => FALSE
      ._mouseOverTopRightCorner      => FALSE
      ._mouseOverBottomRightCorner   => FALSE
      ._mouseOverBottomLeftCorner      => FALSE
      ._mouseClickLeftBorder         => FALSE
      ._mouseClickTopBorder         => FALSE
      ._mouseClickRightBorder         => FALSE
      ._mouseClickBottomBorder      => FALSE
      ._mouseClickTopLeftCorner      => FALSE
      ._mouseClickTopRightCorner      => FALSE
      ._mouseClickBottomRightCorner   => FALSE
      ._mouseClickBottomLeftCorner   => FALSE
   end with 'THIS
   THIS._mouseOverBoundary            => FALSE
   THIS._mouseClickBoundary         => FALSE
   THIS.ResetAnchorList()
end sub 'RESIZABLERECTANGLE.InitializeResizableRectangle()
destructor RESIZABLERECTANGLE()
   '
end destructor 'RESIZABLERECTANGLE default explicit destructor
property RESIZABLERECTANGLE.TLCXanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)      or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.TLCXanchored
property RESIZABLERECTANGLE.TLCX() as long
   '---->
   return THIS.Xi
end property 'get LNG:=RESIZABLERECTANGLE.TLCX
property RESIZABLERECTANGLE.TLCX(byval SetValue as long)
   if not THIS.TLCXanchored   then
      THIS.W   = THIS.W - (SetValue - THIS.Xi + 1*sgn(SetValue - THIS.Xi))
      THIS.Xi = SetValue
   end if
end property 'set RESIZABLERECTANGLE.TLCX(valLNG)
property RESIZABLERECTANGLE.TLCYanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)      then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.TLCYanchored
property RESIZABLERECTANGLE.TLCY() as long
   '---->
   return THIS.Yi
end property 'get LNG:=RESIZABLERECTANGLE.TLCY
property RESIZABLERECTANGLE.TLCY(byval SetValue as long)
   if not THIS.TLCYanchored then
      THIS.H   = THIS.H - (SetValue - THIS.Yi + 1*sgn(SetValue - THIS.Xi))
      THIS.Yi = SetValue
   end if
end property 'set RESIZABLERECTANGLE.TLCY(valLNG)
property RESIZABLERECTANGLE.TRCXanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)      or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.TRCXanchored
property RESIZABLERECTANGLE.TRCX() as long
   '---->
   return THIS.Xf
end property 'get LNG:=RESIZABLERECTANGLE.TRCX
property RESIZABLERECTANGLE.TRCX(byval SetValue as long)
   if not THIS.TRCXanchored then
      THIS.Xf = SetValue
   end if
end property 'set RESIZABLERECTANGLE.TRCX(valLNG)
property RESIZABLERECTANGLE.TRCYanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)      then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.TRCYanchored
property RESIZABLERECTANGLE.TRCY() as long
   '---->
   return THIS.Yi
end property 'get LNG:=RESIZABLERECTANGLE.TRCY
property RESIZABLERECTANGLE.TRCY(byval SetValue as long)
   if not THIS.TRCYanchored then
      THIS.Yi = SetValue
   end if
end property 'set RESIZABLERECTANGLE.TRCY(valLNG)
property RESIZABLERECTANGLE.BRCXanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._topRightCorner)      or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.BRCXanchored
property RESIZABLERECTANGLE.BRCX() as long
   '---->
   return THIS.Xf
end property 'get LNG:=RESIZABLERECTANGLE.BRCX
property RESIZABLERECTANGLE.BRCX(byval SetValue as long)
   if not THIS.BRCXanchored then
      THIS.Xf = SetValue
   end if
end property 'set RESIZABLERECTANGLE.BRCX(valLNG)
property RESIZABLERECTANGLE.BRCYanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.BRCYanchored
property RESIZABLERECTANGLE.BRCY() as long
   '---->
   return THIS.Yf
end property 'get LNG:=RESIZABLERECTANGLE.BRCY
property RESIZABLERECTANGLE.BRCY(byval SetValue as long)
   if not THIS.BRCYanchored then
      THIS.Yf = SetValue
   end if
end property 'set RESIZABLERECTANGLE.BRCY(valLNG)
property RESIZABLERECTANGLE.BLCXanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._topLeftCorner)      or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.BLCXanchored
property RESIZABLERECTANGLE.BLCX() as long
   '---->
   return THIS.Xi
end property 'get LNG:=RESIZABLERECTANGLE.BLCX
property RESIZABLERECTANGLE.BLCX(byval SetValue as long)
   if not THIS.BLCXanchored then
      THIS.Xi = SetValue
   end if
end property 'set RESIZABLERECTANGLE.BLCX(valLNG)
property RESIZABLERECTANGLE.BLCYanchored() as boolean
   if THIS.IsAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._bottomRightCorner)   or _
      THIS.IsAnchor(RSZ._ANCHORPOINT._allCorner)         then
      '---->
      return TRUE
   else
      '---->
      return FALSE
   end if
end property 'get BOOL:=RESIZABLERECTANGLE.BLCYanchored
property RESIZABLERECTANGLE.BLCY() as long
   '---->
   return THIS.Yf
end property 'get LNG:=RESIZABLERECTANGLE.BLCY
property RESIZABLERECTANGLE.BLCY(byval SetValue as long)
   if not THIS.BLCYanchored then
      THIS.Yf = SetValue
   end if
end property 'set RESIZABLERECTANGLE.BLCY(valLNG)
property RESIZABLERECTANGLE.Thckns() as long
   '---->
   return THIS._borderThickness
end property 'get LNG:=RESIZABLERECTANGLE.Thckns
property RESIZABLERECTANGLE.Thckns(byval SetValue as long)
   THIS._borderThickness = SetValue
end property 'set RESIZABLERECTANGLE.Thckns(valLNG)
property RESIZABLERECTANGLE.MouseOverAnyBoundary() as boolean
   THIS._mouseOverBoundary = FALSE
   if    THIS._mouseOverLeftBorder         orElse _
      THIS._mouseOverTopBorder         orElse _
      THIS._mouseOverRightBorder         orElse _
      THIS._mouseOverBottomBorder         orElse _
      THIS._mouseOverTopLeftCorner      orElse _
      THIS._mouseOverTopRightCorner      orElse _
      THIS._mouseOverBottomRightCorner   orElse _
      THIS._mouseOverBottomLeftCorner      then
         THIS._mouseOverBoundary = TRUE
   end if
   '---->
   return THIS._mouseOverBoundary
end property 'BOOL:=RESIZABLERECTANGLE.MouseOverAnyBoundary
property RESIZABLERECTANGLE.MouseClickAnyBoundary() as boolean
   THIS._mouseClickBoundary = FALSE
   if    THIS._mouseClickLeftBorder         orElse _
      THIS._mouseClickTopBorder         orElse _
      THIS._mouseClickRightBorder         orElse _
      THIS._mouseClickBottomBorder      orElse _
      THIS._mouseClickTopLeftCorner      orElse _
      THIS._mouseClickTopRightCorner      orElse _
      THIS._mouseClickBottomRightCorner   orElse _
      THIS._mouseClickBottomLeftCorner   then   
         THIS._mouseClickBoundary = TRUE
   end if
   '---->
   return THIS._mouseClickBoundary
end property 'BOOL:=RESIZABLERECTANGLE.MouseClickAnyBoundary
property RESIZABLERECTANGLE.AnchorCount() as long
   THIS._anchorPointCount   = uBound(THIS._anchorArray) + 1
   '---->
   return THIS._anchorPointCount
end property 'LNG:=RESIZABLERECTANGLE.AnchorPointCount
sub RESIZABLERECTANGLE.ResetAnchorList()
   'free anchor array
   erase THIS._anchorArray
end sub 'RESIZABLERECTANGLE.ResetAnchorList()
function RESIZABLERECTANGLE.IsAnchor(byval Corner as RESIZABLERECTANGLE._ANCHORPOINT) as boolean
   'search anchor array for corner candidate
   for index as integer = 0 to (THIS.AnchorCount - 1)
      if THIS._anchorArray(index)=Corner then
         '--->
         return TRUE
      end if
   next index
   '---->
   return FALSE
end function 'BOOL:=RESIZABLERECTANGLE.IsAnchor(valRESIZABLERECTANGLE._ANCHORPOINT)
sub RESIZABLERECTANGLE.AddAnchor(byval CornerSet as RSZ._ANCHORPOINT=RSZ._ANCHORPOINT._allCorner)
   if CornerSet=RSZ._ANCHORPOINT._allCorner then
      THIS.ResetAnchorList()
      redim THIS._anchorArray(3)
      THIS._anchorArray(0)   = RSZ._ANCHORPOINT._topLeftCorner
      THIS._anchorArray(1)   = RSZ._ANCHORPOINT._topRightCorner
      THIS._anchorArray(2)   = RSZ._ANCHORPOINT._bottomRightCorner
      THIS._anchorArray(3)   = RSZ._ANCHORPOINT._bottomLeftCorner
   else
      if not THIS.IsAnchor(CornerSet) then
         redim preserve THIS._anchorArray(uBound(THIS._anchorArray) + 1)
         THIS._anchorArray(uBound(THIS._anchorArray)) = CornerSet
      end if
   end if   
end sub  'RESIZABLERECTANGLE.AddAnchor(valRESIZABLERECTANGLE_ANCHORPOINT[0])
sub RESIZABLERECTANGLE.DrawThickContourElement(byval X1 as long, _
                                    byval Y1 as long, _
                                    byval X2 as long, _
                                    byval Y2 as long, _
                                    byval C   as ulong, _
                                    byval FO   as RSZ._FILLBOXOPTION=RSZ._FILLBOXOPTION._fill)
   select case FO
      case RESIZABLERECTANGLE._FILLBOXOPTION._contour
         line (X1, Y1)-(X2, Y2), C, b
      case else '_FILLBOXOPTION._fill
         line (X1, Y1)-(X2, Y2), C, bf
   end select 'FO
end sub 'RESIZABLERECTANGLE.DrawThickContourElement({valLNG}*4,valULNG,val_FILLBOXOPTION[0])
sub RESIZABLERECTANGLE.DrawThickContourElement(byval XY1 as XY, _
                                    byval XY2 as XY, _
                                    byval C   as ulong, _
                                    byval FO   as RSZ._FILLBOXOPTION=RSZ._FILLBOXOPTION._fill)
   select case FO
      case RESIZABLERECTANGLE._FILLBOXOPTION._contour
         line (XY1._x, XY1._y)-(XY2._x, XY2._y), C, b
      case else '_FILLBOXOPTION._fill
         line (XY1._x, XY1._y)-(XY2._x, XY2._y), C, bf
   end select 'FO
end sub 'RESIZABLERECTANGLE.DrawThickContourElement({valXY}*2,valULNG,val_FILLBOXOPTION[0])
sub RESIZABLERECTANGLE.RefreshAnchorArray()
   if THIS._mouseClickLeftBorder then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
   elseif THIS._mouseClickTopBorder         then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
   elseif THIS._mouseClickRightBorder         then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
   elseif THIS._mouseClickBottomBorder         then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
      THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
   elseif THIS._mouseClickTopLeftCorner      then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomRightCorner)
   elseif THIS._mouseClickTopRightCorner      then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._bottomLeftCorner)
   elseif THIS._mouseClickBottomRightCorner   then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._topLeftCorner)
   elseif THIS._mouseClickBottomLeftCorner      then
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._topRightCorner)
   else
      THIS.ResetAnchorList()
      THIS.AddAnchor(RSZ._ANCHORPOINT._allCorner)
   end if
end sub 'RESIZABLERECTANGLE.RefreshAnchorArray()
sub RESIZABLERECTANGLE.SetResizeTimeInitialOffset()
   THIS._tlcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.TLCX
   THIS._tlcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.TLCY
   '
   THIS._trcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.TRCX
   THIS._trcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.TRCY
   '
   THIS._brcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.BRCX
   THIS._brcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.BRCY
   '
   THIS._blcXoffsetAtResizeTime = THIS._xAtResizeTime - THIS.BLCX
   THIS._blcYoffsetAtResizeTime = THIS._yAtResizeTime - THIS.BLCY
end sub '
sub RESIZABLERECTANGLE.TranslateCornerCoordinate(byval DX as long=0, _
                                     byval DY as long=0)
   THIS.TLCX   = THIS.TLCX + DX/2
   THIS.TLCY   = THIS.TLCY + DY/2
   '
   THIS.TRCX   = THIS.TRCX + DX/2
   THIS.TRCY   = THIS.TRCY + DY/2
   '
   THIS.BRCX   = THIS.BRCX + DX/2
   THIS.BRCY   = THIS.BRCY + DY/2
   '
   THIS.BLCX   = THIS.BLCX + DX/2
   THIS.BLCY   = THIS.BLCY + DY/2
end sub 'RESIZABLERECTANGLE.TranslateCornerCoordinate({valLNG[0]}*2)
sub RESIZABLERECTANGLE.TestResizableRectangleForMouse()
   dim as integer gmX, gmY, gmBtn1
   getMouse gmX, gmY, , gmBtn1
   '
   'set resize event status
   if THIS._resizeEnabled                                 and _
      THIS.MouseClickAnyBoundary                           and _
      cBool(THIS._xAtResizeTime<>gmX or THIS._yAtResizeTime<>gmY)   then
      if THIS._resizeStarted=FALSE then
         THIS._resizeStarted = TRUE
         THIS.RefreshAnchorArray()
      end if
   else
      if THIS._resizeStarted=TRUE then
         THIS._resizeStarted = FALSE
      end if
   end if
   if THIS._resizeStarted=TRUE then
      THIS.TranslateCornerCoordinate(gmX - THIS._xAtResizeTime, _
                              gmY - THIS._yAtResizeTime)
      THIS._xAtResizeTime = gmX
      THIS._yAtResizeTime = gmY
      exit sub
   end if
   'test mouse @LeftBorder
   if gmX>=THIS.Xi               and _
      gmX<=(THIS.Xi + THIS.Thckns)   and _
      gmY>=(THIS.Yi + THIS.Thckns)   and _
      gmY<=(THIS.Yf - THIS.Thckns)   then
      if THIS._mouseOverLeftBorder=FALSE then THIS._mouseOverLeftBorder = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickLeftBorder=FALSE then
            THIS._mouseClickLeftBorder = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickLeftBorder=TRUE then THIS._mouseClickLeftBorder = FALSE
      end if
   else
      if THIS._mouseOverLeftBorder=TRUE then THIS._mouseOverLeftBorder = FALSE
      if THIS._mouseClickLeftBorder=TRUE then THIS._mouseClickLeftBorder = FALSE   
   end if
   'test mouse @TopBorder
   if gmX>=(THIS.Xi + THIS.Thckns)   and _
      gmX<=(THIS.Xf - THIS.Thckns)   and _
      gmY>=THIS.Yi               and _
      gmY<=(THIS.Yi + THIS.Thckns)   then
      if THIS._mouseOverTopBorder=FALSE then THIS._mouseOverTopBorder = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickTopBorder=FALSE then
            THIS._mouseClickTopBorder = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickTopBorder=TRUE then THIS._mouseClickTopBorder = FALSE
      end if
   else
      if THIS._mouseOverTopBorder=TRUE then THIS._mouseOverTopBorder = FALSE
      if THIS._mouseClickTopBorder=TRUE then THIS._mouseClickTopBorder = FALSE
   end if
   'test mouse @RightBorder
   if gmX>=(THIS.Xf - THIS.Thckns)   and _
      gmX<=THIS.Xf               and _
      gmY>=(THIS.Yi + THIS.Thckns)   and _
      gmY<=(THIS.Yf - THIS.Thckns)   then
      if THIS._mouseOverRightBorder=FALSE then THIS._mouseOverRightBorder = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickRightBorder=FALSE then
            THIS._mouseClickRightBorder = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickRightBorder=TRUE then THIS._mouseClickRightBorder = FALSE
      end if
   else
      if THIS._mouseOverRightBorder=TRUE then THIS._mouseOverRightBorder = FALSE
      if THIS._mouseClickRightBorder=TRUE then THIS._mouseClickRightBorder = FALSE   
   end if
   'test mouse @BottomBorder
   if gmX>=(THIS.Xi + THIS.Thckns)   and _
      gmX<=(THIS.Xf - THIS.Thckns)   and _
      gmY>=(THIS.Yf - THIS.Thckns)   and _
      gmY<=THIS.Yf               then
      if THIS._mouseOverBottomBorder=FALSE then THIS._mouseOverBottomBorder = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickBottomBorder=FALSE then
            THIS._mouseClickBottomBorder = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickBottomBorder=TRUE then THIS._mouseClickBottomBorder = FALSE
      end if
   else
      if THIS._mouseOverBottomBorder=TRUE then THIS._mouseOverBottomBorder = FALSE
      if THIS._mouseClickBottomBorder=TRUE then THIS._mouseClickBottomBorder = FALSE   
   end if
   'test mouse @TopLeftCorner
   if gmX>=THIS.Xi               and _
      gmX<(THIS.Xi + THIS.Thckns)   and _
      gmY>=THIS.Yi               and _
      gmY<(THIS.Yi + THIS.Thckns)   then
      if THIS._mouseOverTopLeftCorner=FALSE then THIS._mouseOverTopLeftCorner = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickTopLeftCorner=FALSE then
            THIS._mouseClickTopLeftCorner = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickTopLeftCorner=TRUE then THIS._mouseClickTopLeftCorner = FALSE
      end if
   else
      if THIS._mouseOverTopLeftCorner=TRUE then THIS._mouseOverTopLeftCorner = FALSE   
      if THIS._mouseClickTopLeftCorner=TRUE then THIS._mouseClickTopLeftCorner = FALSE   
   end if
   'test mouse @TopRightCorner
   if gmX>(THIS.Xf - THIS.Thckns)   and _
      gmX<=THIS.Xf               and _
      gmY>=THIS.Yi               and _
      gmY<(THIS.Yi + THIS.Thckns)   then
      if THIS._mouseOverTopRightCorner=FALSE then THIS._mouseOverTopRightCorner = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickTopRightCorner=FALSE then
            THIS._mouseClickTopRightCorner = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickTopRightCorner=TRUE then THIS._mouseClickTopRightCorner = FALSE
      end if
   else
      if THIS._mouseOverTopRightCorner=TRUE then THIS._mouseOverTopRightCorner = FALSE
      if THIS._mouseClickTopRightCorner=TRUE then THIS._mouseClickTopRightCorner = FALSE   
   end if
   'test mouse @BottomRightCorner
   if gmX>(THIS.Xf - THIS.Thckns)   and _
      gmX<=THIS.Xf               and _
      gmY>(THIS.Yf - THIS.Thckns)   and _
      gmY<=THIS.Yf                then
      if THIS._mouseOverBottomRightCorner=FALSE then THIS._mouseOverBottomRightCorner = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickBottomRightCorner=FALSE then
            THIS._mouseClickBottomRightCorner = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickBottomRightCorner=TRUE then THIS._mouseClickBottomRightCorner = FALSE
      end if
   else
      if THIS._mouseOverBottomRightCorner=TRUE then THIS._mouseOverBottomRightCorner = FALSE
      if THIS._mouseClickBottomRightCorner=TRUE then THIS._mouseClickBottomRightCorner = FALSE 
   end if
   'test mouse @BottomLeftCorner
   if gmX>=THIS.Xi               and _
      gmX<(THIS.Xi + THIS.Thckns)   and _
      gmY>(THIS.Yf - THIS.Thckns)   and _
      gmY<=THIS.Yf                then
      if THIS._mouseOverBottomLeftCorner=FALSE then THIS._mouseOverBottomLeftCorner = TRUE
      if gmBtn1=+1 then
         if THIS._mouseClickBottomLeftCorner=FALSE then
            THIS._mouseClickBottomLeftCorner = TRUE
            if not THIS._resizeStarted then
               THIS._xAtResizeTime = gmX
               THIS._yAtResizeTime = gmY
               THIS.SetResizeTimeInitialOffset()
            end if
         end if
      else
         if THIS._mouseClickBottomLeftCorner=TRUE then THIS._mouseClickBottomLeftCorner = FALSE
      end if
   else
      if THIS._mouseOverBottomLeftCorner=TRUE then THIS._mouseOverBottomLeftCorner = FALSE
      if THIS._mouseClickBottomLeftCorner=TRUE then THIS._mouseClickBottomLeftCorner = FALSE   
   end if
   '
end sub 'RESIZABLERECTANGLE.TestResizableRectangleForMouse()
sub RESIZABLERECTANGLE.DrawResizableRectangle()
   THIS.TestResizableRectangleForMouse()
   '
   'preamble->
   /'
      ? "resize started="; THIS._resizeStarted
      ? "TLCXanchored="; THIS.TLCXanchored
      ? "TLCYanchored="; THIS.TLCYanchored
      ? "TRCXanchored="; THIS.TRCXanchored
      ? "TRCYanchored="; THIS.TRCYanchored
      ? "BRCXanchored="; THIS.BRCXanchored
      ? "BRCYanchored="; THIS.BRCYanchored
      ? "BLCXanchored="; THIS.BLCXanchored
      ? "BLCYanchored="; THIS.BLCYanchored
      THIS.DrawRectangle()
      if THIS._dragEnabled then
         THIS.DrawDraggableRectangle()
      end if
   '/
   '
   'draw left border
   if THIS._mouseClickLeftBorder then
      THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yi + THIS.Thckns)), _
                      XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                      rgb(220,100,100), _
                      RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverLeftBorder then
      THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yi + THIS.Thckns)), _
                      XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                      rgb(200,120,150), _
                      RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY(THIS.Xi, (THIS.Yi + THIS.Thckns)), _
                         XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw top border
   if THIS._mouseClickTopBorder then
      THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi - 1), _
                            XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverTopBorder then
      THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi - 1), _
                            XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), THIS.Yi), _
                         XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw right border
   if THIS._mouseClickRightBorder then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            XY(THIS.Xf + 1, (THIS.Yf - THIS.Thckns)), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverRightBorder then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            XY(THIS.Xf + 1, (THIS.Yf - THIS.Thckns)), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                         XY(THIS.Xf, (THIS.Yf - THIS.Thckns)), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw bottom border
   if THIS._mouseClickBottomBorder then
      THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                            XY((THIS.Xf - THIS.Thckns), THIS.Yf + 1), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverBottomBorder then
      THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                            XY((THIS.Xf - THIS.Thckns), THIS.Yf + 1), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY((THIS.Xi + THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                         XY((THIS.Xf - THIS.Thckns), THIS.Yf), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw top left corner
   if THIS._mouseClickTopLeftCorner then
      THIS.DrawThickContourElement(XY(THIS.Xi - 2, THIS.Yi - 2), _
                            XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverTopLeftCorner then
      THIS.DrawThickContourElement(XY(THIS.Xi - 2, THIS.Yi - 2), _
                            XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY(THIS.Xi - 1, THIS.Yi - 1), _
                         XY((THIS.Xi + THIS.Thckns), (THIS.Yi + THIS.Thckns)), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw top right corner
   if THIS._mouseClickTopRightCorner then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 2), _
                            XY(THIS.Xf   + 2, (THIS.Yi + THIS.Thckns)), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverTopRightCorner then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 2), _
                            XY(THIS.Xf   + 2, (THIS.Yi + THIS.Thckns)), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), THIS.Yi - 1), _
                         XY(THIS.Xf   + 1, (THIS.Yi + THIS.Thckns)), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw bottom right corner
   if THIS._mouseClickBottomRightCorner then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                            XY(THIS.Xf   + 2, THIS.Yf + 2), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverBottomRightCorner then
      THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                            XY(THIS.Xf   + 2, THIS.Yf + 2), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY((THIS.Xf - THIS.Thckns), (THIS.Yf - THIS.Thckns)), _
                         XY(THIS.Xf   + 1, THIS.Yf + 1), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
   'draw bottom left corner
   if THIS._mouseClickBottomLeftCorner then
      THIS.DrawThickContourElement(XY(THIS.Xi - 2, (THIS.Yf - THIS.Thckns)), _
                            XY((THIS.Xi + THIS.Thckns), THIS.Yf + 2), _
                            rgb(220,100,100), _
                            RSZ._FILLBOXOPTION._fill)
   elseif THIS._mouseOverBottomLeftCorner then
      THIS.DrawThickContourElement(XY(THIS.Xi - 2, (THIS.Yf - THIS.Thckns)), _
                            XY((THIS.Xi + THIS.Thckns), THIS.Yf + 2), _
                            rgb(200,120,150), _
                            RSZ._FILLBOXOPTION._fill)
   end if
   THIS.DrawThickContourElement(XY(THIS.Xi - 1, (THIS.Yf - THIS.Thckns)), _
                         XY((THIS.Xi + THIS.Thckns), THIS.Yf + 1), _
                         rgb(180,180,130), _
                         RSZ._FILLBOXOPTION._contour)
end sub 'RESIZABLERECTANGLE.DrawResizableRectangle()


type ICEBENCH extends RESIZABLERECTANGLE
   declare constructor()
   /'
:TODO:
   declare constructor(byval as long, _
                  byval as long)
   declare constructor(byval as long, _
                  byval as long, _
                  byval as long, _
                  byval as long)
   '/
   declare sub InitializeIceBench()
   declare destructor()
   declare property AdjustedTitleToFitBar() as string
   declare property DraggableZoneXi() as long
   declare property DraggableZoneYi() as long
   declare property DraggableZoneXf() as long
   declare property DraggableZoneYf() as long
   declare property HasBoardFocus() as boolean
   declare property HasBoardFocus(byval as boolean)
   declare property DragEnabled() as boolean
   declare property DragEnabled(byval as boolean)
   declare property ResizeEnabled() as boolean
   declare property ResizeEnabled(byval as boolean)
   declare sub TestIceBenchForMouse()
   declare sub DrawIceBench()
      as long            _zOrder
      as string         _titleBarTitle
      as RECTANGLE      _draggableZone
      as long            _draggableZoneXi
      as long            _draggableZoneYi
      as long            _draggableZoneXf
      as long            _draggableZoneYf
      as boolean         _hasBoardFocus
      as boolean         _mouseOverVisibleArea
      as boolean         _mouseClickVisibleArea
      as boolean         _mouseOverDraggableSubFrame
      as boolean         _mouseClickDraggableSubFrame
      as boolean         _mouseOverResizableBoundary
      as boolean         _mouseClickResizableBoundary
end type 'ICEBENCH <-- RESIZABLERECTANGLE <-- DRAGGABLERECTANGLE <-- RECTANGLE <-- OBJECT
constructor ICEBENCH()
   BASE()
   '
   THIS.InitializeIceBench()
end constructor 'ICEBENCH default explicit constructor
sub ICEBENCH.InitializeIceBench()
   with THIS
      ._titleBarTitle               => ".."
      .DragEnabled               => FALSE
      .ResizeEnabled               => TRUE
      ._draggableZone.Xi            => .DraggableZoneXi
      ._draggableZone.Yi            => .DraggableZoneYi
      ._draggableZone.Xf            => .DraggableZoneXf
      ._draggableZone.Yf            => .DraggableZoneYf
      ._hasBoardFocus               => FALSE
      ._mouseOverVisibleArea         => FALSE
      ._mouseClickVisibleArea         => FALSE
      ._mouseOverDraggableSubFrame   => FALSE
      ._mouseClickDraggableSubFrame   => FALSE
      ._mouseOverResizableBoundary   => FALSE
      ._mouseClickResizableBoundary   => FALSE
      .Thckns                     => 12
   end with 'THIS
end sub 'ICEBENCH.InitializeIceBench()
destructor ICEBENCH()
   '
end destructor 'ICEBENCH default explicit destructor
property ICEBENCH.AdjustedTitleToFitBar() as string
   dim as string   stringResult
   stringResult = THIS._titleBarTitle
   '---->
   return stringResult
end property 'get STR:=ICEBENCH.AdjustedTitleToFitBar
property ICEBENCH.DraggableZoneXi() as long
   THIS._draggableZoneXi = THIS.Xi + THIS.Thckns
   '---->
   return THIS._draggableZoneXi
end property 'get LNG:=ICEBENCH.DraggableZoneXi
property ICEBENCH.DraggableZoneYi() as long
   THIS._draggableZoneYi = THIS.Yi + THIS.Thckns
   '---->
   return THIS._draggableZoneYi
end property 'get LNG:=ICEBENCH.DraggableZoneYi
property ICEBENCH.DraggableZoneXf() as long
   THIS._draggableZoneXf = THIS.Xf - THIS.Thckns
   '---->
   return THIS._draggableZoneXf
end property 'get LNG:=ICEBENCH.DraggableZoneXf
property ICEBENCH.DraggableZoneYf as long
   THIS._draggableZoneYf = THIS.Yi + THIS.Thckns + 24
   '---->
   return THIS._draggableZoneYf
end property 'get LNG:=ICEBENCH.DraggableZoneYf
property ICEBENCH.HasBoardFocus() as boolean
   '---->
   return THIS._hasBoardFocus
end property 'get BOOL:=ICEBENCH.HasBoardFocus
property ICEBENCH.HasBoardFocus(byval SetValue as boolean)
   THIS._hasBoardFocus = SetValue
end property 'set ICEBENCH.HasBoardFocus(valBOOL)
property ICEBENCH.DragEnabled() as boolean
   if not THIS.HasBoardFocus then THIS._dragEnabled = FALSE
   '---->
   return THIS._dragEnabled
end property 'get BOOL:=ICEBENCH.DragEnabled
property ICEBENCH.DragEnabled(byval SetValue as boolean)
   THIS._dragEnabled = SetValue
end property 'set ICEBENCH.DragEnabled(valBOOL)
property ICEBENCH.ResizeEnabled() as boolean
   if not THIS.HasBoardFocus then THIS._resizeEnabled = FALSE
   '---->
   return THIS._resizeEnabled
end property 'get BOOL:=ICEBENCH.ResizeEnabled
property ICEBENCH.ResizeEnabled(byval SetValue as boolean)
   THIS._resizeEnabled = SetValue
end property 'set ICEBENCH.ResizeEnabled(valBOOL)
sub ICEBENCH.TestIceBenchForMouse()
   dim as integer gmX, gmY, gmBtn1
   getMouse gmX, gmY, , gmBtn1
   '
   if gmX>THIS.DraggableZoneXi      and _
      gmX<THIS.DraggableZoneXf      and _
      gmY>THIS.DraggableZoneYi      and _
      gmY<THIS.DraggableZoneYf      then
      if THIS.DragEnabled=FALSE then THIS.DragEnabled = TRUE
   else
      if THIS.DragEnabled=TRUE then THIS.DragEnabled = FALSE
   end if
   '
end sub 'ICEBENCH.TestIceBenchForMouse()
sub ICEBENCH.DrawIceBench()
   THIS.TestIceBenchForMouse()
   if THIS.DragEnabled then
      'just calling the prop.
   end if
   if THIS.ResizeEnabled then
      'just calling the prop.
   end if
   if THIS._resizeStarted then
      THIS.DragEnabled = FALSE
   end if
   if not THIS.HasBoardFocus then
      THIS.Thckns = 0
      'dev.note: check for redundancy! late addition:
      THIS.ResizeEnabled = FALSE
   else
      THIS.Thckns = 10
      'dev.note: check for redundancy! late addition:
      THIS.ResizeEnabled = TRUE
   end if
   '
   THIS.DrawRectangleAsFlatBackground()
   THIS.DrawSilentlyDraggableRectangle()
   THIS._draggableZone.Xi            = THIS.DraggableZoneXi
   THIS._draggableZone.Yi            = THIS.DraggableZoneYi
   THIS._draggableZone.Xf            = THIS.DraggableZoneXf
   THIS._draggableZone.Yf            = THIS.DraggableZoneYf
   THIS._draggableZone.DrawRectangle()
   THIS.DrawResizableRectangle()
   draw string (THIS._draggableZone.Xi + 4, _
             THIS._draggableZone.Yi + 4), _
             THIS.AdjustedTitleToFitBar, _
             rgb(200,200,155)
end sub 'ICEBENCH.DrawIceBench()


'                                  ------------
'                                  ICEBOARD UDT
'                                  ------------
type ICEBOARD
   declare constructor()
   declare destructor()
   declare property IBenchCount() as long
   declare property IBenchZOrderAtIndex(Index as long) as long
   declare function IsIceBenchRegistred(byval as ICEBENCH ptr) as boolean
   declare sub AddIceBench(byval as ICEBENCH ptr)
   declare function GrantFocusToIceBenchAtIndex(byval as long) as long
   declare function TestIBenchArrayForMouseOverAtIndex(byval as long, _
                                          byval as long, _
                                          byval as long) _
                                          as boolean
   declare sub TestIceBoardForMouse()
   declare sub DrawIceBoard()
      as long            _benchCount
      as ICEBENCH ptr      _arrayOfIBenchPtr(any)
end type 'ICEBOARD
constructor ICEBOARD()
   dim as integer deskTopW
   dim as integer deskTopH
   screenInfo deskTopW, deskTopH
   '
   screenRes desktopW, _
             desktopH, _
             32, _
             1, _
             fb.GFX_SHAPED_WINDOW
   color ,rgba(255,0,255,0)   
end constructor 'ICEBOARD default explicit constructor
destructor ICEBOARD()
   '
end destructor 'ICEBOARD default explicit detructor
property ICEBOARD.IBenchCount() as long
   '---->
   return ( (uBound(THIS._arrayOfIBenchPtr) - _
           lBound(THIS._arrayOfIBenchPtr)) + _
           1 )
end property 'get LNG:=ICEBOARD.IBenchCount()
property ICEBOARD.IBenchZOrderAtIndex(Index as long) as long
   if Index>=lBound(THIS._arrayOfIBenchPtr) and _
      Index<=uBound(THIS._arrayOfIBenchPtr) then
         '---->
         return THIS._arrayOfIBenchPtr(Index)->_zOrder
   else
         '---->
         return -1
   end if
end property 'get LNG:=IBenchZOrderAtIndex(LNG_INDEX)
function ICEBOARD.IsIceBenchRegistred(byval IBenchPtr as ICEBENCH ptr) as boolean
   dim as boolean   returnValue   => FALSE
   for index as long = 0 to uBound(THIS._arrayOfIBenchPtr)
      if IBenchPtr=THIS._arrayOfIBenchPtr(index) then
         returnValue = TRUE
         exit for
      end if
   next index
   '---->
   return returnValue
end function 'BOOL:=ICEBOARD.IsIceBenchRegistred(valICEBENCH_PTR)
sub ICEBOARD.AddIceBench(byval IBenchPtr as ICEBENCH ptr)
   if THIS.IsIceBenchRegistred(IBenchPtr)   or _
      cBool(IBenchPtr=0)               then
      exit sub
   else
      if uBound(THIS._arrayOfIBenchPtr)>=0 then
         THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->HasBoardFocus = _
                                                            FALSE
      end if
      redim preserve THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr) + 1)
      THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr)) => IBenchPtr
      THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->HasBoardFocus => TRUE
      THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_zOrder => _
                                       uBound(THIS._arrayOfIBenchPtr)
   end if
end sub 'ICEBOARD.AddIceBench(valICEBENCH_PTR)
function ICEBOARD.GrantFocusToIceBenchAtIndex(byval Index as long) as long
   if Index>=lBound(THIS._arrayOfIBenchPtr) and _
      Index<=uBound(THIS._arrayOfIBenchPtr) then
         THIS._arrayOfIBenchPtr(Index)->HasBoardFocus = TRUE
         if Index<>uBound(THIS._arrayOfIBenchPtr) then
            swap THIS._arrayOfIBenchPtr(Index), _
                THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))   
            for localIndex as long = 0 to uBound(THIS._arrayOfIBenchPtr) - 1
               THIS._arrayOfIBenchPtr(Index)->HasBoardFocus = FALSE
         THIS._arrayOfIBenchPtr(Index)->_dragEnabled = FALSE
         THIS._arrayOfIBenchPtr(Index)->_resizeStarted = FALSE
            next localIndex
         end if
         'todo:
         'rearrange according to previous zOrder (not just swap)
         '---->
         return +0
   else
         '---->
         return +1
   end if
end function 'LNG:=ICEBOARD.GrantFocusToIceBenchAtIndex(valLNG)
function ICEBOARD.TestIBenchArrayForMouseOverAtIndex(byval Index   as long, _
                                        byval GMX      as long, _
                                        byval GMY      as long) _
                                                   as boolean
   dim as boolean   returnValue   => FALSE
   if GMX>=THIS._arrayOfIBenchPtr(Index)->Xi   and _
      GMX<=THIS._arrayOfIBenchPtr(Index)->Xf   and _
      GMY>=THIS._arrayOfIBenchPtr(Index)->Yi   and _
      GMY<=THIS._arrayOfIBenchPtr(Index)->Yf   then
       ? Index
       ? THIS._arrayOfIBenchPtr(0)->HasBoardFocus
       ? THIS._arrayOfIBenchPtr(1)->HasBoardFocus
      ? THIS._arrayOfIBenchPtr(Index)->Xi
      ? THIS._arrayOfIBenchPtr(Index)->Xf
      ? THIS._arrayOfIBenchPtr(Index)->Yi
      ? THIS._arrayOfIBenchPtr(Index)->Yf
      returnValue = TRUE
   end if
   '---->
   return returnValue
end function 'BOOL:=ICEBOARD.TestIBenchArrayForMouseOverAtIndex({valLNG}*3)
sub ICEBOARD.TestIceBoardForMouse()
   '
   'dev.note:
   'this below to prevent sudden weird partial focus flip (partial) while moving
   'unfortunately that doesn't work...
   if THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_dragEnabled      or _
      THIS._arrayOfIBenchPtr(uBound(THIS._arrayOfIBenchPtr))->_resizeStarted   then
         exit sub
   end if
   '
   dim as integer gmX, gmY, gmBtn1
   getMouse gmX, gmY, , gmBtn1   
   '
   dim as long   index
   for index = (THIS.IBenchCount - 1) to 0 step -1
      if THIS.TestIBenchArrayForMouseOverAtIndex(index, gmX, gmY) then exit for
   next index
   if index<0 then
      exit sub
   else
      if gmBtn1=+1 then
         THIS.GrantFocusToIceBenchAtIndex(index)
      end if
   end if
end sub 'ICEBOARD.TestIceBoardForMouse()
sub ICEBOARD.DrawIceBoard()
   dim as integer deskTopW
   dim as integer deskTopH
   screenInfo deskTopW, deskTopH
   'non-priotary todo: check&update if desktop changed
   '
   for row as long = 200\8 to (desktopH - 200)\8
      for col as long = 200\8 to (desktopW - 200)\8
         locate row, col, 0 : ? ".";
      next col
   next row
   locate (desktopH - 200)\8, 200\8 :    ? "development version"
   '
   THIS.TestIceBoardForMouse()
   '
   for index as long = 0 to uBound(THIS._arrayOfIBenchPtr)
      THIS._arrayOfIBenchPtr(index)->DrawIceBench()
   next index
end sub 'ICEBOARD.DrawIceBoard()


'----------------------------------------------
'------------------------------------------MAIN

'--------------------------------INITIALIZATION
'screenRes 600,480,32
'color rgb(0,220,220), rgb(080,080,120)

dim as ICEBENCH   testIBench1
dim as ICEBENCH   testIBench2
dim as ICEBENCH   testIBench3

dim as ICEBOARD   testIBoard
testIBoard.AddIceBench(@testIBench1)
testIBoard.AddIceBench(@testIBench2)
testIBoard.AddIceBench(@testIBench3)


'-------------------------------------MAIN LOOP
color rgb(100,220,220)
do
   screenLock
      cls
         testIBoard.DrawIceBoard()
   screenUnlock

   sleep 25
loop until inkey=chr(27)

'----------------------------------FINALIZATION

sleep
end 0


'[you've reached the end of the freebasic file]
Post Reply