22
33import cbit .vcell .client .data .ODEDataViewer ;
44import cbit .vcell .client .desktop .biomodel .DocumentEditorSubPanel ;
5+ import cbit .vcell .parser .ExpressionException ;
56import cbit .vcell .util .ColumnDescription ;
7+ import org .vcell .util .ColorUtil ;
68import org .vcell .util .gui .JToolBarToggleButton ;
79import org .vcell .util .gui .VCellIcons ;
810
1719import java .awt .event .ActionListener ;
1820import java .beans .PropertyChangeEvent ;
1921import java .beans .PropertyChangeListener ;
22+ import java .util .*;
23+ import java .util .List ;
2024
2125
2226public class ClusterVisualizationPanel extends DocumentEditorSubPanel {
2327
2428 ODEDataViewer owner ;
2529 IvjEventHandler ivjEventHandler = new IvjEventHandler ();
2630
31+ private final Map <String , Color > persistentColorMap = new LinkedHashMap <>();
32+ private final java .util .List <Color > globalPalette = new ArrayList <>();
33+ private int nextColorIndex = 0 ;
34+
35+
36+
2737 private JPanel ivjJPanel1 = null ;
2838 private JPanel ivjJPanelPlot = null ;
2939 private JPanel ivjPlot2DPanel1 = null ; // here
@@ -57,8 +67,13 @@ public void actionPerformed(ActionEvent e) {
5767 public void propertyChange (PropertyChangeEvent evt ) {
5868 if (evt .getSource () == owner .getClusterSpecificationPanel () && "ClusterSelection" .equals (evt .getPropertyName ())) {
5969 ClusterSpecificationPanel .ClusterSelection sel = (ClusterSpecificationPanel .ClusterSelection ) evt .getNewValue ();
60- updateLegend (sel ); // update legend (one plot, multiple curves)
61- redrawPlot (sel ); // redraw plot (one plot, multiple curves)
70+ ensureColorsAssigned (sel .columns );
71+ try {
72+ redrawPlot (sel ); // redraw plot (one plot, multiple curves)
73+ } catch (ExpressionException e ) {
74+ throw new RuntimeException (e );
75+ }
76+ redrawLegend (sel ); // update legend (one plot, multiple curves)
6277 updateDataTable (sel ); // update data table
6378 return ;
6479 }
@@ -90,7 +105,8 @@ private void initialize() {
90105 add (getJPanel1 (), "Center" );
91106 add (getBottomRightPanel (), "South" );
92107 add (getJPanelLegend (), "East" );
93- initConnectionsRight ();
108+ setBackground (Color .white );
109+ initConnections ();
94110 }
95111
96112 private JPanel getJPanel1 () {
@@ -231,11 +247,14 @@ private JPanel getJPanelLegend() {
231247 ivjJPanelLegend .setName ("JPanelLegend" );
232248 ivjJPanelLegend .setLayout (new BorderLayout ());
233249 getJPanelLegend ().add (new JLabel (" " ), "South" );
234- getJPanelLegend ().add (new JLabel ("Plot Legend:" ), "North" );
250+ JLabel labelLegendTitle = new JLabel ("Plot Legend:" );
251+ labelLegendTitle .setBorder (new EmptyBorder (10 , 4 , 10 , 4 ));
252+ getJPanelLegend ().add (labelLegendTitle , "North" );
235253 getJPanelLegend ().add (getPlotLegendsScrollPane (), "Center" );
236254 }
237255 return ivjJPanelLegend ;
238256 }
257+
239258 private JScrollPane getPlotLegendsScrollPane () {
240259 if (ivjPlotLegendsScrollPane == null ) {
241260 ivjPlotLegendsScrollPane = new JScrollPane ();
@@ -256,8 +275,22 @@ private JPanel getJPanelPlotLegends() {
256275 return ivjJPanelPlotLegends ;
257276 }
258277
278+ public void setBackground (Color color ) {
279+ super .setBackground (color );
280+ getBottomRightPanel ().setBackground (color );
281+ getJBottomLabel ().setBackground (color );
282+ getJPanelLegend ().setBackground (color );
283+ getJPanelPlotLegends ().setBackground (color );
284+ getJPanel1 ().setBackground (color );
285+ getPlot2DPanel1 ().setBackground (color );
286+ getPlot2DDataPanel1 ().setBackground (color );
287+ getJPanelData ().setBackground (color );
288+ getJPanelPlot ().setBackground (color );
289+
290+ }
259291
260- private void initConnectionsRight () {
292+ private void initConnections () {
293+ initializeGlobalPalette (); // get a stable, high contrast palette
261294 // group the two buttons so only one stays selected
262295 ButtonGroup bg = new ButtonGroup ();
263296 bg .add (getPlotButton ());
@@ -290,15 +323,101 @@ public void refreshData() {
290323
291324 // ---------------------------------------------------------------------
292325
293- private void updateLegend (ClusterSpecificationPanel .ClusterSelection sel ) {
294- System .out .println ("ClusterVisualizationPanel.updateLegend() called" );
326+ private void initializeGlobalPalette () {
327+ // Use a curated palette from ColorUtil
328+ globalPalette .clear ();
329+ globalPalette .addAll (Arrays .asList (ColorUtil .TABLEAU20 ));
330+ }
331+ private void ensureColorsAssigned (List <ColumnDescription > columns ) {
332+ // assign colors only when needed, and keep them consistent across updates
333+ for (ColumnDescription cd : columns ) {
334+ String name = cd .getName ();
335+ if (!persistentColorMap .containsKey (name )) {
336+ Color c = globalPalette .get (nextColorIndex % globalPalette .size ());
337+ persistentColorMap .put (name , c );
338+ nextColorIndex ++;
339+ }
340+ }
341+ }
342+ private JComponent createLegendEntry (String name , Color color , ClusterSpecificationPanel .DisplayMode mode ) {
343+ JPanel p = new JPanel ();
344+ p .setName ("JPanelClusterColorLegends" );
345+ BoxLayout bl = new BoxLayout (p , BoxLayout .Y_AXIS );
346+ p .setLayout (bl );
347+ p .setBounds (0 , 0 , 72 , 360 );
348+ p .setOpaque (false );
349+
350+ String unitSymbol = "" ;
351+ if (ClusterSpecificationPanel .DisplayMode .COUNTS == mode ) {
352+ unitSymbol = "molecules" ;
353+ }
354+ String shortLabel = "<html>" + name + "<font color=\" #8B0000\" >" + " [" + unitSymbol + "] " + "</font></html>" ;
355+
356+ JLabel line = new JLabel (new LineIcon (color ));
357+ JLabel text = new JLabel (shortLabel );
358+ line .setBorder (new EmptyBorder (6 ,0 ,1 ,0 ));
359+ text .setBorder (new EmptyBorder (1 ,8 ,6 ,0 ));
360+ p .add (line );
361+ p .add (text );
362+
363+ return p ;
364+ }
365+ public class LineIcon implements Icon {
366+ private final Color color ;
367+ public LineIcon (Color color ) {
368+ this .color = color ;
369+ }
370+ @ Override
371+ public void paintIcon (Component c , Graphics g , int x , int y ) {
372+ Graphics2D g2 = (Graphics2D )g ;
373+ g2 .setStroke (new BasicStroke (3.0f ));
374+ g2 .setPaint (color );
375+ int midY = y + getIconHeight () / 2 ;
376+ g2 .drawLine (x , midY , x + getIconWidth (), midY );
377+ }
378+ @ Override
379+ public int getIconWidth () { return 50 ; }
380+ @ Override
381+ public int getIconHeight () {
382+ return 4 ; // more vertical room for a wider stroke
383+ }
295384 }
296- private void redrawPlot (ClusterSpecificationPanel .ClusterSelection sel ) {
385+ public static String getUnitSymbol (ClusterSpecificationPanel .ClusterSelection sel ) {
386+ if (ClusterSpecificationPanel .DisplayMode .COUNTS == sel .mode ) {
387+
388+
389+ }
390+ return "" ;
391+ }
392+
393+ private void redrawPlot (ClusterSpecificationPanel .ClusterSelection sel ) throws ExpressionException {
297394 System .out .println ("ClusterVisualizationPanel.redrawPlot() called" );
298- java .util .List <ColumnDescription > columnDescriptions = sel .columns ;
299- for (ColumnDescription cd : columnDescriptions ) {
300- System .out .println (" column name: '" + cd .getName () + "'" );
395+ // java.util.List<ColumnDescription> columnDescriptions = sel.columns;
396+ // for(ColumnDescription cd : columnDescriptions) {
397+ // System.out.println(" column name: '" + cd.getName() + "'");
398+ // }
399+ // getPlot2DPanel1().removeAllPlots();
400+ //
401+ // int index = sel.resultSet.findColumn("t");
402+ // double[] t = sel.resultSet.extractColumn(index);
403+ //
404+ // for (ColumnDescription cd : sel.columns) {
405+ // index = sel.resultSet.findColumn(cd.getName());
406+ // double[] y = sel.resultSet.extractColumn(index);
407+ // Color c = persistentColorMap.get(cd.getName());
408+ // getPlot2DPanel1().addLinePlot(cd.getName(), c, t, y);
409+ // }
410+ // getPlot2DPanel1().repaint();
411+ }
412+ private void redrawLegend (ClusterSpecificationPanel .ClusterSelection sel ) {
413+ System .out .println ("ClusterVisualizationPanel.updateLegend() called" );
414+ getJPanelPlotLegends ().removeAll ();
415+ for (ColumnDescription cd : sel .columns ) {
416+ Color c = persistentColorMap .get (cd .getName ());
417+ getJPanelPlotLegends ().add (createLegendEntry (cd .getName (), c , sel .mode ));
301418 }
419+ getJPanelPlotLegends ().revalidate ();
420+ getJPanelPlotLegends ().repaint ();
302421 }
303422 private void updateDataTable (ClusterSpecificationPanel .ClusterSelection sel ) {
304423 System .out .println ("ClusterVisualizationPanel.updateDataTable() called" );
0 commit comments