Indigo Rose Software
  #1  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
Sample: Splitter Framework

Splitter Framework:
Thanks to Tig and Dermot for helping me with the code and optimization.

How To Use:
1. Add these function calls to the following Page Events
On Show
Code:
--Sets the splitter cursor to the NS/WE arrows
InitSplitters()


-- SetSplitterMinMax(Name of the Splitter, 
--					Minimum X or Y value for  for the Left or Top pane,
--					Minimum  X or Y value for the Right or Bottom pane)

-- Example that will stop splitter movement 
-- 10 pixels from either side of the page.
-- SetSplitterMinMax("vsplit_Vertical", 10, 10)
On Size
Code:
DoSplitter_OnSize(e_WindowWidth, e_WindowHeight, e_PageWidth, e_PageHeight, e_Type);
On Mouse Button
Code:
DoSplitter_MouseButton(e_Type, e_X, e_Y);
On Mouse Move
Code:
DoSplitter_MouseMove(e_X, e_Y);
2. Copy this code to your Global Functions
Code:
--[[********************************************************]]--
--[[********************************************************]]--
--[[****************** SPLITTER FRAMEWORK ******************]]--
--[[********************************************************]]--
--[[********************************************************]]--

--[[********************************************************]]--
--[[                   SPLITTER EVENTS                      ]]--
--[[********************************************************]]--
function On_Splitter_Move(m_sSplitterName, m_nDiff)
	-- use this function for your own actions
	--  when a splitter is moved.
	

end


--[[********************************************************]]--
--[[     Set up a table to reference the objects in AMS     ]]--
--[[********************************************************]]--
tbObjectType = {}
tbObjectType[OBJECT_BUTTON] = Button;
tbObjectType[OBJECT_LABEL] = Label;
tbObjectType[OBJECT_PARAGRAPH] = Paragraph;
tbObjectType[OBJECT_IMAGE] = Image;
tbObjectType[OBJECT_FLASH] = Flash;
tbObjectType[OBJECT_VIDEO] = Video;
tbObjectType[OBJECT_WEB] = Web;
tbObjectType[OBJECT_INPUT] = Input;
tbObjectType[OBJECT_HOTSPOT] = Hotspot;
tbObjectType[OBJECT_LISTBOX] = ListBox;
tbObjectType[OBJECT_COMBOBOX] = ComboBox;
tbObjectType[OBJECT_PROGRESS] = Progress;
tbObjectType[OBJECT_TREE] = Tree;
tbObjectType[OBJECT_PLUGIN] = Plugin;


-- Function to initialize the splitters with code to change the cursors
-- also initiates the table that holds the ratios for sizing objects
function InitSplitters()
	m_nCursor = nil;
	m_tblObjectData = {};
	tblObjects = Page.EnumerateObjects();
	if tblObjects then
		for index, sObject in tblObjects do
			if String.Left(sObject, 7) == "vsplit_" or String.Left(sObject, 7) == "hsplit_" then
				--add the script to the object to set the cursor to NS/EW arrows
				m_sScript = Page.GetObjectScript(sObject, "ON ENTER");
				if String.Left(sObject, 1) == "v" then
					m_sScript = "m_nCursor = 32644\r\n"..m_sScript;
				else
					m_sScript = "m_nCursor = 32645\r\n"..m_sScript;				
				end
				m_sScript = Page.SetObjectScript(sObject, "ON ENTER", m_sScript);
				m_sScript = Page.GetObjectScript(sObject, "ON LEAVE");
				m_sScript = [[if not m_blnMoveSplitter then
				                 m_nCursor = nil;
				              end]].."\r\n"..m_sScript;
				              
				m_sScript = Page.SetObjectScript(sObject, "ON LEAVE", m_sScript);
			end
			-- set the ratio data in a table
			local Object = tbObjectType[Page.GetObjectType(sObject)];
			local m_XR = Object.GetPos(sObject).X / Page.GetSize().Width;
			local m_YR = Object.GetPos(sObject).Y / Page.GetSize().Height;
			local m_WR = Object.GetSize(sObject).Width / Page.GetSize().Width;
			local m_HR = Object.GetSize(sObject).Height / Page.GetSize().Height;
			m_tblObjectData[Table.Count(m_tblObjectData) + 1] = {Name=sObject, PosXR=m_XR , PosYR=m_YR, SizeWR=m_WR, SizeHR=m_HR};
		end
	end
end


-- Function to set the splitters Min and Max X/Y values
function SetSplitterMinMax(sSplitter, nMin, nMax)
	if m_tbMinMax == nil then
		m_tbMinMax = {};
	end
	m_tbMinMax[Table.Count(m_tbMinMax) + 1] = {Splitter=sSplitter, Min=nMin, Max=nMax};
end


-- Function to tell whether a point is in a given
-- objects rectangle
function IsInRect(m_nX, m_nY, m_tblPos, m_tblSize)
	local bReturn = false;
	if (m_nX >= m_tblPos.X) and (m_nX <= m_tblPos.X + m_tblSize.Width) then
		if (m_nY >= m_tblPos.Y) and (m_nY <= m_tblPos.Y + m_tblSize.Height) then
			bReturn = true;
		end
	end
	return bReturn;
end


-- Function to set the ratios of the objects on the page.  These
-- values are used in positioning the objects and splitters in a Resize
function SetNewRatios()
	local z;
	for z=1, Table.Count(m_tblObjectData) do
			local SplitterObject = tbObjectType[Page.GetObjectType(m_tblObjectData[z].Name)];
			m_tblObjectData[z].PosXR = SplitterObject.GetPos(m_tblObjectData[z].Name).X / Page.GetSize().Width  
			m_tblObjectData[z].PosYR = SplitterObject.GetPos(m_tblObjectData[z].Name).Y / Page.GetSize().Height
			m_tblObjectData[z].SizeWR = SplitterObject.GetSize(m_tblObjectData[z].Name).Width / Page.GetSize().Width  
			m_tblObjectData[z].SizeHR = SplitterObject.GetSize(m_tblObjectData[z].Name).Height / Page.GetSize().Height
	end
end


-- Function to detect when a splitter has been selected
function DoSplitter_MouseButton(e_Type, e_X, e_Y)
	local bReturn = false;
	local Object = nil;
	
	if e_Type == LEFT_BUTTON_DOWN then
		-- Get the objects on the page
		tblObjects = Page.EnumerateObjects();
		--if there are objects, and we are not currently moving a splitter
		if tblObjects and not m_blnMoveSplitter then
			for index, sObject in tblObjects do
				--if the object is a splitter
				if (String.Left(sObject, 7) == "vsplit_") or (String.Left(sObject, 7) == "hsplit_") then
					--get the object type
					Object = tbObjectType[Page.GetObjectType(sObject)];
					--if our mouse pointer is inside of a splitters rectangle
					if IsInRect(e_X, e_Y,  Object.GetPos(sObject), Object.GetSize(sObject)) then
						if not m_blnMoveSplitter then
							--Get the initial Original Positions and Size
							m_nOrigX = Object.GetPos(sObject).X;
							m_nOrigY = Object.GetPos(sObject).Y;
							m_nSplitterHeight = Object.GetSize(sObject).Height;
							m_nSplitterWidth = Object.GetSize(sObject).Width;
						end
						--set the variables to allow the splitter to move
						m_blnMoveSplitter = true;
						m_sCurrentSplitter = sObject;
						m_XOffset = e_X - Object.GetPos(sObject).X;
						m_YOffset = e_Y - Object.GetPos(sObject).Y;
						break;
					end
				end
			end
		end
	else
		-- we're no longer on a splitter, reset the variables that 
		-- allow the splitter to be moved.
		m_nCursor = nil;
		m_blnMoveSplitter = false;
		SetNewRatios();
	end
end


-- Function to move the splitter
function DoSplitter_MouseMove(e_X, e_Y)
	local z;
	
	if m_nCursor then
		-- if we are over a splitter, set the cursor appropriately
		local hCursor = DLL.CallFunction(_SystemFolder.."\\User32.dll", "LoadCursorA", "0, "..m_nCursor, DLL_RETURN_TYPE_LONG, DLL_CALL_STDCALL);
		local retVal = DLL.CallFunction(_SystemFolder.."\\User32.dll", "SetCursor", hCursor, DLL_RETURN_TYPE_LONG, DLL_CALL_STDCALL);
	end
	
	if not System.IsKeyDown(1) then
		m_blnMoveSplitter = false;
	end
	
	m_nDiff = 0;
	
	if m_blnMoveSplitter then
		-- set the application to *NOT* redraw for smoother
		-- object movement
		Application.SetRedraw(false)
		-- get the current splitter's objecy type
		local SplitterObject = tbObjectType[Page.GetObjectType(m_sCurrentSplitter)];
		
		m_blnAllowMove = true;
		if String.Left(m_sCurrentSplitter, 7) == "vsplit_" then
			-- it's a vertical splitter
			for z=1, Table.Count(m_tbMinMax) do
				if m_sCurrentSplitter == m_tbMinMax[z].Splitter then
					-- if we'ver reached the min or mac X value, do not allow
					-- the splitter to be moved
					if e_X - m_XOffset <= m_tbMinMax[z].Min or e_X + (SplitterObject.GetSize(m_sCurrentSplitter).Width - m_XOffset) >= Page.GetSize().Width - m_tbMinMax[z].Max then
						m_blnAllowMove = false;
					end
					break;
				end
			end
			if m_blnAllowMove then
				-- Set the splitters position
				SplitterObject.SetPos(m_sCurrentSplitter, e_X - m_XOffset, SplitterObject.GetPos(m_sCurrentSplitter).Y);
				-- get the value of pixels the splitter was moved
				m_nDiff = e_X - (m_nOrigX  + m_XOffset);
				for index, sObject in tblObjects do
					Object = tbObjectType[Page.GetObjectType(sObject)];
					-- if the object hasn't been designated to *NOT* move
					if String.Left(sObject, 7) ~= "nomove_" then
						-- if the object isn't another vertical splitter
						if String.Left(sObject, 7) ~= "vsplit_" then
							-- Move the objects
							if (Object.GetPos(sObject).X <= m_nOrigX) and ((Object.GetPos(sObject).Y >= m_nOrigY) and (Object.GetPos(sObject).Y <= m_nOrigY + m_nSplitterHeight)) then
								if Object.GetSize(sObject).Width + m_nDiff <=0 then
									Object.SetSize(sObject, 0, Object.GetSize(sObject).Height);
									Application.SetRedraw(true);
									Object.SetVisible(sObject, false);
									Page.Redraw();
									Application.SetRedraw(false);
								else
									Object.SetVisible(sObject, true);
									Object.SetSize(sObject, Object.GetSize(sObject).Width + m_nDiff, Object.GetSize(sObject).Height);
								end
							elseif (Object.GetPos(sObject).X >= m_nOrigX) and ((Object.GetPos(sObject).Y >= m_nOrigY) and (Object.GetPos(sObject).Y <= m_nOrigY + m_nSplitterHeight)) then
								if Object.IsVisible(sObject) then
									Object.SetPos(sObject, Object.GetPos(sObject).X + m_nDiff, Object.GetPos(sObject).Y );
									Object.SetSize(sObject, Object.GetSize(sObject).Width - m_nDiff, Object.GetSize(sObject).Height);
								end
							end
						end
					end
				end
				-- set our splitters origanal position to the new position
				m_nOrigX = m_nOrigX + m_nDiff;
			end
		elseif String.Left(m_sCurrentSplitter, 7) == "hsplit_" then
			-- it's a Horizontal Splitter
			for z=1, Table.Count(m_tbMinMax) do
				if m_sCurrentSplitter == m_tbMinMax[z].Splitter then
					-- if we'ver reached the min or mac X value, do not allow
					-- the splitter to be moved
					if e_Y - m_YOffset <= m_tbMinMax[z].Min or e_Y + (SplitterObject.GetSize(m_sCurrentSplitter).Height - m_YOffset) >= Page.GetSize().Height - m_tbMinMax[z].Max then
						m_blnAllowMove = false;
					end
					break;
				end
			end
			if m_blnAllowMove then
				-- Set the splitters position			
				SplitterObject.SetPos(m_sCurrentSplitter, SplitterObject.GetPos(m_sCurrentSplitter).X, e_Y - m_YOffset);
				-- get the value of pixels the splitter was moved
				m_nDiff = e_Y - (m_nOrigY  + m_YOffset);
				for index, sObject in tblObjects do
					Object = tbObjectType[Page.GetObjectType(sObject)];
					-- if the object hasn't been designated to *NOT* move
					if String.Left(sObject, 7) ~= "nomove_" then
						-- if the object isn't another horizontal splitter
						if String.Left(sObject, 7) ~= "hsplit_" then
							-- Move the objects
							if (Object.GetPos(sObject).Y <= m_nOrigY) and ((Object.GetPos(sObject).X >= m_nOrigX) and (Object.GetPos(sObject).X <= m_nOrigX + m_nSplitterWidth)) then
								if Object.GetSize(sObject).Height + m_nDiff <= 0 then
									Object.SetSize(sObject, Object.GetSize(sObject).Width, 0);
									Application.SetRedraw(true);
									Object.SetVisible(sObject, false);
									Page.Redraw();
									Application.SetRedraw(false);
								else
									Object.SetVisible(sObject, true);
									Object.SetSize(sObject, Object.GetSize(sObject).Width, Object.GetSize(sObject).Height + m_nDiff);
								end 
							elseif (Object.GetPos(sObject).Y >= m_nOrigY) and ((Object.GetPos(sObject).X >= m_nOrigX) and (Object.GetPos(sObject).X <= m_nOrigX + m_nSplitterWidth)) then
								if Object.IsVisible(sObject) then
									Object.SetPos(sObject, Object.GetPos(sObject).X, Object.GetPos(sObject).Y + m_nDiff );
									Object.SetSize(sObject, Object.GetSize(sObject).Width, Object.GetSize(sObject).Height - m_nDiff);
								end
							end
						end
					end
				end
				-- set our splitters origanal position to the new position
				m_nOrigY = m_nOrigY + m_nDiff;
			end
		end

		-- fire event our own event
		On_Splitter_Move(m_sCurrentSplitter, m_nDiff);
		
		-- Allow the app to redraw
		Application.SetRedraw(true);
		-- Force redraw
		Page.Redraw();
	end
end


-- Function to Resize all objects and splitters
function DoSplitter_OnSize(e_WindowWidth, e_WindowHeight, e_PageWidth, e_PageHeight, e_Type)
	if m_tblObjectData then
		-- set redraw to false for smoother object moving
		Application.SetRedraw(false)
		for z=1, Table.Count(m_tblObjectData) do
			m_Object = tbObjectType[Page.GetObjectType(m_tblObjectData[z].Name)];
			-- if it's a vertical splitter, don't change its width
			if String.Left(m_tblObjectData[z].Name, 7) == "vsplit_" then
				m_Object.SetSize(m_tblObjectData[z].Name, m_Object.GetSize(m_tblObjectData[z].Name).Width, e_PageHeight * m_tblObjectData[z].SizeHR)
			elseif String.Left(m_tblObjectData[z].Name, 7) == "hsplit_" then
				-- if it's a horizontal splitter, don't change its height
				m_Object.SetSize(m_tblObjectData[z].Name, e_PageWidth * m_tblObjectData[z].SizeWR, m_Object.GetSize(m_tblObjectData[z].Name).Height)
			else
				-- change the objects dimensions proportionately
				m_Object.SetSize(m_tblObjectData[z].Name, e_PageWidth * m_tblObjectData[z].SizeWR, e_PageHeight * m_tblObjectData[z].SizeHR)
			end
			-- Set the objects position proportionately
			m_Object.SetPos(m_tblObjectData[z].Name, e_PageWidth * m_tblObjectData[z].PosXR, e_PageHeight * m_tblObjectData[z].PosYR)
		end
		-- redraw!
		Application.SetRedraw(true)
	end
end

3. Add splitters to your page. The splitters can be any object that has an ON ENTER and ON LEAVE event. Rename your objects to the following convention:

The first 7 characters in the name of an Object that is a Vertical Splitter must be: "vsplit_"
The first 7 characters in the name of an Object that is a Horizontal Splitter must be: "hsplit_"

Once you've named your objects this way, the framework will automatically make them moveable splitters, nothing more to do.

4. Place the objects you want in each pane on the page, size them accordingly.

5. If you have an object that you do not want to be moved by the splitters, rename it to the following convention:

The first 7 characters in the name of an Object that should not be moved by a splitter must be: "nomove_"

6. In the Global Functions there is a code generated event named On_Splitter_Move. Use this event to manually move objects that are not handled correctly by the framework for your design.


Guidelines:
Just like in Ghost Busters, its important to not cross the streams, err splitters. The framework is designed to move/resize any object that falls within a splitters plain of movement. If another splitter is in that area, it too will be moved/resized.


Have Fun!!
Attached Files
File Type: apz SplitterFrameWork_Example.apz (41.1 KB, 628 views)
Reply With Quote
  #2  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
Here are the available splitter configs when using a Horizontal splitter across the page
Attached Images
File Type: jpg Splitter1.jpg (2.2 KB, 86 views)
File Type: jpg Splitter2.jpg (2.4 KB, 63 views)
File Type: jpg Splitter3.jpg (2.4 KB, 44 views)
File Type: jpg Splitter4.jpg (2.6 KB, 58 views)
Reply With Quote
  #3  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
Here are the available splitter configs when using a Vertical splitter across the page
Attached Images
File Type: jpg Splitter5.jpg (2.1 KB, 46 views)
File Type: jpg Splitter6.jpg (2.3 KB, 33 views)
File Type: jpg Splitter7.jpg (2.5 KB, 29 views)
File Type: jpg Splitter8.jpg (2.7 KB, 48 views)
Reply With Quote
  #4  
Old 02-17-2006
rhosk's Avatar
rhosk rhosk is offline
Indigo Rose Customer
 
Join Date: Aug 2003
Location: Maine, USA
Posts: 1,692
Whoa, this definitely opens all kinds of new doors
__________________
Regards,

-Ron

Music | Video | Pictures
Reply With Quote
  #5  
Old 02-17-2006
Brett's Avatar
Brett Brett is offline
Indigo Rose Staff Member
 
Join Date: Jan 2000
Posts: 2,001
OK, Worm. You are officially more knowledgeable about AMS60 than I am! Good job!
Reply With Quote
  #6  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
Thanks... but you're very modest.
Reply With Quote
  #7  
Old 02-17-2006
Lorne's Avatar
Lorne Lorne is offline
Indigo Rose Staff Member
 
Join Date: Feb 2001
Location: Indigo Rose Software
Posts: 2,588
That makes two of us! My hats off to you, Worm.
__________________
--[[ Indigo Rose Software Developer ]]
Reply With Quote
  #8  
Old 02-17-2006
TJ_Tigger's Avatar
TJ_Tigger TJ_Tigger is offline
Indigo Rose Customer
 
Join Date: Sep 2002
Location: Sol 3
Posts: 3,188
Great work Worm.
__________________
TJ-Tigger
"A common mistake that people make when trying to design something completely foolproof was to underestimate the ingenuity of complete fools."
"Draco dormiens nunquam titillandus."
Map of IR Forum Users - IR Project CodeViewer - Online Help - TiggTV - QuizEngine
Reply With Quote
  #9  
Old 02-17-2006
Corey's Avatar
Corey Corey is offline
Registered User
 
Join Date: Aug 2002
Posts: 9,746
Amazening.
Reply With Quote
  #10  
Old 02-17-2006
Intrigued's Avatar
Intrigued Intrigued is offline
Indigo Rose Customer
 
Join Date: Dec 2003
Location: Location! Location!
Posts: 6,058
You dun Spliter-r-dun Worm'inator.

__________________
Intrigued
www.amsuser.com
Reply With Quote
  #11  
Old 02-17-2006
Eagle Eagle is offline
Indigo Rose Customer
 
Join Date: Mar 2005
Location: WA 'wait a while' - Australia
Posts: 827
Great Idea, Fantastic Result Worm

you da man
Reply With Quote
  #12  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
I really wanted to make it so you could throw an app together with splitters very quickly. Being able to throw a control on the page and have it automatically taken care of was the goal. I think its as close as I can get it. Its kinda cool that you don't have to write any code at all, simply name the objects accordingly, and you're off.
Reply With Quote
  #13  
Old 02-17-2006
Intrigued's Avatar
Intrigued Intrigued is offline
Indigo Rose Customer
 
Join Date: Dec 2003
Location: Location! Location!
Posts: 6,058
OH! And for what it is worth... Worm must get one of them two (2) hour lunch breaks that I have heard about.

@Worm
__________________
Intrigued
www.amsuser.com
Reply With Quote
  #14  
Old 02-17-2006
Worm Worm is offline
Indigo Rose Customer
 
Join Date: Jul 2002
Location: USA
Posts: 3,937
Hee, this things been cooking for a couple weeks now. Took a while to bring it to a boil.
Reply With Quote
  #15  
Old 02-17-2006
Intrigued's Avatar
Intrigued Intrigued is offline
Indigo Rose Customer
 
Join Date: Dec 2003
Location: Location! Location!
Posts: 6,058
Worm, I fired it up and it looks great, no doubt. How about performance issues, run into any yet?
__________________
Intrigued
www.amsuser.com
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dependency Module: Microsoft .NET Framework 2.0 Adam Setup Factory 8.0 Examples 30 13 Hours Ago 09:27 PM
Dependency Module: Microsoft .NET Framework 1.1 Darryl Setup Factory 8.0 Examples 12 06-10-2008 03:26 AM
Microsoft .NET Framework 1.1 Jason Pate Setup Factory 7.0 Discussion 2 12-23-2004 02:04 PM
My Native Indian Flute sample... Intrigued General Chat 9 10-28-2004 09:32 PM
New Sample Project Available Darryl Setup Factory 7.0 Discussion 1 09-27-2004 05:00 PM


All times are GMT -6. The time now is 10:30 AM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Copyright © 2000 - 2009 Indigo Rose Corporation. All rights reserved.
Indigo Rose Software