Community
Participate
Working Groups
This is the log... Log: Mon Jan 28 13:54:55 MSK 2002 4 org.eclipse.jdt.ui 1 Internal Error org.eclipse.core.internal.resources.ResourceException: Errors during build. at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:222) at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:701) at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1237) at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:78) at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:296) at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:249) at org.eclipse.jface.wizard.WizardDialog.run(WizardDialog.java:713) at org.eclipse.jdt.internal.ui.wizards.NewProjectCreationWizard.performFinish(NewProjectCreationWizard.java:63) at org.eclipse.jface.wizard.WizardDialog.finishPressed(WizardDialog.java:570) at org.eclipse.jface.wizard.WizardDialog.buttonPressed(WizardDialog.java:311) at org.eclipse.jface.dialogs.Dialog$1.widgetSelected(Dialog.java:344) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:85) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:74) at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:637) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1413) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1205) at org.eclipse.jface.window.Window.runEventLoop(Window.java:536) at org.eclipse.jface.window.Window.open(Window.java:523) at org.eclipse.ui.actions.NewProjectAction.run(NewProjectAction.java:96) at org.eclipse.jface.action.Action.runWithEvent(Action.java:452) at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:407) at org.eclipse.jface.action.ActionContributionItem.handleWidgetEvent(ActionContributionItem.java:361) at org.eclipse.jface.action.ActionContributionItem.access$0(ActionContributionItem.java:352) at org.eclipse.jface.action.ActionContributionItem$ActionListener.handleEvent(ActionContributionItem.java:47) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:74) at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:637) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1413) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1205) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:844) at org.eclipse.ui.internal.Workbench.run(Workbench.java:827) at org.eclipse.core.internal.boot.InternalBootLoader.run(InternalBootLoader.java:878) at org.eclipse.core.boot.BootLoader.run(BootLoader.java:321) at java.lang.reflect.Method.invoke(Native Method) at org.eclipse.core.launcher.Main.basicRun(Main.java:151) at org.eclipse.core.launcher.Main.run(Main.java:502) at org.eclipse.core.launcher.Main.main(Main.java:362) 2 org.eclipse.core.resources 566 Errors during build. 2=============<children>============= 2 org.eclipse.jdt.core 75 java.lang.NullPointerException encountered while running org.eclipse.jdt.internal.core.newbuilder.JavaBuilder. java.lang.NullPointerException at org.eclipse.jdt.internal.compiler.lookup.BlockScope.emulateOuterAccess(BlockScope.java:347) at org.eclipse.jdt.internal.compiler.ast.SingleNameReference.manageEnclosingInstanceAccessIfNecessary(SingleNameReference.java:558) at org.eclipse.jdt.internal.compiler.ast.SingleNameReference.analyseCode(SingleNameReference.java:119) at org.eclipse.jdt.internal.compiler.ast.MessageSend.analyseCode(MessageSend.java:31) at org.eclipse.jdt.internal.compiler.ast.Block.analyseCode(Block.java:36) at org.eclipse.jdt.internal.compiler.ast.IfStatement.analyseCode(IfStatement.java:59) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.analyseCode(AbstractMethodDeclaration.java:79) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.analyseCode(TypeDeclaration.java:145) at org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression.analyseCode(QualifiedAllocationExpression.java:41) at org.eclipse.jdt.internal.compiler.ast.MessageSend.analyseCode(MessageSend.java:35) at org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration.analyseCode(ConstructorDeclaration.java:79) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.analyseCode(TypeDeclaration.java:208) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.analyseCode(TypeDeclaration.java:345) at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.analyseCode(CompilationUnitDeclaration.java:67) at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:456) at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:261) at org.eclipse.jdt.internal.core.newbuilder.AbstractImageBuilder.compile(AbstractImageBuilder.java:212) at org.eclipse.jdt.internal.core.newbuilder.AbstractImageBuilder.compile(AbstractImageBuilder.java:188) at org.eclipse.jdt.internal.core.newbuilder.BatchImageBuilder.build(BatchImageBuilder.java:49) at org.eclipse.jdt.internal.core.newbuilder.JavaBuilder.buildAll(JavaBuilder.java:117) at org.eclipse.jdt.internal.core.newbuilder.JavaBuilder.build(JavaBuilder.java:68) at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:358) at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:821) at org.eclipse.core.runtime.Platform.run(Platform.java:395) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:116) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:181) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:191) at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:140) at org.eclipse.core.internal.runtime.InternalPlatform.run(InternalPlatform.java:821) at org.eclipse.core.runtime.Platform.run(Platform.java:395) at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:154) at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:216) at org.eclipse.core.internal.resources.Workspace.endOperation(Workspace.java:701) at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1237) at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:78) at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:296) at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:249) at org.eclipse.jface.wizard.WizardDialog.run(WizardDialog.java:713) at org.eclipse.jdt.internal.ui.wizards.NewProjectCreationWizard.performFinish(NewProjectCreationWizard.java:63) at org.eclipse.jface.wizard.WizardDialog.finishPressed(WizardDialog.java:570) at org.eclipse.jface.wizard.WizardDialog.buttonPressed(WizardDialog.java:311) at org.eclipse.jface.dialogs.Dialog$1.widgetSelected(Dialog.java:344) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:85) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:74) at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:637) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1413) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1205) at org.eclipse.jface.window.Window.runEventLoop(Window.java:536) at org.eclipse.jface.window.Window.open(Window.java:523) at org.eclipse.ui.actions.NewProjectAction.run(NewProjectAction.java:96) at org.eclipse.jface.action.Action.runWithEvent(Action.java:452) at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:407) at org.eclipse.jface.action.ActionContributionItem.handleWidgetEvent(ActionContributionItem.java:361) at org.eclipse.jface.action.ActionContributionItem.access$0(ActionContributionItem.java:352) at org.eclipse.jface.action.ActionContributionItem$ActionListener.handleEvent(ActionContributionItem.java:47) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:74) at org.eclipse.swt.widgets.Widget.notifyListeners(Widget.java:637) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:1413) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:1205) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:844) at org.eclipse.ui.internal.Workbench.run(Workbench.java:827) at org.eclipse.core.internal.boot.InternalBootLoader.run(InternalBootLoader.java:878) at org.eclipse.core.boot.BootLoader.run(BootLoader.java:321) at java.lang.reflect.Method.invoke(Native Method) at org.eclipse.core.launcher.Main.basicRun(Main.java:151) at org.eclipse.core.launcher.Main.run(Main.java:502) at org.eclipse.core.launcher.Main.main(Main.java:362) 2=============</children>=============
Could you produce ? 1- the build number of your Eclipse SDK 2- a source sample exposing this defect
There should be an error logged against the offending compilation unit, which message should be the stack trace from the .log. This might help you to narrow the offending source. Good luck !
build number: 20011219
Could you find the source of the offending compilation unit and paste it in ? This problem occurs while performing the innerclass emulation, and there should be a compilation error on this offending unit, which message is the stack trace which was in the log. I am interested in the source of the unit so as to reproduce it.
I will give you test class in near future but now I resposible saying that - it have about 10 inner classes and third level of innerness.
Seems like a good stress test of innerclasses. Please just send me the whole thing, I will give it a try.
Deferring since waiting for a testcase.
import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.util.*; import javax.swing.*; import javax.swing.table.*; import javax.swing.border.*; import javax.swing.plaf.ToolTipUI; import javax.swing.plaf.ComponentUI; public class FTOchartFrame { //constants private static final int GENERATE_RANDOM_DEMO = 1; private static final int GENERATE_CUSTOM_DEMO = 2; /** Field <code>DEMO_LENGTH</code> */ protected static int DEMO_LENGTH = 5; //data /** Field <code>parent</code> */ private java.util.List pieData = new ArrayList(); private FTOpiePiece[] workCopy; private Map content = new HashMap(); //components private JSplitPane split; /** Field <code>chart</code> */ protected FTO2dChart chart; /** Field <code>legend</code> */ protected FTOchartLegend legend; //formatting /** Field <code>legendWidth</code> */ protected int legendWidth = 100; /** Field <code>minSize</code> */ protected int minSize = 125; /** Field <code>m_backgroundColor</code> */ public static Color m_backgroundColor; //options /** Field <code>isLegendVisible</code> */ protected boolean isLegendVisible = true; /** Field <code>isEllipseEnabled</code> */ public boolean isEllipseEnabled = false; /** Field <code>isDataModified</code> */ public boolean isDataModified = true; private boolean isInitializing = true; private boolean isCallbackNeeded = true; //for test /** Field <code>test</code> */ Thread test; protected FTOchartFrame( int mode ) { Thread test = new Thread( new Runnable() { public void run() { try { while ( true ) { Thread.currentThread().sleep( 3000 ); Vector newData = new Vector( Arrays .asList( generateRandomTest() ) ); rebuildPie( newData ); } } catch ( Exception e ) {} } } ); //test.start(); } /** * Constructor <code>FTOchartFrame</code> * * * @param <code>t</code> is of <code>FTOaccJtable</code> type * @param <code>data</code> is of <code>java.util.List</code> type * @param <code>title</code> is of <code>String</code> type * @param <code>conf</code> is of <code>String</code> type * */ public FTOchartFrame( java.util.List data, String title, String conf ) { initContent(); //pieData = createDataSet( data ); rebuildPie( data ); chart = createPieChart(); legend = new FTOchartLegend( this ); chart.setLegend( legend ); split = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, true, chart, legend ); split.setDividerSize( 0 ); split.setEnabled( false ); WindowListener wndCloser = new WindowAdapter() { public void windowClosing( WindowEvent e ) { if ( ( test != null ) && test.isAlive() ) test.interrupt(); dispose(); } public void windowActivated( WindowEvent e ) { } }; resetFromConfig(); SwingUtilities.invokeLater( new Runnable() { public void run() { } } ); } /** * Method <code>dispose</code> * * */ public void dispose() { SwingUtilities.invokeLater( new Runnable() { public void run() { destroy(); } } ); } private void destroy() { if ( chart == null ) return; chart.destroy(); legend.destroy(); pieData.clear(); workCopy = null; content.clear(); split.removeAll(); split = null; chart = null; legend = null; } /** * Method <code>reapplyConfig</code> * * * @param <code>conf</code> is of <code>String</code> type * */ public void reapplyConfig( String conf ) { resetFromConfig(); } /** * Method <code>activateChart</code> * * */ public void activateChart() { isCallbackNeeded = false; } protected void resetFromConfig() { } /** * Method <code>getConfig</code> * * * @return the value of <code>String</code> type * */ // public String getConfig() protected void centerWindow() { } //Convert FTOpieChartableElement to FTOpiePiece private void initContent() { content = Collections.synchronizedMap( content ); } private static java.util.List createTestData( int mode ) { java.util.List data = null; if ( mode == GENERATE_RANDOM_DEMO ) data = new ArrayList( Arrays.asList( generateRandomTest() ) ); else if ( mode == GENERATE_CUSTOM_DEMO ) data = new ArrayList( Arrays.asList( generateCustomTest() ) ); return Collections.synchronizedList( data ); } /** * Method <code>rebuildPie</code> * * * @param <code>v</code> is of <code>java.util.List</code> type * */ public void rebuildPie( java.util.List v ) { HashMap update = new HashMap(); HashSet updates = new HashSet( update.keySet() ); Set current = content.keySet(); Set newItems = new HashSet(); Set oldItems = new HashSet(); //check for new items if ( !current.containsAll( updates ) ) { newItems = new HashSet( updates ); newItems.removeAll( current ); isDataModified = true; } //check for removed items if ( !updates.containsAll( current ) ) { oldItems = new HashSet( current ); oldItems.removeAll( updates ); isDataModified = true; } //removing old items for ( Iterator i = oldItems.iterator(); i.hasNext(); ) { FTOpiePiece p = (FTOpiePiece) content.get( i.next() ); if ( p.isPieceSelected() ) selectionChanged( -1, false ); pieData.remove( p ); } current.removeAll( oldItems ); //checking for modifications in existing data for ( Iterator i = current.iterator(); i.hasNext(); ) { } //adding new Items for ( Iterator i = newItems.iterator(); i.hasNext(); ) { } } /** * Method <code>isEmpty</code> * * * @return the value of <code>boolean</code> type * */ public boolean isEmpty() { //return workCopy.length == 0; return pieData.size() == 0; } /** * Method <code>getWorkCopy</code> * * * @return the value of <code>FTOpiePiece[]</code> type * */ public FTOpiePiece[] getWorkCopy() { return workCopy; } /** * Method <code>setWorkCopy</code> * * * @param <code>c</code> is of <code>FTOpiePiece[]</code> type * */ public void setWorkCopy( FTOpiePiece[] c ) { workCopy = c; if ( legend != null ) legend.m_pieData = c; } /** * Method <code>getChart</code> * * * @return the value of <code>FTO2dChart</code> type * */ public FTO2dChart getChart() { return chart; } /** * Method <code>getData</code> * * * @return the value of <code>java.util.List</code> type * */ public java.util.List getData() { return pieData; } /** * Method <code>selectionChanged</code> * * * @param <code>index</code> is of <code>int</code> type * @param <code>notify</code> is of <code>boolean</code> type * */ public void selectionChanged( int index, boolean notify ) { chart.selectionChanged( index, notify ); } /** * Method <code>selectionChanged</code> * * * @param <code>id</code> is of <code>String</code> type * */ public void selectionChanged( String id ) { chart.selectionChanged( id ); } /** * Method <code>clearSelection</code> * * */ public void clearSelection() { chart.clearSelection(); } /** * Method <code>getGradientPaint</code> * * * @return the value of <code>boolean</code> type * */ public boolean getGradientPaint() { return ( chart.getEffectIndex() == chart.EFFECT_GRADIENT ); } /** * Method <code>invertGradient</code> * * */ public void invertGradient() { if ( chart.getEffectIndex() == chart.EFFECT_GRADIENT ) chart.setEffectIndex( chart.EFFECT_PLAIN ); else chart.setEffectIndex( chart.EFFECT_GRADIENT ); } /** * Method <code>getShadows</code> * * * @return the value of <code>boolean</code> type * */ public boolean getShadows() { return chart.getDrawShadow(); } /** * Method <code>invertShadows</code> * * */ public void invertShadows() { if ( chart.getDrawShadow() ) chart.setDrawShadow( false ); else chart.setDrawShadow( true ); } /** * Method <code>getLegend</code> * * * @return the value of <code>boolean</code> type * */ public boolean getLegend() { return isLegendVisible; } /** * Method <code>invertLegend</code> * * */ public void invertLegend() { isLegendVisible = !isLegendVisible; setDevLocation(); //chart.repaint(); } /** * Method <code>getSortingNeeded</code> * * * @return the value of <code>boolean</code> type * */ public boolean getSortingNeeded() { return chart.getSorting(); } /** * Method <code>invertSorting</code> * * */ public void invertSorting() { if ( chart.getSorting() ) chart.setSorting( false ); else chart.setSorting( true ); } /** * Method <code>getEllipseEnabled</code> * * * @return the value of <code>boolean</code> type * */ public boolean getEllipseEnabled() { return isEllipseEnabled; } /** * Method <code>invertEllipse</code> * * */ public void invertEllipse() { isEllipseEnabled = !isEllipseEnabled; chart.calculateDimensions(); chart.repaint(); } /** * Method <code>getGap</code> * * * @return the value of <code>double</code> type * */ public double getGap() { return chart.getGap(); } /** * Method <code>increaseGap</code> * * */ public void increaseGap() { chart.increaseGap(); } /** * Method <code>decreaseGap</code> * * */ public void decreaseGap() { chart.decreaseGap(); } protected void processComponentEvent( ComponentEvent e ) { setDevLocation(); } protected void setDevLocation() { if ( split == null ) return; int devider = split.getWidth() - split.getDividerSize(); if ( ( isLegendVisible ) && ( split.getWidth() >= 2 * legendWidth ) ) devider -= legendWidth; split.setDividerLocation( devider ); } private FTO2dChart createPieChart() { FTO2dChart chart = new FTO2dChart( FTO2dChart.CHART_DOUBLE_PIE, this ); chart.setEffectIndex( FTO2dChart.EFFECT_PLAIN ); chart.setDrawShadow( true ); return chart; } //For testing only private static FTOinputData[] generateRandomTest() { int[] yData = new int[DEMO_LENGTH]; int[] yDataPL = new int[DEMO_LENGTH]; for ( int k = 0; k < DEMO_LENGTH; k++ ) { yData[k] = (int) ( Math.random() * 100 ); yDataPL[k] = (int) ( Math.random() * 100 ); boolean sign = ( (int) ( Math.random() * 100 ) ) % 2 == 0; if ( k > 0 ) { yData[k] = ( yData[k - 1] + yData[k] ) / 2; yDataPL[k] = ( yDataPL[k - 1] + yDataPL[k] ) / 2; if ( sign ) yDataPL[k] *= -1; } } FTOinputData[] pieData = new FTOinputData[DEMO_LENGTH]; for ( int k = 0; k < DEMO_LENGTH; k++ ) { FTOinputData piece = new FTOinputData( " piece " + k, " piece " + k, yData[k], yDataPL[k] ); pieData[k] = piece; } return pieData; } //For testing only private static FTOinputData[] generateCustomTest() { int nData = 8; DEMO_LENGTH = nData; FTOinputData[] data = new FTOinputData[nData]; double volume = 50; double pl = 0; FTOinputData piece = new FTOinputData( " piece " + 0, " piece " + 0, volume, pl ); data[0] = piece; volume = 45; pl = 60; piece = new FTOinputData( " piece " + 1, " piece " + 1, volume, pl ); data[1] = piece; volume = 45; pl = -100; piece = new FTOinputData( " piece " + 2, " piece " + 2, volume, pl ); data[2] = piece; volume = 45; pl = 15; piece = new FTOinputData( " piece " + 3, " piece " + 3, volume, pl ); data[3] = piece; volume = 45; pl = -30; piece = new FTOinputData( " piece " + 4, " piece " + 4, volume, pl ); data[4] = piece; volume = 45; pl = -50; piece = new FTOinputData( " piece " + 5, " piece " + 5, volume, pl ); data[5] = piece; volume = 45; pl = 105; piece = new FTOinputData( " piece " + 6, " piece " + 6, volume, pl ); data[6] = piece; volume = 40; pl = 0; piece = new FTOinputData( " piece " + 7, " piece " + 7, volume, pl ); data[7] = piece; return data; } /** * Method <code>removeWhiteSpacing</code> * * * @param <code>dimension</code> is of <code>double</code> type * */ public void removeWhiteSpacing( double dimension ) { } //For testing only /** * Method <code>main</code> * * * @param <code>argv</code> is of <code>String[]</code> type * */ public static void main( String argv[] ) { new FTOchartFrame( GENERATE_RANDOM_DEMO ); } } class FTOchartLegend extends JPanel { /** Field <code>legend</code> */ FTOlegendPanel legend; /** Field <code>scroll</code> */ JScrollPane scroll; /** Field <code>m_pieData</code> */ FTOpiePiece[] m_pieData; /** Field <code>parent</code> */ FTOchartFrame parent; /** Field <code>isSelectionChanged</code> */ boolean isSelectionChanged = false; /** * Constructor <code>FTOchartLegend</code> * * * @param <code>parent</code> is of <code>FTOchartFrame</code> type * */ public FTOchartLegend( FTOchartFrame parent ) { super( new BorderLayout() ); setBackground( FTOchartFrame.m_backgroundColor ); m_pieData = parent.getWorkCopy(); this.parent = parent; legend = new FTOlegendPanel(); scroll = new JScrollPane( legend, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ); add( scroll, BorderLayout.CENTER ); } /** * Method <code>destroy</code> * * */ public void destroy() { scroll.removeAll(); removeAll(); scroll = null; parent = null; legend = null; m_pieData = null; } /** * Method <code>selectionChanged</code> * * */ public void selectionChanged() { isSelectionChanged = true; repaint(); } class FTOlegendPanel extends JComponent { /** Field <code>m_xMargin</code> */ int m_xMargin = 5; /** Field <code>m_yMargin</code> */ int m_yMargin = 10; /** Field <code>rect_width</code> */ int rect_width = 15; /** Field <code>rect_height</code> */ int rect_height = 10; /** Field <code>isHidden</code> */ boolean isHidden = false; /** Field <code>m_lineThickness</code> */ int m_lineThickness = 3; /** Field <code>m_stroke</code> */ Stroke m_stroke = new BasicStroke( m_lineThickness, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL ); /** Field <code>textFont</code> */ Font textFont = new Font( "Arial", Font.BOLD, rect_height ); /** Field <code>selFont</code> */ Font selFont = new Font( "Arial", Font.BOLD, rect_height + 1 ); /** * Constructor <code>FTOlegendPanel</code> * * */ public FTOlegendPanel() { super(); addMouseListener( new MouseAdapter() { public void mousePressed( MouseEvent e ) { if ( ( e.getModifiers() & MouseEvent.BUTTON1_MASK ) > 0 ) { Point p = e.getPoint(); int index = getPieceIndexAtPoint( p ); parent.selectionChanged( index, true ); } } } ); enableEvents( ComponentEvent.COMPONENT_RESIZED ); } /** * Method <code>processComponentEvent</code> * * * @param <code>e</code> is of <code>ComponentEvent</code> type * */ public void processComponentEvent( ComponentEvent e ) { if ( getWidth() == 0 ) { if ( !isHidden ) { parent.getChart().repaint(); isHidden = true; } } else if ( isHidden ) { isHidden = false; parent.getChart().repaint(); } } protected int getPieceIndexAtPoint( Point p ) { int result = -1; if ( m_pieData.length == 0 ) return result; int x = ( getWidth() - ( 2 * m_xMargin + rect_width + textFont .getSize() / 2 * m_pieData[0].getName().length() ) ) / 2; int y = m_yMargin; for ( int i = 0; i < m_pieData.length; i++ ) { Rectangle2D.Double r = new Rectangle2D.Double( x, y, rect_width, rect_height ); if ( r.contains( p.getX(), p.getY() ) ) { result = i; break; } y += rect_height + m_yMargin; } return result; } /** * Method <code>paintComponent</code> * * * @param <code>g</code> is of <code>Graphics</code> type * */ public void paintComponent( Graphics g ) { if ( parent.isEmpty() || ( m_pieData.length == 0 ) ) return; Rectangle selection = null; Graphics2D g2 = (Graphics2D) g; //setting background g2.setColor( FTOchartFrame.m_backgroundColor ); int x = ( getWidth() - ( 2 * m_xMargin + rect_width + textFont .getSize() / 2 * m_pieData[0].getName().length() ) ) / 2; int y = m_yMargin; int textX = x + rect_width + m_xMargin; g2.setFont( textFont ); g2.setStroke( m_stroke ); for ( int i = 0; i < m_pieData.length; i++ ) { Rectangle2D.Double r = new Rectangle2D.Double( x, y, rect_width, rect_height ); g2.setColor( m_pieData[i].getPieceColor() ); g2.fill3DRect( x, y, rect_width, rect_height, true ); if ( m_pieData[i].isPieceSelected() ) { g2.setColor( FTO2dChart.m_SelectionColor ); g2.draw( r ); g2.setFont( selFont ); g2.drawString( m_pieData[i].getName().toUpperCase(), textX, y + selFont.getSize() - 2 ); g2.setFont( textFont ); g2.setColor( m_pieData[i].getPieceColor() ); selection = new Rectangle( x, y, rect_width, rect_height ); } g2.drawString( m_pieData[i].getName().toUpperCase(), textX, y + textFont.getSize() ); y += rect_height + m_yMargin; } setPreferredSize( new Dimension( getWidth(), y ) ); revalidate(); if ( selection != null ) { if ( isSelectionChanged ) { scrollRectToVisible( selection ); isSelectionChanged = false; } } } } } class FTO2dChart extends JPanel { /** Field <code>CHART_DOUBLE_PIE</code> */ public static final int CHART_DOUBLE_PIE = 1; /** Field <code>EFFECT_PLAIN</code> */ public static final int EFFECT_PLAIN = 0; /** Field <code>EFFECT_GRADIENT</code> */ public static final int EFFECT_GRADIENT = 1; /** Field <code>EFFECT_IMAGE</code> */ public static final int EFFECT_IMAGE = 2; /** Field <code>MAX_GAP</code> */ final static double MAX_GAP = 0.055; /** Field <code>MIN_GAP</code> */ final static double MIN_GAP = 0; /** Field <code>m_chartType</code> */ protected int m_chartType = CHART_DOUBLE_PIE; /** Field <code>parent</code> */ protected FTOchartFrame parent; /** Field <code>m_title</code> */ protected JLabel m_title; /** Field <code>m_chart</code> */ protected FTOchartPanel m_chart; /** Field <code>m_xData</code> */ protected int[] m_xData; /** Field <code>m_yData</code> */ protected int[] m_yData; /** Field <code>m_xMin</code> */ protected int m_xMin; /** Field <code>m_xMax</code> */ protected int m_xMax; /** Field <code>m_yMin</code> */ protected int m_yMin; /** Field <code>m_yMax</code> */ protected int m_yMax; private FTOpiePiece[] m_model = new FTOpiePiece[0]; /** Field <code>m_effectIndex</code> */ protected int m_effectIndex = EFFECT_PLAIN; /** Field <code>m_stroke</code> */ protected Stroke m_stroke; /** Field <code>m_sel_stroke</code> */ protected Stroke m_sel_stroke; /** Field <code>m_foregroundImage</code> */ protected Image m_foregroundImage; /** Field <code>m_lineColor</code> */ public static Color m_lineColor = Color.black; /** Field <code>m_SelectionColor</code> */ public static Color m_SelectionColor = Color.white; /** Field <code>m_drawShadow</code> */ protected boolean m_drawShadow = false; /** Field <code>m_lineThickness</code> */ protected float m_lineThickness = (float) 1.6; /** Field <code>isRotated</code> */ protected boolean isRotated = true; /** Field <code>isSortingNeeded</code> */ protected boolean isSortingNeeded = true; /** Field <code>legend</code> */ protected FTOchartLegend legend; /** * Constructor <code>FTO2dChart</code> * * * @param <code>type</code> is of <code>int</code> type * @param <code>parent</code> is of <code>FTOchartFrame</code> type * */ public FTO2dChart( int type, FTOchartFrame parent ) { super( new BorderLayout() ); setBackground( FTOchartFrame.m_backgroundColor ); this.parent = parent; m_chartType = type; if ( type == CHART_DOUBLE_PIE ) { m_stroke = new BasicStroke( m_lineThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ); m_sel_stroke = new BasicStroke( m_lineThickness + 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ); } m_chart = new FTOchartPanel(); add( m_chart, BorderLayout.CENTER ); } /** * Method <code>destroy</code> * * */ public void destroy() { m_chart.destroy(); removeAll(); parent = null; m_chart = null; legend = null; m_model = null; } /** * Method <code>setGap</code> * * * @param <code>d</code> is of <code>double</code> type * */ public void setGap( double d ) { m_chart.setGap( d ); } /** * Method <code>getGap</code> * * * @return the value of <code>double</code> type * */ public double getGap() { return m_chart.getGap(); } /** * Method <code>calculateDimensions</code> * * */ public void calculateDimensions() { m_chart.calcDimensions(); } /** * Method <code>increaseGap</code> * * */ public void increaseGap() { m_chart.increaseGap(); m_chart.isGap = true; } /** * Method <code>decreaseGap</code> * * */ public void decreaseGap() { m_chart.decreaseGap(); m_chart.isGap = true; } /** * Method <code>selectionChanged</code> * * * @param <code>index</code> is of <code>int</code> type * @param <code>notify</code> is of <code>boolean</code> type * */ public void selectionChanged( int index, boolean notify ) { m_chart.selectionChanged( index, notify ); } /** * Method <code>clearSelection</code> * * */ public void clearSelection() { m_chart.clearSelection(); } /** * Method <code>selectionChanged</code> * * * @param <code>id</code> is of <code>String</code> type * */ public void selectionChanged( String id ) { int index = -1; for ( int i = 0; i < m_model.length; i++ ) { if ( m_model[i].getId().equals( id ) ) { index = i; break; } } selectionChanged( index, false ); } /** * Method <code>guiCallback</code> * * * @param <code>index</code> is of <code>int</code> type * */ public void guiCallback( int index ) { } /** * Method <code>getSorting</code> * * * @return the value of <code>boolean</code> type * */ public boolean getSorting() { return isSortingNeeded; } /** * Method <code>getChartHeight</code> * * * @return the value of <code>int</code> type * */ public int getChartHeight() { return m_chart.getHeight(); } /** * Method <code>setSorting</code> * * * @param <code>par</code> is of <code>boolean</code> type * */ public void setSorting( boolean par ) { isSortingNeeded = par; isRotated = true; m_chart.isSorted = false; } /** * Method <code>setLegend</code> * * * @param <code>legend</code> is of <code>FTOchartLegend</code> type * */ public void setLegend( FTOchartLegend legend ) { this.legend = legend; } /** * Method <code>setEffectIndex</code> * * * @param <code>effectIndex</code> is of <code>int</code> type * */ public void setEffectIndex( int effectIndex ) { m_effectIndex = effectIndex; if ( m_effectIndex == EFFECT_GRADIENT ) m_chart.isGradient = true; repaint(); } /** * Method <code>getEffectIndex</code> * * * @return the value of <code>int</code> type * */ public int getEffectIndex() { return m_effectIndex; } /** * Method <code>setStroke</code> * * * @param <code>stroke</code> is of <code>Stroke</code> type * */ public void setStroke( Stroke stroke ) { m_stroke = stroke; m_chart.repaint(); } /** * Method <code>setForegroundImage</code> * * * @param <code>img</code> is of <code>Image</code> type * */ public void setForegroundImage( Image img ) { m_foregroundImage = img; repaint(); } /** * Method <code>getForegroundImage</code> * * * @return the value of <code>Image</code> type * */ public Image getForegroundImage() { return m_foregroundImage; } /** * Method <code>getStroke</code> * * * @return the value of <code>Stroke</code> type * */ public Stroke getStroke() { return m_stroke; } /** * Method <code>setLineColor</code> * * * @param <code>c</code> is of <code>Color</code> type * */ public void setLineColor( Color c ) { m_lineColor = c; m_chart.repaint(); } /** * Method <code>getLineColor</code> * * * @return the value of <code>Color</code> type * */ public Color getLineColor() { return m_lineColor; } /** * Method <code>setDrawShadow</code> * * * @param <code>drawShadow</code> is of <code>boolean</code> type * */ public void setDrawShadow( boolean drawShadow ) { m_drawShadow = drawShadow; m_chart.repaint(); } /** * Method <code>getDrawShadow</code> * * * @return the value of <code>boolean</code> type * */ public boolean getDrawShadow() { return m_drawShadow; } class FTOchartPanel extends JComponent implements ActionListener { /** Field <code>m_xMargin</code> */ int m_xMargin = 10; /** Field <code>m_yMargin</code> */ int m_yMargin = 10; /** Field <code>m_pieGap</code> */ double m_pieGap; //min 0.025 max 0.055 /** Field <code>gapStep</code> */ double gapStep = 0.01; /** Field <code>min_gap</code> */ double min_gap = 0.025; /** Field <code>m_gapCoefficient</code> */ double m_gapCoefficient = 0; //0.035; /** Field <code>m_ringCoefficient</code> */ final double m_ringCoefficient = 0.1; /** Field <code>m_x</code> */ int m_x; /** Field <code>m_y</code> */ int m_y; /** Field <code>m_w</code> */ int m_w; /** Field <code>m_h</code> */ int m_h; /** Field <code>lastSelectedPiece</code> */ int lastSelectedPiece = -1; /** Field <code>startIndex</code> */ int startIndex = 0; /** Field <code>isSorted</code> */ boolean isSorted = false; /** Field <code>isResized</code> */ boolean isResized = true; /** Field <code>isGradient</code> */ boolean isGradient = false; /** Field <code>isGap</code> */ boolean isGap = false; private final String ACTION_SHADOWS = "shadows"; private final String ACTION_ELLIPSE = "ellipse"; private final String ACTION_PAINTING = "gradient"; private final String ACTION_SORTING = "sorting"; private final String ACTION_GAP_UP = "gap+"; private final String ACTION_GAP_DOWN = "gap-"; private final String ACTION_LEGEND = "legend"; /** Field <code>popup</code> */ protected FTOchartPopupMenu popup; /** Field <code>comp</code> */ protected Comparator comp = new FTOchartComparator(); FTOchartPanel() { enableEvents( ComponentEvent.COMPONENT_RESIZED ); popup = new FTOchartPopupMenu( parent ); registerKeyboardActions(); restoreOriginal(); //Initializing tooltips setToolTipText( "" ); } /** * Method <code>destroy</code> * * */ public void destroy() { popup.destroy(); removeAll(); comp = null; popup = null; } /** * Method <code>setGap</code> * * * @param <code>d</code> is of <code>double</code> type * */ public void setGap( double d ) { m_gapCoefficient = d; } /** * Method <code>getGap</code> * * * @return the value of <code>double</code> type * */ public double getGap() { return m_gapCoefficient; } /** * Method <code>createToolTip</code> * * * @return the value of <code>JToolTip</code> type * */ public JToolTip createToolTip() { JToolTip tip = new FTOtoolTip(); tip.setComponent( this ); return tip; } private synchronized void restoreOriginal() { m_model = new FTOpiePiece[0]; java.util.List data = parent.getData(); java.util.List copy = new ArrayList( data ); m_model = (FTOpiePiece[]) copy.toArray( m_model ); parent.setWorkCopy( m_model ); } private void registerKeyboardActions() { KeyStroke ks = KeyStroke.getKeyStroke( KeyEvent.VK_S, 0, false ); registerKeyboardAction( this, ACTION_SHADOWS, ks, WHEN_IN_FOCUSED_WINDOW ); ks = KeyStroke.getKeyStroke( KeyEvent.VK_E, 0, false ); registerKeyboardAction( this, ACTION_ELLIPSE, ks, WHEN_IN_FOCUSED_WINDOW ); /*ks = KeyStroke.getKeyStroke( KeyEvent.VK_O, 0, false ); registerKeyboardAction( this, ACTION_SORTING, ks, WHEN_IN_FOCUSED_WINDOW );*/ ks = KeyStroke.getKeyStroke( KeyEvent.VK_G, 0, false ); registerKeyboardAction( this, ACTION_PAINTING, ks, WHEN_IN_FOCUSED_WINDOW ); ks = KeyStroke.getKeyStroke( KeyEvent.VK_UP, 0, false ); registerKeyboardAction( this, ACTION_GAP_UP, ks, WHEN_IN_FOCUSED_WINDOW ); ks = KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, 0, false ); registerKeyboardAction( this, ACTION_GAP_DOWN, ks, WHEN_IN_FOCUSED_WINDOW ); ks = KeyStroke.getKeyStroke( KeyEvent.VK_L, 0 ); registerKeyboardAction( this, ACTION_LEGEND, ks, WHEN_IN_FOCUSED_WINDOW ); } /** * Method <code>actionPerformed</code> * * * @param <code>e</code> is of <code>ActionEvent</code> type * */ public void actionPerformed( ActionEvent e ) { if ( parent.isEmpty() ) return; String command = e.getActionCommand(); if ( command.equals( ACTION_ELLIPSE ) ) parent.invertEllipse(); else if ( command.equals( ACTION_GAP_DOWN ) ) parent.decreaseGap(); else if ( command.equals( ACTION_GAP_UP ) ) parent.increaseGap(); else if ( command.equals( ACTION_LEGEND ) ) parent.invertLegend(); else if ( command.equals( ACTION_PAINTING ) ) parent.invertGradient(); else if ( command.equals( ACTION_SHADOWS ) ) parent.invertShadows(); else if ( command.equals( ACTION_SORTING ) ) parent.invertSorting(); } /** * Method <code>processMouseEvent</code> * * * @param <code>e</code> is of <code>MouseEvent</code> type * */ public void processMouseEvent( MouseEvent e ) { if ( e.isPopupTrigger() ) { popup.show( this, e.getX(), e.getY() ); } else { if ( ( e.getID() == MouseEvent.MOUSE_PRESSED ) && ( e.getModifiers() & MouseEvent.BUTTON1_MASK ) > 0 ) { Point p = e.getPoint(); int index = getPieceIndexAtPoint( p ); selectionChanged( index, true ); } } super.processMouseEvent( e ); } /** * Method <code>increaseGap</code> * * */ public void increaseGap() { if ( (int) ( m_gapCoefficient * 1000 ) == (int) ( MAX_GAP * 1000 ) ) return; m_gapCoefficient += gapStep; if ( m_gapCoefficient < min_gap ) m_gapCoefficient = min_gap; repaint(); } /** * Method <code>decreaseGap</code> * * */ public void decreaseGap() { m_gapCoefficient -= gapStep; if ( m_gapCoefficient < min_gap ) m_gapCoefficient = 0; repaint(); } /** * Method <code>selectionChanged</code> * * * @param <code>index</code> is of <code>int</code> type * @param <code>isNotifyNeeded</code> is of <code>boolean</code> type * */ public void selectionChanged( int index, boolean isNotifyNeeded ) { if ( index < 0 ) return; if ( lastSelectedPiece == index ) return; if ( lastSelectedPiece >= 0 ) m_model[lastSelectedPiece].setPieceSelected( false ); lastSelectedPiece = index; m_model[index].setPieceSelected( true ); legend.selectionChanged(); isRotated = true; repaint(); if ( isNotifyNeeded ) guiCallback( index ); } /** * Method <code>clearSelection</code> * * */ public void clearSelection() { if ( lastSelectedPiece < 0 ) return; m_model[lastSelectedPiece].setPieceSelected( false ); lastSelectedPiece = -1; legend.selectionChanged(); repaint(); } protected void arrangePieces() { isSorted = false; if ( !isSortingNeeded ) restoreOriginal(); else { java.util.List copy = Arrays.asList( m_model ); Collections.sort( copy, comp ); } legend.repaint(); } protected void resetColors() { if ( m_model.length == 0 ) return; int plCount = 0; int profitCount = 0; int zeroCount = 0; for ( int i = 0; i < m_model.length; i++ ) { if ( m_model[i].isProfitPiece() > 0 ) profitCount++; else if ( m_model[i].isProfitPiece() < 0 ) plCount++; else zeroCount++; } int profitStep = 155 / ( profitCount + 1 ); int plStep = 200 / ( plCount + 1 ); int zeroStep = 200 / ( zeroCount + 1 ); java.util.List copy = Arrays.asList( m_model ); ArrayList l = new ArrayList( copy ); Collections.sort( l, comp ); //pl < 0 - red for ( int i = 0; i < plCount; i++ ) { FTOpiePiece p = (FTOpiePiece) l.get( i ); Color c = new Color( 255 - plStep * i, 0, 0 ); p.setGradientStart( new Color( 255, 0, 0 ) ); p.setPieceColor( c ); } //pl = 0 - blue for ( int i = plCount; i < plCount + zeroCount; i++ ) { FTOpiePiece p = (FTOpiePiece) l.get( i ); Color c = new Color( 0, 0, 255 - zeroStep * ( i - plCount ) ); p.setGradientStart( new Color( 0, 0, 255 ) ); p.setPieceColor( c ); } // pl > 0 - green for ( int i = plCount + zeroCount; i < m_model.length; i++ ) { FTOpiePiece p = (FTOpiePiece) l.get( i ); Color c = new Color( 0, 100 + profitStep * ( i - plCount - zeroCount ), 0 ); p.setGradientStart( new Color( 0, 255, 0 ) ); p.setPieceColor( c ); } } private int getPieceIndexAtPoint( Point p ) { int result = -1; for ( int i = 0; i < m_model.length; i++ ) { if ( ( m_model[i].getShape() != null ) && ( m_model[i].getShapePL() != null ) ) { if ( m_model[i].getShape().contains( p.getX(), p.getY() ) || m_model[i].getShapePL().contains( p.getX(), p.getY() ) ) { result = i; break; } } } return result; } protected void processComponentEvent( ComponentEvent e ) { calcDimensions(); isResized = true; repaint(); } /** * Method <code>calcDimensions</code> * * */ public void calcDimensions() { if ( parent == null ) return; Dimension d = getSize(); m_x = m_xMargin; m_y = m_yMargin; m_w = d.width - 2 * m_xMargin; m_h = d.height - 2 * m_yMargin; if ( !parent.isEllipseEnabled && ( Math.abs( d.getWidth() - d.getHeight() ) > 1 ) ) parent.removeWhiteSpacing( Math.min( d.getWidth(), d.getHeight() ) ); } /** * Method <code>getToolTipText</code> * * * @param <code>event</code> is of <code>MouseEvent</code> type * * @return the value of <code>String</code> type * */ public String getToolTipText( MouseEvent event ) { int index = getPieceIndexAtPoint( new Point( event.getX(), event.getY() ) ); String result = null; if ( index >= 0 ) { } return result; } /** * Method <code>paint</code> * * * @param <code>g</code> is of <code>Graphics</code> type * */ public void paint( Graphics g ) { if ( parent.isEmpty() ) return; Graphics2D g2 = (Graphics2D) g; //setting graphics quality options setGraphicOptions( g2 ); //calculating gap absolute value m_pieGap = m_gapCoefficient * Math.min( m_w, m_h ); //setting stroke if ( m_stroke != null ) g2.setStroke( m_stroke ); //setting background g2.setColor( FTOchartFrame.m_backgroundColor ); g2.fill( g2.getClip() ); switch ( m_chartType ) { case CHART_DOUBLE_PIE : { //Calculating angles if ( parent.isDataModified ) { restoreOriginal(); convertToAngles(); isRotated = true; parent.isDataModified = false; } if ( !isSorted ) arrangePieces(); //initializing painting area double ww = m_w - 2 * m_pieGap; double hh = m_h - 2 * m_pieGap; if ( !parent.isEllipseEnabled ) { ww = Math.min( ww, hh ); hh = ww; } //if ( m_drawShadow ) //{ ww -= m_pieGap; hh -= m_pieGap; //} //recalculating angles, rotating if needed if ( isRotated ) calculateAngles(); //creating shapes, if needed if ( isRotated || isResized || isGradient || isGap ) { for ( int k = 0; k < m_model.length; k++ ) { createPiePiece( k, ww, hh ); } isRotated = false; isResized = false; isGradient = false; isGap = false; } break; } } //drawing shadows, if needed if ( m_drawShadow ) for ( int k = 0; k < m_model.length; k++ ) { g2.setColor( Color.gray ); g2.fill( m_model[k].getShadow() ); } lastSelectedPiece = -1; //drawing pieces ( exclude selected ) for ( int k = 0; k < m_model.length; k++ ) { if ( !m_model[k].isPieceSelected() ) { //setting gradient paint if ( ( m_effectIndex == EFFECT_GRADIENT ) && ( m_model[k].getGradient() != null ) ) { g2.setPaint( m_model[k].getGradient() ); g2.fill( m_model[k].getShape() ); g2.fill( m_model[k].getShapePL() ); } //setting plain color else if ( ( m_effectIndex == EFFECT_PLAIN ) && ( m_model[k].getPieceColor() != null ) ) { g2.setColor( m_model[k].getPieceColor() ); g2.fill( m_model[k].getShape() ); g2.fill( m_model[k].getShapePL() ); } //if no gap, then border painting needed if ( m_gapCoefficient == 0 ) g2.setColor( m_lineColor ); g2.draw( m_model[k].getShape() ); g2.draw( m_model[k].getShapePL() ); } else lastSelectedPiece = k; } //drawing selected piece if ( lastSelectedPiece >= 0 ) { //setting stroke if ( m_stroke != null ) g2.setStroke( m_sel_stroke ); int k = lastSelectedPiece; //setting gradient paint if ( ( m_effectIndex == EFFECT_GRADIENT ) && ( m_model[k].getGradient() != null ) ) { g2.setPaint( m_model[k].getGradient() ); g2.fill( m_model[k].getShape() ); g2.fill( m_model[k].getShapePL() ); } //setting plain color else if ( ( m_effectIndex == EFFECT_PLAIN ) && ( m_model[k].getPieceColor() != null ) ) { g2.setColor( m_model[k].getPieceColor() ); g2.fill( m_model[k].getShape() ); g2.fill( m_model[k].getShapePL() ); } //setting selection color g2.setColor( m_SelectionColor ); g2.draw( m_model[k].getShape() ); g2.draw( m_model[k].getShapePL() ); } } /** * Method <code>updateUI</code> * * */ public void updateUI() { super.updateUI(); if ( popup == null ) return; SwingUtilities.updateComponentTreeUI( popup ); popup.pack(); SwingUtilities.invokeLater( new Runnable() { public void run() { setupFontsAndColors(); } } ); } /** */ public void setupFontsAndColors() {} protected void convertToAngles() { double sum = 0; double sumPL = 0; for ( int k = 0; k < m_model.length; k++ ) { m_model[k].setVolumeAngle( Math.max( m_model[k].getVolume(), 0 ) ); m_model[k].setPLAngle( Math.max( m_model[k].getPL(), 0 ) ); sum += m_model[k].getVolumeAngle(); sumPL += m_model[k].getPLAngle(); } for ( int k = 0; k < m_model.length; k++ ) { m_model[k].setVolumeAngle( m_model[k].getVolumeAngle() * 360.0 / sum ); m_model[k].setPLAngle( m_model[k].getPLAngle() * 360.0 / sumPL ); } isSorted = false; resetColors(); } protected void calculateAngles() { double start = 0.0; double finish = 0.0; startIndex = 0; lastSelectedPiece = -1; for ( int i = 0; i < m_model.length; i++ ) { if ( m_model[i].isPieceSelected() ) { lastSelectedPiece = i; break; } } if ( ( lastSelectedPiece >= 0 ) && ( m_model[lastSelectedPiece].isProfitPiece() != 0 ) ) startIndex = lastSelectedPiece; for ( int k = 0; k < m_model.length; k++ ) { finish = start + m_model[k].getVolumeAngle(); m_model[k].setStart( start ); m_model[k].setFinish( finish ); start = finish; } calculatePLangles(); } protected void calculatePLangles() { double startPL = m_model[startIndex].getStart(); double finishPL = 0.0; for ( int k = startIndex; k < m_model.length; k++ ) { finishPL = startPL + m_model[k].getPLAngle(); m_model[k].setStartPL( startPL ); m_model[k].setFinishPL( finishPL ); startPL = finishPL; } for ( int k = 0; k < startIndex; k++ ) { finishPL = startPL + m_model[k].getPLAngle(); m_model[k].setStartPL( startPL ); m_model[k].setFinishPL( finishPL ); startPL = finishPL; } } protected void createPiePiece( int index, double ww, double hh ) { //calculating ring width double ringWidthX = ww * m_ringCoefficient; double ringWidthY = hh * m_ringCoefficient; //calculating angles double f1 = Math.min( 90 - m_model[index].getStart(), 90 - m_model[index].getFinish() ); double f2 = Math.max( 90 - m_model[index].getStart(), 90 - m_model[index].getFinish() ); double f1PL = Math.min( 90 - m_model[index].getStartPL(), 90 - m_model[index].getFinishPL() ); double f2PL = Math.max( 90 - m_model[index].getStartPL(), 90 - m_model[index].getFinishPL() ); //creating shapes Arc2D.Double shp = new Arc2D.Double( m_x, m_y, ww, hh, f2PL, ( -1 ) * ( f2PL - f1PL ), Arc2D.PIE ); Shape shp2 = new Ellipse2D.Double( m_x + ringWidthX, m_y + ringWidthY, ww - 2 * ringWidthX, hh - 2 * ringWidthY ); Shape shp3 = new Arc2D.Double( m_x + ringWidthX + m_pieGap, m_y + ringWidthY + m_pieGap, ww - 2 * ( m_pieGap + ringWidthX ), hh - 2 * ( m_pieGap + ringWidthY ), f2, ( -1 ) * ( f2 - f1 ), Arc2D.PIE ); Area a = new Area( shp ); Area a2 = new Area( shp2 ); Area a3 = new Area( shp3 ); a.subtract( a2 ); double f = ( f1 + f2 ) / 2 * Math.PI / 180; double fPL = ( f1PL + f2PL ) / 2 * Math.PI / 180; if ( m_effectIndex == EFFECT_GRADIENT ) { Point center = new Point( (int) shp.getCenterX(), (int) shp.getCenterY() ); double radius = Math.min( ww / 2, hh / 2 ); Point finish = new Point( (int) ( center.x + radius * Math.cos( f ) ), (int) ( center.y - radius * Math.sin( f ) ) ); m_model[index].setGradient( new GradientPaint( center.x, center.y, m_model[index].getGradientStart(), finish.x, finish.y, m_model[index].getPieceColor(), true ) ); } //translating if needed if ( m_pieGap != 0 ) { AffineTransform s1 = AffineTransform.getTranslateInstance( m_pieGap * Math.cos( fPL ), -m_pieGap * Math.sin( fPL ) ); a = new Area( s1.createTransformedShape( a ) ); AffineTransform s2 = AffineTransform.getTranslateInstance( m_pieGap * Math.cos( f ), -m_pieGap * Math.sin( f ) ); a3 = new Area( s2.createTransformedShape( a3 ) ); } if ( m_pieGap != 0 ) { AffineTransform s3 = AffineTransform.getTranslateInstance( m_pieGap, m_pieGap ); a3 = new Area( s3.createTransformedShape( a3 ) ); a = new Area( s3.createTransformedShape( a ) ); } m_model[index].setShape( new Area( a3 ) ); m_model[index].setShapePL( a ); a3.add( a ); //creating shadows if needed //if ( m_drawShadow ) //{ AffineTransform s0 = AffineTransform.getTranslateInstance( m_pieGap, m_pieGap ); Shape shadow = s0.createTransformedShape( a3 ); m_model[index].setShadow( shadow ); //} } protected void fillByImage( Graphics2D g2, Shape shape, int xOffset ) { if ( m_foregroundImage == null ) return; int wImg = m_foregroundImage.getWidth( this ); int hImg = m_foregroundImage.getHeight( this ); if ( ( wImg <= 0 ) || ( hImg <= 0 ) ) return; g2.setClip( shape ); Rectangle bounds = shape.getBounds(); for ( int xx = bounds.x + xOffset; xx < bounds.x + bounds.width; xx += wImg ) for ( int yy = bounds.y; yy < bounds.y + bounds.height; yy += hImg ) g2.drawImage( m_foregroundImage, xx, yy, this ); } protected void setGraphicOptions( Graphics2D g ) { g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); g.setRenderingHint( RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY ); g.setRenderingHint( RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints .VALUE_ALPHA_INTERPOLATION_QUALITY ); g.setRenderingHint( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON ); g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); g.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY ); g.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON ); g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints .VALUE_INTERPOLATION_NEAREST_NEIGHBOR ); g.setRenderingHint( RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE ); } } } class FTOpiePiece { private boolean isSelected = false; private int isProfit; private double angleOfVolume; private double angleOfPL; private double volume; private double pl; private Color pieceColor; private GradientPaint gradient; private String pieceName; private String id; private double start; private double finish; private double startPL; private double finishPL; private Shape instance; private Shape instancePL; private Shape shadow; private boolean isRepaintNeeded = false; private Color gradStart = Color.white; private Object source; /** * Constructor <code>FTOpiePiece</code> * * * @param <code>id</code> is of <code>String</code> type * @param <code>name</code> is of <code>String</code> type * @param <code>volume</code> is of <code>double</code> type * @param <code>pl</code> is of <code>double</code> type * @param <code>isProfit</code> is of <code>int</code> type * */ public FTOpiePiece( String id, String name, double volume, double pl, int isProfit, Object source ) { this.pieceName = name; this.volume = volume; this.pl = pl; this.isProfit = isProfit; this.start = start; this.finish = finish; this.id = id; this.source = source; } protected Object getSource() { return source; } /** * Method <code>getId</code> * * * @return the value of <code>String</code> type * */ public String getId() { return id; } /** * Method <code>getGradientStart</code> * * * @return the value of <code>Color</code> type * */ public Color getGradientStart() { return gradStart; } /** * Method <code>setGradientStart</code> * * * @param <code>c</code> is of <code>Color</code> type * */ public void setGradientStart( Color c ) { gradStart = c; } /** * Method <code>getName</code> * * * @return the value of <code>String</code> type * */ public String getName() { return pieceName; } /** * Method <code>getVolume</code> * * * @return the value of <code>double</code> type * */ public double getVolume() { return volume; } /** * Method <code>setVolume</code> * * * @param <code>v</code> is of <code>double</code> type * */ public void setVolume( double v ) { volume = v; } /** * Method <code>getPL</code> * * * @return the value of <code>double</code> type * */ public double getPL() { return pl; } /** * Method <code>setPL</code> * * * @param <code>pl</code> is of <code>double</code> type * */ public void setPL( double pl ) { this.pl = pl; } /** * Method <code>getVolumeAngle</code> * * * @return the value of <code>double</code> type * */ public double getVolumeAngle() { return angleOfVolume; } /** * Method <code>setVolumeAngle</code> * * * @param <code>v</code> is of <code>double</code> type * */ public void setVolumeAngle( double v ) { angleOfVolume = v; } /** * Method <code>getPLAngle</code> * * * @return the value of <code>double</code> type * */ public double getPLAngle() { return angleOfPL; } /** * Method <code>setPLAngle</code> * * * @param <code>pl</code> is of <code>double</code> type * */ public void setPLAngle( double pl ) { angleOfPL = pl; } /** * Method <code>isProfitPiece</code> * * * @return the value of <code>int</code> type * */ public int isProfitPiece() { return isProfit; } /** * Method <code>setProfit</code> * * * @param <code>p</code> is of <code>int</code> type * */ public void setProfit( int p ) { isProfit = p; } /** * Method <code>isPieceSelected</code> * * * @return the value of <code>boolean</code> type * */ public boolean isPieceSelected() { return isSelected; } /** * Method <code>setPieceSelected</code> * * * @param <code>selected</code> is of <code>boolean</code> type * */ public void setPieceSelected( boolean selected ) { isSelected = selected; } /** * Method <code>getPieceColor</code> * * * @return the value of <code>Color</code> type * */ public Color getPieceColor() { return pieceColor; } /** * Method <code>setPieceColor</code> * * * @param <code>color</code> is of <code>Color</code> type * */ public void setPieceColor( Color color ) { pieceColor = color; } /** * Method <code>getGradient</code> * * * @return the value of <code>GradientPaint</code> type * */ public GradientPaint getGradient() { return gradient; } /** * Method <code>setGradient</code> * * * @param <code>gradient</code> is of <code>GradientPaint</code> type * */ public void setGradient( GradientPaint gradient ) { this.gradient = gradient; } /** * Method <code>getStart</code> * * * @return the value of <code>double</code> type * */ public double getStart() { return start; } /** * Method <code>setStart</code> * * * @param <code>startAngle</code> is of <code>double</code> type * */ public void setStart( double startAngle ) { start = startAngle; } /** * Method <code>getFinish</code> * * * @return the value of <code>double</code> type * */ public double getFinish() { return finish; } /** * Method <code>setFinish</code> * * * @param <code>finishAngle</code> is of <code>double</code> type * */ public void setFinish( double finishAngle ) { finish = finishAngle; } /** * Method <code>getStartPL</code> * * * @return the value of <code>double</code> type * */ public double getStartPL() { return startPL; } /** * Method <code>setStartPL</code> * * * @param <code>startAngle</code> is of <code>double</code> type * */ public void setStartPL( double startAngle ) { startPL = startAngle; } /** * Method <code>getFinishPL</code> * * * @return the value of <code>double</code> type * */ public double getFinishPL() { return finishPL; } /** * Method <code>setFinishPL</code> * * * @param <code>finishAngle</code> is of <code>double</code> type * */ public void setFinishPL( double finishAngle ) { finishPL = finishAngle; } /** * Method <code>getShape</code> * * * @return the value of <code>Shape</code> type * */ public Shape getShape() { return instance; } /** * Method <code>setShape</code> * * * @param <code>shape</code> is of <code>Shape</code> type * */ public void setShape( Shape shape ) { instance = shape; } /** * Method <code>getShapePL</code> * * * @return the value of <code>Shape</code> type * */ public Shape getShapePL() { return instancePL; } /** * Method <code>setShapePL</code> * * * @param <code>shape</code> is of <code>Shape</code> type * */ public void setShapePL( Shape shape ) { instancePL = shape; } /** * Method <code>getShadow</code> * * * @return the value of <code>Shape</code> type * */ public Shape getShadow() { return shadow; } /** * Method <code>setShadow</code> * * * @param <code>shape</code> is of <code>Shape</code> type * */ public void setShadow( Shape shape ) { shadow = shape; } /** * Method <code>isRepaintRequired</code> * * * @return the value of <code>boolean</code> type * */ public boolean isRepaintRequired() { return isRepaintNeeded; } /** * Method <code>setRepaintRequired</code> * * * @param <code>proceed</code> is of <code>boolean</code> type * */ public void setRepaintRequired( boolean proceed ) { isRepaintNeeded = proceed; } /** * Method <code>toString</code> * * * @return the value of <code>String</code> type * */ public String toString() { String text = "\n"; text += "**********************" + "\n"; text += "**********************" + "\n"; text += "ID = " + id + "\n"; text += "Name = " + pieceName + "\n"; text += "Volume = " + volume + "\n"; text += "Pl = " + pl + "\n"; text += "Profit = " + isProfit + "\n"; text += "**********************" + "\n"; return text; } } class FTOchartComparator implements Comparator { /** * Method <code>compare</code> * * * @param <code>o1</code> is of <code>Object</code> type * @param <code>o2</code> is of <code>Object</code> type * * @return the value of <code>int</code> type * */ public int compare( Object o1, Object o2 ) { int result = 0; FTOpiePiece p1 = (FTOpiePiece) o1; FTOpiePiece p2 = (FTOpiePiece) o2; int pr1 = p1.isProfitPiece(); int pr2 = p2.isProfitPiece(); if ( pr1 != pr2 ) { result = pr1 - pr2; } else { double a1 = p1.getPL(); double a2 = p2.getPL(); if ( pr1 == 0 ) { a1 = p1.getVolume(); a2 = p2.getVolume(); } if ( pr1 < 0 ) result = (int) ( a2 - a1 ); else result = (int) ( a1 - a2 ); } return result; } } class FTOchartPopupMenu extends JPopupMenu implements ActionListener { private FTOchartFrame parent; private JMenuItem showLegend = null; private JMenuItem showShadows = null; private JMenuItem gradientPaint = null; private JMenuItem ellipseEnabled = null; private JMenuItem sortingEnabled = null; private JMenuItem increaseGap = null; private JMenuItem decreaseGap = null; /** * Constructor <code>FTOchartPopupMenu</code> * * * @param <code>parent</code> is of <code>FTOchartFrame</code> type * */ public FTOchartPopupMenu( FTOchartFrame parent ) { super(); this.parent = parent; addMenuItems(); } /** * Method <code>destroy</code> * * */ public void destroy() { parent = null; removeAll(); } /** * Method <code>actionPerformed</code> * * * @param <code>e</code> is of <code>ActionEvent</code> type * */ public void actionPerformed( ActionEvent e ) { JMenuItem source = (JMenuItem) e.getSource(); if ( source == showLegend ) parent.invertLegend(); else if ( source == showShadows ) parent.invertShadows(); else if ( source == gradientPaint ) parent.invertGradient(); else if ( source == ellipseEnabled ) parent.invertEllipse(); else if ( source == sortingEnabled ) parent.invertSorting(); else if ( source == increaseGap ) parent.increaseGap(); else if ( source == decreaseGap ) parent.decreaseGap(); } private void addMenuItems() { showShadows = new JMenuItem( "" ); showShadows.addActionListener( this ); add( showShadows ); showShadows.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_S, 0, false ) ); ellipseEnabled = new JMenuItem( "" ); ellipseEnabled.addActionListener( this ); add( ellipseEnabled ); ellipseEnabled.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_E, 0, false ) ); sortingEnabled = new JMenuItem( "" ); sortingEnabled.addActionListener( this ); /*add( sortingEnabled ); sortingEnabled.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_O, 0,false ) );*/ gradientPaint = new JMenuItem( "" ); gradientPaint.addActionListener( this ); add( gradientPaint ); gradientPaint.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_G, 0, false ) ); JSeparator s = new JSeparator(); add( s ); increaseGap = new JMenuItem( "Increase gap" ); increaseGap.addActionListener( this ); add( increaseGap ); increaseGap.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_UP, 0, false ) ); decreaseGap = new JMenuItem( "Decrease gap" ); decreaseGap.addActionListener( this ); add( decreaseGap ); decreaseGap.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, 0, false ) ); s = new JSeparator(); add( s ); showLegend = new JMenuItem( "" ); showLegend.addActionListener( this ); add( showLegend ); showLegend.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_L, 0 ) ); //resetPopup(); } /** * Method <code>show</code> * * * @param <code>invoker</code> is of <code>Component</code> type * @param <code>x</code> is of <code>int</code> type * @param <code>y</code> is of <code>int</code> type * */ public void show( Component invoker, int x, int y ) { if ( parent.isEmpty() ) return; resetPopup(); super.show( invoker, x, y ); } private void resetPopup() { String text = new String(); if ( parent.getShadows() ) text = "Hide shadows"; else text = "Show shadows"; showShadows.setText( text ); if ( parent.getEllipseEnabled() ) text = "Disable ellipse"; else text = "Enable ellipse"; ellipseEnabled.setText( text ); if ( parent.getLegend() ) text = "Hide legend"; else text = "Show legend"; showLegend.setText( text ); if ( parent.getSortingNeeded() ) text = "Sorting disabled"; else text = "Sorting enabled"; sortingEnabled.setText( text ); if ( parent.getGradientPaint() ) text = "Use plain painting"; else text = "Use Gradient painting"; gradientPaint.setText( text ); if ( (int) ( parent.getGap() * 1000 ) == (int) ( FTO2dChart.MAX_GAP * 1000 ) ) increaseGap.setEnabled( false ); else increaseGap.setEnabled( true ); if ( parent.getGap() == FTO2dChart.MIN_GAP ) decreaseGap.setEnabled( false ); else decreaseGap.setEnabled( true ); } } //Test class class FTOinputData { private Object id; private String name; private double value; private double delta; /** * Constructor <code>FTOinputData</code> * * * @param <code>id</code> is of <code>Object</code> type * @param <code>name</code> is of <code>String</code> type * @param <code>value</code> is of <code>double</code> type * @param <code>delta</code> is of <code>double</code> type * */ public FTOinputData( Object id, String name, double value, double delta ) { this.id = id; this.name = name; this.value = value; this.delta = delta; } /** * Method <code>cloneMe</code> * * * @return the value of <code>Object</code> type * */ public Object cloneMe() { try { return super.clone(); } catch ( java.lang.CloneNotSupportedException ex ) { // do nothing - we're cloneable // this try/catch block is only to make the compiler happy return null; } } /** * Method <code>getId</code> * * * @return the value of <code>Object</code> type * */ public Object getId() { return id; } /** * Method <code>getSymbol</code> * * * @return the value of <code>String</code> type * */ public String getSymbol() { return name; } /** * Method <code>getCurrentValue</code> * * * @return the value of <code>double</code> type * */ public double getCurrentValue() { return value; } /** * Method <code>getDeltaValue</code> * * * @return the value of <code>double</code> type * */ public double getDeltaValue() { return delta; } /** * Method <code>getDateTime</code> * * * @return the value of <code>Date</code> type * */ public Date getDateTime() { return new Date( System.currentTimeMillis() ); } } class FTOplafMacros implements SwingConstants { // don't make these final, since the value is // different on each platform private static String LINE_SEPARATOR = System.getProperty( "line.separator" ); private static int LINE_SEPARATOR_LEN = LINE_SEPARATOR.length(); /** * Method <code>breakupLines</code> * * * @param <code>text</code> is of <code>String</code> type * * @return the value of <code>String[]</code> type * */ public static String[] breakupLines( String text ) { int len = text.length(); if ( len == 0 ) return new String[]{ "" }; else { Vector data = new Vector( 10 ); int start = 0; int i = 0; while ( i < len ) { if ( text.startsWith( LINE_SEPARATOR, i ) ) { data.addElement( text.substring( start, i ) ); start = i + LINE_SEPARATOR_LEN; i = start; } else if ( text.charAt( i ) == '\n' ) { data.addElement( text.substring( start, i ) ); start = i + 1; i = start; } else { i++; } } if ( start != len ) data.addElement( text.substring( start ) ); int numlines = data.size(); String lines[] = new String[numlines]; data.copyInto( lines ); return lines; } } } class FTOmultiLineToolTipUI extends ToolTipUI { /** Field <code>SINGLETON</code> */ static FTOmultiLineToolTipUI SINGLETON = new FTOmultiLineToolTipUI(); /** Field <code>DISPLAY_ACCELERATOR</code> */ static boolean DISPLAY_ACCELERATOR = true; /** Field <code>accelerator_offset</code> */ int accelerator_offset = 15; /** Field <code>inset</code> */ int inset = 3; private FTOmultiLineToolTipUI() {} /** * Method <code>initialize</code> * * */ public static void initialize() { // don't hardcode class name, this way we can obfuscate. String key = "ToolTipUI"; Class cls = SINGLETON.getClass(); String name = cls.getName(); UIManager.put( key, name ); UIManager.put( name, cls ); } /** * Method <code>createUI</code> * * * @param <code>c</code> is of <code>JComponent</code> type * * @return the value of <code>ComponentUI</code> type * */ public static ComponentUI createUI( JComponent c ) { return SINGLETON; } /** * Method <code>installUI</code> * * * @param <code>c</code> is of <code>JComponent</code> type * */ public void installUI( JComponent c ) { LookAndFeel.installColorsAndFont( c, "ToolTip.background", "ToolTip.foreground", "ToolTip.font" ); LookAndFeel.installBorder( c, "ToolTip.border" ); } /** * Method <code>uninstallUI</code> * * * @param <code>c</code> is of <code>JComponent</code> type * */ public void uninstallUI( JComponent c ) { LookAndFeel.uninstallBorder( c ); } /** * Method <code>setDisplayAcceleratorKey</code> * * * @param <code>val</code> is of <code>boolean</code> type * */ public static void setDisplayAcceleratorKey( boolean val ) { DISPLAY_ACCELERATOR = val; } /** * Method <code>getPreferredSize</code> * * * @param <code>c</code> is of <code>JComponent</code> type * * @return the value of <code>Dimension</code> type * */ public Dimension getPreferredSize( JComponent c ) { Font font = c.getFont(); // FontMetrics fontMetrics = // Toolkit.getDefaultToolkit().getFontMetrics( font ); FontMetrics fontMetrics = c.getFontMetrics( font ); //Toolkit.getDefaultToolkit().getFontMetrics( font ); int fontHeight = fontMetrics.getHeight(); String tipText = ( (JToolTip) c ).getTipText(); if ( tipText == null ) tipText = ""; String lines[] = FTOplafMacros.breakupLines( tipText ); int num_lines = lines.length; Dimension dimension; int width, height, onewidth; height = num_lines * fontHeight; width = 0; for ( int i = 0; i < num_lines; i++ ) { onewidth = fontMetrics.stringWidth( lines[i] ); if ( DISPLAY_ACCELERATOR && ( i == num_lines - 1 ) ) { String keyText = getAcceleratorString( (JToolTip) c ); if ( !keyText.equals( "" ) ) onewidth += fontMetrics.stringWidth( keyText ) + accelerator_offset; } width = Math.max( width, onewidth ); } return new Dimension( width + inset * 2, height + inset * 2 ); } /** * Method <code>getMinimumSize</code> * * * @param <code>c</code> is of <code>JComponent</code> type * * @return the value of <code>Dimension</code> type * */ public Dimension getMinimumSize( JComponent c ) { return getPreferredSize( c ); } /** * Method <code>getMaximumSize</code> * * * @param <code>c</code> is of <code>JComponent</code> type * * @return the value of <code>Dimension</code> type * */ public Dimension getMaximumSize( JComponent c ) { return getPreferredSize( c ); } /** * Method <code>paint</code> * * * @param <code>g</code> is of <code>Graphics</code> type * @param <code>c</code> is of <code>JComponent</code> type * */ public void paint( Graphics g, JComponent c ) { Font font = c.getFont(); //FontMetrics fontMetrics = // Toolkit.getDefaultToolkit().getFontMetrics( font ); FontMetrics fontMetrics = c.getFontMetrics( font ); Dimension dimension = c.getSize(); int fontHeight = fontMetrics.getHeight(); int fontAscent = fontMetrics.getAscent(); String tipText = ( (JToolTip) c ).getTipText(); String lines[] = FTOplafMacros.breakupLines( tipText ); int num_lines = lines.length; int height; int i; g.setColor( c.getBackground() ); g.fillRect( 0, 0, dimension.width, dimension.height ); g.setColor( c.getForeground() ); for ( i = 0, height = 2 + fontAscent; i < num_lines; i++, height += fontHeight ) { g.drawString( lines[i], inset, height ); if ( DISPLAY_ACCELERATOR && ( i == num_lines - 1 ) ) { String keyText = getAcceleratorString( (JToolTip) c ); if ( !keyText.equals( "" ) ) { Font smallFont = new Font( font.getName(), font.getStyle(), font.getSize() - 2 ); g.setFont( smallFont ); g.drawString( keyText, fontMetrics.stringWidth( lines[i] ) + accelerator_offset, height ); } } } } /** * Method <code>getAcceleratorString</code> * * * @param <code>tip</code> is of <code>JToolTip</code> type * * @return the value of <code>String</code> type * */ public String getAcceleratorString( JToolTip tip ) { JComponent comp = tip.getComponent(); if ( comp == null ) return ""; KeyStroke[] keys = comp.getRegisteredKeyStrokes(); String controlKeyStr = ""; KeyStroke postTip = KeyStroke.getKeyStroke( KeyEvent.VK_F1, Event.CTRL_MASK ); for ( int i = 0; i < keys.length; i++ ) { // Ignore ToolTipManager postTip action, // in swing1.1beta3 and onward if ( postTip.equals( keys[i] ) ) continue; char c = (char) keys[i].getKeyCode(); int mod = keys[i].getModifiers(); if ( mod == InputEvent.CTRL_MASK ) { controlKeyStr = "Ctrl+" + (char) keys[i].getKeyCode(); break; } else if ( mod == InputEvent.ALT_MASK ) { controlKeyStr = "Alt+" + (char) keys[i].getKeyCode(); break; } } return controlKeyStr; } } class FTOtoolTip extends JToolTip { /** * Method <code>updateUI</code> * * */ public void updateUI() { setUI( FTOmultiLineToolTipUI.SINGLETON ); } }
Was able to reproduce with test case, thanks much.
Simplified test case: import javax.swing.JComponent; import javax.swing.JPanel; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class FTOchartFrame { public void selectionChanged(int index, boolean notify) {} } class FTOchartLegend extends JPanel { FTOchartFrame parent; class FTOlegendPanel extends JComponent { public FTOlegendPanel() { Object x = new Object() { public void mousePressed(MouseEvent e) { parent.selectionChanged(0, true); } }; } } } as soon as removing the super type (JComponent from FTOlegendPanel, it compiles ok)...
Dmitry, As a work-around, you can qualify the invocation of parent.selectionChanged (...) as follows, and it will compile ok. FTOchartLegend.this.parent.selectionChanged(...)
Problem identified. When resolving single names, we did set the depth incorrectly (during each iteration of the loop through enclosing scopes) instead of when returning the found file only. Fixed, regression test added (will go into next integration build).