Help adding custom toolbar icons to add-in tools
Copy link to clipboard
Copied
I have three simple javascript add-ins that I have used successfully for years. I would like to add custom icons to them, but am having problems. When I use this code, I get an error saying "this.importIcon is not a function". I am a cut-and-paste Javascripter so likely I'm making a simple mistake. Could anyone tell me what it is and how to fix it? Thank you!
this.importIcon("myIconCW", "/D/J/CAD Standards/Stamps/Acrobat tools/clockwise.jpg", 0);
this.importIcon("myIconCCW", "/D/J/CAD Standards/Stamps/Acrobat tools/counterclockwise.jpg", 0);
this.importIcon("myIconFlat", "/D/J/CAD Standards/Stamps/Acrobat tools/flatten.jpg", 0);
var cwIcon = util.iconStreamFromIcon(this.getIcon("myIconCW"));
var ccwIcon = util.iconStreamFromIcon(this.getIcon("myIconCCW"));
var flatIcon = util.iconStreamFromIcon(this.getIcon("myIconFlat"));
app.addToolButton({cName: "MyFlattenButton",
cLabel: "Flatten",
oIcon: flatIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "flattenPages();"
});
app.addToolButton({cName: "MyCWButton",
cLabel: "CW",
oIcon: cwIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "rotatepage(this.pageNum,90);"
});
app.addToolButton({cName: "MyCCWButton",
cLabel: "CCW",
oIcon: ccwIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "rotatepage(this.pageNum,270);"
});
function rotatepage(pageno,degrees) {
var rotateangle = this.getPageRotation(pageno);
var newangle = (rotateangle + degrees) % 360;
this.setPageRotations(pageno,pageno,newangle);
return 0;
}
Copy link to clipboard
Copied
Have you opened a document?
Copy link to clipboard
Copied
Yes, the error message occurs when I open a document.
Copy link to clipboard
Copied
That's because the code executes before the document is opened, so the "this" keyword doesn't point to it at that point. You can't do it like that. Instead, you should either create a new blank document and use the reference to it to import the icons, or convert the icons to strings and embed that directly in your code.
Copy link to clipboard
Copied
Ok, thank you for that insight.
How do I convert the icons to strings and embed them?
Copy link to clipboard
Copied
Ok, I have changed the code to the following, which opens a blank doc and then tries to import the icons. But I get an error "GeneralError: Operation failed.
App.addToolButton:26:Folder-Level:App:newbuttons2.js"
when I open up a doc in Acrobat.
Here is the revised code:
var cwIcon;
var ccwIcon;
var flatIcon;
// Create a document
app.beginPriv();
var myDoc = app.newDoc();
// import icon (20x20 pixels) from the file specified
myDoc.importIcon("mycwIcon", "/D/J/CAD Standards/Stamps/Acrobat tools/2clockwise.jpg", 0);
myDoc.importIcon("myccwIcon", "/D/J/CAD Standards/Stamps/Acrobat tools/2counterclockwise.jpg", 0);
myDoc.importIcon("myflatIcon", "/D/J/CAD Standards/Stamps/Acrobat tools/2flatten.jpg", 0);
// convert the icon to a stream.
cwIcon = util.iconStreamFromIcon(myDoc.getIcon("mycwIcon"));
ccwIcon = util.iconStreamFromIcon(myDoc.getIcon("myccwIcon"));
flatIcon = util.iconStreamFromIcon(myDoc.getIcon("myflatIcon"));
// close the doc now that we have grabbed the icon stream
myDoc.closeDoc(true);
app.endPriv();
app.addToolButton({
cName: "MyFlattenButton",
cLabel: "Flatten",
oIcon: flatIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "flattenPages();"
});
app.addToolButton({
cName: "MyCWButton",
cLabel: "CW",
oIcon: cwIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "rotatepage(this.pageNum,90);"
});
app.addToolButton({
cName: "MyCCWButton",
cLabel: "CCW",
oIcon: ccwIcon,
cEnable: "event.rc = (app.doc != null);",
cExec: "rotatepage(this.pageNum,270);"
});
function rotatepage(pageno,degrees) {
var rotateangle = this.getPageRotation(pageno);
var newangle = (rotateangle + degrees) % 360;
this.setPageRotations(pageno,pageno,newangle);
return 0;
}
Copy link to clipboard
Copied
Works fine for me... Did you make sure the file paths are correct?
Copy link to clipboard
Copied
Yes, paths are correct.
I saw in a post somewhere that Acrobat can be picky about the format of the icon file. They are 20x20 JPG files, downsampled in Corel PhotoPaint from 50x50 and saved at 100% quality. Is there anything else I should check? I have attached the files here in case anyone has something to check them.
It seems from the error message, though, that the error is occurring when the "App.addToolButton" function is called. Is that correct? That would be after the icon files have loaded, right? What could be the problem there?
Copy link to clipboard
Copied
I used your icons and it worked fine as well, although the rotation ones are pretty small and hard to make out. Check your JS preferences and make sure that "Enable menu items..." is enabled. Also check the Security (Enhanced) prefs., and disable everything there.
Copy link to clipboard
Copied
Just tried those setting changes -- see attached files for my current preferences in Javascript and Enhanced Security. Still the same error message. Very strange. Does the "26" mean something in the error message? Line 26 of the script is " cExec: "flattenPages();" " which worked before I changed the icons.
Thank you for the help!
Copy link to clipboard
Copied
Change this:
"event.rc = (app.doc != null);",
To this:
"event.rc = (event.target != null);"
Copy link to clipboard
Copied
Tried it, but same error message.
Copy link to clipboard
Copied
Line 26 is the last line of the "app.addToolButton" call. It means it failed on this function. Acrobat JS doen't report errors inside a single function call. It's the whole thing.
Have you checked the actual icon size being returned from "util.iconStreamFromIcon"? Although an excessive size shouldn't cause an error, it just doesn't draw the icon. I always hard code the icon data rather than relying on loading images, especially with Acrobat DC which destroys image quality.
Here's your clockwise icon hard coded.
var str2CWImgData = "fffffffffffffffffffffffffffefefefffdfffefffdfefefffefdfcfffbfafaffe7e7edfff8f9fefffffffffffdfdfcfffdfcf8fffffffbfffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffefffffffdfefffffeffffff848792ff585c68ffc4c7d1fffcfefffffefffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffefefefffffffffffffffefffffffefffefffffffdfffffffcffffffe3e8f6ff687086ff0e1832ff1f2944ff6b738affd1d5e2fffdfffffffefffffffffffffffffffffffffffffffffefffffffefffffefefefffefefefffffffefffcfdfdfffcffffffe5e9f2ff7d8393ff30384fff17223fff182547ff172447ff131e3cff252b3dff7c7f88ffedeef1fffefefefffffffffffffffffffffefffffffefffffefefefffefefefffefffffffdffffffcbd0dcff42495cff141b37ff141d3dff172244ff182548ff182548ff111c38ff2d3444ff91949bfff1f2f4fffbfbfbfffffffffffffffffffffffffffffffffffefefefffdfefffffcffffffdae0e8ff384053ff141d36ff161d39ff303754ff464e6bff121c38ff19243eff626b80ffd3d8e3fffdfffffff9fafcfff9f9f9fffffffffffffffffffffffffffffffffffdfcfbfffcfdfffff3faffff606a79ff121d37ff16203aff4f5565ffd9dbe8ffa3a5b4ff3a3d4bffb1b5c0fff9fdfffffdfffffffcfdfffffefdfefffffefefffffffffffffffffffffffffffffffffffdfbfbfffdffffffc2cbd6ff1b283aff121f39ff374058ffdde1eafffdfeffffdfdee3ffe6e5eafffefffffffdfefffffdfdfdfffefefefffffffffffffffffffffffffffffffffffffffefffffffefffdfbfdfffdffffff848e9eff121f35ff131f37ff969eb1fffcfffffffdfdfcfffffffffffffffffffffefefffefdfcfffcfcfbfffefefdfffffffefffffffefffffffffffffffefffffffdfffffffcfffcfcfdfffbfeffff5b6578ff0f1c34ff222c43ffd3daeafffcfffffffffffcfffefefefffffffffffffffefffffefcfffffffefffdfdfcfffefefdfffdfdfdfffbfbfcfffefefefffdfdfbfffffffcfffcfffefff8fdffff4d586cff0f1b34ff2f374effe4e9f8fffcfffffffffffcfffefffffffdfefffffefffefffefffefffffffefffefefefffdfdfffffffefffffffefffffffdfffffefefdfffffffdfffcfffdfff9ffffff5a6579ff121d38ff242c44ffd4d9e9fffdfffffffefffdfffdfefefffefffffffefffefffdfffcfffffffefffcfcfefffcfdffffa8a9b2ffc1c1cbfff5f5fdfffdfdfefffffffefffafcf7fffcffffff808a9dff101b37ff151f3aff98a0b4fffcfffffffbfdfbfffcfefbfffcfefafffcfefafffcfefafffdfefbfffcfdffffe4e8f4ff303447ff1a1f35ff5f6274fff3f3f9fffffefefffcfbf8fffcfeffffc4cbdbff1d273fff15203bff39435bffd9deebfffcfffffffafcfbfffcfefcfffafdfbfffafdfdfffcfffffffafeffff7e8598ff172039ff131c35ff6e7387fffcfcfffffffcfcfffefbfdfffcfbfffff5f8ffff636b79ff121e37ff13203bff4f576cffd2d8e7fffcfffffffdfffffffcfffffffbfffffff1f8ffff8b94a5ff18253eff14213cff253045ffcad0ddfffffffffffefcf8fffdf9fefffbf9fdfffcfdffffdbe0e7ff353f52ff131f38ff151f38ff2b344aff767d8fffa9afbfffb2b9c9ff8e97a7ff495366ff142036ff16233dff152239ff8f98a7fffbfffffffefefefffffffbfffefefffffefefffffffffefffdffffffc8cfdaff3d4759ff121e36ff12203bff101d39ff13203cff12203cff111f3aff111f39ff121f36ff1d283bff8b93a0fff9fefffffefffffffefefdfffffefbfffbfefefffcfefdfffffffefffcfcfcfffcffffffdfe6f0ff778193ff2b374eff14213bff121e3bff101c39ff111e38ff1e2a40ff4f596affbac1ccfffbfffffffefffffffffffefffefefdfffdfdfcfff9fffcfff9fdfbfffefffffffefefffffcfcfdfffdfefffffcffffffe3e7f1ffb4b9c7ff9599a9ff9195a5ffa3a8b6ffcfd3ddfff5f8fefffefffffffbfcfcfffcfefdfffefffffffdfffefffefffffffbfffdfffbfffdfffdfefffffffffffffffffefffffffefffffffffffffffffffdfdfffffefefffffefefffffefefffffffefffffffffffffffffdfffffffcfffefffefffefffffffefffffffeffff";
var oImg2CWStream = {count:0, width:20, height:20, read:function(nBytes){return str2CWImgData.slice(this.count,this.count+=2*nBytes)}};
I have had the "addToolButton" function throw an error when a button name already exists. To fix this issue add this code before the call
app.removeToolButton("MyCWButton");
I would also suggest cutting the code down to only one button until you have it debugged.
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
Good idea about cutting the code down. After trying that and messing about some, it turns out that the flatten icon is the one causing a problem for some reason. If I substitute one of the rotate icons for the flatten icon, all loads up ok and works.
Now a different question, though -- is there any way to get the icons larger? The other toolbar icons are a usable size but I have a 4K monitor and these new 20x20 are very small. Perhaps after all this it will turn out that I'm better off with the generic "folder" icon that appears for the tools and just remembering which one goes where. Am I stuck with this small size?
Copy link to clipboard
Copied
By the way, I have a "stamp multiple pages" add-in tool that comes with its own icon (hard-coded into the javascript, I think) and that is not so small. How did they do it?
Copy link to clipboard
Copied
Plug-in icons are different from JavaScript icons. Different animals. And Adobe writes the code, so they can do anything they want.
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
No, back when JS toolbar icons were first introduce in Arcobat 6, they could be quite large. I had fun using photos as button icons. But that didn't last long. 20x20 is it.
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
The stamp multiple pages tool is a javascript add-in tool, and they have a larger icon. It sits in my Javascript folder and seems to be written the same way as the tools I am trying to add. It was made by IDTPlans.com but they don't seem to have it on their site anymore. I would not want to post it all here but could perhaps send it to you if you wanted to see how they did it. As far as I can tell it is all just Javascript in that one file.
Copy link to clipboard
Copied
Perhaps hard-coding the icon allows it to be scaled up along with the other toolbar icons? Maybe that is how the stamp tool works, whereas my icons are loaded with the first document opened and they are small?
Copy link to clipboard
Copied
No 20x20 is the largest a JavaScript toolbar icon can get. The icon size in your stamp tool is 20x20.
The function doc.importIcon, and all other function that import images, rescale the image so that it is smaller than the original. It also totally screws up the image quality. This is something that just started happening last year or so. So I stopped using all image import functions.
Anyway, that's why your imported icons are smaller, and it's why I suggested you check the actual imported size.
myDoc.importIcon("myflatIcon", "/D/J/CAD Standards/Stamps/Acrobat tools/2flatten.jpg", 0);
// convert the icon to a stream.
cwIcon = util.iconStreamFromIcon(myDoc.getIcon("mycwIcon"));
cw.width;
cw.height;
// You'll find the width and height are not the same as the original image.
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
Ok, I understand the problem now thanks to your description. Also when I used the hex version of the icon that you provided earlier here, I was able to include that in my Javascript and it appears correctly in Acrobat. So it seems the solution is to only have icons as hex codes in the script and not import them as images.
Is there a way to generate the hex codes from the image? I suppose it can't be done in Acrobat because the process of importing it messes up the image -- is that right?
Copy link to clipboard
Copied
That's right. I used to have an Acrobat script that generated the Hex text code for images, but that's useless now.
Currently I use an HTML script that does it using the Canvas element.
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
Is that HTML script something you can share? It would be greatly appreciated and likely useful to many in the community!
Copy link to clipboard
Copied
I'll be putting it up as a tool at www.pdfscripting.com
Use the Acrobat JavaScript Reference early and often
Copy link to clipboard
Copied
Thom,
Have you posted the script on your site? Is it in the free section or the paid section?
Thanks.
-
- 1
- 2