<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">// -=&lt; Построение графиков по набору данных &gt;=-

import java.awt.*;
import java.applet.Applet;
import java.util.Vector;
import OS2.*;

import NumericSet;
import BarChartGarbageCollector;

// -*- Окно графика -*-

public class BarChart extends Panel
{
 // Всегда можно узнать высоту точки.
 Vp Vp = new Vp();

 // Окно аплета.
 protected Applet applet;
 // Размеры окна.
 protected Rectangle bounds;

 // Цвета.
 private Color backgroundColor;
 private Color hiliteColor = Color.white;
 private Color shadowColor = Color.darkGray;

 // Набор данных, по которому строится график.
 private NumericSet set;
 // Внешний вид графика.
 private String presentation;
 private String language;
 private boolean colored;

 // Надо ли использовать память для рисования.
 private boolean useMemorySpaceForDrawing;

 // Поток для освобождения памяти.
 private BarChartGarbageCollector garbageCollector;
 public boolean garbageCollectorIsRunning;

 // Расстояние от края окна.
 private int margin = 15;
 // Высота строки состояния.
 private int statusBarHeight = 35;
 // Расстояние между точками.
 private int spaceBetweenPoints;
 private int minSpaceBetweenPoints = 20;
 // Ширина прямоугольника.
 private int barWidth;

 // Полоска просмотра.
 Scrollbar scrollBar;
 // Высота полоски просмотра.
 private int scrollBarHeight = 0;
 private int scrollBarDefaultHeight = 22;
 // Отступ от строки состояния.
 private int scrollBarMargin = 7;

 // Текст в строке состояния.
 Label statusBarText;

 // Точки графика.
 private Vector chartPoints;
 // Прямоугольники, которые составляют график.
 private Vector chartBars;
 // Цвета прямоугольников.
 private Vector chartColors;

 // Точка, в которой был расположен указатель мыши.
 private Point previousMousePoint;
 // Выделенный прямоугольник, над которым был расположен указатель мыши.
 private int hilitedBar = -1;
 // Нажатый прямоугольник.
 private int pressedBar;

 // ─── Вызывается при создании графика ───

 // Applet - окно аплета.
 public BarChart( Applet applet )
  {
   // Запоминаем окно аплета.
   this.applet = applet;

   // Задаем цвет, которым будет закрашено окно.
   // backgroundColor = applet.getBackground();
   backgroundColor = new Color( 64, 192, 192 );

   // Задаем расположение предметов в окне.
   setLayout( new BorderLayout() );

   // Память будет выделена при задании набора данных.
   return;
  }

 // ─── Задает набор данных для графика ───

 // ExternalSet - внешний набор данных.
 public void numericSet( NumericSet externalSet )
  {
   // Создаем новый набор данных, соответствующий внешнему.
   set = new NumericSet( externalSet );

   // Выделяем память для точек графика, прямоугольников и т. д.
   chartPoints = new Vector( set.dataLength );
   chartBars = new Vector( set.dataLength );
   chartColors = new Vector( set.dataLength );
   previousMousePoint = new Point( 0, 0 );

   // Перерисовываем окно.
   repaint();

   // Возврат.
   return;
  }

 // ─── Устанавливает русский или английский язык для графика ───

 // NewLanguage - новое значение.
 public void language( String newLanguage )
  {
   // Переводим все буквы в строчные.
   newLanguage = newLanguage.toLowerCase();

   // Запоминаем новый внешний вид графика.
   if( newLanguage.indexOf( "russian" ) != -1 ) language = "Russian";
   if( newLanguage.indexOf( "english" ) != -1 ) language = "English";

   // Перерисовываем окно.
   repaint();

   // Возврат.
   return;
  }

 // ─── Устанавливает внешний вид графика ───

 // NewPresentation - новый внешний вид.
 public void presentation( String newPresentation )
  {
   // Переводим все буквы в строчные.
   newPresentation = newPresentation.toLowerCase();

   // Запоминаем новый внешний вид графика.
   if( newPresentation.indexOf( "nodes" ) != -1 ) presentation = "Nodes";
   if( newPresentation.indexOf( "bars" )  != -1 ) presentation = "Bars";

   if( newPresentation.indexOf( "colored" )    != -1 ) colored = true;
   if( newPresentation.indexOf( "monochrome" ) != -1 ) colored = false;

   // Перерисовываем окно.
   repaint();

   // Возврат.
   return;
  }

 // ─── Вызывается при перерисовке окна ───

 public void paint( Graphics defaultSpace )
  {
   // Запоминаем размеры окна.
   bounds = bounds();

   // Рисование может производиться на картинке в памяти, затем картинка переносится в окно.
   Image image = null; Graphics space = null;
   if( useMemorySpaceForDrawing )
    {
     // Создаем картинку в памяти.
     image = applet.createImage( bounds.width, bounds.height );

     // Для окна может быть установлена область отсечения, а картинку надо рисовать полностью.
     defaultSpace = getGraphics();
    }

   // Запоминаем пространство отображения.
   if( image != null ) space = image.getGraphics();
   else space = defaultSpace;

   // Закрашиваем окно.
   space.setColor( backgroundColor );
   space.fillRect( 0, 0, bounds.width, bounds.height );

   // Вычисляем расположение точек.
   calculatePoints();

   // Рисуем строку состояния.
   paintStatusBar( space );

   // Рисуем рамку.
   paintFrame( space );

   // Рисуем оси координат.
   paintCoordinates( space );

   // Рисуем график.
   paintChart( space );

   // Переносим картинку в окно.
   if( image != null )
    {
     // Рисуем картинку.
     defaultSpace.drawImage( image, 0, 0, bounds.width, bounds.height, applet );

     // Освобождаем память.
     if( !garbageCollectorIsRunning )
      {
       // Вызываем поток.
       BarChartGarbageCollector thread = new BarChartGarbageCollector( this );
       thread.start();

       // Запоминаем, что поток работает.
       garbageCollectorIsRunning = true;
      }
    }

   // Возврат.
   return;
  }

 // ─── Вызывается при движении мыши ───

 // Event - событие, x и y - расположение мыши.
 public boolean mouseMove( Event event, int x, int y )
  {
   // Если прямоугольники еще не нарисованы - возврат.
   if( chartBars.isEmpty() ) return false;

   // Если указатель мыши расположен не над графиком - возврат.
   Rectangle chartRectangle = calculateClipRect();
   if( x &lt; chartRectangle.x || x &gt; chartRectangle.x + chartRectangle.width ||
       y &lt; chartRectangle.y || y &gt; chartRectangle.y + chartRectangle.height )
    {
     // Перерисовываем прямоугольник, над которым был расположен указатель.
     if( hilitedBar != -1 ) mouseExit( null, -1, -1 );

     // Возврат.
     return false;
    }

   // Перерисовываем прямоугольник в этой точке.
   boolean barWasHilited = false;
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Узнаем расположение прямоугольника.
     Rectangle chartBar = new Rectangle();
     chartBar = (Rectangle) chartBars.elementAt( count );

     // Если указатель мыши расположен над этим прямоугольником - перерисовываем его.
     if( x &gt; chartBar.x ) if( x &lt; chartBar.x + chartBar.width )
      if( Vp.h( y, bounds ) &lt; Vp.h( chartBar.y, bounds ) )
       if( Vp.h( y, bounds ) &gt; Vp.h( chartBar.y + chartBar.height, bounds ) )
        {
         // Перерисовываем прямоугольник.
         if( count != hilitedBar )
          {
           // Узнаем пространство отображения.
           Graphics space = getGraphics();

           // Устанавливаем границы изображения для рисования графика.
           setClipRect( space );

           // Перерисовываем прямоугольник, над которым был расположен указатель мыши.
           repaintHilitedBar( space );
           // Перерисовываем прямоугольник, над которым указатель расположен сейчас.
           if( count != pressedBar ) paintBar( space, chartBar, hiliteColor );
           else paintPressedBar( space, chartBar, backgroundColor );

           // Запоминаем прямоугольник.
           hilitedBar = count;

           // Перерисовываем строку состояния.
           paintStatusBar( getGraphics() );
          }

         // Запоминаем, что прямоугольник был перерисован.
         barWasHilited = true;

         // Завершаем перебор.
         break;
        }
    }

   // Если ни один прямоугольник не был перерисован - все прямоугольники должны выглядеть как обычно.
   if( hilitedBar != -1 ) if( barWasHilited != true ) mouseExit( null, -1, -1 );

   // Запоминаем точку, в которой расположен указатель мыши.
   previousMousePoint.move( x, y );

   // Возврат.
   return true;
  }

 // ─── Вызывается при нажатии кнопки мыши ───

 // Event - событие, x и y - расположение мыши.
 public boolean mouseDown( Event event, int x, int y )
  {
   // Если прямоугольники еще не нарисованы - возврат.
   if( chartBars.isEmpty() ) return false;

   // Если указатель мыши расположен не над графиком - возврат.
   Rectangle chartRectangle = calculateClipRect();
   if( x &lt; chartRectangle.x || x &gt; chartRectangle.x + chartRectangle.width ||
       y &lt; chartRectangle.y || y &gt; chartRectangle.y + chartRectangle.height )
    return false;

   // Прямоугольник в этой точке становится нажатым.
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Узнаем расположение прямоугольника.
     Rectangle chartBar = new Rectangle();
     chartBar = (Rectangle) chartBars.elementAt( count );

     // Если указатель мыши расположен над этим прямоугольником - он становится нажатым.
     if( x &gt; chartBar.x ) if( x &lt; chartBar.x + chartBar.width )
      if( Vp.h( y, bounds ) &lt; Vp.h( chartBar.y, bounds ) )
       if( Vp.h( y, bounds ) &gt; Vp.h( chartBar.y + chartBar.height, bounds ) )
        {
         // Перерисовываем прямоугольник.
         if( count != pressedBar )
          {
           // Узнаем пространство отображения.
           Graphics space = getGraphics();

           // Устанавливаем границы изображения для рисования графика.
           setClipRect( space );

           // Узнаем расположение и цвет прямоугольника, который был нажатым.
           Rectangle previousBar = new Rectangle();
           previousBar = (Rectangle) chartBars.elementAt( pressedBar );
           Color barColor = new Color( 0, 0, 0 );
           barColor = (Color) chartColors.elementAt( pressedBar );
           // Перерисовываем прямоугольник, который был нажатым.
           paintBar( space, previousBar, barColor );

           // Перерисовываем прямоугольник, над которым расположен указатель мыши.
           paintPressedBar( space, chartBar, backgroundColor );

           // Запоминаем нажатый прямоугольник.
           pressedBar = count;

           // Перерисовываем строку состояния.
           paintStatusBar( getGraphics() );

           // Завершаем перебор.
           break;
          }
        }
    }

   // Возврат.
   return true;
  }

 // ─── Вызывается, когда мышь покидает окно ───

 // Event - событие, x и y - расположение мыши.
 public boolean mouseExit( Event event, int x, int y )
  {
   // Перерисовываем прямоугольники.
   if( hilitedBar != -1 )
    {
     // Узнаем пространство отображения.
     Graphics space = getGraphics();

     // Устанавливаем границы изображения для рисования графика.
     setClipRect( space );

     // Перерисовываем прямоугольник.
     repaintHilitedBar( space );

     // Указатель мыши не расположен над прямоугольниками.
     hilitedBar = -1;

     // Перерисовываем строку состояния.
     paintStatusBar( getGraphics() );
    }

   // Возврат.
   return true;
  }

 // ─── Обработчик событий ───

 // Event - событие.
 public boolean handleEvent( Event event )
  {
   // Если событие пришло от полоски просмотра - перерисовываем график.
   if( event.target instanceof Scrollbar )
    {
     // Рисование может производиться на картинке в памяти, затем картинка переносится в окно.
     Image image = null; Graphics space = null;
     if( useMemorySpaceForDrawing ) image = applet.createImage( bounds.width, bounds.height );

     // Запоминаем пространство отображения.
     if( image != null ) space = image.getGraphics();
     else space = getGraphics();

     // Устанавливаем границы изображения для рисования графика.
     Rectangle chartRectangle = setClipRect( space );

     // Рисуем график в памяти и запоминаем его расположение.
     calculatePoints(); paintChart( space );

     // Переносим часть картинки в окно.
     if( image != null )
      {
       // Рисуем картинку.
       Graphics defaultSpace = getGraphics();
       defaultSpace.clipRect( chartRectangle.x, chartRectangle.y, chartRectangle.width, chartRectangle.height );
       defaultSpace.drawImage( image, 0, 0, bounds.width, bounds.height, applet );

       // Освобождаем память.
       if( !garbageCollectorIsRunning )
        {
         // Вызываем поток.
         BarChartGarbageCollector thread = new BarChartGarbageCollector( this );
         thread.start();

         // Запоминаем, что поток работает.
         garbageCollectorIsRunning = true;
        }
      }

     // Возврат.
     return true;
    }

   // Возврат.
   return super.handleEvent( event );
  }

 // ─── Вычисляет расположение точек ───

 private void calculatePoints()
  {
   // Вычисляем расстояние между точками и отступ слева.
   spaceBetweenPoints = bounds.width / set.dataLength;
   int leftMargin;
   // Проверяем расстояние.
   while( true )
    {
     // Вычисляем отступ слева.
     leftMargin = ( bounds.width - spaceBetweenPoints * set.dataLength ) / 2;
     // Если он получится меньше, чем отступ от края окна - уменьшаем расстояние.
     if( leftMargin &lt; margin ) spaceBetweenPoints --;
     else break;
    }

   // Если расстояние между точками слишком мало - изображение будет иметь
   // размеры больше, чем размеры окна, и в окно будет добавлена полоска просмотра.
   if( spaceBetweenPoints &lt; minSpaceBetweenPoints )
    {
     // Устанавливаем расстояние между точками по умолчанию.
     spaceBetweenPoints = minSpaceBetweenPoints; leftMargin = margin;

     // Число делений полоски просмотра соответствует числу точек.
     int maxPoints = spaceBetweenPoints * set.dataLength + leftMargin * 2;
     int rate = maxPoints - bounds.width; int currentRate = 0;
     int position = 0; int buttonSize = rate / 10;
     int lineIncrement = rate / 10; int pageIncrement = rate / 4;

     // Если в окне уже есть полоска просмотра - изменяем ее состояние.
     if( scrollBar != null )
      {
       // Запоминаем состояние.
       currentRate = scrollBar.getMaximum();

       // Вычисляем новое положение движка.
       position = scrollBar.getValue() * rate / currentRate;
       if( position &gt; rate ) position = rate;
      }
     // А если полоски нет - создаем ее.
     else
      {
       // Создаем полоску просмотра.
       scrollBar = new Scrollbar( Scrollbar.HORIZONTAL, position, buttonSize, 0, rate );
       scrollBarHeight = scrollBarDefaultHeight;

       // Добавляем полоску в окно.
       add( scrollBar );
      }

     // Если состояние полоски изменилось - задаем новое состояние.
     if( rate != currentRate )
      {
       scrollBar.setValues( position, buttonSize, 0, rate );
       scrollBar.setLineIncrement( lineIncrement );
       scrollBar.setPageIncrement( pageIncrement );
      }

     // Задаем расположение полоски просмотра.
     scrollBar.reshape( margin, Vp.y( statusBarHeight + scrollBarHeight - 1, bounds ), bounds.width - margin * 2, scrollBarHeight - scrollBarMargin );
    }
   // Иначе - удаляем полоску просмотра, если она есть.
   else if( scrollBar != null )
    {
     // Удаляем полоску просмотра.
     remove( scrollBar ); scrollBar = null; scrollBarHeight = 0;
    }

   // Высота графика должна быть достаточной для отображения наибольшего значения.
   float scaleFactor = (float) ( bounds.height - statusBarHeight - scrollBarHeight - margin * 2 ) / set.max();

   // Освобождаем память, выделенную ранее для точек.
   chartPoints.removeAllElements();

   // Вычисляем расположение точек.
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Вычисляем расположение точки.
     int x = spaceBetweenPoints * count + spaceBetweenPoints / 2 + leftMargin;
     int h = (int) ( set.value( count ) * scaleFactor ) + statusBarHeight + scrollBarHeight + margin;
     int y = Vp.y( h, bounds );

     // Передвигаем точку с учетом значения в полоске просмотра.
     if( scrollBar != null ) x -= scrollBar.getValue();

     // Запоминаем точку.
     chartPoints.addElement( new Point( x, y ) );
    }

   // Возврат.
   return;
  }

 // ─── Устанавливает границы изображения для рисования графика ───

 private Rectangle setClipRect( Graphics space )
  {
   // Устанавливаем новые границы пространства отображения.
   Rectangle chartRectangle = calculateClipRect();
   space.clipRect( chartRectangle.x, chartRectangle.y, chartRectangle.width, chartRectangle.height );

   // Возвращаем прямоугольник, который содержит новые границы.
   return chartRectangle;
  }

 // ─── Вычисляет границы изображения для рисования графика ───

 private Rectangle calculateClipRect()
  {
   // Вычисляем границы пространства отображения.
   Rectangle chartRectangle = new Rectangle( margin, Vp.y( bounds.height - margin, bounds ), bounds.width - margin * 2, bounds.height - statusBarHeight - scrollBarHeight - margin * 2 + 1 );

   // Возвращаем прямоугольник, который содержит новые границы.
   return chartRectangle;
  }

 // ─── Рисует строку состояния ───

 private void paintStatusBar( Graphics space )
  {
   // Задаем прямоугольник для строки состояния.
   Rectangle bar = new Rectangle( margin / 2, Vp.y( statusBarHeight + margin / 4 - 2, bounds ), bounds.width - margin, statusBarHeight - margin / 2 );

   // Подчеркиваем объем строки состояния.
   space.setColor( hiliteColor );
   space.drawLine( bar.x, bar.y, bar.x + bar.width, bar.y );
   space.drawLine( bar.x, bar.y, bar.x, bar.y + bar.height );
   space.setColor( shadowColor );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x, bar.y + bar.height );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x + bar.width, bar.y );

   // Составляем сообщение.
   String Message;
   if( pressedBar == 0 &amp;&amp; hilitedBar == -1 )
    {
     if( presentation == "Nodes" )
      {
       if( language == "Russian" ) Message = "Вы можете выбрать точку с помощью мыши.";
       else Message = "You can select a chart point using a mouse.";
      }
     else
      {
       if( language == "Russian" ) Message = "Вы можете выбрать прямоугольник с помощью мыши.";
       else Message = "You can select a chart bar using a mouse.";
      }
    }
   else
    {
     int valueOfPressedBar = set.value( pressedBar );
     if( language == "Russian" ) Message = "Значение " + pressedBar + " = " + valueOfPressedBar;
     else Message = "Value " + pressedBar + " = " + valueOfPressedBar;
     int valueOfHilitedBar = 0; int valueBetweenBars = 0;
     if( hilitedBar != pressedBar ) if( hilitedBar != -1 )
      {
       valueOfHilitedBar = set.value( hilitedBar );
       if( language == "Russian" ) Message = Message + " Значение " + hilitedBar + " = " + valueOfHilitedBar;
       else Message = Message + " Value " + hilitedBar + " = " + valueOfHilitedBar;
       valueBetweenBars = Math.abs( valueOfHilitedBar - valueOfPressedBar );
       if( language == "Russian" ) Message = Message + " Изменение = " + valueBetweenBars;
       else Message = Message + " Changes = " + valueBetweenBars;
      }
    }

   // Если текстовое поле для строки состояния не создано - создаем его.
   if( statusBarText == null )
    {
     statusBarText = new Label( "", Label.CENTER );
     add( statusBarText );
    }

   // Устанавливаем текст в строке состояния.
   statusBarText.setText( Message );

   // Задаем цвет текстового поля.
   statusBarText.setBackground( backgroundColor );

   // Передвигаем текстовое поле.
   statusBarText.reshape( bar.x + 1, bar.y + 1, bar.width - 2, bar.height - 2 );

   // Возврат.
   return;
  }

 // ─── Рисует рамку ───

 private void paintFrame( Graphics space )
  {
   // Рисуем обрамление.
   space.setColor( backgroundColor );
   space.drawRect( 0, 0, bounds.width - 1, bounds.height - 1 );

   // Рисуем темную часть рамки.
   space.setColor( shadowColor );
   space.drawRect( 2, 2, bounds.width - 4, bounds.height - 4 );

   // Рисуем светлую часть рамки.
   space.setColor( hiliteColor );
   space.drawRect( 1, 1, bounds.width - 4, bounds.height - 4 );

   // Возврат.
   return;
  }

 // ─── Рисует оси координат ───

 private void paintCoordinates( Graphics space )
  {
   // Отступ от края окна.
   int coordMargin = margin / 2;
   // Размер стрелки.
   int arrowWidth = margin / 4;

   // Рисуем ось Y.
   space.setColor( shadowColor );
   space.drawLine( coordMargin + 1, Vp.y( statusBarHeight + scrollBarHeight + coordMargin, bounds ), coordMargin + 1, Vp.y( bounds.height - coordMargin, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + 1, bounds ), coordMargin, Vp.y( bounds.height - coordMargin, bounds ) );

   space.setColor( shadowColor );
   space.drawLine( coordMargin - arrowWidth + 1, Vp.y( bounds.height - coordMargin - arrowWidth * 2, bounds ), coordMargin + 1, Vp.y( bounds.height - coordMargin, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( coordMargin - arrowWidth, Vp.y( bounds.height - coordMargin - arrowWidth * 2, bounds ), coordMargin, Vp.y( bounds.height - coordMargin, bounds ) );

   space.setColor( shadowColor );
   space.drawLine( coordMargin + arrowWidth + 1, Vp.y( bounds.height - coordMargin - arrowWidth * 2, bounds ), coordMargin + 1, Vp.y( bounds.height - coordMargin + 1, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( coordMargin + arrowWidth, Vp.y( bounds.height - coordMargin - arrowWidth * 2, bounds ), coordMargin, Vp.y( bounds.height - coordMargin + 1, bounds ) );

   // Рисуем ось X.
   space.setColor( shadowColor );
   space.drawLine( coordMargin + 1, Vp.y( statusBarHeight + scrollBarHeight + coordMargin, bounds ), bounds.width - coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + 1, bounds ), bounds.width - coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + 1, bounds ) );

   space.setColor( shadowColor );
   space.drawLine( bounds.width - coordMargin - arrowWidth * 2, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + arrowWidth, bounds ), bounds.width - coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( bounds.width - coordMargin - arrowWidth * 2, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + arrowWidth + 1, bounds ), bounds.width - coordMargin, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + 1, bounds ) );

   space.setColor( shadowColor );
   space.drawLine( bounds.width - coordMargin - arrowWidth * 2, Vp.y( statusBarHeight + scrollBarHeight + coordMargin - arrowWidth, bounds ), bounds.width - coordMargin + 1, Vp.y( statusBarHeight + scrollBarHeight + coordMargin, bounds ) );
   space.setColor( hiliteColor );
   space.drawLine( bounds.width - coordMargin - arrowWidth * 2, Vp.y( statusBarHeight + scrollBarHeight + coordMargin - arrowWidth + 1, bounds ), bounds.width - coordMargin + 1, Vp.y( statusBarHeight + scrollBarHeight + coordMargin + 1, bounds ) );

   // Возврат.
   return;
  }

 // ───  Рисует график ───

 private void paintChart( Graphics space )
  {
   // Устанавливаем границы изображения для рисования графика.
   Rectangle chartRectangle = setClipRect( space );

   // Закрашиваем эту область.
   space.setColor( backgroundColor );
   space.fillRect( chartRectangle.x, chartRectangle.y, chartRectangle.width, chartRectangle.height );

   // Рисуем график.
   if( presentation == "Nodes" )
    {
     paintGuideLines( space );
     paintNodes( space );
    }
   else paintBars( space );

   // Возврат.
   return;
  }

 // ─── Рисует линии сетки. ───

 private void paintGuideLines( Graphics space )
  {
   // Устанавливаем цвет.
   space.setColor( new Color( 64, 128, 128 ) );

   // Рисуем линии снизу вверх.
   int maxLines = 10;
   int deltaHeight = ( bounds.height - statusBarHeight - scrollBarHeight - margin * 2 ) / maxLines;
   for( int count = 0; count &lt; maxLines; count ++ )
    {
     int height = Vp.h( statusBarHeight + scrollBarHeight + margin + count * deltaHeight + deltaHeight / 2, bounds );
     space.drawLine( margin, height, bounds.width - margin, height );
    }

   // Цвета линий будут меняться.
   int saturation = 254;
   int deltaColor = 255 / set.dataLength;
   if( deltaColor == 0 ) deltaColor = 1;

   // Рисуем линии слева направо.
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Узнаем расположение точки.
     Point Point = new Point( 0, 0 );
     Point = (Point) chartPoints.elementAt( count );

     // Вычисляем цвет.
     saturation -= deltaColor;
     if( saturation &lt;= 0 || saturation &gt;= 255 ) deltaColor *= (-1);

     // Если линия будет видна в окне - рисуем ее.
     if( Point.x &gt; 0 ) if( Point.x &lt; bounds.width )
      {
       // Задаем цвет.
       int red = 255 - saturation;
       int green = saturation / 2;
       int blue = green;

       // Рисуем линию.
       space.setColor( new Color( red, green, blue ) );
       space.drawLine( Point.x, Vp.h( statusBarHeight + scrollBarHeight + margin, bounds ), Point.x, Vp.h( bounds.height - margin, bounds ) );
      }
    }

   // Возврат.
   return;
  }

 // ─── Рисует график в виде линий с прямоугольниками ───

 private void paintNodes( Graphics space )
  {
   // Цвета прямоугольников будут меняться.
   Color barColor = backgroundColor.darker();
   int colorsCount = 0;

   // Освобождаем память, выделенную ранее для прямоугольников.
   chartBars.removeAllElements();
   chartColors.removeAllElements();

   // Рисуем график.
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Узнаем расположение точек.
     Point Point = new Point( 0, 0 ); Point nextPoint = null;
     Point = (Point) chartPoints.elementAt( count );
     if( count &lt; set.dataLength - 1 )
      {
       nextPoint = new Point( 0, 0 );
       nextPoint = (Point) chartPoints.elementAt( count + 1 );
      }

     // Задаем размеры прямоугольника.
     barWidth = spaceBetweenPoints / 3;
     Rectangle bar = new Rectangle( Point.x - barWidth / 2, Point.y, barWidth, barWidth );

     // Запоминаем прямоугольник.
     chartBars.addElement( bar );

     // Если цвета должны меняться - задаем цвет.
     if( colored == true )
      {
       colorsCount ++; if( colorsCount == 6 ) colorsCount = 0;
       switch( colorsCount )
        {
         case 0: barColor = Color.red;    break;
         case 1: barColor = Color.orange; break;
         case 2: barColor = Color.yellow; break;
         case 3: barColor = Color.green;  break;
         case 4: barColor = Color.cyan;   break;
         case 5: barColor = Color.blue;   break;
        }
      }

     // Запоминаем цвет.
     chartColors.addElement( barColor );

     // Если точка графика будет видна в окне - рисуем линии и прямоугольник.
     if( Point.x &gt; (-1) * ( spaceBetweenPoints ) )
      if( Point.x &lt; bounds.width + spaceBetweenPoints )
       {
        // Рисуем линии.
        if( nextPoint != null )
         {
          space.setColor( hiliteColor );
          space.drawLine( Point.x, Point.y + barWidth / 2, nextPoint.x, nextPoint.y + barWidth / 2 );
          space.setColor( shadowColor );
          space.drawLine( Point.x, Point.y + barWidth / 2 + 1, nextPoint.x, nextPoint.y + barWidth / 2 + 1 );
         }

        // Рисуем прямоугольник.
        if( count != pressedBar ) paintBar( space, bar, barColor );
        else paintPressedBar( space, bar, backgroundColor );
       }
    }

   // Возврат.
   return;
  }

 // ─── Рисует график в виде прямоугольников ───

 private void paintBars( Graphics space )
  {
   // Цвета прямоугольников будут меняться.
   Color barColor = backgroundColor.darker();
   int colorsCount = 0;

   // Освобождаем память, выделенную ранее для прямоугольников.
   chartBars.removeAllElements();
   chartColors.removeAllElements();

   // Рисуем график.
   for( int count = 0; count &lt; set.dataLength; count ++ )
    {
     // Узнаем расположение точки.
     Point Point = new Point( 0, 0 );
     Point = (Point) chartPoints.elementAt( count );

     // Задаем размеры прямоугольника.
     barWidth = spaceBetweenPoints / 6 * 5;
     Rectangle bar = new Rectangle( Point.x - barWidth / 2, Point.y, barWidth, Vp.h( Point.y, bounds ) - statusBarHeight - scrollBarHeight - margin );

     // Запоминаем прямоугольник.
     chartBars.addElement( bar );

     // Если цвета должны меняться - задаем цвет.
     if( colored == true )
      {
       colorsCount ++; if( colorsCount == 6 ) colorsCount = 0;
       switch( colorsCount )
        {
         case 0: barColor = Color.red;    break;
         case 1: barColor = Color.orange; break;
         case 2: barColor = Color.yellow; break;
         case 3: barColor = Color.green;  break;
         case 4: barColor = Color.cyan;   break;
         case 5: barColor = Color.blue;   break;
        }
      }

     // Запоминаем цвет.
     chartColors.addElement( barColor );

     // Если точка графика будет видна в окне - рисуем прямоугольник.
     if( Point.x &gt; (-1) * ( spaceBetweenPoints ) )
      if( Point.x &lt; bounds.width + spaceBetweenPoints )
       {
        // Рисуем прямоугольник.
        if( count != pressedBar ) paintBar( space, bar, barColor );
        else paintPressedBar( space, bar, backgroundColor );
       }
    }

   // Возврат.
   return;
  }

 // ─── Рисует один прямоугольник ───

 // Bar - прямоугольник, color - цвет.
 private void paintBar( Graphics space, Rectangle bar, Color color )
  {
   // Рисуем прямоугольник.
   space.setColor( color );
   space.fillRect( bar.x, bar.y, bar.width, bar.height );

   // Подчеркиваем объем прямоугольника.
   space.setColor( hiliteColor );
   space.drawLine( bar.x, bar.y, bar.x + bar.width, bar.y );
   space.drawLine( bar.x, bar.y, bar.x, bar.y + bar.height );
   space.setColor( shadowColor );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x, bar.y + bar.height );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x + bar.width, bar.y );

   // Возврат.
   return;
  }

 // ─── Рисует нажатый прямоугольник ───

 // Bar - прямоугольник, color - цвет.
 private void paintPressedBar( Graphics space, Rectangle bar, Color color )
  {
   // Рисуем прямоугольник.
   space.setColor( color );
   space.fillRect( bar.x, bar.y, bar.width, bar.height );

   // Прямоугольник должен быть нажатым.
   space.setColor( shadowColor );
   space.drawLine( bar.x, bar.y, bar.x + bar.width, bar.y );
   space.drawLine( bar.x, bar.y, bar.x, bar.y + bar.height );
   space.setColor( hiliteColor );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x, bar.y + bar.height );
   space.drawLine( bar.x + bar.width, bar.y + bar.height, bar.x + bar.width, bar.y );

   // Возврат.
   return;
  }

 // ─── Перерисовывает прямоугольник, над которым был расположен указатель мыши ───

 private void repaintHilitedBar( Graphics space )
  {
   // Перерисовываем прямоугольник, над которым был расположен указатель мыши.
   if( hilitedBar != -1 )
    {
     // Узнаем расположение и цвет прямоугольника.
     Rectangle previousBar = new Rectangle();
     previousBar = (Rectangle) chartBars.elementAt( hilitedBar );
     Color barColor = new Color( 0, 0, 0 );
     barColor = (Color) chartColors.elementAt( hilitedBar );

     // Перерисовываем прямоугольник.
     if( hilitedBar != pressedBar ) paintBar( space, previousBar, barColor );
     else paintPressedBar( space, previousBar, backgroundColor );
    }

   // Возврат.
   return;
  }
}
</pre></body></html>