Web Development | Ios and Android App Development Company in Charlotte Nc
+1 704 215 4622
[email protected]

Print all GMF diagrams with a single click

Print all GMF diagrams with a single click

We know that GMF gives only three types of Print Options for the Print Range.

a. Current Diagram

b. All diagrams from open models

c. Selected diagrams.

Suppose consider your projects contain a large number of diagrams and you wish to Print all the diagrams. What are the options left? You need to open up each of the diagram and click print. This is a hard task when you have a large number of diagrams. I have found a better way by automating it.

Please note that there will be a lot of methods to accomplish this. This is one method I am going to detail. Since GMF doesn’t allow us to do this directly I am customizing four GMF internal classes. The classes we need to customize are

DiagramWithPrintGlobalActionHandlerProvider class

DiagramWithPrintGlobalActionHandler class

EnhancedPrintActionHelper class

DiagramPrinterUtil class

DiagramWithPrintGlobalActionHandlerProvider is the class that provides GlobalActionHandlerProvider for print functionality. This will be defined in our plugin’s plugin.xml

Before we start we need to make these four classes as custom ones. I am doing this because we cannot edit the source code of dependent plugins. If we have attached source for these classes in out target platform definition we can view the code while debugging but We cannot the edit the code for our own customization.

As the first step create four new classes in a package of your choice with names

CustomDiagramWithPrintGlobalActionHandlerProvider.java

CustomDiagramWithPrintGlobalActionHandler.java

CustomEnhancedPrintActionHelper.java

CustomDiagramPrinterUtil.java

Copy the original code itself in to these classes from its respective original counterparts. Once done that open up your plugin’s plugin.xml and change the GlobalActionHandlerProvider definition to as shown below.

<extension point=”org.eclipse.gmf.runtime.common.ui.services.action.globalActionHandlerProviders”>

<GlobalActionHandlerProvider

class=”mypackage.printing.CustomDiagramWithPrintGlobalActionHandlerProvider

id=”mydomainPresentationPrint”>

<Priority name=”High”/>

<ViewId id=”mypackage.CustomDiagramEditorID”>

<ElementType class=”org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart”>

<GlobalActionId actionId=”print”/>

</ElementType>

</ViewId>

</GlobalActionHandlerProvider>

</extension>

Once you are done with this, start your application using the Run configuration. Yep, We haven’t changed anything in our custom classes, but We want to make sure it works in the default way. If this works fine we can make sure that the print mechanism is actually referencing our custom classes instead of the GMF internal classes. Still having doubts? put some break points in the code and see whether our class is called while running in eclipse DEBUG mode.

Make sure this works fine. ie. The print options given above should work the same way as it existed because we have copied the original code itself to our custom classes.

So whats our ultimate AIM? We want to automate the printing of all diagrams with a single click. For that we need to make a lot of changes in code for these 4 classes that we have just made.

Step 1: Open up CustomDiagramWithPrintGlobalActionHandlerProvider.java and make changes shown below.

………………………

if (!getHandlerList().containsKey(context.getActivePart())) {

getHandlerList().put(context.getActivePart(),

new CustomDiagramWithPrintGlobalActionHandler());

………………………

return (CustomDiagramWithPrintGlobalActionHandler) getHandlerList().get(context.getActivePart());

………………………

Step 2:Open up CustomDiagramWithPrintGlobalActionHandler and make changes as shown below.

protected void doPrint(IGlobalActionContext cntxt) {

IPrintActionHelper helper = new CustomEnhancedPrintActionHelper();

helper.doPrint(cntxt.getActivePart());

}

…………………………

Step 3:open up CustomDiagramPrinterUtil.java

This is the class we are going to do a lot of coding to attain our goal.

What we are going to do is

#1.Get all the diagram files from the Workspace using our diagram file’s extension as an Array list.

#2.Ina loop we Will Open a diagram,Print the Diagram and Close the diagram. This loop will iterate for n times where, n is the size of the array list described in #1.

#1.I find all the diagram files present in my workspace using my diagram’s extension.

private static Collection getWorkspaceFiles(String extension)

{

ArrayList files = new ArrayList();

IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

IProject[] projects = root.getProjects();

for (int i=0;i<projects.length;i++)

{

try {

IResource[] resources = projects[i].members();

for (int j=0;j<resources.length;j++)

{

getChildren(resources[j], files, extension);

}

}

catch (CoreException ex)

{/*ignore*/}

}

return files;

}

private static void getChildren(IResource res, ArrayList files, String extension)

{

if (res instanceof IFile)

{

if (extension == null ||( res.getFileExtension()!=null && res.getFileExtension().endsWith(extension) ))

files.add(res.getFullPath().toString());

}

if (res instanceof IFolder)

{

try {

IResource[] resources = ((IFolder)res).members();

for (int j=0;j<resources.length;j++)

{

getChildren(resources[j], files, extension);

}

}

catch (CoreException ex)

{}

}

}

#2.Ina loop we Will Open a diagram,Print the Diagram and Close the diagram.

For anyone there will be a doubt where to put this loop and call the function calls. In my case I put this inside the code block that gets called when we select “All diagrams from open models” in the print dialog.

…………….

else if (helper.getDlgDiagramPrintRangeAll()) {

flag=1;

ArrayList files = (ArrayList)getWorkspaceFiles(“mydomain_diagram”);

System.out.println(“Number of diagrams to be printed is”+files.size());

for(int i=0;i<files.size();i++){

System.out.println(“Diagram opened is”+files.get(i));

openDiagram(files.get(i).toString());

PrintDiagram(diagramPrinter,helper);

closeDiagram();

}

…………

And the Functions for Opening and Printing and Closing are as follows:

//Method for Opening the Diagram

private static void openDiagram(String DiagramName){

URI diagramModelFilename = URI.createURI(DiagramName);

GMFResource myGMFDiagram = new GMFResource(diagramModelFilename);

try {

myGMFDiagram.load(Collections.EMPTY_MAP);

myDomainDiagramEditorUtil.openDiagram(myGMFDiagram);

} catch (IOException e1) {

e1.printStackTrace();

} catch (PartInitException e) {

System.out.println(“Error opening diagram editor”+e.getStatus());

}

}

……..

//Method for Printing the Diagram

……..

private static void PrintDiagram(DiagramPrinter diagramPrinter,IPrintHelper helper){

DiagramEditor dEditor = null;

List diagramEditors = EditorService.getInstance().getRegisteredEditorParts();

Iterator it = diagramEditors.iterator();

while (it.hasNext()) {

Object obje = it.next();

if (obje instanceof DiagramEditor) { //DiagramDocumentEditor

dEditor = (DiagramEditor) obje;

}

}

diagramPrinter.setDiagrams(Collections.singletonList(dEditor.getDiagram()));

printDiagrams(diagramPrinter, helper);

System.out.println(“File Printed”);

}

……..

//Method for Closing the Diagram

……..

private static void closeDiagram(){

IWorkbench workbench = PlatformUI.getWorkbench();

if (workbench != null) {

if (workbench.getWorkbenchWindows() != null

&&workbench.getWorkbenchWindows()[0].getActivePage() != null) {

IWorkbenchPage page = workbench.getWorkbenchWindows()[0].getActivePage();

if (page != null&& page.getEditorReferences().length > 0) {

ArrayList<Resource> resource = new ArrayList<Resource>();

for (IEditorReference editorReference : page.getEditorReferences()) {

TransactionalEditingDomain editingDomain = ((SgmoduleDiagramEditor) editorReference

.getPart(false))

.getEditingDomain();

if (editingDomain != null) {

ResourceSet resourceSet = editingDomain

.getResourceSet();

for (Resource element : resourceSet

.getResources()) {

resource.add(element);

}

for (Resource element : resource) {

resourceSet.getResources()

.remove(element);

}

}

((SgmoduleDiagramEditor) editorReference

.getPart(false)).close(false);

}

}

}

}

System.out.println(“Diagram closed”);

}

This works perfectly for me. But When you have lots of diagrams to be printed in a single stretch, make sure You allot more memory for your application else it may throw a java heap memory exception.

Hope this helps some one. Queries/Suggestions Welcome

Anoop Menon

About author View all posts Author website

anoopmenon

5 CommentsLeave a comment

  • Hello chunhc,

    @q 1: You can set the default scaling by pages in the dialog box that comes up after print.

    @q 2: I fear I didn’t understand what you really meant.Can you explain what you are looking for?

    Mean while I have made another method for “Printing” by doing some R&D which is more good. The new one doesn’t/never throws any memory issues…there is a progress monitor that displays which all diagrams printed and stuff…and instead of printing each diagram to a new filename while you use CutePDF ..it will print all to a single file with all the diagrams as pages. I will upload the new tutorial at the end of this month.I need to find some time to type all these stuff. Basically I am little busy with my job right now and I am looking for some new opportunities in some new companies where I could get more exposure..so need to attend some interviews here.

    Thanks,

    Anoop

  • Thanks for this tutorial.
    I am currently looking at printing GMF diagrams. One of the things I have to investigate, is drawing print boundaries on the diagram. Do you have some ideas, how this could be done?

  • Hello bartoszes,

    I am very very sorry for the late reply.

    I don’t know whether your issue is fixed or not.
    Let me know. As such I dont know the solution to your query. I will give it a shot and find it for you if you are still looking for a solution.

    Thanks,

    Anoop

Leave a Reply

Your email address will not be published. Required fields are marked *