/// <summary>
 /// Zaznacza przebieg prostej linii (kanał) w tabeli linesMap w celu późniejszego testowania zawierania kursora
 /// </summary>
 /// <param name="lin">linia prosta która ma zostać naniesiona na mapę</param>
 /// <param name="idx">numer indeksu identyfikujący dana linię w tabeli</param>
 static public void WriteLineOnMap(SimpleLine lin, int idx)
 {
     if (lin.x1 <= GraphGUIMainForm.pW & lin.x2 <= GraphGUIMainForm.pW & lin.y1 <= GraphGUIMainForm.pH & lin.y2 <= GraphGUIMainForm.pH & lin.y1 == lin.y2) // zapobiega błędowi IndexOutOfArray po wyjściu linii poza obręb panelu rysowania
     {
         // nanoszenie linii na mapę (szerokość linii na mapie = 5)
         for (int i = lin.x1; i <= lin.x2; i++)
         {
             surfaceMap[lin.y1 - 2, i] = 3000 + idx;
             surfaceMap[lin.y1 - 1, i] = 3000 + idx;
             surfaceMap[lin.y1, i]     = 3000 + idx;
             surfaceMap[lin.y1 + 1, i] = 3000 + idx;
             surfaceMap[lin.y1 + 2, i] = 3000 + idx;
         }
     }
 }
 /// <summary>
 /// Generuje schemat na podstawie pliku konfiguracji i zapamiętuje położenie bloków i połączeń
 /// </summary>
 /// <param name="generacja">true=obliczanie punktów położenia bloków i linii wg. algorytmu rozmieszczeń; false=wyświetla schemat na podstawie zapamiętanych informacji</param>
 public void GenerateSchema(bool generacja)
 {
     if (Data.comunicationNet1.Channels.Rows.Count > 0) // zapobiega próbom generacji schematu przed wczytaniem bazy
     {
         SetSchemaAttributes();
         // rozpoczynamy rysowanie
         g = schemaPanel.CreateGraphics();
         g.Clear(System.Drawing.SystemColors.ControlLight);// czyści powierzchnię zapobiegając nałożeniom schematów
         try
         {
             // przydatne zmienne
             Point     act = new Point();     // punkt aktualnego położenia "pióra"
             Rectangle rec = new Rectangle(); // odzwierciedla prostokąt obramowania etykiet i czcionek - wykorzystywany do analizy położenia kurrora myszy
             // ..:: COMM Server ::...................................................................................
             server = new Icon(20, pH - 4 * iconSz, serverSize.Height, serverSize.Width, commServerPic, blockType.server);
             server.DrawBlock(g, activeItem[0, 0]);
             Map.WriteBlockOnMap(server, 0);
             // obliczam współrzędne punktów dołączania
             y1 = server.rec.Top;
             y2 = server.rec.Bottom;
             x1 = server.rec.Left;
             x2 = server.rec.Right;
             l  = (x2 - x1) / 3;
             l  = Math.Floor(l);
             // wyznaczam punkty połączeniowe servera
             ethSock1   = new Point(x1 + (int)l, y2);
             ethSock2   = ethSock1;
             ethSock2.X = ethSock2.X + (int)l;
             l          = (y2 - y1) / (Data.comunicationNet1.Channels.Rows.Count + 1);
             l          = Math.Floor(l);
             for (int i = 1; i <= Data.comunicationNet1.Channels.Rows.Count; i++)
             {
                 serverChannelSocket[i - 1] = new Point(x2, y1 + (int)l * i);
             }
             // ..:: SCADA & ADMIN Stations ::........................................................................
             PrintLAN(scadaPic);
             // ..:: PROTOCOLS ::.....................................................................................
             if (generacja)
             {
                 l     = pW / (Data.comunicationNet1.Protocol.Rows.Count + 2);
                 l     = Math.Floor(l);
                 act.Y = (int)Math.Floor((double)(pH / 2)); // odległośc od góry okna = 1/2 powierzchni rysowania
                 l     = l / (Data.comunicationNet1.Protocol.Rows.Count + 1);
                 l     = 2 * Math.Floor(l);                 // odstępy pomiedzy ramkami
             }
             for (int i = 0; i < Data.comunicationNet1.Protocol.Rows.Count; i++)
             {
                 if (generacja)
                 {
                     act.X       = (int)l * (i + 1) + protocolBlockWidth * i;
                     protocol[i] = new Block(act.X, act.Y, iconSz, protocolBlockWidth, Data.comunicationNet1.Protocol.Rows[i]["Name"].ToString(), blockType.protocol);
                 }
                 protocol[i].DrawBlock(g, activeItem[4, i]);
                 Map.WriteBlockOnMap(protocol[i], i);
             }
             // ..:: CHANNELS ::......................................................................................
             for (int i = 0; i < Data.comunicationNet1.Channels.Rows.Count; i++)
             {
                 pomString      = Data.comunicationNet1.Channels.Rows[i]["Name"].ToString();
                 channelLine[i] = new SimpleLine(serverChannelSocket[i].X, serverChannelSocket[i].Y, serverChannelSocket[i].X + channelLineLenght, serverChannelSocket[i].Y, Configuration.channelPen);
                 channelLine[i].DrawLine(g);
                 channel[i] = new Block(serverChannelSocket[i].X + channelLineLenght + 5, serverChannelSocket[i].Y - 8, 17, pomString.Length * 9, pomString, blockType.channel);
                 channel[i].DrawBlock(g, activeItem[3, i]);
                 Map.WriteBlockOnMap(channel[i], i);
             }
             // ..:: SEGMENTS ::......................................................................................
             if (generacja)
             {
                 l     = pW / (Data.comunicationNet1.Segments.Rows.Count + 2);
                 l     = Math.Floor(l);
                 act.Y = (int)Math.Floor((double)(pH / 3)) + 5; // odległośc od góry okna = 1/3 powierzchni rysowania + 5 by kanały nie wchodziły na webBrowser'a
                 l     = l / (Data.comunicationNet1.Segments.Rows.Count + 1);
                 l     = 2 * Math.Floor(l);                     // odstępy pomiedzy ramkami
             }
             for (int i = 0; i < Data.comunicationNet1.Segments.Rows.Count; i++)
             {
                 if (generacja)
                 {
                     act.X      = (int)l * (i + 1) + segmentBlockWidth * i;
                     segment[i] = new Block(act.X, act.Y, iconSz, segmentBlockWidth, Data.comunicationNet1.Segments.Rows[i]["Name"].ToString(), blockType.segment);
                 }
                 segment[i].DrawBlock(g, activeItem[5, i]);
                 Map.WriteBlockOnMap(segment[i], i);
             }
             // ..:: STATIONS ::......................................................................................
             if (generacja)
             {
                 act.Y    = 20;
                 rec.Size = new Size(iconSz + (int)Configuration.iconFrame.Width * 2, iconSz + (int)Configuration.iconFrame.Width * 2);
                 act.X    = 0 - halfIconSz;
                 l        = pW / (Data.comunicationNet1.Station.Rows.Count + 1); // odległość między lewymi górnymi narożnikami ikonek stacji
             }
             for (int i = 0; i < Data.comunicationNet1.Station.Rows.Count; i++)
             {
                 if (generacja)
                 {
                     act.X      = act.X + (int)l;
                     station[i] = new Icon(act.X, act.Y, iconSz, iconSz, stationPic, blockType.station);
                 }
                 Configuration.iconFrame.Color = Configuration.stationColors[i % 6];
                 station[i].DrawBlock(g, activeItem[6, i]);
                 Map.WriteBlockOnMap(station[i], i);
                 g.DrawString(Data.comunicationNet1.Station.Rows[i]["Name"].ToString(), Configuration.infoFont, Brushes.Blue, station[i].x, station[i].y - 20);
             }
             if (generacja)
             {
                 GenerateLines(); // wymusza generowanie połączeń od podstaw
             }
             ConnectLines();      // rysuje połączenia
             for (int i = 0; i < Data.comunicationNet1.Channels.Rows.Count; i++)
             {
                 Map.WriteLineOnMap(channelLine[i], i); // kanały zaznaczamy na mapie na końcu aby nie przesłoniły ich linie
             }
         }
         finally
         {
             g.Dispose();
         }
     }
 }