How to change colour of form object

I have 2 rectangles with a solid fill and I am trying to get my procedure to change the colour of them

Not working and I have no idea what I am doing wrong.

let newColour = "00FF00"
let oldColour = "B6FFE1"

selectobjects objectinfo("color") = oldColour

changeobjects "color",newColour

This should be:

let newColour = htmlrgb("00FF00")
let oldColour = htmlrgb("B6FFE1")

If I do this:

displaydata (objectinfo("color","theColourBox"))

I get this:

streamtypedÅËÑ@ÑÑÑaNSColorÑÑNSObjectÖÑcÑffffÜ

I was expecting, and wanting, a hex color value that I could use to set the colour of other objects. Is that possible?

You should probably take a look at this page to learn about how Panorama handles colors.

Or, you can skip to exactly what you want, which is here:

So your code needs to be:

displaydata htmlrgbstr(objectinfo("color","theColourBox"))

But really, check out the first topic, then this won’t be so mysterious. And it’s only a page or two.

I’m still struggling with manipulating colours on a form.

I have form with two coloured rectangles. One is black and the other is named “theColourBox” with a colour of “B6FFE1”

Here is the code I am using:

openform "Colour Picker Form"
selectobjects objectinfo("name") = "theColourBox"
message htmlrgbstr(objectinfo("color"))

Here is the really strange part of this:

If I send that box to the back and then run the code, the message says “000000"

If I send that box to the front is says “B6FFE1” as it should.

Why does the object stacking order make any difference?

Sounds like both rectangles are named theColourBox.

Nope. One was freshly dragged in from the Object Library. I have triple checked to make sure that there are no other items at all in the the form.

The same thing happens in a brand new database with brand new rectangles but pasted in code.

Please try this:

openform "Colour Picker Form"
message htmlrgbstr(objectinfo("color"),"theColourBox")

If that doesn’t work, I suggest looking at the form blueprint. You may find there is something else in your form you aren’t seeing. Use the Entire Form option to see all of the objects in your form.

If I send the colored rectangle to front the code shows the correct hexadecimal color value. If I send that rectangle to the back the code shows the color as “000000”, which is wrong.

I don’t see any anomalies in the blueprint at all. Do you want me to paste it in here?

Yes, please post the blueprint.

Here it is:

/*
<BLUEPRINT_FORM>
	<FORM>Colour Picker Form</FORM>
	<DATABASE>3theFirstDB</DATABASE>
</BLUEPRINT_FORM>
*/

local targetFormName
define targetFormName,"Colour Picker Form"

makenewform targetFormName
openform targetFormName

restoreFormFromBlueprint:

/* <BLUEPRINT_FORM_PROPERTIES> */

setformoptions "",targetFormName,
	"ALTERNATINGBACKGROUNDCOLORS",-1,
	"BACKGROUNDCOLOR",htmlrgb("FFFFFF"),
	"EVENTCODE","",
	"EVENTCODESYNTAXERROR","",
	"MAXIMUMHEIGHT",0.00,
	"MAXIMUMWIDTH",0.00,
	"MINIMUMHEIGHT",0.00,
	"MINIMUMWIDTH",0.00,
	"NOTES","",
	"REPORTCOLUMNDIRECTION","Down",
	"REPORTCOLUMNS","Automatic",
	"TABORDER","Natural",
	"TAG","",
	"USESERVERFORLOOKUP",0,
	"VARIABLETYPE","FileGlobal",
	"VIEWASLISTBACKGROUNDCOLORS","",
	"VIEWASLISTGRIDSTYLE","Solid",
	"VIEWASLISTHILIGHTCOLOR","",
	"VIEWMODE","Individual Pages"

/* </BLUEPRINT_FORM_PROPERTIES> */

makeFormObjectsFromBluePrint:

/* <BLUEPRINT_FORM_OBJECTS> */

newformobject "RectangleShapeObject",
	"rectangle",rectanglesize(51, 87, 300, 663),
	"color",htmlrgb("4287FC"),
	"name","theColourBox",
	"Tags","",
	"$ShadowOpacity","75%",
	"Opacity","100 %",
	"$ShadowDepth","6",
	"$ShadowBlur","10",
	"$Stroke","None",
	"Procedure","",
	"Expandable","0",
	"$Fill","Solid",
	"LineWidth","0.5 px",
	"$ShadowAngle","45°",
	"$DropShadow","0",
	"ExpandShrink","0",
	"Locked","0",
	"$ToolTip","",
	"$ShadowBrightness","0%"

newformobject "RectangleShapeObject",
	"rectangle",rectanglesize(237, 224, 183, 182),
	"color",htmlrgb("000000"),
	"name","",
	"Tags","",
	"$ShadowOpacity","75%",
	"Opacity","100 %",
	"$ShadowDepth","6",
	"$ShadowBlur","10",
	"$Stroke","Solid",
	"Procedure","",
	"Expandable","0",
	"$Fill","Solid",
	"LineWidth","1 px",
	"$ShadowAngle","45°",
	"$DropShadow","0",
	"ExpandShrink","0",
	"Locked","0",
	"$ToolTip","",
	"$ShadowBrightness","0%"

selectnoobjects

/* </BLUEPRINT_FORM_OBJECTS> */

Here is how to reproduce the problem:
Make a new database and save it as whatever
Make a new form
Add a rectangle and give it a name like “name”
Give it some color other than black
Add another rectangle without a name
Make a procedure with this code:

openform “Form_A"
selectobjects objectinfo(“name”) = “name”
message htmlrgbstr(objectinfo(“color"))

Open the form and bring the named rectangle to the front
Run the procedure and get the correct hex colour
Back to the form, send the coloured rectangle to the back.
Run the procedure and get the incorrect hex color.

I took your blueprint code and made a clone of your form in a test database on my computer. I then tried the code that I asked you to try.

message htmlrgbstr(objectinfo("color"),"theColourBox")

This didn’t work, because the code has a syntax error! So, I fixed that, here is the correct version.

message htmlrgbstr(objectinfo("color","theColourBox"))

This works correctly, no matter what the order of the objects is.

So next I tried what you were doing.

selectobjects objectinfo("name") = "theColourBox"
message htmlrgbstr(objectinfo("color"))

You are correct, there is a bug. The result changes depending on the front to back order of the objects. But this is kind of a minor bug, since the simpler method does work, and that is the recommended method now.

Finally, I tried changing the color of the object with this code, which I think was your original objective.

selectobjects objectinfo("name") = "theColourBox"
changeobjects "color",htmlrgb("0000FF")

This code worked correctly no matter what the order of the objects was.

Finally, I tried this simpler code for changing the color of this item. If you just want to change one object, this one line is all you need in Panorama X.

changeobject "theColourBox","color",htmlrgb("FF00FF")

This code also worked no matter what the front-to-back order of the objects was. In fact, it will also work without the htmlrgb( function, like this:

changeobject "theColourBox","color","FF00FF"

Jim,

My overall intent was to write a procedures would let the user select a new color to be used as a highlight color in all forms in all open databases. I tried my procedure with partial success. In some of the forms it worked properly but others it would leave the old color untouched.

In forms that were unsuccessful I made doubly sure that the color to be changed was the same color used everywhere else.

In trying to figure out what the root cause was I came across the stacking order issue.

I overcame the issue by copying rectangles that worked for changing in my procedure and replacing the ones that didn’t work. They all work now but I still wonder why they didn’t work originally.

Thanks for your help.

Are all of the objects in question going to be rectangles? If so, I would recommend instead that you use the Image Display pure color option. It would be much simpler for you, you can just change a variable and do a showvariables and every object will change to the new color.

This is something I ended up playing with and not exactly what is being discussed here but kind of related. Maybe someone might get an idea or two from the code.

This will allow a user to change the background color of the current window’s form or all the forms in the database. This will include View=As-List forms even though their background does not show. Also, if the All Forms option is chosen, all forms will change whether or not they are currently open.

If windowinfo("","Type") notcontains "Form"
    AlertSheet "Can only be used in a form window!"
    stop
Endif
let allTheForms=dbinfo("forms","")
let theColor=""
AlertSheet "Change just this form's background
color or all forms in this database?","Buttons","This Form,All Forms,Cancel" 
If info("dialogtrigger")="Cancel"
    stop
elseif info("dialogtrigger")="This Form"
    colorwheel "",theColor
    if info("dialogtrigger") contains "Cancel"
        stop
    endif
    setformoptions "", info(“formname”), "BackGroundColor", theColor
else
    colorwheel "",theColor
    if info("dialogtrigger") contains "Cancel"
        stop
    endif
    looparray allTheForms,cr(),element,item
        setformoptions "", element, "BackGroundColor", theColor
    endloop
endif

Thanks for that code snippet, Gary. Always interesting to see how others handle achieving tasks.

I have been using rectangles as highlights in most of my forms. I just wanted to be able to change all of them at once, by procedure. It sort of works but it seems as though “all rectangles are not created equal”.
This is what I used to go through all my forms:

/* Procedure Name: 	Colour Changer
Database: 			Control
Keyboard Shortcut:	none
Created: 			March 26, 2020
Modified: 			2020-03-27, 4:13 PM
Called From: 		none
Inputs:				colour from apple colorwheel
Outputs:			none
Variable use:
	Fileglobals:	none
	Globals: 		none
	Permanents:		none
Procedures Called:	none
DBs Referenced:		all open databases
Description:		This procedure will go through all forms in all 
					opendatabases and change the highlight colour
					to a new colour as chosen by the user.
-----------------------------------------------------------------------------*/
executeapplescript |||set volume with output muted|||

local newColour,oldColour

openform "Colour Picker Form"
oldColour = objectinfo("color","theColourBox")	//oldColour is binary

Restart:
colorwheel "",newColour
	if info("dialogtrigger") contains "Cancel"
		executeapplescript |||set volume without output muted|||
		STOP
	endif
selectobjects
	(objectinfo("class") = "RectangleShapeObject" or
	objectinfo("class") = "RoundedRectangleShapeObject") and 
	objectinfo("color") = oldColour
changeobjects "color",newColour	// test out the newColour

alertmodal {If you want to proceed with changing} + cr() + {ALL FORMS to use this new colour press "Go_For_It".}
+ cr() + cr() + {If you want to select a} + cr() + {different colour press "Pick_New_Colour".} + 
cr() + cr() + {If you want to stop this operation press "Cancel".} + cr(),
		"Button","Pick_New_Colour","Button","Cancel","Button","Go_For_It"

if info("dialogtrigger") = "Cancel"
	executeapplescript |||set volume without output muted|||
	changeobject "theColourBox","color",oldColour
endif

if info("dialogtrigger") = "Pick_New_Colour"
	changeobject "theColourBox","color",oldColour
	goto Restart
endif

if info("dialogtrigger") = "Go_For_It"
	let allDBs = info("files")
		looparray allDBs,cr(),theDatabaseName
			if theDatabaseName ≠ "PDF_Maker"
				setactivedatabase theDatabaseName
				let allForms = dbinfo("forms",theDatabaseName)
				looparray allForms,cr(),formName
					openform formName
					selectobjects
						(objectinfo("class") = "RectangleShapeObject"
							or
						objectinfo("class") = "RoundedRectangleShapeObject")
							and 
						objectinfo("color") = oldColour
						changeobjects "color",newColour	// apply newColour
					//closewindow
					selectnoobjects
				endloop
			endif
		endloop
endif
executeapplescript |||set volume without output muted|||
nsnotify "All forms have been colour changed"

I am going to mess around with Jim’s suggestion about using Image Display Objects. Sounds interesting.

This is how my typical forms look:
Form Colour Use

I may just end up naming those highlight boxes so that selecting them would be easier.

I like the way you made provisions to turn off that annoying ping when selecting a color from the color wheel. I noticed this ping even occurs if you use an AppleScript to open the color picker. It is annoying. I did notice one minor place to simplify your code when selecting the rectangles.

Instead of:

selectobjects
	(objectinfo("class") = "RectangleShapeObject" or
	objectinfo("class") = "RoundedRectangleShapeObject") and 
	objectinfo("color") = oldColour

You could use:

selectobjects
	(objectinfo("class") contains "RectangleShapeObject" and 
	objectinfo("color") = oldColour

Since both objects will contain that string there is no need to separate them. I agree that it might be best to name the desired rectangles with a common name which can easily be done once you have all the ones desired selected using this (substituting the name you want to use):

changeobjects "name", "HighlightColor"

This should make things more reliable in the future by selecting by name instead of color.

The other alternative that Jim suggested is to use Image Display Objects instead of rectangles. This option requires more labor to set up and would use a variable for the color formula. Once set up, all of the objects could be changed by simply changing the value of the variable and using showvariables to force an update. The shortcoming with this method is your only option for a rounded rectangle version is to set the boarder to Rounded and that leaves a visible boarder with hardly any rounding of the rectangle.

I would have used Jim’s suggestion if it weren’t for one form that has rounded corners on it’s highlight item. I really love the look of that form and don’t want to change it at all, except for maybe the colour.

Thanks for your input, Gary and Jim. It is so much appreciated.