Skip to main content

skip to main content

developerWorks  >  Rational  >

Customizing IBM Rational ProjectConsole to modify default font used in graphs

developerWorks
Document options

Document options requiring JavaScript are not displayed

Discuss


Rate this page

Help us improve this content


Level: Intermediate

Miguel Pozos (mpozos@us.ibm.com), Software Engineer, IBM

03 May 2005

IBM Rational ProjectConsole's interactive Dashboard, which lets users create charts for inclusion in HTML reports, uses a simple font on all charts. The customization described here modifies what font is used for these charts in the event that a user prefers a different one.

Introduction

IBM® Rational® ProjectConsole, part of the IBM Rational Team Unifying Platform, is a Web-based project management tool that automates reporting on project status and progress. It gathers data from a variety of sources and automatically generates HTML reports containing charts that display trends or distributions. Its interactive Dashboard lets users create charts for inclusion in the HTML reports and dynamically analyze these charts through drill-downs. When creating graphs, however, a default font is used for all chart labels and axis. While this suits the need of most users, some may need a different font to emphasize certain trends or simply to conform to the culture or standard of one's company.



Back to top


An example

Consider being assigned the task of creating charts that really grab the attention of the audience, say in a marketing department. The defaults for the ProjectConsole Dashboard are ideal for progress charting but sometimes a sales pitch requires something less professional and more appealing.


Figure 1. The standard graph
The standard graph

The growth shown on Figure 1 is, in this scenario, a positive trend of the progress of the report. The goal of this article is to illustrate how to change the text of this chart to suit your needs.



Back to top


What you will need to start

First and foremost, you will need a Java 2 SDK installed on your system. The author used the Sun distribution of Java 2 SDK, SE v1.4.2_07 on Windows XP Professional, but you may use another version as long as you have a Java compiler available (javac) and the Java Archive application (JAR). After installing a version of Java 2 SDK, it is important to check that the executables are in the PATH environment variable. To do this, right-click on the My Computer icon and select Properties. On the Advanced tab of the System Properties dialog box, click Environment Variables. Under System variables, verify that the path to the Java 2 SDK is present. The actual directory will vary with the different versions of Java 2 SDK. Figure 2 shows the directory in the PATH environment variable on the author's system.


Figure 2. The PATH environment variable
The PATH environment variable

At this point, you should perform a quick test. Open the Microsoft Windows Command Prompt and issue the command javac without any parameters. If successful, issue the command jar without any parameters. If either of the commands return an error indicating that the executable could not be found, there are two possible causes: Either an incorrect PATH environment variable or missing executables. If the PATH is incorrectly set, you can manually correct it in the dialog box shown in Figure 2. If you cannot find the Java 2 SDK executables, download them once more and reinstall them.



Back to top


Technical details

The generation of the graphs on the Dashboard is done through two JAR files. One is called analyzer.jar and the other is publisher.jar, analyzer.jar handles how the graphs are displayed within the Dashboard while publisher.jar handles the publication of graphs to other supported file formats (like PNG, PCL, PS, etc.). Both of these JARs contain a Java class called Chart. Full description of this class is listed in the next section. It is important to only make the suggested changes as described or the Dashboard will not work properly. Depending on your particular needs you may only need to modify one of the two JAR files. For instance, if in your implementation of the ProjectConsole, you only use the Dashboard to generate the graphs and these are never published to other formats, you may only want to modify the analyzer.jar file. In this case, it is not worth the additional effort to also modify the publisher.jar file. Note that if that is what you decide to do, subsequent publish actions from the graphs will result in files with the original default font.

There is an additional file that will be needed but not modified. It is called klg45.jar but we only need to reference it at compile time. It is recommended to create a directory at the root level to store these JAR files while we modify them. Once we are done, we can place our modified files at the original location (though they must have the same name, of course). The author created a folder titled "PjC" at the root level, which is where the three JAR files are stored. The analyzer.jar and klg45.jar are both located at <Install_Dir>\Common\rwp\webapps\projectconsole\pjc while publisher.jar is located at <Install_Dir>\ProjectConsole\bin. <Install_Dir> is C:\Program Files\Rational by default. Once these three files are in the same location, another environment variable must be modified, CLASSPATH. We'll have to append the full path and filename of these JARs to the end of the present value of this environment variable. This is to ensure that all classes can find one another at compile time. In this example, the directory is C:\PjC so we will append C:\PjC\klg45.jar;C:\PjC\analyzer.jar;C:\PjC\publisher.jar Figure 3 displays this modification.


Figure 3. The CLASSPATH environment variable
The CLASSPATH environment variable


Back to top


Fonts and classes

Before we decide what font to use, we need to determine what fonts we have available. As expected, well-known fonts Times New Roman, Courier New and Helvetica could be used, but what other fonts are available? It is fairly easy to get a complete list so you may choose one that is more to your liking. To obtain a list of the available fonts, we can run a simple Java program and use the output to choose the font name. This code is presented for a good reason, if you have a different version of Java SDK, your output may vary. The Java program here is aptly named FontNames and is presented in Listing 1, below.


Listing 1. The FontNames program
				
import java.awt.Font;
import java.awt.GraphicsEnvironment;

class FontNames {
	public static void main(String args[]){
		String[] fontNames = 

GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
		for (int i = 0; i < fontNames.length; i++)
		{
			System.out.println(fontNames[i]);
		}

    }
}

To run this program, it must first be compiled. Save this text to a file called FontNames.java Be sure to include all characters as they appear, especially the soft brackets, or the program will not compile. Open the Command Prompt and change to the directory that contains this file. Then issue the command javac FontNames.java. As a result, a file called FontNames.class should appear. We are now ready to run the command java FontNames. Note that we are running the java command with the parameter <FontNames> and not <FontNames.class>. Listing 2 displays the output received by the author. Again, depending on which version of Java SDK you use, other fonts may be available.


Listing 2. The FontNames output
				
Arial
Arial Black
Arial Narrow
Baskerville
Batang
BatangChe
Binner Gothic
Book Antiqua
Bookman Old Style
Botanical
Brush Script
Centaur
Century
Century Gothic
Comic Sans MS
Courier New
Default
Dialog
DialogInput
Dotum
DotumChe
Estrangelo Edessa
Franklin Gothic Medium
Garamond
Gautami
Georgia
Gill Sans
Gill Sans Condensed
Gill Sans Ultra Bold
Gulim
GulimChe
Gungsuh
GungsuhChe
Haettenschweiler
Impact
Latha
Letter Gothic
Lotus Postal Barcode
LotusWP Box
LotusWP Icon
LotusWP Int A
LotusWP Int B
LotusWP Type
Lucida Bright
Lucida Console
Lucida Sans
Lucida Sans Typewriter
Lucida Sans Unicode
Lydian
Mangal
Map Symbols
MapInfo Cartographic
Marlett
Math A
Math B
Math C
Microsoft Sans Serif
MingLiU
Monospaced
Monotype Corsiva
Monotype Sorts
MS Gothic
MS Mincho
MS Outlook
MS PGothic
MS PMincho
MS UI Gothic
MV Boli
News Gothic
News Gothic Condensed
Nimrod
NSimSun
Onyx
Palatino Linotype
Perpetua
Photina Casual Black
PMingLiU
Raavi
Rockwell
Rockwell Condensed
Rockwell Light
SansSerif
Serif
Shruti
SimHei
SimSun
Sylfaen
Symbol
Tahoma
Times New Roman
Trebuchet MS
Tunga
Verdana
Webdings
Wingdings
Wingdings 2
Wingdings 3

Beside the well-known fonts mentioned before, we also have personal favorites such as Impact, Nimrod, and Onyx. In the examples following, the Impact font will be used.

We can now look at the code that defines the Chart class that controls the charts that are displayed in the Dashboard. Listing 3 displays the Chart class definition.


Listing 3. The Chart class definition
				
package com.rational.dashboard.thirdpartycontrols;

import com.klg.jclass.chart.ChartDataModel;
import com.klg.jclass.chart.ChartDataView;
import com.klg.jclass.chart.ChartDataViewSeries;
import com.klg.jclass.chart.ChartText;
import com.klg.jclass.chart.EventTrigger;
import com.klg.jclass.chart.JCAxis;
import com.klg.jclass.chart.JCAxisTitle;
import com.klg.jclass.chart.JCChart;
import com.klg.jclass.chart.JCChartArea;
import com.klg.jclass.chart.JCChartStyle;
import com.klg.jclass.chart.JCDataIndex;
import com.klg.jclass.chart.JCPickEvent;
import com.klg.jclass.chart.JCPickListener;
import com.rational.dashboard.utilities.ColorUtil;
import java.awt.Color;
import java.util.Iterator;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.border.BevelBorder;

public class Chart extends JCChart

{
    class SymPick
    implements JCPickListener
    {
        public void pick(JCPickEvent jcpickevent)
        {
            JCDataIndex jcdataindex = jcpickevent.getPickResult();
            boolean flag = false;
            if(jcdataindex != null)
            {
                Object obj = jcdataindex.getObject();
                ChartDataView chartdataview = jcdataindex.getDataView();
                int i = jcdataindex.getSeriesIndex();
                int j = jcdataindex.getPoint();
                if(chartdataview != null && (obj instanceof JCChartArea))
                {
                    String s = chartdataview.getPointLabel(j);
                    setPickedValue(s);
                } else
                {
                    setPickedValue(null);
                }
            }
        }
        SymPick()
        {
        }
    }

    public Chart()
    {
        mShowValueLabels = false;
        colors = (new Color[] {
ColorUtil.BLUE, ColorUtil.RED, ColorUtil.YELLOW, ColorUtil.ORANGE, ColorUtil.MAGENTA, 
ColorUtil.GREEN, ColorUtil.CYAN, ColorUtil.BLACK, ColorUtil.PINK, ColorUtil.AQUAMARINE, 
ColorUtil.BEIGE, ColorUtil.DARK_TURQUOISE, ColorUtil.NAVY_BLUE, ColorUtil.ROSY_BROWN, 
ColorUtil.BLANCHED_ALMOND, ColorUtil.SANDYBROWN, ColorUtil.DARK_GREEN, 
ColorUtil.DARK_ORANGE, ColorUtil.MEDIUM_PURPLE, ColorUtil.ALICE_BLUE, 
ColorUtil.DODGER_BLUE, ColorUtil.DARK_TURQUOISE, ColorUtil.THISTLE, ColorUtil.PLUM, 
ColorUtil.HOT_PINK, ColorUtil.TOMATO, ColorUtil.BISQUE, ColorUtil.MIDNIGHT_BLUE, 
ColorUtil.DARK_GOLDENROD, ColorUtil.SEA_GREEN, ColorUtil.BURLYWOOD, ColorUtil.VIOLET, 
ColorUtil.PALE_VIOLET_RED, ColorUtil.SALMON, ColorUtil.PURPLE, ColorUtil.OLIVE_GREEN, 
ColorUtil.ALICE_BLUE, ColorUtil.CHOCOLATE, ColorUtil.LIGHT_YELLOW, ColorUtil.LAVENDER_BLUSH
        });
        SymPick sympick = new SymPick();
        addPickListener(sympick);
        ((JLabel)getHeader()).setText("Untitled");
        getLegend().setVisible(true);
        getDataView(0).setAutoLabel(true);
        getDataView(0).setPickFocus(1);
        setTrigger(0, new EventTrigger(0, 4));
        setTrigger(0, new EventTrigger(4, 4));
        setFillColorIndex(2);
        setLineColorIndex(2);
        setSymbolColorIndex(2);
        getLegend().setBorder(new BevelBorder(0));
        getChartArea().setBorder(new BevelBorder(0));
    }

    public void setPickedValue(String s)
    {
        mszPickedValue = s;
    }

    public String getPickedValue()
    {
        return mszPickedValue;
    }

    public int getPickedIndex(String s)
    {
        if(s != null)
        {
            java.util.List list = mChartDataView.getPointLabels();
            Iterator iterator = list.iterator();
            for(int i = 0; iterator.hasNext(); i++)
            {
                String s1 = (String)iterator.next();
                if(s1.equals(s))
                    return i;
            }

            return -1;
        } else
        {
            return -1;
        }
    }

    public void setModel(ChartDataModel chartdatamodel)
    {
        mChartDataView = addDataView(0);
        mChartDataView.setDataSource(chartdatamodel);
        mChartDataView.setAutoLabel(true);
        getDataView(0).setPickFocus(1);
        mChartDataView.getYAxis().getTitle().setPlacement(2);
        mChartDataView.getYAxis().getTitle().setRotation(1);
        mChartDataView.setHoleValue(0.0D);
        setSeriesColor();
    }

    public boolean getShowValueLabelsStatus()
    {
        return mShowValueLabels;
    }

    public void setShowValueLabelsStatus(boolean flag)
    {
        mShowValueLabels = flag;
    }

    public void setSeriesColor()
    {
        if(mChartDataView != null)
        {
            if(mChartDataView.getNumSeries() > 0)
            {
                java.util.List list = mChartDataView.getSeries();
                Iterator iterator = list.iterator();
                int i = 0;
                for(int j = colors.length; iterator.hasNext() && i < j; i++)
                {
ChartDataViewSeries chartdataviewseries = (ChartDataViewSeries)iterator.next();
chartdataviewseries.getStyle().setFillColor(colors[i]);
chartdataviewseries.getStyle().setLineColor(colors[i]);
chartdataviewseries.getStyle().setSymbolColor(colors[i]);
                }

            }
            setBatched(false);
            update();
        }
    }

    boolean mShowValueLabels;
    Color colors[];
    protected ChartDataView mChartDataView;
    protected String mszPickedValue;
}

The easiest way to get started is to copy the entire text of Listing 3 into a text file and save it as Chart.java. The suggested place to keep these files is the same directory where the three JAR files are stored. All commands given in this procedure assume this location C:\PjC is the directory. There are only two lines that must be inserted to get the effect we desire. One is in the import section. We need to include the following: import java.awt.Font; A good place to put it is after the import java.awt.Color; line. The other line is in the public constructor of the Chart class. The line is of the form setFont(new Font("<Name of Font>",Font.<Style>,<Size>)); where <Name of Font> is one of the names in the FontNames output, <Style> is either PLAIN, BOLD, ITALIC, or BOLD+ITALIC and <Size> is an integer. In our example, the line I will insert is setFont(new Font("Impact", Font.PLAIN, 10)); A good place to insert it is before the line setFillColorIndex(2);



Back to top


Last item before compile

In order for the modified JARs to function as the originals, certain information must be added to the manifest file of each file. Specifically, we will need to create two text files with certain information so different components of the ProjectConsole can continue to communicate correctly. In the directory that contains the three JAR files as well as your modified Java files, create a text file called "manifest.analyzer" consisting only of the following line:


				
Main-Class: com.rational.dashboard.analyzer.AnalyzerMain

Then, create another text file, "manifest.publisher" consisting of the following lines:


				
Main-Class: com.rational.dashboard.displayserver.publisher.Publisher
Class-Path: ..\\Classes\\klg45.jar



Back to top


Compile and update

Once all changes are made, the classes can be once more compiled. The best way to do this is to start the Command Prompt and change the directory to the location of the JARs and the created directory structure ("C:\PjC" in the example given). It is then a simple matter of compiling the classes with the javac executable. The most important thing to note is that compiling the Chart.java file will result in two class files, since Chart contains an inner class. The command to compile the Chart.java class is javac Chart.java As a result of this command, two class files are created, Chart.class and Chart$SymPick.class Though we made no changes to the SymPick inner class, we will update the JAR files with this file also. Remember that you may only want to update analyzer.jar if you only use the Dashboard to display graphs. This example assumes graphs are published to PNG files for inclusion in ProjectConsole Web reports. To update the contents of the analyzer JAR, we must first extract its contents with this command: jar xvf analyzer.jar. This will take a few seconds and will create several directories and files under the present directory, including "com", "sun", "images", "netscape", and "symantec". We should now copy the compiled Chart.class and Chart$SymPick.class files to the location of the original files with this command: copy /Y Chart*.class com\rational\dashboard\thirdpartycontrols Next, we can delete the now obsolete analyzer.jar with del analyzer.jar We can now recreate the analyzer.jar file so it has the new font definitions with the command: jar cvfm analyzer.jar manifest.analyzer com images netscape sun symantec Finally, we can delete the directories of analyzer.jar, since some of the same directory names are used by publisher.jar. That command is: rmdir /q /s com netscape images sun symantec To update the publisher.jar file, the series of commands is:


				
jar xvf publisher.jar
copy /Y Chart*.class com\rational\dashboard\thirdpartycontrols
del publisher.jar
jar cvfm publisher.jar manifest.publisher com images netscape sun
rmdir /q /s com images netscape sun



Back to top


Final steps

The JAR files are now updated with all of the necessary changes. Before copying the files to the original location, check one more time that you have a backup copy of each JAR file. I cannot stress enough the importance of this since we are making multiple changes and it is much faster to restore the original files than to try to roll back each change. Once you have verified that your backup copies are safely stored somewhere, you may copy analyzer.jar to <Install_Dir>\Common\rwp\webapps\projectconsole\pjc and publisher.jar to <Install_Dir>\ProjectConsole\bin where <Install_Dir> is C:\Program Files\Rational by default. Note that making changes to the installed ProjectConsole files isn't supported, so keep the files in an accessible location should you ever need to restore them. In addition, if you install a new Service Release, you will need to recreate your changes so save your java source files.

Before the changes can take effect, it is necessary to stop six Windows services, then start them again. These are: 1) Rational ProjectConsole Collection Server, 2) Rational ProjectConsole Dashboard Server, 3) Rational ProjectConsole Report Server, 4) Rational Web Platform, HTTP server, 5) Rational Web Platform, servlet engine, and 6) Rational Web Platform, ReqWeb servlet engine.

You may need to clear your browser's cache since the now obsolete Java archive files may still be stored there.

Finally, you can do some cleanup. Delete the directory you used to hold the three JAR files ("C:\PjC", in this example). You can also remove the entries from the CLASSPATH environment variable.



Back to top


After you're done

The graphs you have previously created and future graphs will have the font you selected. The legend also has the same font. Since this is a small and easy change, you can experiment with different fonts, styles and sizes until you find the one that best suits your needs.



Resources



About the author

Miguel Angel Pozos

Miguel Angel Pozos has been a software engineer at IBM/Tivoli since June 2002. He holds a BS in computer science from the University of Texas at Austin and has recently begun using the IBM Rational suite of products for project management and test progress reporting.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top